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 */
*/
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
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.
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 */
case LTTNG_SAVE_SESSION:
case LTTNG_SET_SESSION_SHM_PATH:
case LTTNG_REGENERATE_METADATA:
+ case LTTNG_REGENERATE_STATEDUMP:
need_domain = 0;
break;
default:
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;
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;
+}
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)
{
return 0;
}
+static inline
+int ust_app_regenerate_metadata_all(struct ltt_ust_session *usess)
+{
+ return 0;
+}
#endif /* HAVE_LIBLTTNG_UST_CTL */
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,
static struct cmd_struct actions[] = {
{ "metadata", regenerate_metadata },
+ { "statedump", regenerate_statedump },
{ NULL, NULL } /* Array closure */
};
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;
[ 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"
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,
int kernctl_list_tracker_pids(int fd);
int kernctl_session_regenerate_metadata(int fd);
+int kernctl_session_regenerate_statedump(int fd);
/* Buffer operations */
LTTNG_LIST_TRACKER_PIDS = 34,
LTTNG_SET_SESSION_SHM_PATH = 40,
LTTNG_REGENERATE_METADATA = 41,
+ LTTNG_REGENERATE_STATEDUMP = 42,
};
enum lttcomm_relayd_command {
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.
*/