From: Julien Desfossez Date: Wed, 16 Aug 2017 19:48:16 +0000 (-0400) Subject: Move mkdir/rename code to the consumer X-Git-Url: https://git.efficios.com/?a=commitdiff_plain;h=e8ed1ed178e1c4cc24ecb44044e429400dd604c0;p=deliverable%2Flttng-tools.git Move mkdir/rename code to the consumer Signed-off-by: Julien Desfossez --- diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am index bc0d60ad1..592a5d7e0 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -42,7 +42,7 @@ lttng_sessiond_SOURCES += trace-ust.c ust-registry.c ust-app.c \ ust-metadata.c ust-clock.h agent-thread.c agent-thread.h endif -lttng_sessiond_SOURCES += rotation-thread.c +lttng_sessiond_SOURCES += rotation-thread.c rotate.c # Add main.c at the end for compile order lttng_sessiond_SOURCES += lttng-sessiond.h main.c diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 386e5649c..1ec3891b8 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -51,6 +51,7 @@ #include "buffer-registry.h" #include "notification-thread.h" #include "notification-thread-commands.h" +#include "rotate.h" #include "rotation-thread.h" #include "cmd.h" @@ -2749,6 +2750,22 @@ int cmd_destroy_session(struct ltt_session *session, int wpipe) usess = session->ust_session; ksess = session->kernel_session; + if (session->rotate_count > 0) { + session->rotate_count++; + /* + * The currently active tracing path is now the folder we + * want to rename. + */ + snprintf(session->rotation_chunk.current_rotate_path, + PATH_MAX, "%s", + session->rotation_chunk.active_tracing_path); + ret = rename_complete_chunk(session, + session->session_last_stop_ts); + if (ret < 0) { + ERR("Renaming session on destroy"); + } + } + /* Clean kernel session teardown */ kernel_destroy_session(ksess); @@ -2767,22 +2784,6 @@ int cmd_destroy_session(struct ltt_session *session, int wpipe) trace_ust_destroy_session(usess); } - if (session->rotate_count > 0) { - session->rotate_count++; - /* - * The currently active tracing path is now the folder we - * want to rename. - */ - snprintf(session->rotation_chunk.current_rotate_path, - PATH_MAX, "%s", - session->rotation_chunk.active_tracing_path); - ret = rename_complete_chunk(session, - session->session_last_stop_ts); - if (ret < 0) { - ERR("Renaming session on destroy"); - } - } - /* * Must notify the kernel thread here to update it's poll set in order to * remove the channel(s)' fd just destroyed. @@ -4132,7 +4133,8 @@ int cmd_set_session_shm_path(struct ltt_session *session, } static -int rename_first_chunk(struct consumer_output *consumer, char *datetime) +int rename_first_chunk(struct ltt_session *session, + struct consumer_output *consumer, char *datetime) { int ret; char *tmppath = NULL, *tmppath2 = NULL; @@ -4159,7 +4161,7 @@ int rename_first_chunk(struct consumer_output *consumer, char *datetime) * Move the per-domain folder inside the first rotation * folder. */ - ret = rename(tmppath, tmppath2); + ret = session_rename_chunk(session, tmppath, tmppath2, 1); if (ret < 0) { PERROR("Rename first trace directory"); ret = -LTTNG_ERR_ROTATE_NO_DATA; @@ -4213,6 +4215,7 @@ int cmd_rotate_session(struct ltt_session *session, if (session->rotate_count == 0) { timeinfo = localtime(&session->session_start_ts); strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo); + /* Either one of the two sessions is enough to get the root path. */ if (session->kernel_session) { snprintf(session->rotation_chunk.current_rotate_path, PATH_MAX, "%s/%s-", @@ -4241,14 +4244,16 @@ int cmd_rotate_session(struct ltt_session *session, } } if (session->kernel_session) { - ret = rename_first_chunk(session->kernel_session->consumer, + ret = rename_first_chunk(session, + session->kernel_session->consumer, datetime); if (ret < 0) { goto error; } } if (session->ust_session) { - ret = rename_first_chunk(session->ust_session->consumer, + ret = rename_first_chunk(session, + session->ust_session->consumer, datetime); if (ret < 0) { goto error; @@ -4367,8 +4372,6 @@ int cmd_rotate_pending(struct ltt_session *session, goto end; -error: - (*pending_return)->status = LTTNG_ROTATE_ERROR; end: return ret; } diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c index 54f8804d6..13d96578d 100644 --- a/src/bin/lttng-sessiond/consumer.c +++ b/src/bin/lttng-sessiond/consumer.c @@ -1633,6 +1633,7 @@ int consumer_rotate_channel(struct consumer_socket *socket, uint64_t key, msg.u.rotate_channel.pathname); /* Create directory. Ignore if exist. */ + /* FIXME: not sure this is useful */ ret = run_as_mkdir_recursive(msg.u.rotate_channel.pathname, S_IRWXU | S_IRWXG, uid, gid); if (ret < 0) { @@ -1654,3 +1655,51 @@ error: health_code_update(); return ret; } + +int consumer_rotate_rename(struct consumer_socket *socket, uint64_t session_id, + struct consumer_output *output, char *current_path, char *new_path, + uint32_t create, uid_t uid, gid_t gid) +{ + int ret; + struct lttcomm_consumer_msg msg; + + assert(socket); + + DBG("Consumer rotate rename session %" PRIu64, session_id); + + memset(&msg, 0, sizeof(msg)); + msg.cmd_type = LTTNG_CONSUMER_ROTATE_RENAME; + msg.u.rotate_rename.session_id = session_id; + msg.u.rotate_rename.create = create; + msg.u.rotate_rename.uid = uid; + msg.u.rotate_rename.gid = gid; + + if (output->type == CONSUMER_DST_NET) { + ERR("TODO"); + ret = -1; + msg.u.rotate_rename.relayd_id = output->net_seq_index; + goto error; + } else { + msg.u.rotate_rename.relayd_id = (uint64_t) -1ULL; + snprintf(msg.u.rotate_rename.current_path, PATH_MAX, "%s", + current_path); + snprintf(msg.u.rotate_rename.new_path, PATH_MAX, "%s", + new_path); + fprintf(stderr, "rotate rename from %s to %s\n", current_path, + new_path); + } + + health_code_update(); + fprintf(stderr, "send %d to the consumer\n", + LTTNG_CONSUMER_ROTATE_RENAME); + + ret = 0; + ret = consumer_send_msg(socket, &msg); + if (ret < 0) { + goto error; + } + +error: + health_code_update(); + return ret; +} diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h index b69cd8597..6e92cb18e 100644 --- a/src/bin/lttng-sessiond/consumer.h +++ b/src/bin/lttng-sessiond/consumer.h @@ -327,5 +327,8 @@ int consumer_snapshot_channel(struct consumer_socket *socket, uint64_t key, int consumer_rotate_channel(struct consumer_socket *socket, uint64_t key, uid_t uid, gid_t gid, struct consumer_output *output, char *tmp, uint32_t metadata); +int consumer_rotate_rename(struct consumer_socket *socket, uint64_t session_id, + struct consumer_output *output, char *current_path, char *new_path, + uint32_t create, uid_t uid, gid_t gid); #endif /* _CONSUMER_H */ diff --git a/src/bin/lttng-sessiond/rotate.c b/src/bin/lttng-sessiond/rotate.c new file mode 100644 index 000000000..2a861bc7b --- /dev/null +++ b/src/bin/lttng-sessiond/rotate.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2017 - Julien Desfossez + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License, version 2 only, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define _LGPL_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "session.h" +#include "rotate.h" +#include "rotation-thread.h" +#include "lttng-sessiond.h" +#include "health-sessiond.h" +#include "cmd.h" + +#include +#include +#include + +unsigned long hash_channel_key(struct rotation_channel_key *key) +{ + return hash_key_u64(&key->key, lttng_ht_seed) ^ hash_key_ulong( + (void *) (unsigned long) key->domain, lttng_ht_seed); +} + +int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain, + struct ltt_session *session) +{ + int ret; + struct rotation_channel_info *new_info; + struct rotation_channel_key channel_key = { .key = key, + .domain = domain }; + + new_info = zmalloc(sizeof(struct rotation_channel_info)); + if (!new_info) { + goto error; + } + + new_info->channel_key.key = key; + new_info->channel_key.domain = domain; + new_info->session = session; + cds_lfht_node_init(&new_info->rotate_channels_ht_node); + + session->nr_chan_rotate_pending++; + cds_lfht_add(channel_pending_rotate_ht, + hash_channel_key(&channel_key), + &new_info->rotate_channels_ht_node); + + ret = 0; + goto end; + +error: + ret = -1; +end: + return ret; +} + +int session_rename_chunk(struct ltt_session *session, char *current_path, + char *new_path, uint32_t create) +{ + int ret; + struct consumer_socket *socket; + struct consumer_output *output; + struct lttng_ht_iter iter; + uid_t uid; + gid_t gid; + + /* + * Either one of the sessions is enough to find the consumer_output + * and uid/gid. + */ + if (session->kernel_session) { + output = session->kernel_session->consumer; + uid = session->kernel_session->uid; + gid = session->kernel_session->gid; + } else if (session->ust_session) { + output = session->ust_session->consumer; + uid = session->ust_session->uid; + gid = session->ust_session->gid; + } else { + assert(0); + } + + if (!output || !output->socks) { + ERR("No consumer output found"); + ret = -1; + goto end; + } + + rcu_read_lock(); + /* + * We have to iterate to find a socket, but we only need to send the + * rename command to one consumer, so we break after the first one. + */ + cds_lfht_for_each_entry(output->socks->ht, &iter.iter, socket, node.node) { + pthread_mutex_lock(socket->lock); + ret = consumer_rotate_rename(socket, session->id, output, + current_path, new_path, create, uid, gid); + pthread_mutex_unlock(socket->lock); + if (ret) { + ERR("Consumer rename chunk"); + ret = -1; + rcu_read_unlock(); + goto end; + } + break; + } + rcu_read_unlock(); + + ret = 0; + +end: + return ret; +} + +int rename_complete_chunk(struct ltt_session *session, time_t ts) +{ + struct tm *timeinfo; + char datetime[16]; + char *tmppath = NULL; + int ret; + + timeinfo = localtime(&ts); + strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo); + + tmppath = zmalloc(PATH_MAX * sizeof(char)); + if (!tmppath) { + ERR("Alloc tmppath"); + ret = -1; + goto end; + } + + snprintf(tmppath, PATH_MAX, "%s%s-%" PRIu64, + session->rotation_chunk.current_rotate_path, + datetime, session->rotate_count); + + fprintf(stderr, "rename %s to %s\n", session->rotation_chunk.current_rotate_path, + tmppath); + + ret = session_rename_chunk(session, + session->rotation_chunk.current_rotate_path, + tmppath, 0); + if (ret) { + ERR("Session rename"); + ret = -1; + goto end; + } + + /* + * Store the path where the readable chunk is. This path is valid + * and can be queried by the client with rotate_pending until the next + * rotation is started. + */ + snprintf(session->rotation_chunk.current_rotate_path, PATH_MAX, + "%s", tmppath); + session->rotate_pending = 0; + +end: + free(tmppath); + return ret; +} + diff --git a/src/bin/lttng-sessiond/rotate.h b/src/bin/lttng-sessiond/rotate.h new file mode 100644 index 000000000..2d7213b58 --- /dev/null +++ b/src/bin/lttng-sessiond/rotate.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 - Julien Desfossez + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License, version 2 only, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef ROTATE_H +#define ROTATE_H + +#include "rotation-thread.h" + +extern struct cds_lfht *channel_pending_rotate_ht; + +unsigned long hash_channel_key(struct rotation_channel_key *key); + +int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain, + struct ltt_session *session); + +int session_rename_chunk(struct ltt_session *session, char *current_path, + char *new_path, uint32_t create); + +int rename_complete_chunk(struct ltt_session *session, time_t ts); + +#endif /* ROTATE_H */ diff --git a/src/bin/lttng-sessiond/rotation-thread.c b/src/bin/lttng-sessiond/rotation-thread.c index fa3638b67..ded83a7a9 100644 --- a/src/bin/lttng-sessiond/rotation-thread.c +++ b/src/bin/lttng-sessiond/rotation-thread.c @@ -35,6 +35,7 @@ #include "rotation-thread.h" #include "lttng-sessiond.h" #include "health-sessiond.h" +#include "rotate.h" #include "cmd.h" #include @@ -43,13 +44,6 @@ struct cds_lfht *channel_pending_rotate_ht; -static -unsigned long hash_channel_key(struct rotation_channel_key *key) -{ - return hash_key_u64(&key->key, lttng_ht_seed) ^ hash_key_ulong( - (void *) (unsigned long) key->domain, lttng_ht_seed); -} - static void channel_rotation_info_destroy(struct rotation_channel_info *channel_info) { @@ -57,38 +51,6 @@ void channel_rotation_info_destroy(struct rotation_channel_info *channel_info) free(channel_info); } -int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain, - struct ltt_session *session) -{ - int ret; - struct rotation_channel_info *new_info; - struct rotation_channel_key channel_key = { .key = key, - .domain = domain }; - - new_info = zmalloc(sizeof(struct rotation_channel_info)); - if (!new_info) { - goto error; - } - - new_info->channel_key.key = key; - new_info->channel_key.domain = domain; - new_info->session = session; - cds_lfht_node_init(&new_info->rotate_channels_ht_node); - - session->nr_chan_rotate_pending++; - cds_lfht_add(channel_pending_rotate_ht, - hash_channel_key(&channel_key), - &new_info->rotate_channels_ht_node); - - ret = 0; - goto end; - -error: - ret = -1; -end: - return ret; -} - static int match_channel_info(struct cds_lfht_node *node, const void *key) { @@ -298,49 +260,6 @@ end: return 0; } -int rename_complete_chunk(struct ltt_session *session, time_t ts) -{ - struct tm *timeinfo; - char datetime[16]; - char *tmppath = NULL; - int ret; - - timeinfo = localtime(&ts); - strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo); - - tmppath = zmalloc(PATH_MAX * sizeof(char)); - if (!tmppath) { - ERR("Alloc tmppath"); - ret = -1; - goto end; - } - - snprintf(tmppath, PATH_MAX, "%s%s-%" PRIu64, - session->rotation_chunk.current_rotate_path, - datetime, session->rotate_count); - - fprintf(stderr, "rename %s to %s\n", session->rotation_chunk.current_rotate_path, - tmppath); - ret = rename(session->rotation_chunk.current_rotate_path, - tmppath); - if (ret < 0) { - PERROR("Rename completed rotation chunk"); - goto end; - } - /* - * Store the path where the readable chunk is. This path is valid - * and can be queried by the client with rotate_pending until the next - * rotation is started. - */ - snprintf(session->rotation_chunk.current_rotate_path, PATH_MAX, - "%s", tmppath); - session->rotate_pending = 0; - -end: - free(tmppath); - return ret; -} - static int handle_channel_rotation_pipe(int fd, uint32_t revents, struct rotation_thread_handle *handle, diff --git a/src/bin/lttng-sessiond/rotation-thread.h b/src/bin/lttng-sessiond/rotation-thread.h index 77fd88322..580ddbbb4 100644 --- a/src/bin/lttng-sessiond/rotation-thread.h +++ b/src/bin/lttng-sessiond/rotation-thread.h @@ -27,8 +27,6 @@ #include #include -struct cds_lfht *channel_pending_rotate_ht; - struct rotation_channel_key { uint64_t key; enum lttng_domain_type domain; @@ -73,11 +71,7 @@ void rotation_thread_quit(struct rotation_thread_handle *handle); int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain, struct ltt_session *session); -void rotate_del_channel_pending(uint64_t key, enum lttng_domain_type domain); void *thread_rotation(void *data); -/* FIXME: TMP */ -int rename_complete_chunk(struct ltt_session *session, time_t ts); - #endif /* ROTATION_THREAD_H */ diff --git a/src/common/consumer/consumer.c b/src/common/consumer/consumer.c index 193b9ea1b..54491b89f 100644 --- a/src/common/consumer/consumer.c +++ b/src/common/consumer/consumer.c @@ -4196,3 +4196,26 @@ end: rcu_read_unlock(); return ret; } + +int lttng_consumer_rotate_rename(char *current_path, char *new_path, + uint32_t create, uid_t uid, gid_t gid) +{ + int ret; + + if (create) { + ret = utils_mkdir_recursive(new_path, S_IRWXU | S_IRWXG, + uid, gid); + if (ret < 0) { + ERR("Create directory on rotate"); + goto end; + } + + } + ret = rename(current_path, new_path); + if (ret < 0) { + PERROR("Rename completed rotation chunk"); + } + +end: + return ret; +} diff --git a/src/common/consumer/consumer.h b/src/common/consumer/consumer.h index d8df7adb4..3aa63eed1 100644 --- a/src/common/consumer/consumer.h +++ b/src/common/consumer/consumer.h @@ -64,6 +64,7 @@ enum lttng_consumer_command { LTTNG_CONSUMER_SET_CHANNEL_MONITOR_PIPE, LTTNG_CONSUMER_SET_CHANNEL_ROTATE_PIPE, LTTNG_CONSUMER_ROTATE_CHANNEL, + LTTNG_CONSUMER_ROTATE_RENAME, }; /* State of each fd in consumer */ @@ -821,5 +822,7 @@ int lttng_consumer_rotate_stream(struct lttng_consumer_local_data *ctx, struct lttng_consumer_stream *stream); int lttng_consumer_rotate_ready_streams(uint64_t key, struct lttng_consumer_local_data *ctx); +int lttng_consumer_rotate_rename(char *current_path, char *new_path, + uint32_t create, uid_t uid, gid_t gid); #endif /* LIB_CONSUMER_H */ diff --git a/src/common/kernel-consumer/kernel-consumer.c b/src/common/kernel-consumer/kernel-consumer.c index 76c031063..bbce28ccc 100644 --- a/src/common/kernel-consumer/kernel-consumer.c +++ b/src/common/kernel-consumer/kernel-consumer.c @@ -1167,6 +1167,29 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, } break; } + case LTTNG_CONSUMER_ROTATE_RENAME: + { + DBG("Consumer rename session %" PRIu64 " after rotation", + msg.u.rotate_rename.session_id); + ret = lttng_consumer_rotate_rename(msg.u.rotate_rename.current_path, + msg.u.rotate_rename.new_path, + msg.u.rotate_rename.create, + msg.u.rotate_rename.uid, + msg.u.rotate_rename.gid); + if (ret < 0) { + ERR("Rotate rename failed"); + ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND; + } + + health_code_update(); + + ret = consumer_send_status_msg(sock, ret_code); + if (ret < 0) { + /* Somehow, the session daemon is not responding anymore. */ + goto end_nosignal; + } + + } default: goto end_nosignal; } diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 566425402..e91e06984 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -547,6 +547,15 @@ struct lttcomm_consumer_msg { uint64_t relayd_id; /* Relayd id if apply. */ uint64_t key; } LTTNG_PACKED rotate_channel; + struct { + char current_path[PATH_MAX]; + char new_path[PATH_MAX]; + uint64_t relayd_id; /* Relayd id if apply. */ + uint64_t session_id; + uint32_t create; /* Create new_path before move. */ + uint32_t uid; + uint32_t gid; + } LTTNG_PACKED rotate_rename; } u; } LTTNG_PACKED; diff --git a/src/common/ust-consumer/ust-consumer.c b/src/common/ust-consumer/ust-consumer.c index db6ec8bff..1ec0a0e46 100644 --- a/src/common/ust-consumer/ust-consumer.c +++ b/src/common/ust-consumer/ust-consumer.c @@ -1965,6 +1965,29 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx, } break; } + case LTTNG_CONSUMER_ROTATE_RENAME: + { + DBG("Consumer rename session %" PRIu64 " after rotation", + msg.u.rotate_rename.session_id); + ret = lttng_consumer_rotate_rename(msg.u.rotate_rename.current_path, + msg.u.rotate_rename.new_path, + msg.u.rotate_rename.create, + msg.u.rotate_rename.uid, + msg.u.rotate_rename.gid); + if (ret < 0) { + ERR("Rotate rename failed"); + ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND; + } + + health_code_update(); + + ret = consumer_send_status_msg(sock, ret_code); + if (ret < 0) { + /* Somehow, the session daemon is not responding anymore. */ + goto end_nosignal; + } + + } default: break; }