X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=c522d51c2dc27e46efa08ccb7f85085e16e4e4d3;hb=5c786dedd0156b93984f89ba47ec841277ed7dae;hp=a6a81c5dbd79989b474ffa1ee5b5d3c5edc83389;hpb=10a5031171c7bca5b4498c871b119e5a88b6a3fb;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index a6a81c5db..c522d51c2 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. */ @@ -2188,27 +2254,6 @@ int cmd_snapshot_add_output(struct ltt_session *session, goto free_error; } - /* - * Copy sockets so the snapshot output can use them on destroy. - */ - - if (session->ust_session) { - ret = consumer_copy_sockets(new_output->consumer, - session->ust_session->consumer); - if (ret < 0) { - goto free_error; - } - new_output->ust_sockets_copied = 1; - } - if (session->kernel_session) { - ret = consumer_copy_sockets(new_output->consumer, - session->kernel_session->consumer); - if (ret < 0) { - goto free_error; - } - new_output->kernel_sockets_copied = 1; - } - rcu_read_lock(); snapshot_add_output(&session->snapshot, new_output); if (id) { @@ -2396,7 +2441,8 @@ error: * Return 0 on success or else a negative value. */ static int record_kernel_snapshot(struct ltt_kernel_session *ksess, - struct snapshot_output *output, struct ltt_session *session, int wait) + struct snapshot_output *output, struct ltt_session *session, + int wait, int nb_streams) { int ret; @@ -2412,24 +2458,32 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess, goto error; } - if (!output->kernel_sockets_copied) { - ret = consumer_copy_sockets(output->consumer, ksess->consumer); - if (ret < 0) { - goto error; - } - output->kernel_sockets_copied = 1; + /* + * Copy kernel session sockets so we can communicate with the right + * consumer for the snapshot record command. + */ + ret = consumer_copy_sockets(output->consumer, ksess->consumer); + if (ret < 0) { + goto error; } ret = set_relayd_for_snapshot(ksess->consumer, output, session); if (ret < 0) { - goto error; + goto error_snapshot; } - ret = kernel_snapshot_record(ksess, output, wait); + ret = kernel_snapshot_record(ksess, output, wait, nb_streams); if (ret < 0) { - goto error; + ret = -LTTNG_ERR_SNAPSHOT_FAIL; + if (ret == -EINVAL) { + ret = -LTTNG_ERR_INVALID; + } + goto error_snapshot; } +error_snapshot: + /* Clean up copied sockets so this output can use some other later on. */ + consumer_destroy_output_sockets(output->consumer); error: return ret; } @@ -2440,7 +2494,8 @@ error: * Return 0 on success or else a negative value. */ static int record_ust_snapshot(struct ltt_ust_session *usess, - struct snapshot_output *output, struct ltt_session *session, int wait) + struct snapshot_output *output, struct ltt_session *session, + int wait, int nb_streams) { int ret; @@ -2456,28 +2511,59 @@ static int record_ust_snapshot(struct ltt_ust_session *usess, goto error; } - if (!output->ust_sockets_copied) { - ret = consumer_copy_sockets(output->consumer, usess->consumer); - if (ret < 0) { - goto error; - } - output->ust_sockets_copied = 1; + /* + * Copy kernel session sockets so we can communicate with the right + * consumer for the snapshot record command. + */ + ret = consumer_copy_sockets(output->consumer, usess->consumer); + if (ret < 0) { + goto error; } ret = set_relayd_for_snapshot(usess->consumer, output, session); if (ret < 0) { - goto error; + goto error_snapshot; } - ret = ust_app_snapshot_record(usess, output, wait); + ret = ust_app_snapshot_record(usess, output, wait, nb_streams); if (ret < 0) { - goto error; + ret = -LTTNG_ERR_SNAPSHOT_FAIL; + if (ret == -EINVAL) { + ret = -LTTNG_ERR_INVALID; + } + goto error_snapshot; } +error_snapshot: + /* Clean up copied sockets so this output can use some other later on. */ + consumer_destroy_output_sockets(output->consumer); error: return ret; } +/* + * Returns the total number of streams for a session or a negative value + * on error. + */ +static unsigned int get_total_nb_stream(struct ltt_session *session) +{ + unsigned int total_streams = 0; + + if (session->kernel_session) { + struct ltt_kernel_session *ksess = session->kernel_session; + + total_streams += ksess->stream_count_global; + } + + if (session->ust_session) { + struct ltt_ust_session *usess = session->ust_session; + + total_streams += ust_app_get_nb_stream(usess); + } + + return total_streams; +} + /* * Command LTTNG_SNAPSHOT_RECORD from lib lttng ctl. * @@ -2491,6 +2577,7 @@ int cmd_snapshot_record(struct ltt_session *session, { int ret = LTTNG_OK; struct snapshot_output *tmp_sout = NULL; + unsigned int nb_streams; assert(session); @@ -2532,11 +2619,18 @@ int cmd_snapshot_record(struct ltt_session *session, } } + /* + * Get the total number of stream of that session which is used by the + * maximum size of the snapshot feature. + */ + nb_streams = get_total_nb_stream(session); + if (session->kernel_session) { struct ltt_kernel_session *ksess = session->kernel_session; if (tmp_sout) { - ret = record_kernel_snapshot(ksess, tmp_sout, session, wait); + ret = record_kernel_snapshot(ksess, tmp_sout, session, + wait, nb_streams); if (ret < 0) { goto error; } @@ -2547,7 +2641,8 @@ int cmd_snapshot_record(struct ltt_session *session, rcu_read_lock(); cds_lfht_for_each_entry(session->snapshot.output_ht->ht, &iter.iter, sout, node.node) { - ret = record_kernel_snapshot(ksess, sout, session, wait); + ret = record_kernel_snapshot(ksess, sout, + session, wait, nb_streams); if (ret < 0) { rcu_read_unlock(); goto error; @@ -2561,7 +2656,8 @@ int cmd_snapshot_record(struct ltt_session *session, struct ltt_ust_session *usess = session->ust_session; if (tmp_sout) { - ret = record_ust_snapshot(usess, tmp_sout, session, wait); + ret = record_ust_snapshot(usess, tmp_sout, session, + wait, nb_streams); if (ret < 0) { goto error; } @@ -2572,7 +2668,8 @@ int cmd_snapshot_record(struct ltt_session *session, rcu_read_lock(); cds_lfht_for_each_entry(session->snapshot.output_ht->ht, &iter.iter, sout, node.node) { - ret = record_ust_snapshot(usess, sout, session, wait); + ret = record_ust_snapshot(usess, sout, session, + wait, nb_streams); if (ret < 0) { rcu_read_unlock(); goto error;