From 3d07185530211f3a650a7218199af44d4c77bf13 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sun, 14 Dec 2014 22:29:53 -0500 Subject: [PATCH] shm-path: remove directory hierarchy on destroy MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- src/bin/lttng-sessiond/buffer-registry.c | 8 ++- src/bin/lttng-sessiond/buffer-registry.h | 6 +- src/bin/lttng-sessiond/consumer.c | 6 ++ src/bin/lttng-sessiond/consumer.h | 1 + src/bin/lttng-sessiond/main.c | 3 + src/bin/lttng-sessiond/session.c | 2 + src/bin/lttng-sessiond/trace-ust.h | 1 + src/bin/lttng-sessiond/ust-app.c | 15 +++-- src/bin/lttng-sessiond/ust-app.h | 1 + src/bin/lttng-sessiond/ust-consumer.c | 5 +- src/bin/lttng-sessiond/ust-registry.c | 10 +++ src/bin/lttng-sessiond/ust-registry.h | 2 + src/common/consumer.c | 5 ++ src/common/consumer.h | 2 + src/common/kernel-consumer/kernel-consumer.c | 2 +- src/common/sessiond-comm/sessiond-comm.h | 1 + src/common/ust-consumer/ust-consumer.c | 13 +++- src/common/utils.c | 65 ++++++++++++++++++++ src/common/utils.h | 1 + 19 files changed, 136 insertions(+), 13 deletions(-) diff --git a/src/bin/lttng-sessiond/buffer-registry.c b/src/bin/lttng-sessiond/buffer-registry.c index b96e58500..b4667a41b 100644 --- a/src/bin/lttng-sessiond/buffer-registry.c +++ b/src/bin/lttng-sessiond/buffer-registry.c @@ -107,7 +107,7 @@ void buffer_reg_init_uid_registry(void) */ int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid, enum lttng_domain_type domain, struct buffer_reg_uid **regp, - const char *shm_path) + const char *root_shm_path, const char *shm_path) { int ret = 0; struct buffer_reg_uid *reg = NULL; @@ -133,6 +133,8 @@ int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid reg->uid = uid; reg->domain = domain; if (shm_path[0]) { + strncpy(reg->root_shm_path, root_shm_path, sizeof(reg->root_shm_path)); + reg->root_shm_path[sizeof(reg->root_shm_path) - 1] = '\0'; strncpy(reg->shm_path, shm_path, sizeof(reg->shm_path)); reg->shm_path[sizeof(reg->shm_path) - 1] = '\0'; DBG3("shm path '%s' is assigned to uid buffer registry for session id %" PRIu64, @@ -233,7 +235,7 @@ void buffer_reg_init_pid_registry(void) * Return 0 on success else a negative value and regp is untouched. */ int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp, - const char *shm_path) + const char *root_shm_path, const char *shm_path) { int ret = 0; struct buffer_reg_pid *reg = NULL; @@ -257,6 +259,8 @@ int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp, /* A cast is done here so we can use the session ID as a u64 ht node. */ reg->session_id = session_id; if (shm_path[0]) { + strncpy(reg->root_shm_path, root_shm_path, sizeof(reg->root_shm_path)); + reg->root_shm_path[sizeof(reg->root_shm_path) - 1] = '\0'; strncpy(reg->shm_path, shm_path, sizeof(reg->shm_path)); reg->shm_path[sizeof(reg->shm_path) - 1] = '\0'; DBG3("shm path '%s' is assigned to pid buffer registry for session id %" PRIu64, diff --git a/src/bin/lttng-sessiond/buffer-registry.h b/src/bin/lttng-sessiond/buffer-registry.h index d17bbab62..7a817ec70 100644 --- a/src/bin/lttng-sessiond/buffer-registry.h +++ b/src/bin/lttng-sessiond/buffer-registry.h @@ -89,6 +89,7 @@ struct buffer_reg_uid { /* Node of a linked list used to teardown object at a destroy session. */ struct cds_list_head lnode; + char root_shm_path[PATH_MAX]; char shm_path[PATH_MAX]; }; @@ -103,6 +104,7 @@ struct buffer_reg_pid { /* Indexed by session id. */ struct lttng_ht_node_u64 node; + char root_shm_path[PATH_MAX]; char shm_path[PATH_MAX]; }; @@ -110,7 +112,7 @@ struct buffer_reg_pid { void buffer_reg_init_uid_registry(void); int buffer_reg_uid_create(uint64_t session_id, uint32_t bits_per_long, uid_t uid, enum lttng_domain_type domain, struct buffer_reg_uid **regp, - const char *shm_path); + const char *root_shm_path, const char *shm_path); void buffer_reg_uid_add(struct buffer_reg_uid *reg); struct buffer_reg_uid *buffer_reg_uid_find(uint64_t session_id, uint32_t bits_per_long, uid_t uid); @@ -121,7 +123,7 @@ void buffer_reg_uid_destroy(struct buffer_reg_uid *regp, /* Buffer registry per PID. */ void buffer_reg_init_pid_registry(void); int buffer_reg_pid_create(uint64_t session_id, struct buffer_reg_pid **regp, - const char *shm_path); + const char *root_shm_path, const char *shm_path); void buffer_reg_pid_add(struct buffer_reg_pid *reg); struct buffer_reg_pid *buffer_reg_pid_find(uint64_t session_id); void buffer_reg_pid_remove(struct buffer_reg_pid *regp); diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c index 628201e07..87d5f3438 100644 --- a/src/bin/lttng-sessiond/consumer.c +++ b/src/bin/lttng-sessiond/consumer.c @@ -802,6 +802,7 @@ void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg, uint64_t session_id_per_pid, unsigned int monitor, uint32_t ust_app_uid, + const char *root_shm_path, const char *shm_path) { assert(msg); @@ -841,6 +842,11 @@ void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg, strncpy(msg->u.ask_channel.name, name, sizeof(msg->u.ask_channel.name)); msg->u.ask_channel.name[sizeof(msg->u.ask_channel.name) - 1] = '\0'; + if (root_shm_path) { + strncpy(msg->u.ask_channel.root_shm_path, root_shm_path, + sizeof(msg->u.ask_channel.root_shm_path)); + msg->u.ask_channel.root_shm_path[sizeof(msg->u.ask_channel.root_shm_path) - 1] = '\0'; + } if (shm_path) { strncpy(msg->u.ask_channel.shm_path, shm_path, sizeof(msg->u.ask_channel.shm_path)); diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h index 0b67c0828..e4845f527 100644 --- a/src/bin/lttng-sessiond/consumer.h +++ b/src/bin/lttng-sessiond/consumer.h @@ -241,6 +241,7 @@ void consumer_init_ask_channel_comm_msg(struct lttcomm_consumer_msg *msg, uint64_t session_id_per_pid, unsigned int monitor, uint32_t ust_app_uid, + const char *root_shm_path, const char *shm_path); void consumer_init_stream_comm_msg(struct lttcomm_consumer_msg *msg, enum lttng_consumer_command cmd, diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index c54217937..f8f2a7ce3 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -2766,6 +2766,9 @@ static int create_ust_session(struct ltt_session *session, lus->live_timer_interval = session->live_timer; session->ust_session = lus; if (session->shm_path[0]) { + strncpy(lus->root_shm_path, session->shm_path, + sizeof(lus->root_shm_path)); + lus->root_shm_path[sizeof(lus->root_shm_path) - 1] = '\0'; strncpy(lus->shm_path, session->shm_path, sizeof(lus->shm_path)); lus->shm_path[sizeof(lus->shm_path) - 1] = '\0'; diff --git a/src/bin/lttng-sessiond/session.c b/src/bin/lttng-sessiond/session.c index 99b016507..b82a330e9 100644 --- a/src/bin/lttng-sessiond/session.c +++ b/src/bin/lttng-sessiond/session.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index 63564ff71..8be813877 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -117,6 +117,7 @@ struct ltt_ust_session { /* * Path where to keep the shared memory files. */ + char root_shm_path[PATH_MAX]; char shm_path[PATH_MAX]; }; diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index 480971b89..183d12559 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -1637,6 +1637,9 @@ static void shadow_copy_session(struct ust_app_session *ua_sess, goto error; } + strncpy(ua_sess->root_shm_path, usess->root_shm_path, + sizeof(ua_sess->root_shm_path)); + ua_sess->root_shm_path[sizeof(ua_sess->root_shm_path) - 1] = '\0'; strncpy(ua_sess->shm_path, usess->shm_path, sizeof(ua_sess->shm_path)); ua_sess->shm_path[sizeof(ua_sess->shm_path) - 1] = '\0'; @@ -1758,7 +1761,7 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, * registry available, we have to create one for this session. */ ret = buffer_reg_pid_create(ua_sess->id, ®_pid, - ua_sess->shm_path); + ua_sess->root_shm_path, ua_sess->shm_path); if (ret < 0) { goto error; } @@ -1772,7 +1775,8 @@ static int setup_buffer_reg_pid(struct ust_app_session *ua_sess, app->uint16_t_alignment, app->uint32_t_alignment, app->uint64_t_alignment, app->long_alignment, app->byte_order, app->version.major, - app->version.minor, reg_pid->shm_path, + app->version.minor, reg_pid->root_shm_path, + reg_pid->shm_path, ua_sess->euid, ua_sess->egid); if (ret < 0) { /* @@ -1824,7 +1828,8 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, * registry available, we have to create one for this session. */ ret = buffer_reg_uid_create(usess->id, app->bits_per_long, app->uid, - LTTNG_DOMAIN_UST, ®_uid, ua_sess->shm_path); + LTTNG_DOMAIN_UST, ®_uid, + ua_sess->root_shm_path, ua_sess->shm_path); if (ret < 0) { goto error; } @@ -1838,8 +1843,8 @@ static int setup_buffer_reg_uid(struct ltt_ust_session *usess, app->uint16_t_alignment, app->uint32_t_alignment, app->uint64_t_alignment, app->long_alignment, app->byte_order, app->version.major, - app->version.minor, reg_uid->shm_path, - usess->uid, usess->gid); + app->version.minor, reg_uid->root_shm_path, + reg_uid->shm_path, usess->uid, usess->gid); if (ret < 0) { /* * reg_uid->registry->reg.ust is NULL upon error, so we need to diff --git a/src/bin/lttng-sessiond/ust-app.h b/src/bin/lttng-sessiond/ust-app.h index 59ef85b78..d6b675bec 100644 --- a/src/bin/lttng-sessiond/ust-app.h +++ b/src/bin/lttng-sessiond/ust-app.h @@ -216,6 +216,7 @@ struct ust_app_session { /* Metadata channel attributes. */ struct ustctl_consumer_channel_attr metadata_attr; + char root_shm_path[PATH_MAX]; char shm_path[PATH_MAX]; }; diff --git a/src/bin/lttng-sessiond/ust-consumer.c b/src/bin/lttng-sessiond/ust-consumer.c index 8a3533ba1..78e50df43 100644 --- a/src/bin/lttng-sessiond/ust-consumer.c +++ b/src/bin/lttng-sessiond/ust-consumer.c @@ -110,6 +110,7 @@ static int ask_channel_creation(struct ust_app_session *ua_sess, struct lttcomm_consumer_msg msg; struct ust_registry_channel *chan_reg; char shm_path[PATH_MAX] = ""; + char root_shm_path[PATH_MAX] = ""; assert(ua_sess); assert(ua_chan); @@ -156,6 +157,8 @@ static int ask_channel_creation(struct ust_app_session *ua_sess, strncat(shm_path, "_", sizeof(shm_path) - strlen(shm_path) - 1); } + strncpy(root_shm_path, ua_sess->root_shm_path, sizeof(root_shm_path)); + root_shm_path[sizeof(root_shm_path) - 1] = '\0'; } switch (ua_chan->attr.output) { @@ -188,7 +191,7 @@ static int ask_channel_creation(struct ust_app_session *ua_sess, ua_sess->id, ua_sess->output_traces, ua_sess->uid, - shm_path); + root_shm_path, shm_path); health_code_update(); diff --git a/src/bin/lttng-sessiond/ust-registry.c b/src/bin/lttng-sessiond/ust-registry.c index 26f306d52..f9ddd25a5 100644 --- a/src/bin/lttng-sessiond/ust-registry.c +++ b/src/bin/lttng-sessiond/ust-registry.c @@ -547,6 +547,7 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, int byte_order, uint32_t major, uint32_t minor, + const char *root_shm_path, const char *shm_path, uid_t euid, gid_t egid) @@ -571,6 +572,9 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, session->long_alignment = long_alignment; session->byte_order = byte_order; session->metadata_fd = -1; + strncpy(session->root_shm_path, root_shm_path, + sizeof(session->root_shm_path)); + session->root_shm_path[sizeof(session->root_shm_path) - 1] = '\0'; if (shm_path[0]) { strncpy(session->shm_path, shm_path, sizeof(session->shm_path)); @@ -676,4 +680,10 @@ void ust_registry_session_destroy(struct ust_registry_session *reg) PERROR("unlink"); } } + if (reg->root_shm_path[0]) { + /* + * Try deleting the directory hierarchy. + */ + (void) utils_recursive_rmdir(reg->root_shm_path); + } } diff --git a/src/bin/lttng-sessiond/ust-registry.h b/src/bin/lttng-sessiond/ust-registry.h index a22009efa..91a0534e9 100644 --- a/src/bin/lttng-sessiond/ust-registry.h +++ b/src/bin/lttng-sessiond/ust-registry.h @@ -67,6 +67,7 @@ struct ust_registry_session { /* Length of bytes sent to the consumer. */ size_t metadata_len_sent; + char root_shm_path[PATH_MAX]; char shm_path[PATH_MAX]; char metadata_path[PATH_MAX]; int metadata_fd; /* file-backed metadata FD */ @@ -231,6 +232,7 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, int byte_order, uint32_t major, uint32_t minor, + const char *root_shm_path, const char *shm_path, uid_t euid, gid_t egid); diff --git a/src/common/consumer.c b/src/common/consumer.c index 1cb1c4743..effa5f86f 100644 --- a/src/common/consumer.c +++ b/src/common/consumer.c @@ -937,6 +937,7 @@ struct lttng_consumer_channel *consumer_allocate_channel(uint64_t key, uint64_t session_id_per_pid, unsigned int monitor, unsigned int live_timer_interval, + const char *root_shm_path, const char *shm_path) { struct lttng_consumer_channel *channel; @@ -994,6 +995,10 @@ struct lttng_consumer_channel *consumer_allocate_channel(uint64_t key, strncpy(channel->name, name, sizeof(channel->name)); channel->name[sizeof(channel->name) - 1] = '\0'; + if (root_shm_path) { + strncpy(channel->root_shm_path, root_shm_path, sizeof(channel->root_shm_path)); + channel->root_shm_path[sizeof(channel->root_shm_path) - 1] = '\0'; + } if (shm_path) { strncpy(channel->shm_path, shm_path, sizeof(channel->shm_path)); channel->shm_path[sizeof(channel->shm_path) - 1] = '\0'; diff --git a/src/common/consumer.h b/src/common/consumer.h index a80bc40ab..7f885370e 100644 --- a/src/common/consumer.h +++ b/src/common/consumer.h @@ -207,6 +207,7 @@ struct lttng_consumer_channel { /* Timer value in usec for live streaming. */ unsigned int live_timer_interval; + char root_shm_path[PATH_MAX]; char shm_path[PATH_MAX]; }; @@ -602,6 +603,7 @@ struct lttng_consumer_channel *consumer_allocate_channel(uint64_t key, uint64_t session_id_per_pid, unsigned int monitor, unsigned int live_timer_interval, + const char *root_shm_path, const char *shm_path); void consumer_del_stream(struct lttng_consumer_stream *stream, struct lttng_ht *ht); diff --git a/src/common/kernel-consumer/kernel-consumer.c b/src/common/kernel-consumer/kernel-consumer.c index 0af417b9c..e30d21b1a 100644 --- a/src/common/kernel-consumer/kernel-consumer.c +++ b/src/common/kernel-consumer/kernel-consumer.c @@ -481,7 +481,7 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, msg.u.channel.tracefile_count, 0, msg.u.channel.monitor, msg.u.channel.live_timer_interval, - NULL); + NULL, NULL); if (new_channel == NULL) { lttng_consumer_send_error(ctx, LTTCOMM_CONSUMERD_OUTFD_ERROR); goto end_nosignal; diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index baf608ffd..5078b522b 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -430,6 +430,7 @@ struct lttcomm_consumer_msg { * because the application can be in the tracing for instance. */ uint32_t ust_app_uid; + char root_shm_path[PATH_MAX]; char shm_path[PATH_MAX]; } LTTNG_PACKED ask_channel; struct { diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index 81f685912..6898bb115 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -81,6 +81,10 @@ static void destroy_channel(struct lttng_consumer_channel *channel) if (channel->uchan) { lttng_ustconsumer_del_channel(channel); } + /* Try to rmdir all directories under shm_path root. */ + if (channel->root_shm_path[0]) { + (void) utils_recursive_rmdir(channel->root_shm_path); + } free(channel); } @@ -125,7 +129,7 @@ static struct lttng_consumer_channel *allocate_channel(uint64_t session_id, uint64_t tracefile_size, uint64_t tracefile_count, uint64_t session_id_per_pid, unsigned int monitor, unsigned int live_timer_interval, - const char *shm_path) + const char *root_shm_path, const char *shm_path) { assert(pathname); assert(name); @@ -133,7 +137,7 @@ static struct lttng_consumer_channel *allocate_channel(uint64_t session_id, return consumer_allocate_channel(key, session_id, pathname, name, uid, gid, relayd_id, output, tracefile_size, tracefile_count, session_id_per_pid, monitor, - live_timer_interval, shm_path); + live_timer_interval, root_shm_path, shm_path); } /* @@ -1213,6 +1217,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, msg.u.ask_channel.session_id_per_pid, msg.u.ask_channel.monitor, msg.u.ask_channel.live_timer_interval, + msg.u.ask_channel.root_shm_path, msg.u.ask_channel.shm_path); if (!channel) { goto end_channel_error; @@ -1678,6 +1683,10 @@ void lttng_ustconsumer_del_channel(struct lttng_consumer_channel *chan) } consumer_metadata_cache_destroy(chan); ustctl_destroy_channel(chan->uchan); + /* Try to rmdir all directories under shm_path root. */ + if (chan->root_shm_path[0]) { + (void) utils_recursive_rmdir(chan->root_shm_path); + } } void lttng_ustconsumer_del_stream(struct lttng_consumer_stream *stream) diff --git a/src/common/utils.c b/src/common/utils.c index 9a5333000..f9e6a99ea 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -1058,3 +1059,67 @@ char *utils_generate_optstring(const struct option *long_options, end: return optstring; } + +/* + * Try to remove a hierarchy of empty directories, recursively. Don't unlink + * any file. + */ +LTTNG_HIDDEN +int utils_recursive_rmdir(const char *path) +{ + DIR *dir; + int dir_fd, ret = 0, closeret; + struct dirent *entry; + + /* Open directory */ + dir = opendir(path); + if (!dir) { + PERROR("Cannot open '%s' path", path); + return -1; + } + dir_fd = dirfd(dir); + if (dir_fd < 0) { + PERROR("dirfd"); + return -1; + } + + while ((entry = readdir(dir))) { + if (!strcmp(entry->d_name, ".") + || !strcmp(entry->d_name, "..")) + continue; + switch (entry->d_type) { + case DT_DIR: + { + char subpath[PATH_MAX]; + + strncpy(subpath, path, PATH_MAX); + subpath[PATH_MAX - 1] = '\0'; + strncat(subpath, "/", + PATH_MAX - strlen(subpath) - 1); + strncat(subpath, entry->d_name, + PATH_MAX - strlen(subpath) - 1); + ret = utils_recursive_rmdir(subpath); + if (ret) { + goto end; + } + break; + } + case DT_REG: + ret = -EBUSY; + goto end; + default: + ret = -EINVAL; + goto end; + } + } +end: + closeret = closedir(dir); + if (closeret) { + PERROR("closedir"); + } + if (!ret) { + DBG3("Attempting rmdir %s", path); + ret = rmdir(path); + } + return ret; +} diff --git a/src/common/utils.h b/src/common/utils.h index 537fe0f9e..05914cc37 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -54,5 +54,6 @@ gid_t utils_get_group_id(const char *name); char *utils_generate_optstring(const struct option *long_options, size_t opt_count); int utils_create_lock_file(const char *filepath); +int utils_recursive_rmdir(const char *path); #endif /* _COMMON_UTILS_H */ -- 2.34.1