From c25613651ac7525a16b9877230a682fc1a64e036 Mon Sep 17 00:00:00 2001 From: Julien Desfossez Date: Tue, 5 Jul 2016 10:54:36 -0400 Subject: [PATCH] Allow regenerating the statedump of a running session MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The "lttng regenerate statedump" command can be used to regenerate the statedump of a running session whenever needed. This is particularly useful in snapshot and trace-file rotation modes where the original statedump may be lost. Signed-off-by: Julien Desfossez Signed-off-by: Jérémie Galarneau --- include/lttng/lttng-error.h | 2 + include/lttng/lttng.h | 9 ++++ src/bin/lttng-sessiond/cmd.c | 55 ++++++++++++++++++++ src/bin/lttng-sessiond/cmd.h | 1 + src/bin/lttng-sessiond/main.c | 6 +++ src/bin/lttng-sessiond/ust-app.c | 66 ++++++++++++++++++++++++ src/bin/lttng-sessiond/ust-app.h | 6 +++ src/bin/lttng/commands/regenerate.c | 19 +++++++ src/common/error.c | 2 + src/common/kernel-ctl/kernel-ctl.c | 5 ++ src/common/kernel-ctl/kernel-ctl.h | 1 + src/common/sessiond-comm/sessiond-comm.h | 1 + src/lib/lttng-ctl/lttng-ctl.c | 30 +++++++++++ 13 files changed, 203 insertions(+) diff --git a/include/lttng/lttng-error.h b/include/lttng/lttng-error.h index 72194ef2c..df59f8f7b 100644 --- a/include/lttng/lttng-error.h +++ b/include/lttng/lttng-error.h @@ -142,6 +142,8 @@ enum lttng_error_code { LTTNG_ERR_LIVE_SESSION = 119, /* Live session unsupported */ LTTNG_ERR_PER_PID_SESSION = 120, /* Per-PID sessions unsupported */ LTTNG_ERR_KERN_CONTEXT_UNAVAILABLE = 121, /* Context unavailable on this kernel */ + LTTNG_ERR_REGEN_STATEDUMP_FAIL = 122, /* Failed to regenerate the state dump */ + LTTNG_ERR_REGEN_STATEDUMP_NOMEM = 123, /* Failed to regenerate the state dump, not enough memory */ /* MUST be last element */ LTTNG_ERR_NR, /* Last element */ diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 09aa969f5..d37d6c065 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -173,6 +173,15 @@ extern int lttng_metadata_regenerate(const char *session_name); */ extern int lttng_regenerate_metadata(const char *session_name); +/* + * Trigger the regeneration of the statedump for a session. The new statedump + * information is appended to the currently active trace, the session needs to + * be active. + * + * Return 0 on success, a negative LTTng error code on error. + */ +extern int lttng_regenerate_statedump(const char *session_name); + #ifdef __cplusplus } #endif diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index bd63389ee..a57afe2c3 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -3539,6 +3539,61 @@ end: return ret; } +/* + * Command LTTNG_REGENERATE_STATEDUMP from the lttng-ctl library. + * + * Ask the tracer to regenerate a new statedump. + * + * Return 0 on success or else a LTTNG_ERR code. + */ +int cmd_regenerate_statedump(struct ltt_session *session) +{ + int ret; + + assert(session); + + if (!session->active) { + ret = LTTNG_ERR_SESSION_NOT_STARTED; + goto end; + } + ret = 0; + + if (session->kernel_session) { + ret = kernctl_session_regenerate_statedump( + session->kernel_session->fd); + /* + * Currently, the statedump in kernel can only fail if out + * of memory. + */ + if (ret < 0) { + if (ret == -ENOMEM) { + ret = LTTNG_ERR_REGEN_STATEDUMP_NOMEM; + } else { + ret = LTTNG_ERR_REGEN_STATEDUMP_FAIL; + } + ERR("Failed to regenerate the kernel statedump"); + goto end; + } + } + + if (session->ust_session) { + ret = ust_app_regenerate_statedump_all(session->ust_session); + /* + * Currently, the statedump in UST always returns 0. + */ + if (ret < 0) { + ret = LTTNG_ERR_REGEN_STATEDUMP_FAIL; + ERR("Failed to regenerate the UST statedump"); + goto end; + } + } + DBG("Cmd regenerate statedump for session %s", session->name); + ret = LTTNG_OK; + +end: + return ret; +} + /* * Send relayd sockets from snapshot output to consumer. Ignore request if the * snapshot output is *not* set with a remote destination. diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 320d717a3..975a7f10f 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -111,5 +111,6 @@ int cmd_snapshot_record(struct ltt_session *session, int cmd_set_session_shm_path(struct ltt_session *session, const char *shm_path); int cmd_regenerate_metadata(struct ltt_session *session); +int cmd_regenerate_statedump(struct ltt_session *session); #endif /* CMD_H */ diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index afd0cc6e1..67df2fa2f 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -3005,6 +3005,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, case LTTNG_SAVE_SESSION: case LTTNG_SET_SESSION_SHM_PATH: case LTTNG_REGENERATE_METADATA: + case LTTNG_REGENERATE_STATEDUMP: need_domain = 0; break; default: @@ -4120,6 +4121,11 @@ error_add_context: ret = cmd_regenerate_metadata(cmd_ctx->session); break; } + case LTTNG_REGENERATE_STATEDUMP: + { + ret = cmd_regenerate_statedump(cmd_ctx->session); + break; + } default: ret = LTTNG_ERR_UND; break; diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c index f30df2097..47bd04cd8 100644 --- a/src/bin/lttng-sessiond/ust-app.c +++ b/src/bin/lttng-sessiond/ust-app.c @@ -6148,3 +6148,69 @@ end: rcu_read_unlock(); return ret; } + +static +int ust_app_regenerate_statedump(struct ltt_ust_session *usess, + struct ust_app *app) +{ + int ret = 0; + struct ust_app_session *ua_sess; + + DBG("Regenerating the metadata for ust app pid %d", app->pid); + + rcu_read_lock(); + + ua_sess = lookup_session_by_app(usess, app); + if (ua_sess == NULL) { + /* The session is in teardown process. Ignore and continue. */ + goto end; + } + + pthread_mutex_lock(&ua_sess->lock); + + if (ua_sess->deleted) { + goto end_unlock; + } + + pthread_mutex_lock(&app->sock_lock); + ret = ustctl_regenerate_statedump(app->sock, ua_sess->handle); + pthread_mutex_unlock(&app->sock_lock); + +end_unlock: + pthread_mutex_unlock(&ua_sess->lock); + +end: + rcu_read_unlock(); + health_code_update(); + return ret; +} + +/* + * Regenerate the statedump for each app in the session. + */ +int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess) +{ + int ret = 0; + struct lttng_ht_iter iter; + struct ust_app *app; + + DBG("Regenerating the metadata for all UST apps"); + + rcu_read_lock(); + + cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) { + if (!app->compatible) { + continue; + } + + ret = ust_app_regenerate_statedump(usess, app); + if (ret < 0) { + /* Continue to the next app even on error */ + continue; + } + } + + rcu_read_unlock(); + + return 0; +} diff --git a/src/bin/lttng-sessiond/ust-app.h b/src/bin/lttng-sessiond/ust-app.h index d02f353c8..8369d149c 100644 --- a/src/bin/lttng-sessiond/ust-app.h +++ b/src/bin/lttng-sessiond/ust-app.h @@ -352,6 +352,7 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess, struct ltt_ust_channel *uchan, struct consumer_output *consumer, int overwrite, uint64_t *discarded, uint64_t *lost); +int ust_app_regenerate_statedump_all(struct ltt_ust_session *usess); static inline int ust_app_supported(void) @@ -583,6 +584,11 @@ int ust_app_pid_get_channel_runtime_stats(struct ltt_ust_session *usess, { return 0; } +static inline +int ust_app_regenerate_metadata_all(struct ltt_ust_session *usess) +{ + return 0; +} #endif /* HAVE_LIBLTTNG_UST_CTL */ diff --git a/src/bin/lttng/commands/regenerate.c b/src/bin/lttng/commands/regenerate.c index c64d8fe53..5c982c8a6 100644 --- a/src/bin/lttng/commands/regenerate.c +++ b/src/bin/lttng/commands/regenerate.c @@ -32,6 +32,7 @@ static char *opt_session_name; static char *session_name = NULL; static int regenerate_metadata(int argc, const char **argv); +static int regenerate_statedump(int argc, const char **argv); enum { OPT_HELP = 1, @@ -52,6 +53,7 @@ static struct poptOption long_options[] = { static struct cmd_struct actions[] = { { "metadata", regenerate_metadata }, + { "statedump", regenerate_statedump }, { NULL, NULL } /* Array closure */ }; @@ -88,6 +90,23 @@ end: return ret; } +static int regenerate_statedump(int argc, const char **argv) +{ + int ret; + + if (argc > 1) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + ret = lttng_regenerate_statedump(session_name); + if (ret == 0) { + MSG("State dump successfully regenerated for session %s", session_name); + } + +end: + return ret; +} + static int handle_command(const char **argv) { struct cmd_struct *cmd; diff --git a/src/common/error.c b/src/common/error.c index bc42577bd..d3d952a7d 100644 --- a/src/common/error.c +++ b/src/common/error.c @@ -183,6 +183,8 @@ static const char *error_string_array[] = { [ ERROR_INDEX(LTTNG_ERR_LIVE_SESSION) ] = "Live sessions are not supported", [ ERROR_INDEX(LTTNG_ERR_PER_PID_SESSION) ] = "Per-PID tracing sessions are not supported", [ ERROR_INDEX(LTTNG_ERR_KERN_CONTEXT_UNAVAILABLE) ] = "Context unavailable on this kernel", + [ ERROR_INDEX(LTTNG_ERR_REGEN_STATEDUMP_FAIL) ] = "Failed to regenerate the state dump", + [ ERROR_INDEX(LTTNG_ERR_REGEN_STATEDUMP_NOMEM) ] = "Failed to regenerate the state dump, not enough memory", /* Last element */ [ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code" diff --git a/src/common/kernel-ctl/kernel-ctl.c b/src/common/kernel-ctl/kernel-ctl.c index e1de0e715..1c2ab6188 100644 --- a/src/common/kernel-ctl/kernel-ctl.c +++ b/src/common/kernel-ctl/kernel-ctl.c @@ -230,6 +230,11 @@ int kernctl_session_regenerate_metadata(int fd) return LTTNG_IOCTL_CHECK(fd, LTTNG_KERNEL_SESSION_METADATA_REGEN); } +int kernctl_session_regenerate_statedump(int fd) +{ + return LTTNG_IOCTL_CHECK(fd, LTTNG_KERNEL_SESSION_STATEDUMP); +} + int kernctl_create_stream(int fd) { return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_STREAM, diff --git a/src/common/kernel-ctl/kernel-ctl.h b/src/common/kernel-ctl/kernel-ctl.h index f30e6f3b4..7c25a17c3 100644 --- a/src/common/kernel-ctl/kernel-ctl.h +++ b/src/common/kernel-ctl/kernel-ctl.h @@ -66,6 +66,7 @@ int kernctl_untrack_pid(int fd, int pid); int kernctl_list_tracker_pids(int fd); int kernctl_session_regenerate_metadata(int fd); +int kernctl_session_regenerate_statedump(int fd); /* Buffer operations */ diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 29740c1d0..628b1ea67 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -95,6 +95,7 @@ enum lttcomm_sessiond_command { LTTNG_LIST_TRACKER_PIDS = 34, LTTNG_SET_SESSION_SHM_PATH = 40, LTTNG_REGENERATE_METADATA = 41, + LTTNG_REGENERATE_STATEDUMP = 42, }; enum lttcomm_relayd_command { diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 8c78e1c19..bcd59f0c6 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -2418,6 +2418,36 @@ int lttng_metadata_regenerate(const char *session_name) return lttng_regenerate_metadata(session_name); } +/* + * Regenerate the statedump of a session. + * Return 0 on success, a negative error code on error. + */ +int lttng_regenerate_statedump(const char *session_name) +{ + int ret; + struct lttcomm_session_msg lsm; + + if (!session_name) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + memset(&lsm, 0, sizeof(lsm)); + lsm.cmd_type = LTTNG_REGENERATE_STATEDUMP; + + lttng_ctl_copy_string(lsm.session.name, session_name, + sizeof(lsm.session.name)); + + ret = lttng_ctl_ask_sessiond(&lsm, NULL); + if (ret < 0) { + goto end; + } + + ret = 0; +end: + return ret; +} + /* * lib constructor. */ -- 2.34.1