From 27babd3a0a164f71d4dc02884ef20099ddfc6755 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Mon, 8 Jul 2013 15:19:12 -0400 Subject: [PATCH] Add create session snapshot API in lttng-sessiond This commit adds the "lttng_create_session_snapshot()" call to the API which will create on the session daemon a session in snapshot mode meaning that all channel will be in overwrite mode and mmap output. Signed-off-by: David Goulet --- include/lttng/lttng.h | 15 ++++++ src/bin/lttng-sessiond/channel.c | 12 +++++ src/bin/lttng-sessiond/cmd.c | 66 ++++++++++++++++++++++++ src/bin/lttng-sessiond/cmd.h | 2 + src/bin/lttng-sessiond/main.c | 43 +++++++++++++++ src/bin/lttng-sessiond/session.h | 6 +++ src/bin/lttng-sessiond/snapshot.h | 4 ++ src/bin/lttng-sessiond/trace-kernel.h | 1 + src/bin/lttng-sessiond/trace-ust.h | 1 + src/bin/lttng/commands/snapshot.c | 2 - src/common/defaults.h | 1 + src/common/sessiond-comm/sessiond-comm.h | 1 + src/lib/lttng-ctl/lttng-ctl.c | 35 +++++++++++++ 13 files changed, 187 insertions(+), 2 deletions(-) diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 3e7fb6316..9e3924e67 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -390,6 +390,21 @@ extern void lttng_destroy_handle(struct lttng_handle *handle); */ extern int lttng_create_session(const char *name, const char *url); +/* + * Create a tracing session that will exclusively be used for snapshot meaning + * the session will be in no output mode and every channel enabled for that + * session will be set in overwrite mode and in mmap output since splice is not + * supported. + * + * If an url is given, it will be used to create a default snapshot output + * using it as a destination. If NULL, no output will be defined and an + * add-output call will be needed. + * + * Name can't be NULL. + */ +extern int lttng_create_session_snapshot(const char *name, + const char *snapshot_url); + /* * Destroy a tracing session. * diff --git a/src/bin/lttng-sessiond/channel.c b/src/bin/lttng-sessiond/channel.c index d826125c9..984576edc 100644 --- a/src/bin/lttng-sessiond/channel.c +++ b/src/bin/lttng-sessiond/channel.c @@ -184,6 +184,12 @@ int channel_kernel_create(struct ltt_kernel_session *ksession, attr = defattr; } + if (ksession->snapshot_mode) { + /* Force channel attribute for snapshot mode. */ + attr->attr.overwrite = 1; + attr->attr.output = LTTNG_EVENT_MMAP; + } + /* Channel not found, creating it */ ret = kernel_create_channel(ksession, attr); if (ret < 0) { @@ -263,6 +269,12 @@ int channel_ust_create(struct ltt_ust_session *usess, attr = defattr; } + if (usess->snapshot_mode) { + /* Force channel attribute for snapshot mode. */ + attr->attr.overwrite = 1; + attr->attr.output = LTTNG_EVENT_MMAP; + } + /* * Validate UST buffer size and number of buffers: must both be power of 2 * and nonzero. We validate right here for UST, because applications will diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index a6a81c5db..60a4ef2fb 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -1743,6 +1743,72 @@ find_error: return ret; } +/* + * Command LTTNG_CREATE_SESSION_SNAPSHOT processed by the client thread. + */ +int cmd_create_session_snapshot(char *name, struct lttng_uri *uris, + size_t nb_uri, lttng_sock_cred *creds) +{ + int ret; + struct ltt_session *session; + struct snapshot_output *new_output = NULL; + + assert(name); + assert(creds); + + /* + * Create session in no output mode with URIs set to NULL. The uris we've + * received are for a default snapshot output if one. + */ + ret = cmd_create_session_uri(name, NULL, 0, creds); + if (ret != LTTNG_OK) { + goto error; + } + + /* Get the newly created session pointer back. This should NEVER fail. */ + session = session_find_by_name(name); + assert(session); + + /* Flag session for snapshot mode. */ + session->snapshot_mode = 1; + + /* Skip snapshot output creation if no URI is given. */ + if (nb_uri == 0) { + goto end; + } + + new_output = snapshot_output_alloc(); + if (!new_output) { + ret = LTTNG_ERR_NOMEM; + goto error_snapshot_alloc; + } + + ret = snapshot_output_init_with_uri(DEFAULT_SNAPSHOT_MAX_SIZE, NULL, + uris, nb_uri, session->consumer, new_output, &session->snapshot); + if (ret < 0) { + if (ret == -ENOMEM) { + ret = LTTNG_ERR_NOMEM; + } else { + ret = LTTNG_ERR_INVALID; + } + goto error_snapshot; + } + + rcu_read_lock(); + snapshot_add_output(&session->snapshot, new_output); + rcu_read_unlock(); + +end: + return LTTNG_OK; + +error_snapshot: + snapshot_output_destroy(new_output); +error_snapshot_alloc: + session_destroy(session); +error: + return ret; +} + /* * Command LTTNG_DESTROY_SESSION processed by the client thread. */ diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 5be1688c9..830d8216a 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -30,6 +30,8 @@ void cmd_init(void); /* Session commands */ int cmd_create_session_uri(char *name, struct lttng_uri *uris, size_t nb_uri, lttng_sock_cred *creds); +int cmd_create_session_snapshot(char *name, struct lttng_uri *uris, + size_t nb_uri, lttng_sock_cred *creds); int cmd_destroy_session(struct ltt_session *session, int wpipe); /* Channel commands */ diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 048c1e16d..1d047fd85 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -2428,6 +2428,7 @@ static int create_ust_session(struct ltt_session *session, lus->uid = session->uid; lus->gid = session->gid; lus->output_traces = session->output_traces; + lus->snapshot_mode = session->snapshot_mode; session->ust_session = lus; /* Copy session output to the newly created UST session */ @@ -2485,6 +2486,7 @@ static int create_kernel_session(struct ltt_session *session) session->kernel_session->uid = session->uid; session->kernel_session->gid = session->gid; session->kernel_session->output_traces = session->output_traces; + session->kernel_session->snapshot_mode = session->snapshot_mode; return LTTNG_OK; @@ -2540,6 +2542,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, switch (cmd_ctx->lsm->cmd_type) { case LTTNG_CREATE_SESSION: + case LTTNG_CREATE_SESSION_SNAPSHOT: case LTTNG_DESTROY_SESSION: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_DOMAINS: @@ -2602,6 +2605,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, /* Commands that DO NOT need a session. */ switch (cmd_ctx->lsm->cmd_type) { case LTTNG_CREATE_SESSION: + case LTTNG_CREATE_SESSION_SNAPSHOT: case LTTNG_CALIBRATE: case LTTNG_LIST_SESSIONS: case LTTNG_LIST_TRACEPOINTS: @@ -3293,6 +3297,45 @@ skip_domain: cmd_ctx->lsm->u.snapshot_record.wait); break; } + case LTTNG_CREATE_SESSION_SNAPSHOT: + { + size_t nb_uri, len; + struct lttng_uri *uris = NULL; + + nb_uri = cmd_ctx->lsm->u.uri.size; + len = nb_uri * sizeof(struct lttng_uri); + + if (nb_uri > 0) { + uris = zmalloc(len); + if (uris == NULL) { + ret = LTTNG_ERR_FATAL; + goto error; + } + + /* Receive variable len data */ + DBG("Waiting for %zu URIs from client ...", nb_uri); + ret = lttcomm_recv_unix_sock(sock, uris, len); + if (ret <= 0) { + DBG("No URIs received from client... continuing"); + *sock_error = 1; + ret = LTTNG_ERR_SESSION_FAIL; + free(uris); + goto error; + } + + if (nb_uri == 1 && uris[0].dtype != LTTNG_DST_PATH) { + DBG("Creating session with ONE network URI is a bad call"); + ret = LTTNG_ERR_SESSION_FAIL; + free(uris); + goto error; + } + } + + ret = cmd_create_session_snapshot(cmd_ctx->lsm->session.name, uris, + nb_uri, &cmd_ctx->creds); + free(uris); + break; + } default: ret = LTTNG_ERR_UND; break; diff --git a/src/bin/lttng-sessiond/session.h b/src/bin/lttng-sessiond/session.h index 7b927efe1..0fd2fb16a 100644 --- a/src/bin/lttng-sessiond/session.h +++ b/src/bin/lttng-sessiond/session.h @@ -93,6 +93,12 @@ struct ltt_session { struct snapshot snapshot; /* Indicate if the session has to output the traces or not. */ unsigned int output_traces; + /* + * This session is in snapshot mode. This means that every channel enabled + * will be set in overwrite mode and mmap. It is considered exclusively for + * snapshot purposes. + */ + unsigned int snapshot_mode; }; /* Prototypes */ diff --git a/src/bin/lttng-sessiond/snapshot.h b/src/bin/lttng-sessiond/snapshot.h index bf594b5fe..44d2ae7f5 100644 --- a/src/bin/lttng-sessiond/snapshot.h +++ b/src/bin/lttng-sessiond/snapshot.h @@ -69,6 +69,10 @@ int snapshot_output_init(uint64_t max_size, const char *name, const char *ctrl_url, const char *data_url, struct consumer_output *consumer, struct snapshot_output *output, struct snapshot *snapshot); +int snapshot_output_init_with_uri(uint64_t max_size, const char *name, + struct lttng_uri *uris, size_t nb_uri, + struct consumer_output *consumer, struct snapshot_output *output, + struct snapshot *snapshot); struct snapshot_output *snapshot_find_output_by_id(uint32_t id, struct snapshot *snapshot); diff --git a/src/bin/lttng-sessiond/trace-kernel.h b/src/bin/lttng-sessiond/trace-kernel.h index 68301967a..5502e42bd 100644 --- a/src/bin/lttng-sessiond/trace-kernel.h +++ b/src/bin/lttng-sessiond/trace-kernel.h @@ -113,6 +113,7 @@ struct ltt_kernel_session { unsigned int started; /* Tell or not if the session has to output the traces. */ unsigned int output_traces; + unsigned int snapshot_mode; }; /* diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index 0dac36b21..5ca7964ea 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -107,6 +107,7 @@ struct ltt_ust_session { uint64_t used_channel_id; /* Tell or not if the session has to output the traces. */ unsigned int output_traces; + unsigned int snapshot_mode; }; /* diff --git a/src/bin/lttng/commands/snapshot.c b/src/bin/lttng/commands/snapshot.c index 2a223d445..0c15dbb70 100644 --- a/src/bin/lttng/commands/snapshot.c +++ b/src/bin/lttng/commands/snapshot.c @@ -343,8 +343,6 @@ static int record(const char *url) } else if (opt_ctrl_url) { MSG("Snapshot written to ctrl: %s, data: %s", opt_ctrl_url, opt_data_url); - } else { - MSG("Snapshot written in session directory."); } error: diff --git a/src/common/defaults.h b/src/common/defaults.h index 388b9f0d7..242be1e72 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -205,6 +205,7 @@ #define DEFAULT_UST_STREAM_FD_NUM 2 /* Number of fd per UST stream. */ #define DEFAULT_SNAPSHOT_NAME "snapshot" +#define DEFAULT_SNAPSHOT_MAX_SIZE 0 /* Unlimited. */ extern size_t default_channel_subbuf_size; extern size_t default_metadata_subbuf_size; diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index b76135e2c..2ee761749 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -87,6 +87,7 @@ enum lttcomm_sessiond_command { LTTNG_SNAPSHOT_DEL_OUTPUT = 26, LTTNG_SNAPSHOT_LIST_OUTPUT = 27, LTTNG_SNAPSHOT_RECORD = 28, + LTTNG_CREATE_SESSION_SNAPSHOT = 29, }; enum lttcomm_relayd_command { diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 3863aa1ce..d8d5db6c7 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1547,6 +1547,41 @@ int lttng_data_pending(const char *session_name) return ret; } +/* + * Create a session exclusively used for snapshot. + * + * Returns LTTNG_OK on success or a negative error code. + */ +int lttng_create_session_snapshot(const char *name, const char *snapshot_url) +{ + int ret; + ssize_t size; + struct lttcomm_session_msg lsm; + struct lttng_uri *uris = NULL; + + if (name == NULL) { + return -LTTNG_ERR_INVALID; + } + + memset(&lsm, 0, sizeof(lsm)); + + lsm.cmd_type = LTTNG_CREATE_SESSION_SNAPSHOT; + lttng_ctl_copy_string(lsm.session.name, name, sizeof(lsm.session.name)); + + size = uri_parse_str_urls(snapshot_url, NULL, &uris); + if (size < 0) { + return -LTTNG_ERR_INVALID; + } + + lsm.u.uri.size = size; + + ret = lttng_ctl_ask_sessiond_varlen(&lsm, uris, + sizeof(struct lttng_uri) * size, NULL); + + free(uris); + return ret; +} + /* * lib constructor */ -- 2.34.1