X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=lttng-sessiond%2Fmain.c;h=d0c1d406863c471cadfb948f43380c9acc62128b;hp=f13571ab37159fc00d9aac331444eab9cb68db42;hb=fb09408a89eb37b77cc4bd5fe89b61271117ad07;hpb=487cf67c6435255ab3ede6dd8cd7678b8b4d1981 diff --git a/lttng-sessiond/main.c b/lttng-sessiond/main.c index f13571ab3..d0c1d4068 100644 --- a/lttng-sessiond/main.c +++ b/lttng-sessiond/main.c @@ -157,6 +157,26 @@ static struct ust_cmd_queue ust_cmd_queue; */ static struct ltt_session_list *session_list_ptr; +int ust_consumer_fd; + +static const char *compat32_consumer_bindir = + __stringify(CONFIG_COMPAT_BIN_DIR); +static const char *compat32_consumer_prog = "lttng-consumerd"; + +static +void setup_compat32_consumer(void) +{ + const char *bindir; + + /* + * runtime env. var. overrides the build default. + */ + bindir = getenv("LTTNG_TOOLS_COMPAT_BIN_DIR"); + if (bindir) { + compat32_consumer_bindir = bindir; + } +} + /* * Create a poll set with O_CLOEXEC and add the thread quit pipe to the set. */ @@ -303,8 +323,14 @@ static void teardown_kernel_session(struct ltt_session *session) */ static void teardown_ust_session(struct ltt_session *session) { + int ret; + DBG("Tearing down UST session(s)"); + ret = ust_app_destroy_trace_all(session->ust_session); + if (ret) { + ERR("Error in ust_app_destroy_trace_all"); + } trace_ust_destroy_session(session->ust_session); } @@ -338,12 +364,6 @@ static void cleanup(void) DBG("Cleaning up"); - /* */ - MSG("%c[%d;%dm*** assert failed *** ==> %c[%dm%c[%d;%dm" - "Matthew, BEET driven development works!%c[%dm", - 27, 1, 31, 27, 0, 27, 1, 33, 27, 0); - /* */ - if (is_root) { DBG("Removing %s directory", LTTNG_RUNDIR); ret = asprintf(&cmd, "rm -rf " LTTNG_RUNDIR); @@ -388,6 +408,12 @@ static void cleanup(void) close(thread_quit_pipe[0]); close(thread_quit_pipe[1]); + + /* */ + MSG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm" + "Matthew, BEET driven development works!%c[%dm", + 27, 1, 31, 27, 0, 27, 1, 33, 27, 0); + /* */ } /* @@ -588,9 +614,9 @@ static int setup_lttng_msg(struct command_ctx *cmd_ctx, size_t size) buf_size = size; - cmd_ctx->llm = malloc(sizeof(struct lttcomm_lttng_msg) + buf_size); + cmd_ctx->llm = zmalloc(sizeof(struct lttcomm_lttng_msg) + buf_size); if (cmd_ctx->llm == NULL) { - perror("malloc"); + perror("zmalloc"); ret = -ENOMEM; goto error; } @@ -720,7 +746,9 @@ static void update_ust_app(int app_sock) /* For all tracing session(s) */ cds_list_for_each_entry_safe(sess, stmp, &session_list_ptr->head, list) { - ust_app_global_update(sess->ust_session, app_sock); + if (sess->ust_session) { + ust_app_global_update(sess->ust_session, app_sock); + } } } @@ -1050,11 +1078,18 @@ static void *thread_manage_apps(void *data) /* Register applicaton to the session daemon */ ret = ust_app_register(&ust_cmd.reg_msg, ust_cmd.sock); - if (ret < 0) { - /* Only critical ENOMEM error can be returned here */ + if (ret == -ENOMEM) { goto error; + } else if (ret < 0) { + break; } + /* + * Add channel(s) and event(s) to newly registered apps + * from lttng global UST domain. + */ + update_ust_app(ust_cmd.sock); + ret = ustctl_register_done(ust_cmd.sock); if (ret < 0) { /* @@ -1076,11 +1111,6 @@ static void *thread_manage_apps(void *data) ust_cmd.sock); } - /* - * Add channel(s) and event(s) to newly registered apps - * from lttng global UST domain. - */ - update_ust_app(ust_cmd.sock); break; } } else { @@ -1095,7 +1125,7 @@ static void *thread_manage_apps(void *data) goto error; } - /* Socket closed */ + /* Socket closed on remote end. */ ust_app_unregister(pollfd); break; } @@ -1257,9 +1287,9 @@ static void *thread_registration_apps(void *data) } /* Create UST registration command for enqueuing */ - ust_cmd = malloc(sizeof(struct ust_command)); + ust_cmd = zmalloc(sizeof(struct ust_command)); if (ust_cmd == NULL) { - perror("ust command malloc"); + perror("ust command zmalloc"); goto error; } @@ -1718,6 +1748,7 @@ static int create_ust_session(struct ltt_session *session, /* No ustctl for the global UST domain */ break; default: + ERR("Unknown UST domain on create session %d", domain->type); goto error; } session->ust_session = lus; @@ -1784,6 +1815,7 @@ static void list_lttng_sessions(struct lttng_session *sessions) sessions[i].path[PATH_MAX - 1] = '\0'; strncpy(sessions[i].name, session->name, NAME_MAX); sessions[i].name[NAME_MAX - 1] = '\0'; + sessions[i].enabled = session->enabled; i++; } } @@ -1791,7 +1823,7 @@ static void list_lttng_sessions(struct lttng_session *sessions) /* * Fill lttng_channel array of all channels. */ -static void list_lttng_channels(struct ltt_session *session, +static void list_lttng_channels(int domain, struct ltt_session *session, struct lttng_channel *channels) { int i = 0; @@ -1799,59 +1831,163 @@ static void list_lttng_channels(struct ltt_session *session, DBG("Listing channels for session %s", session->name); - /* Kernel channels */ - if (session->kernel_session != NULL) { - cds_list_for_each_entry(kchan, - &session->kernel_session->channel_list.head, list) { - /* Copy lttng_channel struct to array */ - memcpy(&channels[i], kchan->channel, sizeof(struct lttng_channel)); - channels[i].enabled = kchan->enabled; + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + /* Kernel channels */ + if (session->kernel_session != NULL) { + cds_list_for_each_entry(kchan, + &session->kernel_session->channel_list.head, list) { + /* Copy lttng_channel struct to array */ + memcpy(&channels[i], kchan->channel, sizeof(struct lttng_channel)); + channels[i].enabled = kchan->enabled; + i++; + } + } + break; + case LTTNG_DOMAIN_UST: + { + struct cds_lfht_iter iter; + struct ltt_ust_channel *uchan; + + cds_lfht_for_each_entry(session->ust_session->domain_global.channels, + &iter, uchan, node) { + strncpy(channels[i].name, uchan->name, LTTNG_SYMBOL_NAME_LEN); + channels[i].attr.overwrite = uchan->attr.overwrite; + channels[i].attr.subbuf_size = uchan->attr.subbuf_size; + channels[i].attr.num_subbuf = uchan->attr.num_subbuf; + channels[i].attr.switch_timer_interval = + uchan->attr.switch_timer_interval; + channels[i].attr.read_timer_interval = + uchan->attr.read_timer_interval; + channels[i].attr.output = uchan->attr.output; + } + break; + } + default: + break; + } +} + +/* + * Create a list of ust global domain events. + */ +static int list_lttng_ust_global_events(char *channel_name, + struct ltt_ust_domain_global *ust_global, struct lttng_event **events) +{ + int i = 0, ret = 0; + unsigned int nb_event = 0; + struct cds_lfht_iter iter; + struct ltt_ust_channel *uchan; + struct ltt_ust_event *uevent; + struct lttng_event *tmp; + + DBG("Listing UST global events for channel %s", channel_name); + + rcu_read_lock(); + + /* Count events in all channels */ + cds_lfht_for_each_entry(ust_global->channels, &iter, uchan, node) { + nb_event += hashtable_get_count(uchan->events); + } + + if (nb_event == 0) { + ret = nb_event; + goto error; + } + + DBG3("Listing UST global %d events", nb_event); + + tmp = zmalloc(nb_event * sizeof(struct lttng_event)); + if (tmp == NULL) { + ret = -LTTCOMM_FATAL; + goto error; + } + + cds_lfht_for_each_entry(ust_global->channels, &iter, uchan, node) { + cds_lfht_for_each_entry(uchan->events, &iter, uevent, node) { + strncpy(tmp[i].name, uevent->attr.name, LTTNG_SYMBOL_NAME_LEN); + tmp[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; + tmp[i].enabled = uevent->enabled; + switch (uevent->attr.instrumentation) { + case LTTNG_UST_TRACEPOINT: + tmp[i].type = LTTNG_EVENT_TRACEPOINT; + break; + case LTTNG_UST_PROBE: + tmp[i].type = LTTNG_EVENT_PROBE; + break; + case LTTNG_UST_FUNCTION: + tmp[i].type = LTTNG_EVENT_FUNCTION; + break; + } i++; } } - /* TODO: Missing UST listing */ + ret = nb_event; + *events = tmp; + +error: + rcu_read_unlock(); + return ret; } /* - * Fill lttng_event array of all events in the channel. + * Fill lttng_event array of all kernel events in the channel. */ -static void list_lttng_events(struct ltt_kernel_channel *kchan, - struct lttng_event *events) +static int list_lttng_kernel_events(char *channel_name, + struct ltt_kernel_session *kernel_session, struct lttng_event **events) { - /* - * TODO: This is ONLY kernel. Need UST support. - */ - int i = 0; + int i = 0, ret; + unsigned int nb_event; struct ltt_kernel_event *event; + struct ltt_kernel_channel *kchan; + + kchan = trace_kernel_get_channel_by_name(channel_name, kernel_session); + if (kchan == NULL) { + ret = LTTCOMM_KERN_CHAN_NOT_FOUND; + goto error; + } + + nb_event = kchan->event_count; DBG("Listing events for channel %s", kchan->channel->name); + if (nb_event == 0) { + ret = nb_event; + goto error; + } + + *events = zmalloc(nb_event * sizeof(struct lttng_event)); + if (*events == NULL) { + ret = LTTCOMM_FATAL; + goto error; + } + /* Kernel channels */ cds_list_for_each_entry(event, &kchan->events_list.head , list) { - strncpy(events[i].name, event->event->name, LTTNG_SYMBOL_NAME_LEN); - events[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; - events[i].enabled = event->enabled; + strncpy((*events)[i].name, event->event->name, LTTNG_SYMBOL_NAME_LEN); + (*events)[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; + (*events)[i].enabled = event->enabled; switch (event->event->instrumentation) { case LTTNG_KERNEL_TRACEPOINT: - events[i].type = LTTNG_EVENT_TRACEPOINT; + (*events)[i].type = LTTNG_EVENT_TRACEPOINT; break; case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_KRETPROBE: - events[i].type = LTTNG_EVENT_PROBE; - memcpy(&events[i].attr.probe, &event->event->u.kprobe, + (*events)[i].type = LTTNG_EVENT_PROBE; + memcpy(&(*events)[i].attr.probe, &event->event->u.kprobe, sizeof(struct lttng_kernel_kprobe)); break; case LTTNG_KERNEL_FUNCTION: - events[i].type = LTTNG_EVENT_FUNCTION; - memcpy(&events[i].attr.ftrace, &event->event->u.ftrace, + (*events)[i].type = LTTNG_EVENT_FUNCTION; + memcpy(&((*events)[i].attr.ftrace), &event->event->u.ftrace, sizeof(struct lttng_kernel_function)); break; case LTTNG_KERNEL_NOOP: - events[i].type = LTTNG_EVENT_NOOP; + (*events)[i].type = LTTNG_EVENT_NOOP; break; case LTTNG_KERNEL_SYSCALL: - events[i].type = LTTNG_EVENT_SYSCALL; + (*events)[i].type = LTTNG_EVENT_SYSCALL; break; case LTTNG_KERNEL_ALL: assert(0); @@ -1859,6 +1995,11 @@ static void list_lttng_events(struct ltt_kernel_channel *kchan, } i++; } + + return nb_event; + +error: + return ret; } /* @@ -1935,7 +2076,7 @@ static int cmd_enable_channel(struct ltt_session *session, int ret; struct ltt_ust_session *usess = session->ust_session; - DBG("Enabling channel %s for session %s", session->name, attr->name); + DBG("Enabling channel %s for session %s", attr->name, session->name); switch (domain->type) { case LTTNG_DOMAIN_KERNEL: @@ -1973,6 +2114,7 @@ static int cmd_enable_channel(struct ltt_session *session, ret = LTTCOMM_UST_CHAN_FAIL; goto error; } + rcu_read_lock(); hashtable_add_unique(usess->domain_global.channels, &uchan->node); rcu_read_unlock(); @@ -1982,11 +2124,14 @@ static int cmd_enable_channel(struct ltt_session *session, goto error; } - ret = ust_app_add_channel(usess, uchan); - if (ret != LTTCOMM_OK) { + /* Add channel to all registered applications */ + ret = ust_app_create_channel_all(usess, uchan); + if (ret != 0) { goto error; } + uchan->enabled = 1; + break; } case LTTNG_DOMAIN_UST_PID: @@ -2240,17 +2385,24 @@ static int cmd_enable_event(struct ltt_session *session, int domain, ret = LTTCOMM_FATAL; goto error; } + } - ret = ust_app_add_event(usess, uchan, uevent); + ret = ust_app_create_event_all(usess, uchan, uevent); if (ret < 0) { ret = LTTCOMM_UST_ENABLE_FAIL; goto error; } + /* Add ltt ust event to channel */ rcu_read_lock(); hashtable_add_unique(uchan->events, &uevent->node); rcu_read_unlock(); + + uevent->enabled = 1; + + DBG3("UST ltt event %s added to channel %s", uevent->attr.name, + uchan->name); break; } case LTTNG_DOMAIN_UST_EXEC_NAME: @@ -2354,8 +2506,14 @@ static ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events) goto error; } break; + case LTTNG_DOMAIN_UST: + nb_events = ust_app_list_events(events); + if (nb_events < 0) { + ret = LTTCOMM_UST_LIST_FAIL; + goto error; + } + break; default: - /* TODO: Userspace listing */ ret = LTTCOMM_NOT_IMPLEMENTED; goto error; } @@ -2374,10 +2532,15 @@ static int cmd_start_trace(struct ltt_session *session) { int ret; struct ltt_kernel_session *ksession; - struct ltt_ust_session *usess = session->ust_session; + struct ltt_ust_session *usess; /* Short cut */ ksession = session->kernel_session; + usess = session->ust_session; + + if (session->enabled) + return LTTCOMM_UST_START_FAIL; + session->enabled = 1; /* Kernel tracing */ if (ksession != NULL) { @@ -2433,10 +2596,15 @@ static int cmd_start_trace(struct ltt_session *session) kernel_wait_quiescent(kernel_tracer_fd); } - ret = ust_app_start_trace(usess); - if (ret < 0) { - ret = LTTCOMM_UST_START_FAIL; - goto error; + /* Flag session that trace should start automatically */ + if (usess) { + usess->start_trace = 1; + + ret = ust_app_start_trace_all(usess); + if (ret < 0) { + ret = LTTCOMM_UST_START_FAIL; + goto error; + } } ret = LTTCOMM_OK; @@ -2453,11 +2621,15 @@ static int cmd_stop_trace(struct ltt_session *session) int ret; struct ltt_kernel_channel *kchan; struct ltt_kernel_session *ksession; - //struct ltt_ust_session *usess; - //struct ltt_ust_channel *ustchan; + struct ltt_ust_session *usess; /* Short cut */ ksession = session->kernel_session; + usess = session->ust_session; + + if (!session->enabled) + return LTTCOMM_UST_START_FAIL; + session->enabled = 0; /* Kernel tracer */ if (ksession != NULL) { @@ -2485,32 +2657,16 @@ static int cmd_stop_trace(struct ltt_session *session) kernel_wait_quiescent(kernel_tracer_fd); } -#ifdef DISABLE - /* Stop each UST session */ - DBG("Stop UST tracing"); - cds_list_for_each_entry(usess, &session->ust_session_list.head, list) { - /* Flush all buffers before stopping */ - ret = ustctl_flush_buffer(usess->sock, usess->metadata->obj); - if (ret < 0) { - ERR("UST metadata flush failed"); - } + /* Flag session that trace should start automatically */ + if (usess) { + usess->start_trace = 0; - cds_list_for_each_entry(ustchan, &usess->channels.head, list) { - ret = ustctl_flush_buffer(usess->sock, ustchan->obj); - if (ret < 0) { - ERR("UST flush buffer error"); - } - } - - ret = ustctl_stop_session(usess->sock, usess->handle); + ret = ust_app_stop_trace_all(usess); if (ret < 0) { - ret = LTTCOMM_KERN_STOP_FAIL; + ret = LTTCOMM_UST_START_FAIL; goto error; } - - ustctl_wait_quiescent(usess->sock); } -#endif ret = LTTCOMM_OK; @@ -2545,6 +2701,8 @@ static int cmd_destroy_session(struct ltt_session *session, char *name) /* Clean kernel session teardown */ teardown_kernel_session(session); + /* UST session teardown */ + teardown_ust_session(session); /* * Must notify the kernel thread here to update it's poll setin order @@ -2634,22 +2792,34 @@ error: static ssize_t cmd_list_domains(struct ltt_session *session, struct lttng_domain **domains) { - int ret; + int ret, index = 0; ssize_t nb_dom = 0; if (session->kernel_session != NULL) { + DBG3("Listing domains found kernel domain"); nb_dom++; } - /* TODO: User-space tracer domain support */ + if (session->ust_session != NULL) { + DBG3("Listing domains found UST global domain"); + nb_dom++; + } - *domains = malloc(nb_dom * sizeof(struct lttng_domain)); + *domains = zmalloc(nb_dom * sizeof(struct lttng_domain)); if (*domains == NULL) { ret = -LTTCOMM_FATAL; goto error; } - (*domains)[0].type = LTTNG_DOMAIN_KERNEL; + if (session->kernel_session != NULL) { + (*domains)[index].type = LTTNG_DOMAIN_KERNEL; + index++; + } + + if (session->ust_session != NULL) { + (*domains)[index].type = LTTNG_DOMAIN_UST; + index++; + } return nb_dom; @@ -2660,25 +2830,43 @@ error: /* * Command LTTNG_LIST_CHANNELS processed by the client thread. */ -static ssize_t cmd_list_channels(struct ltt_session *session, +static ssize_t cmd_list_channels(int domain, struct ltt_session *session, struct lttng_channel **channels) { int ret; ssize_t nb_chan = 0; - if (session->kernel_session != NULL) { - nb_chan += session->kernel_session->channel_count; - } - - *channels = malloc(nb_chan * sizeof(struct lttng_channel)); - if (*channels == NULL) { - ret = -LTTCOMM_FATAL; + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + if (session->kernel_session != NULL) { + nb_chan = session->kernel_session->channel_count; + } + DBG3("Number of kernel channels %zd", nb_chan); + break; + case LTTNG_DOMAIN_UST: + if (session->ust_session != NULL) { + nb_chan = hashtable_get_count( + session->ust_session->domain_global.channels); + } + DBG3("Number of UST global channels %zd", nb_chan); + break; + default: + *channels = NULL; + ret = -LTTCOMM_NOT_IMPLEMENTED; goto error; } - list_lttng_channels(session, *channels); + if (nb_chan > 0) { + *channels = zmalloc(nb_chan * sizeof(struct lttng_channel)); + if (*channels == NULL) { + ret = -LTTCOMM_FATAL; + goto error; + } - /* TODO UST support */ + list_lttng_channels(domain, session, *channels); + } else { + *channels = NULL; + } return nb_chan; @@ -2689,34 +2877,33 @@ error: /* * Command LTTNG_LIST_EVENTS processed by the client thread. */ -static ssize_t cmd_list_events(struct ltt_session *session, +static ssize_t cmd_list_events(int domain, struct ltt_session *session, char *channel_name, struct lttng_event **events) { - int ret; + int ret = 0; ssize_t nb_event = 0; - struct ltt_kernel_channel *kchan = NULL; - if (session->kernel_session != NULL) { - kchan = trace_kernel_get_channel_by_name(channel_name, - session->kernel_session); - if (kchan == NULL) { - ret = -LTTCOMM_KERN_CHAN_NOT_FOUND; - goto error; + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + if (session->kernel_session != NULL) { + nb_event = list_lttng_kernel_events(channel_name, + session->kernel_session, events); + } + break; + case LTTNG_DOMAIN_UST: + { + if (session->ust_session != NULL) { + nb_event = list_lttng_ust_global_events(channel_name, + &session->ust_session->domain_global, events); } - nb_event += kchan->event_count; + break; } - - *events = malloc(nb_event * sizeof(struct lttng_event)); - if (*events == NULL) { - ret = -LTTCOMM_FATAL; + default: + ret = -LTTCOMM_NOT_IMPLEMENTED; goto error; } - list_lttng_events(kchan, *events); - - /* TODO: User-space tracer support */ - - return nb_event; + ret = nb_event; error: return ret; @@ -2845,8 +3032,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) goto error; } - cmd_ctx->session->ust_session->consumer_fd = - ustconsumer_data.cmd_sock; + ust_consumer_fd = ustconsumer_data.cmd_sock; } pthread_mutex_unlock(&ustconsumer_data.pid_mutex); } @@ -2992,7 +3178,8 @@ static int process_client_msg(struct command_ctx *cmd_ctx) size_t nb_chan; struct lttng_channel *channels; - nb_chan = cmd_list_channels(cmd_ctx->session, &channels); + nb_chan = cmd_list_channels(cmd_ctx->lsm->domain.type, + cmd_ctx->session, &channels); if (nb_chan < 0) { ret = -nb_chan; goto error; @@ -3014,10 +3201,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } case LTTNG_LIST_EVENTS: { - size_t nb_event; + ssize_t nb_event; struct lttng_event *events = NULL; - nb_event = cmd_list_events(cmd_ctx->session, + nb_event = cmd_list_events(cmd_ctx->lsm->domain.type, cmd_ctx->session, cmd_ctx->lsm->u.list.channel_name, &events); if (nb_event < 0) { ret = -nb_event; @@ -3178,16 +3365,16 @@ static void *thread_manage_clients(void *data) } /* Allocate context command to process the client request */ - cmd_ctx = malloc(sizeof(struct command_ctx)); + cmd_ctx = zmalloc(sizeof(struct command_ctx)); if (cmd_ctx == NULL) { - perror("malloc cmd_ctx"); + perror("zmalloc cmd_ctx"); goto error; } /* Allocate data buffer for reception */ - cmd_ctx->lsm = malloc(sizeof(struct lttcomm_session_msg)); + cmd_ctx->lsm = zmalloc(sizeof(struct lttcomm_session_msg)); if (cmd_ctx->lsm == NULL) { - perror("malloc cmd_ctx->lsm"); + perror("zmalloc cmd_ctx->lsm"); goto error; } @@ -3224,7 +3411,7 @@ static void *thread_manage_clients(void *data) if (ret < 0) { /* * TODO: Inform client somehow of the fatal error. At - * this point, ret < 0 means that a malloc failed + * this point, ret < 0 means that a zmalloc failed * (ENOMEM). Error detected but still accept command. */ clean_command_ctx(&cmd_ctx); @@ -3272,6 +3459,7 @@ static void usage(void) fprintf(stderr, " --kconsumerd-cmd-sock PATH Specify path for the kernel consumer command socket\n"); fprintf(stderr, " --ustconsumerd-err-sock PATH Specify path for the UST consumer error socket\n"); fprintf(stderr, " --ustconsumerd-cmd-sock PATH Specify path for the UST consumer command socket\n"); + fprintf(stderr, " --ustconsumerd-compat32 PATH Specify path for the 32-bit UST consumer daemon binary\n"); fprintf(stderr, " -d, --daemonize Start as a daemon.\n"); fprintf(stderr, " -g, --group NAME Specify the tracing group name. (default: tracing)\n"); fprintf(stderr, " -V, --version Show version number.\n"); @@ -3295,6 +3483,7 @@ static int parse_args(int argc, char **argv) { "kconsumerd-err-sock", 1, 0, 'E' }, { "ustconsumerd-cmd-sock", 1, 0, 'D' }, { "ustconsumerd-err-sock", 1, 0, 'F' }, + { "ustconsumerd-compat32", 1, 0, 'u' }, { "daemonize", 0, 0, 'd' }, { "sig-parent", 0, 0, 'S' }, { "help", 0, 0, 'h' }, @@ -3308,7 +3497,7 @@ static int parse_args(int argc, char **argv) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:C:E:D:F:Z", + c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:C:E:D:F:Z:u", long_options, &option_index); if (c == -1) { break; @@ -3331,7 +3520,7 @@ static int parse_args(int argc, char **argv) opt_daemon = 1; break; case 'g': - opt_tracing_group = strdup(optarg); + opt_tracing_group = optarg; break; case 'h': usage(); @@ -3364,6 +3553,9 @@ static int parse_args(int argc, char **argv) case 'Z': opt_verbose_consumer += 1; break; + case 'u': + compat32_consumer_bindir = optarg; + break; default: /* Unknown option or other error. * Error is printed by getopt, just return */ @@ -3690,6 +3882,8 @@ int main(int argc, char **argv) goto error; } + setup_compat32_consumer(); + /* Parse arguments */ progname = argv[0]; if ((ret = parse_args(argc, argv) < 0)) {