X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-app.c;h=9ab5f77e0067b8f129b8ce4e17c2bba12d386f43;hp=ab08ac0e4d04ccf409c8d02e358e11f0033a0520;hb=57703f6e0047955a0c68829630fcc42aad988a39;hpb=a2ba1ab0fbd794f06d5ba9afac6b3749dace34e4 diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index ab08ac0e4..9ab5f77e0 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#define _LGPL_SOURCE #include #include #include @@ -825,6 +826,7 @@ struct ust_app_session *alloc_ust_app_session(struct ust_app *app) ua_sess->handle = -1; ua_sess->channels = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); + ua_sess->metadata_attr.type = LTTNG_UST_CHAN_METADATA; pthread_mutex_init(&ua_sess->lock, NULL); return ua_sess; @@ -1445,11 +1447,15 @@ int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess, } /* If event not enabled, disable it on the tracer */ - if (ua_event->enabled == 0) { - ret = disable_ust_event(app, ua_sess, ua_event); + if (ua_event->enabled) { + /* + * We now need to explicitly enable the event, since it + * is now disabled at creation. + */ + ret = enable_ust_event(app, ua_sess, ua_event); if (ret < 0) { /* - * If we hit an EPERM, something is wrong with our disable call. If + * If we hit an EPERM, something is wrong with our enable call. If * we get an EEXIST, there is a problem on the tracer side since we * just created it. */ @@ -1551,7 +1557,7 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, } lttng_ht_node_init_ulong(&ua_ctx->node, (unsigned long) ua_ctx->ctx.ctx); - lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node); + lttng_ht_add_ulong(ua_chan->ctx, &ua_ctx->node); cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list); } @@ -1608,6 +1614,8 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, ua_sess->consumer = usess->consumer; ua_sess->output_traces = usess->output_traces; ua_sess->live_timer_interval = usess->live_timer_interval; + copy_channel_attr_to_ustctl(&ua_sess->metadata_attr, + &usess->metadata_attr); switch (ua_sess->buffer_type) { case LTTNG_BUFFER_PER_PID: @@ -1724,7 +1732,6 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, if (ret < 0) { goto error; } - buffer_reg_pid_add(reg_pid); } else { goto end; } @@ -1737,9 +1744,18 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, app->byte_order, app->version.major, app->version.minor); if (ret < 0) { + /* + * reg_pid->registry->reg.ust is NULL upon error, so we need to + * destroy the buffer registry, because it is always expected + * that if the buffer registry can be found, its ust registry is + * non-NULL. + */ + buffer_reg_pid_destroy(reg_pid); goto error; } + buffer_reg_pid_add(reg_pid); + DBG3("UST app buffer registry per PID created successfully"); end: @@ -1780,7 +1796,6 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, if (ret < 0) { goto error; } - buffer_reg_uid_add(reg_uid); } else { goto end; } @@ -1793,13 +1808,21 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, app->byte_order, app->version.major, app->version.minor); if (ret < 0) { + /* + * reg_uid->registry->reg.ust is NULL upon error, so we need to + * destroy the buffer registry, because it is always expected + * that if the buffer registry can be found, its ust registry is + * non-NULL. + */ + buffer_reg_uid_destroy(reg_uid, NULL); goto error; } /* Add node to teardown list of the session. */ cds_list_add(®_uid->lnode, &usess->buffer_reg_uid_list); - DBG3("UST app buffer registry per UID created successfully"); + buffer_reg_uid_add(reg_uid); + DBG3("UST app buffer registry per UID created successfully"); end: if (regp) { *regp = reg_uid; @@ -1852,6 +1875,7 @@ static int create_ust_app_session(struct ltt_ust_session *usess, /* Init local registry. */ ret = setup_buffer_reg_pid(ua_sess, app, NULL); if (ret < 0) { + delete_ust_app_session(-1, ua_sess, app); goto error; } break; @@ -1859,6 +1883,7 @@ static int create_ust_app_session(struct ltt_ust_session *usess, /* Look for a global registry. If none exists, create one. */ ret = setup_buffer_reg_uid(usess, app, NULL); if (ret < 0) { + delete_ust_app_session(-1, ua_sess, app); goto error; } break; @@ -1920,6 +1945,75 @@ error: return ret; } +/* + * Match function for a hash table lookup of ust_app_ctx. + * + * It matches an ust app context based on the context type and, in the case + * of perf counters, their name. + */ +static int ht_match_ust_app_ctx(struct cds_lfht_node *node, const void *_key) +{ + struct ust_app_ctx *ctx; + const struct lttng_ust_context *key; + + assert(node); + assert(_key); + + ctx = caa_container_of(node, struct ust_app_ctx, node.node); + key = _key; + + /* Context type */ + if (ctx->ctx.ctx != key->ctx) { + goto no_match; + } + + /* Check the name in the case of perf thread counters. */ + if (key->ctx == LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER) { + if (strncmp(key->u.perf_counter.name, + ctx->ctx.u.perf_counter.name, + sizeof(key->u.perf_counter.name))) { + goto no_match; + } + } + + /* Match. */ + return 1; + +no_match: + return 0; +} + +/* + * Lookup for an ust app context from an lttng_ust_context. + * + * Must be called while holding RCU read side lock. + * Return an ust_app_ctx object or NULL on error. + */ +static +struct ust_app_ctx *find_ust_app_context(struct lttng_ht *ht, + struct lttng_ust_context *uctx) +{ + struct lttng_ht_iter iter; + struct lttng_ht_node_ulong *node; + struct ust_app_ctx *app_ctx = NULL; + + assert(uctx); + assert(ht); + + /* Lookup using the lttng_ust_context_type and a custom match fct. */ + cds_lfht_lookup(ht->ht, ht->hash_fct((void *) uctx->ctx, lttng_ht_seed), + ht_match_ust_app_ctx, uctx, &iter.iter); + node = lttng_ht_iter_get_node_ulong(&iter); + if (!node) { + goto end; + } + + app_ctx = caa_container_of(node, struct ust_app_ctx, node); + +end: + return app_ctx; +} + /* * Create a context for the channel on the tracer. * @@ -1931,15 +2025,12 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess, struct ust_app *app) { int ret = 0; - struct lttng_ht_iter iter; - struct lttng_ht_node_ulong *node; struct ust_app_ctx *ua_ctx; DBG2("UST app adding context to channel %s", ua_chan->name); - lttng_ht_lookup(ua_chan->ctx, (void *)((unsigned long)uctx->ctx), &iter); - node = lttng_ht_iter_get_node_ulong(&iter); - if (node != NULL) { + ua_ctx = find_ust_app_context(ua_chan->ctx, uctx); + if (ua_ctx) { ret = -EEXIST; goto error; } @@ -1952,7 +2043,7 @@ int create_ust_app_channel_context(struct ust_app_session *ua_sess, } lttng_ht_node_init_ulong(&ua_ctx->node, (unsigned long) ua_ctx->ctx.ctx); - lttng_ht_add_unique_ulong(ua_chan->ctx, &ua_ctx->node); + lttng_ht_add_ulong(ua_chan->ctx, &ua_ctx->node); cds_list_add_tail(&ua_ctx->list, &ua_chan->ctx_list); ret = create_ust_channel_context(ua_chan, ua_ctx, app); @@ -2447,6 +2538,8 @@ static int create_channel_per_uid(struct ust_app *app, /* Create the buffer registry channel object. */ ret = create_buffer_reg_channel(reg_uid->registry, ua_chan, ®_chan); if (ret < 0) { + ERR("Error creating the UST channel \"%s\" registry instance", + ua_chan->name); goto error; } assert(reg_chan); @@ -2458,6 +2551,9 @@ static int create_channel_per_uid(struct ust_app *app, ret = do_consumer_create_channel(usess, ua_sess, ua_chan, app->bits_per_long, reg_uid->registry->reg.ust); if (ret < 0) { + ERR("Error creating UST channel \"%s\" on the consumer daemon", + ua_chan->name); + /* * Let's remove the previously created buffer registry channel so * it's not visible anymore in the session registry. @@ -2474,6 +2570,8 @@ static int create_channel_per_uid(struct ust_app *app, */ ret = setup_buffer_reg_channel(reg_uid->registry, ua_chan, reg_chan); if (ret < 0) { + ERR("Error setting up UST channel \"%s\"", + ua_chan->name); goto error; } @@ -2482,6 +2580,10 @@ static int create_channel_per_uid(struct ust_app *app, /* Send buffers to the application. */ ret = send_channel_uid_to_ust(reg_chan, app, ua_sess, ua_chan); if (ret < 0) { + /* + * Don't report error to the console, since it may be + * caused by application concurrently exiting. + */ goto error; } @@ -2516,6 +2618,8 @@ static int create_channel_per_pid(struct ust_app *app, /* Create and add a new channel registry to session. */ ret = ust_registry_channel_add(registry, ua_chan->key); if (ret < 0) { + ERR("Error creating the UST channel \"%s\" registry instance", + ua_chan->name); goto error; } @@ -2523,11 +2627,17 @@ static int create_channel_per_pid(struct ust_app *app, ret = do_consumer_create_channel(usess, ua_sess, ua_chan, app->bits_per_long, registry); if (ret < 0) { + ERR("Error creating UST channel \"%s\" on the consumer daemon", + ua_chan->name); goto error; } ret = send_channel_pid_to_ust(app, ua_sess, ua_chan); if (ret < 0) { + /* + * Don't report error to the console, since it may be + * caused by application concurrently exiting. + */ goto error; } @@ -2714,8 +2824,7 @@ error: * Called with UST app session lock held and RCU read side lock. */ static int create_ust_app_metadata(struct ust_app_session *ua_sess, - struct ust_app *app, struct consumer_output *consumer, - struct ustctl_consumer_channel_attr *attr) + struct ust_app *app, struct consumer_output *consumer) { int ret = 0; struct ust_app_channel *metadata; @@ -2743,20 +2852,7 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, goto error; } - if (!attr) { - /* Set default attributes for metadata. */ - metadata->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE; - metadata->attr.subbuf_size = default_get_metadata_subbuf_size(); - metadata->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; - metadata->attr.switch_timer_interval = DEFAULT_METADATA_SWITCH_TIMER; - metadata->attr.read_timer_interval = DEFAULT_METADATA_READ_TIMER; - metadata->attr.output = LTTNG_UST_MMAP; - metadata->attr.type = LTTNG_UST_CHAN_METADATA; - } else { - memcpy(&metadata->attr, attr, sizeof(metadata->attr)); - metadata->attr.output = LTTNG_UST_MMAP; - metadata->attr.type = LTTNG_UST_CHAN_METADATA; - } + memcpy(&metadata->attr, &ua_sess->metadata_attr, sizeof(metadata->attr)); /* Need one fd for the channel. */ ret = lttng_fd_get(LTTNG_FD_APPS, 1); @@ -2817,14 +2913,6 @@ error: return ret; } -/* - * Return pointer to traceable apps list. - */ -struct lttng_ht *ust_app_get_ht(void) -{ - return ust_app_ht; -} - /* * Return ust app pointer or NULL if not found. RCU read side lock MUST be * acquired before calling this function. @@ -2972,9 +3060,9 @@ int ust_app_version(struct ust_app *app) ret = ustctl_tracer_version(app->sock, &app->version); if (ret < 0) { if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { - ERR("UST app %d verson failed with ret %d", app->sock, ret); + ERR("UST app %d version failed with ret %d", app->sock, ret); } else { - DBG3("UST app %d verion failed. Application is dead", app->sock); + DBG3("UST app %d version failed. Application is dead", app->sock); } } @@ -3087,20 +3175,6 @@ void ust_app_unregister(int sock) return; } -/* - * Return traceable_app_count - */ -unsigned long ust_app_list_count(void) -{ - unsigned long count; - - rcu_read_lock(); - count = lttng_ht_get_count(ust_app_ht); - rcu_read_unlock(); - - return count; -} - /* * Fill events array with all events name of all registered apps. */ @@ -3147,7 +3221,6 @@ int ust_app_list_events(struct lttng_event **events) &uiter)) != -LTTNG_UST_ERR_NOENT) { /* Handle ustctl error. */ if (ret < 0) { - free(tmp_event); if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { ERR("UST app tp list get failed for app %d with ret %d", app->sock, ret); @@ -3160,25 +3233,32 @@ int ust_app_list_events(struct lttng_event **events) */ break; } + free(tmp_event); goto rcu_error; } health_code_update(); if (count >= nbmem) { /* In case the realloc fails, we free the memory */ - void *ptr; - - DBG2("Reallocating event list from %zu to %zu entries", nbmem, - 2 * nbmem); - nbmem *= 2; - ptr = realloc(tmp_event, nbmem * sizeof(struct lttng_event)); - if (ptr == NULL) { + struct lttng_event *new_tmp_event; + size_t new_nbmem; + + new_nbmem = nbmem << 1; + DBG2("Reallocating event list from %zu to %zu entries", + nbmem, new_nbmem); + new_tmp_event = realloc(tmp_event, + new_nbmem * sizeof(struct lttng_event)); + if (new_tmp_event == NULL) { PERROR("realloc ust app events"); free(tmp_event); ret = -ENOMEM; goto rcu_error; } - tmp_event = ptr; + /* Zero the new memory */ + memset(new_tmp_event + nbmem, 0, + (new_nbmem - nbmem) * sizeof(struct lttng_event)); + nbmem = new_nbmem; + tmp_event = new_tmp_event; } memcpy(tmp_event[count].name, uiter.name, LTTNG_UST_SYM_NAME_LEN); tmp_event[count].loglevel = uiter.loglevel; @@ -3247,7 +3327,6 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) &uiter)) != -LTTNG_UST_ERR_NOENT) { /* Handle ustctl error. */ if (ret < 0) { - free(tmp_event); if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) { ERR("UST app tp list field failed for app %d with ret %d", app->sock, ret); @@ -3256,29 +3335,36 @@ int ust_app_list_event_fields(struct lttng_event_field **fields) /* * This is normal behavior, an application can die during the * creation process. Don't report an error so the execution can - * continue normally. + * continue normally. Reset list and count for next app. */ break; } + free(tmp_event); goto rcu_error; } health_code_update(); if (count >= nbmem) { /* In case the realloc fails, we free the memory */ - void *ptr; - - DBG2("Reallocating event field list from %zu to %zu entries", nbmem, - 2 * nbmem); - nbmem *= 2; - ptr = realloc(tmp_event, nbmem * sizeof(struct lttng_event_field)); - if (ptr == NULL) { + struct lttng_event_field *new_tmp_event; + size_t new_nbmem; + + new_nbmem = nbmem << 1; + DBG2("Reallocating event field list from %zu to %zu entries", + nbmem, new_nbmem); + new_tmp_event = realloc(tmp_event, + new_nbmem * sizeof(struct lttng_event_field)); + if (new_tmp_event == NULL) { PERROR("realloc ust app event fields"); free(tmp_event); ret = -ENOMEM; goto rcu_error; } - tmp_event = ptr; + /* Zero the new memory */ + memset(new_tmp_event + nbmem, 0, + (new_nbmem - nbmem) * sizeof(struct lttng_event_field)); + nbmem = new_nbmem; + tmp_event = new_tmp_event; } memcpy(tmp_event[count].field_name, uiter.field_name, LTTNG_UST_SYM_NAME_LEN); @@ -3352,11 +3438,21 @@ void ust_app_clean_list(void) /* * Init UST app hash table. */ -void ust_app_ht_alloc(void) +int ust_app_ht_alloc(void) { ust_app_ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); + if (!ust_app_ht) { + return -1; + } ust_app_ht_by_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); + if (!ust_app_ht_by_sock) { + return -1; + } ust_app_ht_by_notify_sock = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); + if (!ust_app_ht_by_notify_sock) { + return -1; + } + return 0; } /* @@ -3538,65 +3634,6 @@ int ust_app_disable_event_glb(struct ltt_ust_session *usess, return ret; } -/* - * For a specific UST session and UST channel, the event for all - * registered apps. - */ -int ust_app_disable_all_event_glb(struct ltt_ust_session *usess, - struct ltt_ust_channel *uchan) -{ - int ret = 0; - struct lttng_ht_iter iter, uiter; - struct lttng_ht_node_str *ua_chan_node; - struct ust_app *app; - struct ust_app_session *ua_sess; - struct ust_app_channel *ua_chan; - struct ust_app_event *ua_event; - - DBG("UST app disabling all event for all apps in channel " - "%s for session id %" PRIu64, uchan->name, usess->id); - - rcu_read_lock(); - - /* For all registered applications */ - cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) { - if (!app->compatible) { - /* - * TODO: In time, we should notice the caller of this error by - * telling him that this is a version error. - */ - continue; - } - ua_sess = lookup_session_by_app(usess, app); - if (!ua_sess) { - /* The application has problem or is probably dead. */ - continue; - } - - /* Lookup channel in the ust app session */ - lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter); - ua_chan_node = lttng_ht_iter_get_node_str(&uiter); - /* If the channel is not found, there is a code flow error */ - assert(ua_chan_node); - - ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - - /* Disable each events of channel */ - cds_lfht_for_each_entry(ua_chan->events->ht, &uiter.iter, ua_event, - node.node) { - ret = disable_ust_app_event(ua_sess, ua_event, app); - if (ret < 0) { - /* XXX: Report error someday... */ - continue; - } - } - } - - rcu_read_unlock(); - - return ret; -} - /* * For a specific UST session, create the channel for all registered apps. */ @@ -3651,10 +3688,8 @@ int ust_app_create_channel_glb(struct ltt_ust_session *usess, pthread_mutex_lock(&ua_sess->lock); if (!strncmp(uchan->name, DEFAULT_METADATA_NAME, sizeof(uchan->name))) { - struct ustctl_consumer_channel_attr attr; - copy_channel_attr_to_ustctl(&attr, &uchan->attr); - ret = create_ust_app_metadata(ua_sess, app, usess->consumer, - &attr); + copy_channel_attr_to_ustctl(&ua_sess->metadata_attr, &uchan->attr); + ret = 0; } else { /* Create channel onto application. We don't need the chan ref. */ ret = create_ust_app_channel(ua_sess, uchan, app, @@ -3859,7 +3894,7 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) * Create the metadata for the application. This returns gracefully if a * metadata was already set for the session. */ - ret = create_ust_app_metadata(ua_sess, app, usess->consumer, NULL); + ret = create_ust_app_metadata(ua_sess, app, usess->consumer); if (ret < 0) { goto error_unlock; } @@ -4286,31 +4321,14 @@ void ust_app_global_update(struct ltt_ust_session *usess, int sock) */ cds_lfht_for_each_entry(ua_sess->channels->ht, &iter.iter, ua_chan, node.node) { - /* - * For a metadata channel, handle it differently. - */ - if (!strncmp(ua_chan->name, DEFAULT_METADATA_NAME, - sizeof(ua_chan->name))) { - ret = create_ust_app_metadata(ua_sess, app, usess->consumer, - &ua_chan->attr); - if (ret < 0) { - goto error_unlock; - } - /* Remove it from the hash table and continue!. */ - ret = lttng_ht_del(ua_sess->channels, &iter); - assert(!ret); - delete_ust_app_channel(-1, ua_chan, app); - continue; - } else { - ret = do_create_channel(app, usess, ua_sess, ua_chan); - if (ret < 0) { - /* - * Stop everything. On error, the application failed, no more - * file descriptor are available or ENOMEM so stopping here is - * the only thing we can do for now. - */ - goto error_unlock; - } + ret = do_create_channel(app, usess, ua_sess, ua_chan); + if (ret < 0) { + /* + * Stop everything. On error, the application failed, no more + * file descriptor are available or ENOMEM so stopping here is + * the only thing we can do for now. + */ + goto error_unlock; } /* @@ -4337,7 +4355,7 @@ void ust_app_global_update(struct ltt_ust_session *usess, int sock) pthread_mutex_unlock(&ua_sess->lock); - if (usess->start_trace) { + if (usess->active) { ret = ust_app_start_trace(usess, app); if (ret < 0) { goto error; @@ -4476,69 +4494,6 @@ end: return ret; } -/* - * Disable event for a channel from a UST session for a specific PID. - */ -int ust_app_disable_event_pid(struct ltt_ust_session *usess, - struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent, pid_t pid) -{ - int ret = 0; - struct lttng_ht_iter iter; - struct lttng_ht_node_str *ua_chan_node, *ua_event_node; - struct ust_app *app; - struct ust_app_session *ua_sess; - struct ust_app_channel *ua_chan; - struct ust_app_event *ua_event; - - DBG("UST app disabling event %s for PID %d", uevent->attr.name, pid); - - rcu_read_lock(); - - app = ust_app_find_by_pid(pid); - if (app == NULL) { - ERR("UST app disable event per PID %d not found", pid); - ret = -1; - goto error; - } - - if (!app->compatible) { - ret = 0; - goto error; - } - - ua_sess = lookup_session_by_app(usess, app); - if (!ua_sess) { - /* The application has problem or is probably dead. */ - goto error; - } - - /* Lookup channel in the ust app session */ - lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter); - ua_chan_node = lttng_ht_iter_get_node_str(&iter); - if (ua_chan_node == NULL) { - /* Channel does not exist, skip disabling */ - goto error; - } - ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node); - - lttng_ht_lookup(ua_chan->events, (void *)uevent->attr.name, &iter); - ua_event_node = lttng_ht_iter_get_node_str(&iter); - if (ua_event_node == NULL) { - /* Event does not exist, skip disabling */ - goto error; - } - ua_event = caa_container_of(ua_event_node, struct ust_app_event, node); - - ret = disable_ust_app_event(ua_sess, ua_event, app); - if (ret < 0) { - goto error; - } - -error: - rcu_read_unlock(); - return ret; -} - /* * Calibrate registered applications. */ @@ -5073,27 +5028,19 @@ void ust_app_destroy(struct ust_app *app) * Return 0 on success or else a negative value. */ int ust_app_snapshot_record(struct ltt_ust_session *usess, - struct snapshot_output *output, int wait, unsigned int nb_streams) + struct snapshot_output *output, int wait, uint64_t max_stream_size) { int ret = 0; + unsigned int snapshot_done = 0; struct lttng_ht_iter iter; struct ust_app *app; char pathname[PATH_MAX]; - uint64_t max_stream_size = 0; assert(usess); assert(output); rcu_read_lock(); - /* - * Compute the maximum size of a single stream if a max size is asked by - * the caller. - */ - if (output->max_size > 0 && nb_streams > 0) { - max_stream_size = output->max_size / nb_streams; - } - switch (usess->buffer_type) { case LTTNG_BUFFER_PER_UID: { @@ -5123,33 +5070,20 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, /* Add the UST default trace dir to path. */ cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter, reg_chan, node.node) { - - /* - * Make sure the maximum stream size is not lower than the - * subbuffer size or else it's an error since we won't be able to - * snapshot anything. - */ - if (max_stream_size && - reg_chan->subbuf_size > max_stream_size) { - ret = -EINVAL; - DBG3("UST app snapshot record maximum stream size %" PRIu64 - " is smaller than subbuffer size of %zu", - max_stream_size, reg_chan->subbuf_size); - goto error; - } - ret = consumer_snapshot_channel(socket, reg_chan->consumer_key, output, 0, - usess->uid, usess->gid, pathname, wait, + ret = consumer_snapshot_channel(socket, reg_chan->consumer_key, + output, 0, usess->uid, usess->gid, pathname, wait, max_stream_size); if (ret < 0) { goto error; } } - ret = consumer_snapshot_channel(socket, reg->registry->reg.ust->metadata_key, output, - 1, usess->uid, usess->gid, pathname, wait, - max_stream_size); + ret = consumer_snapshot_channel(socket, + reg->registry->reg.ust->metadata_key, output, 1, + usess->uid, usess->gid, pathname, wait, max_stream_size); if (ret < 0) { goto error; } + snapshot_done = 1; } break; } @@ -5187,22 +5121,8 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, cds_lfht_for_each_entry(ua_sess->channels->ht, &chan_iter.iter, ua_chan, node.node) { - /* - * Make sure the maximum stream size is not lower than the - * subbuffer size or else it's an error since we won't be able to - * snapshot anything. - */ - if (max_stream_size && - ua_chan->attr.subbuf_size > max_stream_size) { - ret = -EINVAL; - DBG3("UST app snapshot record maximum stream size %" PRIu64 - " is smaller than subbuffer size of %" PRIu64, - max_stream_size, ua_chan->attr.subbuf_size); - goto error; - } - - ret = consumer_snapshot_channel(socket, ua_chan->key, output, 0, - ua_sess->euid, ua_sess->egid, pathname, wait, + ret = consumer_snapshot_channel(socket, ua_chan->key, output, + 0, ua_sess->euid, ua_sess->egid, pathname, wait, max_stream_size); if (ret < 0) { goto error; @@ -5217,6 +5137,7 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, if (ret < 0) { goto error; } + snapshot_done = 1; } break; } @@ -5225,6 +5146,15 @@ int ust_app_snapshot_record(struct ltt_ust_session *usess, break; } + if (!snapshot_done) { + /* + * If no snapshot was made and we are not in the error path, this means + * that there are no buffers thus no (prior) application to snapshot + * data from so we have simply NO data. + */ + ret = -ENODATA; + } + error: rcu_read_unlock(); return ret; @@ -5249,10 +5179,12 @@ unsigned int ust_app_get_nb_stream(struct ltt_ust_session *usess) cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) { struct buffer_reg_channel *reg_chan; + rcu_read_lock(); cds_lfht_for_each_entry(reg->registry->channels->ht, &iter.iter, reg_chan, node.node) { ret += reg_chan->stream_count; } + rcu_read_unlock(); } break; }