From: Mathieu Desnoyers Date: Thu, 19 Sep 2019 19:36:03 +0000 (-0400) Subject: Send ust and kernel domain directory handle to consumer X-Git-Tag: v2.12.0-rc1~157 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=5da88b0f58d7f838068037ea449ddfb25d3e85ad;p=lttng-tools.git Send ust and kernel domain directory handle to consumer Send a directory handle to ust/ and kernel/ subdirectories of the chunk to the consumer daemon, and alter the paths sent to consumer so they do not include the domain subdir. This will facilitate implementation of the clear command when no rotation has been performed. The clear command will need to move the ust/ and kernel/ directories to a "deleted" temporary directory while the consumer is still actively using those directories. Making sure that the consumer uses a handle on those subdirectories only ensures that the consumer will not observe any transient state when those directories are moved. Signed-off-by: Mathieu Desnoyers Change-Id: I2357ad702f810561c4d11405edc3ef204fc6c455 Signed-off-by: Jérémie Galarneau --- diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c index c4cfb2fd7..98cd14149 100644 --- a/src/bin/lttng-sessiond/consumer.c +++ b/src/bin/lttng-sessiond/consumer.c @@ -46,7 +46,7 @@ * returned. */ char *setup_channel_trace_path(struct consumer_output *consumer, - const char *session_path) + const char *session_path, size_t *consumer_path_offset) { int ret; char *pathname; @@ -69,13 +69,15 @@ char *setup_channel_trace_path(struct consumer_output *consumer, if (consumer->type == CONSUMER_DST_NET && consumer->relay_major_version == 2 && consumer->relay_minor_version < 11) { - ret = snprintf(pathname, LTTNG_PATH_MAX, "%s%s/%s%s", + ret = snprintf(pathname, LTTNG_PATH_MAX, "%s%s/%s/%s", consumer->dst.net.base_dir, consumer->chunk_path, consumer->domain_subdir, session_path); + *consumer_path_offset = 0; } else { - ret = snprintf(pathname, LTTNG_PATH_MAX, "%s%s", + ret = snprintf(pathname, LTTNG_PATH_MAX, "%s/%s", consumer->domain_subdir, session_path); + *consumer_path_offset = strlen(consumer->domain_subdir) + 1; } DBG3("Consumer trace path relative to current trace chunk: \"%s\"", pathname); @@ -1755,13 +1757,15 @@ error: */ int consumer_create_trace_chunk(struct consumer_socket *socket, uint64_t relayd_id, uint64_t session_id, - struct lttng_trace_chunk *chunk) + struct lttng_trace_chunk *chunk, + const char *domain_subdir) { int ret; enum lttng_trace_chunk_status chunk_status; struct lttng_credentials chunk_credentials; - const struct lttng_directory_handle *chunk_directory_handle; - int chunk_dirfd; + const struct lttng_directory_handle *chunk_directory_handle = NULL; + struct lttng_directory_handle *domain_handle = NULL; + int domain_dirfd; const char *chunk_name; bool chunk_name_overridden; uint64_t chunk_id; @@ -1836,19 +1840,6 @@ int consumer_create_trace_chunk(struct consumer_socket *socket, ret = -LTTNG_ERR_FATAL; goto error; } - - /* - * This will only compile on platforms that support - * dirfd (POSIX.2008). This is fine as the session daemon - * is only built for such platforms. - * - * The ownership of the chunk directory handle's is maintained - * by the trace chunk. - */ - chunk_dirfd = lttng_directory_handle_get_dirfd( - chunk_directory_handle); - assert(chunk_dirfd >= 0); - chunk_status = lttng_trace_chunk_get_credentials( chunk, &chunk_credentials); if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) { @@ -1859,6 +1850,37 @@ int consumer_create_trace_chunk(struct consumer_socket *socket, ret = -LTTNG_ERR_FATAL; goto error; } + ret = lttng_directory_handle_create_subdirectory_as_user( + chunk_directory_handle, + domain_subdir, + S_IRWXU | S_IRWXG, + &chunk_credentials); + if (ret) { + PERROR("Failed to create chunk domain output directory \"%s\"", + domain_subdir); + ret = -LTTNG_ERR_FATAL; + goto error; + } + domain_handle = lttng_directory_handle_create_from_handle( + domain_subdir, + chunk_directory_handle); + if (!domain_handle) { + ret = -LTTNG_ERR_FATAL; + goto error; + } + + /* + * This will only compile on platforms that support + * dirfd (POSIX.2008). This is fine as the session daemon + * is only built for such platforms. + * + * The ownership of the chunk directory handle's is maintained + * by the trace chunk. + */ + domain_dirfd = lttng_directory_handle_get_dirfd( + domain_handle); + assert(domain_dirfd >= 0); + msg.u.create_trace_chunk.credentials.value.uid = chunk_credentials.uid; msg.u.create_trace_chunk.credentials.value.gid = @@ -1881,9 +1903,9 @@ int consumer_create_trace_chunk(struct consumer_socket *socket, } if (chunk_has_local_output) { - DBG("Sending trace chunk directory fd to consumer"); + DBG("Sending trace chunk domain directory fd to consumer"); health_code_update(); - ret = consumer_send_fds(socket, &chunk_dirfd, 1); + ret = consumer_send_fds(socket, &domain_dirfd, 1); health_code_update(); if (ret < 0) { ERR("Trace chunk creation error on consumer"); @@ -1892,6 +1914,7 @@ int consumer_create_trace_chunk(struct consumer_socket *socket, } } error: + lttng_directory_handle_put(domain_handle); return ret; } diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h index 1590788cc..a2dc03e76 100644 --- a/src/bin/lttng-sessiond/consumer.h +++ b/src/bin/lttng-sessiond/consumer.h @@ -315,7 +315,8 @@ int consumer_init(struct consumer_socket *socket, int consumer_create_trace_chunk(struct consumer_socket *socket, uint64_t relayd_id, uint64_t session_id, - struct lttng_trace_chunk *chunk); + struct lttng_trace_chunk *chunk, + const char *domain_subdir); int consumer_close_trace_chunk(struct consumer_socket *socket, uint64_t relayd_id, uint64_t session_id, struct lttng_trace_chunk *chunk, @@ -326,6 +327,6 @@ int consumer_trace_chunk_exists(struct consumer_socket *socket, enum consumer_trace_chunk_exists_status *result); char *setup_channel_trace_path(struct consumer_output *consumer, - const char *session_path); + const char *session_path, size_t *consumer_path_offset); #endif /* _CONSUMER_H */ diff --git a/src/bin/lttng-sessiond/kernel-consumer.c b/src/bin/lttng-sessiond/kernel-consumer.c index 2d0605e9b..273b04f9d 100644 --- a/src/bin/lttng-sessiond/kernel-consumer.c +++ b/src/bin/lttng-sessiond/kernel-consumer.c @@ -33,7 +33,8 @@ #include "session.h" #include "lttng-sessiond.h" -static char *create_channel_path(struct consumer_output *consumer) +static char *create_channel_path(struct consumer_output *consumer, + size_t *consumer_path_offset) { int ret; char tmp_path[PATH_MAX]; @@ -52,10 +53,11 @@ static char *create_channel_path(struct consumer_output *consumer) consumer->domain_subdir); goto error; } + *consumer_path_offset = strlen(consumer->domain_subdir); DBG3("Kernel local consumer trace path relative to current trace chunk: \"%s\"", pathname); } else { - /* Network output. */ + /* Network output, relayd < 2.11. */ ret = snprintf(tmp_path, sizeof(tmp_path), "%s%s", consumer->dst.net.base_dir, consumer->domain_subdir); @@ -74,6 +76,7 @@ static char *create_channel_path(struct consumer_output *consumer) PERROR("lttng_strndup"); goto error; } + *consumer_path_offset = 0; DBG3("Kernel network consumer subdir path: %s", pathname); } @@ -101,6 +104,7 @@ int kernel_consumer_add_channel(struct consumer_socket *sock, struct ltt_session *session = NULL; struct lttng_channel_extended *channel_attr_extended; bool is_local_trace; + size_t consumer_path_offset = 0; /* Safety net */ assert(channel); @@ -115,7 +119,7 @@ int kernel_consumer_add_channel(struct consumer_socket *sock, channel->channel->name); is_local_trace = consumer->net_seq_index == -1ULL; - pathname = create_channel_path(consumer); + pathname = create_channel_path(consumer, &consumer_path_offset); if (!pathname) { ret = -1; goto error; @@ -150,7 +154,7 @@ int kernel_consumer_add_channel(struct consumer_socket *sock, consumer_init_add_channel_comm_msg(&lkm, channel->key, ksession->id, - pathname, + &pathname[consumer_path_offset], ksession->uid, ksession->gid, consumer->net_seq_index, @@ -230,7 +234,7 @@ int kernel_consumer_add_metadata(struct consumer_socket *sock, consumer_init_add_channel_comm_msg(&lkm, ksession->metadata->key, ksession->id, - DEFAULT_KERNEL_TRACE_DIR, + "", ksession->uid, ksession->gid, consumer->net_seq_index, diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index b5c4a5e12..93afc9d6f 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -1289,6 +1289,7 @@ enum lttng_error_code kernel_snapshot_record( struct lttng_ht_iter iter; struct ltt_kernel_metadata *saved_metadata; char *trace_path = NULL; + size_t consumer_path_offset = 0; assert(ksess); assert(ksess->consumer); @@ -1315,7 +1316,7 @@ enum lttng_error_code kernel_snapshot_record( } trace_path = setup_channel_trace_path(ksess->consumer, - DEFAULT_KERNEL_TRACE_DIR); + DEFAULT_KERNEL_TRACE_DIR, &consumer_path_offset); if (!trace_path) { status = LTTNG_ERR_INVALID; goto error; @@ -1338,7 +1339,7 @@ enum lttng_error_code kernel_snapshot_record( cds_list_for_each_entry(chan, &ksess->channel_list.head, list) { status = consumer_snapshot_channel(socket, chan->key, output, 0, ksess->uid, ksess->gid, - trace_path, wait, + &trace_path[consumer_path_offset], wait, nb_packets_per_stream); if (status != LTTNG_OK) { (void) kernel_consumer_destroy_metadata(socket, @@ -1349,7 +1350,8 @@ enum lttng_error_code kernel_snapshot_record( /* Snapshot metadata, */ status = consumer_snapshot_channel(socket, ksess->metadata->key, output, - 1, ksess->uid, ksess->gid, trace_path, wait, 0); + 1, ksess->uid, ksess->gid, &trace_path[consumer_path_offset], + wait, 0); if (status != LTTNG_OK) { goto error_consumer; } diff --git a/src/bin/lttng-sessiond/session.c b/src/bin/lttng-sessiond/session.c index 7ef188049..ee71533f9 100644 --- a/src/bin/lttng-sessiond/session.c +++ b/src/bin/lttng-sessiond/session.c @@ -491,7 +491,8 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, pthread_mutex_lock(socket->lock); ret = consumer_create_trace_chunk(socket, relayd_id, - session->id, new_trace_chunk); + session->id, new_trace_chunk, + DEFAULT_UST_TRACE_DIR); pthread_mutex_unlock(socket->lock); if (ret) { goto error; @@ -521,7 +522,8 @@ int _session_set_trace_chunk_no_lock_check(struct ltt_session *session, pthread_mutex_lock(socket->lock); ret = consumer_create_trace_chunk(socket, relayd_id, - session->id, new_trace_chunk); + session->id, new_trace_chunk, + DEFAULT_KERNEL_TRACE_DIR); pthread_mutex_unlock(socket->lock); if (ret) { goto error; diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 58308dec8..f3e020901 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -1901,12 +1901,12 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, switch (ua_sess->buffer_type) { case LTTNG_BUFFER_PER_PID: ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path), - DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s", + "/" DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s", app->name, app->pid, datetime); break; case LTTNG_BUFFER_PER_UID: ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path), - DEFAULT_UST_TRACE_UID_PATH, + "/" DEFAULT_UST_TRACE_UID_PATH, app->uid, app->bits_per_long); break; default: @@ -5921,6 +5921,7 @@ enum lttng_error_code ust_app_snapshot_record( struct buffer_reg_channel *reg_chan; struct consumer_socket *socket; char pathname[PATH_MAX]; + size_t consumer_path_offset = 0; if (!reg->registry->reg.ust->metadata_key) { /* Skip since no metadata is present */ @@ -5936,12 +5937,8 @@ enum lttng_error_code ust_app_snapshot_record( } memset(pathname, 0, sizeof(pathname)); - /* - * DEFAULT_UST_TRACE_UID_PATH already contains a path - * separator. - */ ret = snprintf(pathname, sizeof(pathname), - DEFAULT_UST_TRACE_DIR DEFAULT_UST_TRACE_UID_PATH, + DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH, reg->uid, reg->bits_per_long); if (ret < 0) { PERROR("snprintf snapshot path"); @@ -5950,7 +5947,8 @@ enum lttng_error_code ust_app_snapshot_record( } /* Free path allowed on previous iteration. */ free(trace_path); - trace_path = setup_channel_trace_path(usess->consumer, pathname); + trace_path = setup_channel_trace_path(usess->consumer, pathname, + &consumer_path_offset); if (!trace_path) { status = LTTNG_ERR_INVALID; goto error; @@ -5961,7 +5959,7 @@ enum lttng_error_code ust_app_snapshot_record( status = consumer_snapshot_channel(socket, reg_chan->consumer_key, output, 0, usess->uid, - usess->gid, trace_path, wait, + usess->gid, &trace_path[consumer_path_offset], wait, nb_packets_per_stream); if (status != LTTNG_OK) { goto error; @@ -5969,7 +5967,8 @@ enum lttng_error_code ust_app_snapshot_record( } status = consumer_snapshot_channel(socket, reg->registry->reg.ust->metadata_key, output, 1, - usess->uid, usess->gid, trace_path, wait, 0); + usess->uid, usess->gid, &trace_path[consumer_path_offset], + wait, 0); if (status != LTTNG_OK) { goto error; } @@ -5985,6 +5984,7 @@ enum lttng_error_code ust_app_snapshot_record( struct ust_app_session *ua_sess; struct ust_registry_session *registry; char pathname[PATH_MAX]; + size_t consumer_path_offset = 0; ua_sess = lookup_session_by_app(usess, app); if (!ua_sess) { @@ -6002,7 +6002,7 @@ enum lttng_error_code ust_app_snapshot_record( /* Add the UST default trace dir to path. */ memset(pathname, 0, sizeof(pathname)); - ret = snprintf(pathname, sizeof(pathname), DEFAULT_UST_TRACE_DIR "%s", + ret = snprintf(pathname, sizeof(pathname), DEFAULT_UST_TRACE_DIR "/%s", ua_sess->path); if (ret < 0) { status = LTTNG_ERR_INVALID; @@ -6011,7 +6011,8 @@ enum lttng_error_code ust_app_snapshot_record( } /* Free path allowed on previous iteration. */ free(trace_path); - trace_path = setup_channel_trace_path(usess->consumer, pathname); + trace_path = setup_channel_trace_path(usess->consumer, pathname, + &consumer_path_offset); if (!trace_path) { status = LTTNG_ERR_INVALID; goto error; @@ -6024,7 +6025,7 @@ enum lttng_error_code ust_app_snapshot_record( .uid, ua_sess->effective_credentials .gid, - trace_path, wait, + &trace_path[consumer_path_offset], wait, nb_packets_per_stream); switch (status) { case LTTNG_OK: @@ -6045,7 +6046,7 @@ enum lttng_error_code ust_app_snapshot_record( registry->metadata_key, output, 1, ua_sess->effective_credentials.uid, ua_sess->effective_credentials.gid, - trace_path, wait, 0); + &trace_path[consumer_path_offset], wait, 0); switch (status) { case LTTNG_OK: break; @@ -6459,7 +6460,7 @@ enum lttng_error_code ust_app_create_channel_subdirectories( cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) { fmt_ret = asprintf(&pathname_index, - DEFAULT_UST_TRACE_DIR DEFAULT_UST_TRACE_UID_PATH "/" DEFAULT_INDEX_DIR, + DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH "/" DEFAULT_INDEX_DIR, reg->uid, reg->bits_per_long); if (fmt_ret < 0) { ERR("Failed to format channel index directory"); @@ -6515,7 +6516,7 @@ enum lttng_error_code ust_app_create_channel_subdirectories( } fmt_ret = asprintf(&pathname_index, - DEFAULT_UST_TRACE_DIR "%s/" DEFAULT_INDEX_DIR, + DEFAULT_UST_TRACE_DIR "/%s/" DEFAULT_INDEX_DIR, ua_sess->path); if (fmt_ret < 0) { ERR("Failed to format channel index directory"); diff --git a/src/bin/lttng-sessiond/ust-consumer.c b/src/bin/lttng-sessiond/ust-consumer.c index a3e7eea00..c2ac56679 100644 --- a/src/bin/lttng-sessiond/ust-consumer.c +++ b/src/bin/lttng-sessiond/ust-consumer.c @@ -56,6 +56,7 @@ static int ask_channel_creation(struct ust_app_session *ua_sess, char shm_path[PATH_MAX] = ""; char root_shm_path[PATH_MAX] = ""; bool is_local_trace; + size_t consumer_path_offset = 0; assert(ua_sess); assert(ua_chan); @@ -67,7 +68,8 @@ static int ask_channel_creation(struct ust_app_session *ua_sess, is_local_trace = consumer->net_seq_index == -1ULL; /* Format the channel's path (relative to the current trace chunk). */ - pathname = setup_channel_trace_path(consumer, ua_sess->path); + pathname = setup_channel_trace_path(consumer, ua_sess->path, + &consumer_path_offset); if (!pathname) { ret = -1; goto error; @@ -148,7 +150,7 @@ static int ask_channel_creation(struct ust_app_session *ua_sess, output, (int) ua_chan->attr.type, ua_sess->tracing_id, - pathname, + &pathname[consumer_path_offset], ua_chan->name, consumer->net_seq_index, ua_chan->key, diff --git a/src/common/consumer/consumer.c b/src/common/consumer/consumer.c index fbbe8ea8f..2963c801d 100644 --- a/src/common/consumer/consumer.c +++ b/src/common/consumer/consumer.c @@ -91,6 +91,20 @@ int consumer_quit; static struct lttng_ht *metadata_ht; static struct lttng_ht *data_ht; +static const char *get_consumer_domain(void) +{ + switch (consumer_data.type) { + case LTTNG_CONSUMER_KERNEL: + return DEFAULT_KERNEL_TRACE_DIR; + case LTTNG_CONSUMER64_UST: + /* Fall-through. */ + case LTTNG_CONSUMER32_UST: + return DEFAULT_UST_TRACE_DIR; + default: + abort(); + } +} + /* * Notify a thread lttng pipe to poll back again. This usually means that some * global state has changed so we just send back the thread in a poll wait @@ -816,7 +830,7 @@ int consumer_send_relayd_stream(struct lttng_consumer_stream *stream, /* Add stream on the relayd */ pthread_mutex_lock(&relayd->ctrl_sock_mutex); ret = relayd_add_stream(&relayd->control_sock, stream->name, - path, &stream->relayd_stream_id, + get_consumer_domain(), path, &stream->relayd_stream_id, stream->chan->tracefile_size, stream->chan->tracefile_count, stream->trace_chunk); diff --git a/src/common/defaults.h b/src/common/defaults.h index 1545d0a74..23f1f7336 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -59,8 +59,8 @@ #define DEFAULT_UST_TRACE_DIR "ust" /* Subpath for per PID or UID sessions. */ -#define DEFAULT_UST_TRACE_PID_PATH "/pid" -#define DEFAULT_UST_TRACE_UID_PATH "/uid/%d/%u-bit" +#define DEFAULT_UST_TRACE_PID_PATH "pid" +#define DEFAULT_UST_TRACE_UID_PATH "uid/%d/%u-bit" /* * Default session name for the lttng command line. This default value will diff --git a/src/common/relayd/relayd.c b/src/common/relayd/relayd.c index 12f70f7e0..228b35cb2 100644 --- a/src/common/relayd/relayd.c +++ b/src/common/relayd/relayd.c @@ -491,21 +491,37 @@ error: * On success return 0 else return ret_code negative value. */ int relayd_add_stream(struct lttcomm_relayd_sock *rsock, const char *channel_name, - const char *pathname, uint64_t *stream_id, + const char *domain_name, const char *_pathname, uint64_t *stream_id, uint64_t tracefile_size, uint64_t tracefile_count, struct lttng_trace_chunk *trace_chunk) { int ret; struct lttcomm_relayd_status_stream reply; + char pathname[RELAYD_COMM_LTTNG_PATH_MAX]; + char *separator; /* Code flow error. Safety net. */ assert(rsock); assert(channel_name); - assert(pathname); + assert(domain_name); + assert(_pathname); assert(trace_chunk); DBG("Relayd adding stream for channel name %s", channel_name); + if (_pathname[0] == '\0') { + separator = ""; + } else { + separator = "/"; + } + ret = snprintf(pathname, RELAYD_COMM_LTTNG_PATH_MAX, "%s%s%s", + domain_name, separator, _pathname); + if (ret <= 0 || ret >= RELAYD_COMM_LTTNG_PATH_MAX) { + ERR("stream path too long."); + ret = -1; + goto error; + } + /* Compat with relayd 2.1 */ if (rsock->minor == 1) { /* For 2.1 */ diff --git a/src/common/relayd/relayd.h b/src/common/relayd/relayd.h index 61829f7bc..2f0c937f6 100644 --- a/src/common/relayd/relayd.h +++ b/src/common/relayd/relayd.h @@ -49,7 +49,7 @@ int relayd_create_session(struct lttcomm_relayd_sock *rsock, time_t creation_time, bool session_name_contains_creation_time, char *output_path); int relayd_add_stream(struct lttcomm_relayd_sock *sock, const char *channel_name, - const char *pathname, uint64_t *stream_id, + const char *domain_name, const char *pathname, uint64_t *stream_id, uint64_t tracefile_size, uint64_t tracefile_count, struct lttng_trace_chunk *trace_chunk); int relayd_streams_sent(struct lttcomm_relayd_sock *rsock); diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index 32dfd5bb4..41317fe65 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -2056,18 +2056,21 @@ end_rotate_channel_nosignal: goto end_nosignal; } + /* + * Receive trace chunk domain dirfd. + */ ret = lttcomm_recv_fds_unix_sock(sock, &chunk_dirfd, 1); if (ret != sizeof(chunk_dirfd)) { - ERR("Failed to receive trace chunk directory file descriptor"); + ERR("Failed to receive trace chunk domain directory file descriptor"); goto error_fatal; } - DBG("Received trace chunk directory fd (%d)", + DBG("Received trace chunk domain directory fd (%d)", chunk_dirfd); chunk_directory_handle = lttng_directory_handle_create_from_dirfd( chunk_dirfd); if (!chunk_directory_handle) { - ERR("Failed to initialize chunk directory handle from directory file descriptor"); + ERR("Failed to initialize chunk domain directory handle from directory file descriptor"); if (close(chunk_dirfd)) { PERROR("Failed to close chunk directory file descriptor"); }