X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-app.c;h=9bd622d87e80df2d50165ae00c5a54c2b8b70d4e;hp=9250433ab1573b4d3534caf677e0bf817fe0c658;hb=dec56f6cc894de41b312354d360b6a4c09fc199d;hpb=7972aab22f74b18faa168c0482216a3dd711a075 diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 9250433ab..9bd622d87 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,19 @@ static inline unsigned long get_next_session_id(void) return uatomic_add_return(&next_session_id, 1); } +static void copy_channel_attr_to_ustctl( + struct ustctl_consumer_channel_attr *attr, + struct lttng_ust_channel_attr *uattr) +{ + /* Copy event attributes since the layout is different. */ + attr->subbuf_size = uattr->subbuf_size; + attr->num_subbuf = uattr->num_subbuf; + attr->overwrite = uattr->overwrite; + attr->switch_timer_interval = uattr->switch_timer_interval; + attr->read_timer_interval = uattr->read_timer_interval; + attr->output = uattr->output; +} + /* * Match function for the hash table lookup. * @@ -354,18 +368,84 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan, free(ua_chan); } +/* + * Push metadata to consumer socket. The socket lock MUST be acquired. + * + * On success, return the len of metadata pushed or else a negative value. + */ +ssize_t ust_app_push_metadata(struct ust_registry_session *registry, + struct consumer_socket *socket, int send_zero_data) +{ + int ret; + char *metadata_str = NULL; + size_t len, offset; + ssize_t ret_val; + + assert(registry); + assert(socket); + /* Should never be 0 which is the initial state. */ + assert(registry->metadata_key); + + pthread_mutex_lock(®istry->lock); + + offset = registry->metadata_len_sent; + len = registry->metadata_len - registry->metadata_len_sent; + if (len == 0) { + DBG3("No metadata to push for metadata key %" PRIu64, + registry->metadata_key); + ret_val = len; + if (send_zero_data) { + DBG("No metadata to push"); + goto push_data; + } + goto end; + } + + /* Allocate only what we have to send. */ + metadata_str = zmalloc(len); + if (!metadata_str) { + PERROR("zmalloc ust app metadata string"); + ret_val = -ENOMEM; + goto error; + } + /* Copy what we haven't send out. */ + memcpy(metadata_str, registry->metadata + offset, len); + registry->metadata_len_sent += len; + +push_data: + pthread_mutex_unlock(®istry->lock); + ret = consumer_push_metadata(socket, registry->metadata_key, + metadata_str, len, offset); + if (ret < 0) { + ret_val = ret; + goto error_push; + } + + free(metadata_str); + return len; + +end: +error: + pthread_mutex_unlock(®istry->lock); +error_push: + free(metadata_str); + return ret_val; +} + /* * For a given application and session, push metadata to consumer. The session * lock MUST be acquired here before calling this. + * Either sock or consumer is required : if sock is NULL, the default + * socket to send the metadata is retrieved from consumer, if sock + * is not NULL we use it to send the metadata. * * Return 0 on success else a negative error. */ static int push_metadata(struct ust_registry_session *registry, struct consumer_output *consumer) { - int ret; - char *metadata_str = NULL; - size_t len, offset; + int ret_val; + ssize_t ret; struct consumer_socket *socket; assert(registry); @@ -378,7 +458,7 @@ static int push_metadata(struct ust_registry_session *registry, * no start has been done previously. */ if (!registry->metadata_key) { - ret = 0; + ret_val = 0; goto error_rcu_unlock; } @@ -386,7 +466,7 @@ static int push_metadata(struct ust_registry_session *registry, socket = consumer_find_socket_by_bitness(registry->bits_per_long, consumer); if (!socket) { - ret = -1; + ret_val = -1; goto error_rcu_unlock; } @@ -401,54 +481,19 @@ static int push_metadata(struct ust_registry_session *registry, * ability to reorder the metadata it receives. */ pthread_mutex_lock(socket->lock); - pthread_mutex_lock(®istry->lock); - - offset = registry->metadata_len_sent; - len = registry->metadata_len - registry->metadata_len_sent; - if (len == 0) { - DBG3("No metadata to push for metadata key %" PRIu64, - registry->metadata_key); - ret = 0; - goto error_reg_unlock; - } - assert(len > 0); - - /* Allocate only what we have to send. */ - metadata_str = zmalloc(len); - if (!metadata_str) { - PERROR("zmalloc ust app metadata string"); - ret = -ENOMEM; - goto error_reg_unlock; - } - /* Copy what we haven't send out. */ - memcpy(metadata_str, registry->metadata + offset, len); - - pthread_mutex_unlock(®istry->lock); - - ret = consumer_push_metadata(socket, registry->metadata_key, - metadata_str, len, offset); + ret = ust_app_push_metadata(registry, socket, 0); + pthread_mutex_unlock(socket->lock); if (ret < 0) { - pthread_mutex_unlock(socket->lock); + ret_val = ret; goto error_rcu_unlock; } - /* Update len sent of the registry. */ - pthread_mutex_lock(®istry->lock); - registry->metadata_len_sent += len; - pthread_mutex_unlock(®istry->lock); - pthread_mutex_unlock(socket->lock); - rcu_read_unlock(); - free(metadata_str); return 0; -error_reg_unlock: - pthread_mutex_unlock(®istry->lock); - pthread_mutex_unlock(socket->lock); error_rcu_unlock: rcu_read_unlock(); - free(metadata_str); - return ret; + return ret_val; } /* @@ -1253,6 +1298,9 @@ static void shadow_copy_channel(struct ust_app_channel *ua_chan, strncpy(ua_chan->name, uchan->name, sizeof(ua_chan->name)); ua_chan->name[sizeof(ua_chan->name) - 1] = '\0'; + ua_chan->tracefile_size = uchan->tracefile_size; + ua_chan->tracefile_count = uchan->tracefile_count; + /* Copy event attributes since the layout is different. */ ua_chan->attr.subbuf_size = uchan->attr.subbuf_size; ua_chan->attr.num_subbuf = uchan->attr.num_subbuf; @@ -1333,7 +1381,7 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, switch (ua_sess->buffer_type) { case LTTNG_BUFFER_PER_PID: ret = snprintf(ua_sess->path, sizeof(ua_sess->path), - DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s/", app->name, app->pid, + DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s", app->name, app->pid, datetime); break; case LTTNG_BUFFER_PER_UID: @@ -1454,7 +1502,9 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, ret = ust_registry_session_init(®_pid->registry->reg.ust, app, app->bits_per_long, app->uint8_t_alignment, app->uint16_t_alignment, app->uint32_t_alignment, - app->uint64_t_alignment, app->long_alignment, app->byte_order); + app->uint64_t_alignment, app->long_alignment, + app->byte_order, app->version.major, + app->version.minor); if (ret < 0) { goto error; } @@ -1505,10 +1555,12 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, } /* Initialize registry. */ - ret = ust_registry_session_init(®_uid->registry->reg.ust, app, + ret = ust_registry_session_init(®_uid->registry->reg.ust, NULL, app->bits_per_long, app->uint8_t_alignment, app->uint16_t_alignment, app->uint32_t_alignment, - app->uint64_t_alignment, app->long_alignment, app->byte_order); + app->uint64_t_alignment, app->long_alignment, + app->byte_order, app->version.major, + app->version.minor); if (ret < 0) { goto error; } @@ -2410,7 +2462,8 @@ 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 ust_app *app, struct consumer_output *consumer, + struct ustctl_consumer_channel_attr *attr) { int ret = 0; struct ust_app_channel *metadata; @@ -2438,14 +2491,20 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, goto error; } - /* 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_UST_CHANNEL_SWITCH_TIMER; - metadata->attr.read_timer_interval = DEFAULT_UST_CHANNEL_READ_TIMER; - metadata->attr.output = LTTNG_UST_MMAP; - metadata->attr.type = LTTNG_UST_CHAN_METADATA; + 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_UST_CHANNEL_SWITCH_TIMER; + metadata->attr.read_timer_interval = DEFAULT_UST_CHANNEL_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; + } /* Get the right consumer socket for the application. */ socket = consumer_find_socket_by_bitness(app->bits_per_long, consumer); @@ -2461,6 +2520,14 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, goto error; } + /* + * Keep metadata key so we can identify it on the consumer side. Assign it + * to the registry *before* we ask the consumer so we avoid the race of the + * consumer requesting the metadata and the ask_channel call on our side + * did not returned yet. + */ + registry->metadata_key = metadata->key; + /* * Ask the metadata channel creation to the consumer. The metadata object * will be created by the consumer and kept their. However, the stream is @@ -2494,9 +2561,6 @@ static int create_ust_app_metadata(struct ust_app_session *ua_sess, goto error_consumer; } - /* Keep metadata key so we can identify it on the consumer side. */ - registry->metadata_key = metadata->key; - DBG2("UST metadata with key %" PRIu64 " created for app pid %d", metadata->key, app->pid); @@ -3320,9 +3384,17 @@ int ust_app_create_channel_glb(struct ltt_ust_session *usess, assert(ua_sess); pthread_mutex_lock(&ua_sess->lock); - /* Create channel onto application. We don't need the chan ref. */ - ret = create_ust_app_channel(ua_sess, uchan, app, - LTTNG_UST_CHAN_PER_CPU, usess, NULL); + 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); + } else { + /* Create channel onto application. We don't need the chan ref. */ + ret = create_ust_app_channel(ua_sess, uchan, app, + LTTNG_UST_CHAN_PER_CPU, usess, NULL); + } pthread_mutex_unlock(&ua_sess->lock); if (ret < 0) { if (ret == -ENOMEM) { @@ -3517,8 +3589,11 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app) } } - /* Create the metadata for the application. */ - ret = create_ust_app_metadata(ua_sess, app, usess->consumer); + /* + * 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); if (ret < 0) { goto error_unlock; } @@ -3865,14 +3940,31 @@ 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) { - 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; + /* + * 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; + } } cds_lfht_for_each_entry(ua_chan->ctx->ht, &iter_ctx.iter, ua_ctx,