X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fcmd.c;h=a351d63de706b8843c7b16059f45ba2173b91e6c;hp=903dfd36defb5f8591aa7532f7b0a202d8be863d;hb=d3f14b8a4532b306e5ab293b97d020ce827bcc8e;hpb=af706bb7e9bda5d6b95414165681abe422f1541e diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 903dfd36d..a351d63de 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -857,6 +857,8 @@ int cmd_enable_channel(struct ltt_session *session, DBG("Enabling channel %s for session %s", attr->name, session->name); + rcu_read_lock(); + /* * Don't try to enable a channel if the session has been started at * some point in time before. The tracer does not allow it. @@ -866,8 +868,6 @@ int cmd_enable_channel(struct ltt_session *session, goto error; } - rcu_read_lock(); - switch (domain->type) { case LTTNG_DOMAIN_KERNEL: { @@ -2160,13 +2160,14 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, uid_t uid, strncpy(sessions[i].name, session->name, NAME_MAX); sessions[i].name[NAME_MAX - 1] = '\0'; sessions[i].enabled = session->enabled; + sessions[i].snapshot_mode = session->snapshot_mode; i++; } } /* * Command LTTNG_DATA_PENDING returning 0 if the data is NOT pending meaning - * ready for trace analysis (or anykind of reader) or else 1 for pending data. + * ready for trace analysis (or any kind of reader) or else 1 for pending data. */ int cmd_data_pending(struct ltt_session *session) { @@ -2222,8 +2223,8 @@ int cmd_snapshot_add_output(struct ltt_session *session, DBG("Cmd snapshot add output for session %s", session->name); /* - * Persmission denied to create an output if the session is not set in no - * output mode. + * Permission denied to create an output if the session is not + * set in no output mode. */ if (session->output_traces) { ret = LTTNG_ERR_EPERM; @@ -2278,26 +2279,31 @@ int cmd_snapshot_del_output(struct ltt_session *session, struct lttng_snapshot_output *output) { int ret; - struct snapshot_output *sout; + struct snapshot_output *sout = NULL; assert(session); assert(output); - DBG("Cmd snapshot del output id %" PRIu32 " for session %s", output->id, - session->name); - rcu_read_lock(); /* - * Persmission denied to create an output if the session is not set in no - * output mode. + * Permission denied to create an output if the session is not + * set in no output mode. */ if (session->output_traces) { ret = LTTNG_ERR_EPERM; goto error; } - sout = snapshot_find_output_by_id(output->id, &session->snapshot); + if (output->id) { + DBG("Cmd snapshot del output id %" PRIu32 " for session %s", output->id, + session->name); + sout = snapshot_find_output_by_id(output->id, &session->snapshot); + } else if (*output->name != '\0') { + DBG("Cmd snapshot del output name %s for session %s", output->name, + session->name); + sout = snapshot_find_output_by_name(output->name, &session->snapshot); + } if (!sout) { ret = LTTNG_ERR_INVALID; goto error; @@ -2333,8 +2339,8 @@ ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, DBG("Cmd snapshot list outputs for session %s", session->name); /* - * Persmission denied to create an output if the session is not set in no - * output mode. + * Permission denied to create an output if the session is not + * set in no output mode. */ if (session->output_traces) { ret = LTTNG_ERR_EPERM; @@ -2395,12 +2401,12 @@ error: * Send relayd sockets from snapshot output to consumer. Ignore request if the * snapshot output is *not* set with a remote destination. * - * Return 0 on success or else a negative value. + * Return 0 on success or a LTTNG_ERR code. */ static int set_relayd_for_snapshot(struct consumer_output *consumer, struct snapshot_output *snap_output, struct ltt_session *session) { - int ret = 0; + int ret = LTTNG_OK; struct lttng_ht_iter iter; struct consumer_socket *socket; @@ -2424,7 +2430,7 @@ static int set_relayd_for_snapshot(struct consumer_output *consumer, socket, node.node) { ret = send_consumer_relayd_sockets(0, session->id, snap_output->consumer, socket); - if (ret < 0) { + if (ret != LTTNG_OK) { rcu_read_unlock(); goto error; } @@ -2438,10 +2444,11 @@ error: /* * Record a kernel snapshot. * - * Return 0 on success or else a negative value. + * Return 0 on success or a LTTNG_ERR code. */ 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; @@ -2453,7 +2460,7 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess, ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime, sizeof(output->datetime)); if (!ret) { - ret = -EINVAL; + ret = LTTNG_ERR_INVALID; goto error; } @@ -2463,19 +2470,26 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess, */ ret = consumer_copy_sockets(output->consumer, ksess->consumer); if (ret < 0) { + ret = LTTNG_ERR_NOMEM; goto error; } ret = set_relayd_for_snapshot(ksess->consumer, output, session); - if (ret < 0) { + if (ret != LTTNG_OK) { goto error_snapshot; } - ret = kernel_snapshot_record(ksess, output, wait); + ret = kernel_snapshot_record(ksess, output, wait, nb_streams); if (ret < 0) { + ret = LTTNG_ERR_SNAPSHOT_FAIL; + if (ret == -EINVAL) { + ret = LTTNG_ERR_INVALID; + } goto error_snapshot; } + ret = LTTNG_OK; + error_snapshot: /* Clean up copied sockets so this output can use some other later on. */ consumer_destroy_output_sockets(output->consumer); @@ -2486,10 +2500,11 @@ error: /* * Record a UST snapshot. * - * Return 0 on success or else a negative value. + * Return 0 on success or a LTTNG_ERR error code. */ 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; @@ -2501,29 +2516,36 @@ static int record_ust_snapshot(struct ltt_ust_session *usess, ret = utils_get_current_time_str("%Y%m%d-%H%M%S", output->datetime, sizeof(output->datetime)); if (!ret) { - ret = -EINVAL; + ret = LTTNG_ERR_INVALID; goto error; } /* - * Copy kernel session sockets so we can communicate with the right + * Copy UST 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) { + ret = LTTNG_ERR_NOMEM; goto error; } ret = set_relayd_for_snapshot(usess->consumer, output, session); - if (ret < 0) { + if (ret != LTTNG_OK) { goto error_snapshot; } - ret = ust_app_snapshot_record(usess, output, wait); + ret = ust_app_snapshot_record(usess, output, wait, nb_streams); if (ret < 0) { + ret = LTTNG_ERR_SNAPSHOT_FAIL; + if (ret == -EINVAL) { + ret = LTTNG_ERR_INVALID; + } goto error_snapshot; } + ret = LTTNG_OK; + error_snapshot: /* Clean up copied sockets so this output can use some other later on. */ consumer_destroy_output_sockets(output->consumer); @@ -2531,6 +2553,29 @@ 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. * @@ -2543,15 +2588,17 @@ int cmd_snapshot_record(struct ltt_session *session, struct lttng_snapshot_output *output, int wait) { int ret = LTTNG_OK; - struct snapshot_output *tmp_sout = NULL; + unsigned int use_tmp_output = 0; + struct snapshot_output tmp_output; + unsigned int nb_streams, snapshot_success = 0; assert(session); DBG("Cmd snapshot record for session %s", session->name); /* - * Persmission denied to create an output if the session is not set in no - * output mode. + * Permission denied to create an output if the session is not + * set in no output mode. */ if (session->output_traces) { ret = LTTNG_ERR_EPERM; @@ -2566,15 +2613,9 @@ int cmd_snapshot_record(struct ltt_session *session, /* Use temporary output for the session. */ if (output && *output->ctrl_url != '\0') { - tmp_sout = snapshot_output_alloc(); - if (!tmp_sout) { - ret = LTTNG_ERR_NOMEM; - goto error; - } - ret = snapshot_output_init(output->max_size, output->name, output->ctrl_url, output->data_url, session->consumer, - tmp_sout, NULL); + &tmp_output, NULL); if (ret < 0) { if (ret == -ENOMEM) { ret = LTTNG_ERR_NOMEM; @@ -2583,16 +2624,27 @@ int cmd_snapshot_record(struct ltt_session *session, } goto error; } + /* Use the global session count for the temporary snapshot. */ + tmp_output.nb_snapshot = session->snapshot.nb_snapshot; + use_tmp_output = 1; } + /* + * 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); - if (ret < 0) { + if (use_tmp_output) { + ret = record_kernel_snapshot(ksess, &tmp_output, session, + wait, nb_streams); + if (ret != LTTNG_OK) { goto error; } + snapshot_success = 1; } else { struct snapshot_output *sout; struct lttng_ht_iter iter; @@ -2600,11 +2652,33 @@ 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); - if (ret < 0) { + /* + * Make a local copy of the output and assign the possible + * temporary value given by the caller. + */ + memset(&tmp_output, 0, sizeof(tmp_output)); + memcpy(&tmp_output, sout, sizeof(tmp_output)); + + /* Use temporary max size. */ + if (output->max_size != (uint64_t) -1ULL) { + tmp_output.max_size = output->max_size; + } + + /* Use temporary name. */ + if (*output->name != '\0') { + strncpy(tmp_output.name, output->name, + sizeof(tmp_output.name)); + } + + tmp_output.nb_snapshot = session->snapshot.nb_snapshot; + + ret = record_kernel_snapshot(ksess, &tmp_output, + session, wait, nb_streams); + if (ret != LTTNG_OK) { rcu_read_unlock(); goto error; } + snapshot_success = 1; } rcu_read_unlock(); } @@ -2613,11 +2687,13 @@ int cmd_snapshot_record(struct ltt_session *session, if (session->ust_session) { struct ltt_ust_session *usess = session->ust_session; - if (tmp_sout) { - ret = record_ust_snapshot(usess, tmp_sout, session, wait); - if (ret < 0) { + if (use_tmp_output) { + ret = record_ust_snapshot(usess, &tmp_output, session, + wait, nb_streams); + if (ret != LTTNG_OK) { goto error; } + snapshot_success = 1; } else { struct snapshot_output *sout; struct lttng_ht_iter iter; @@ -2625,20 +2701,43 @@ 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); - if (ret < 0) { + /* + * Make a local copy of the output and assign the possible + * temporary value given by the caller. + */ + memset(&tmp_output, 0, sizeof(tmp_output)); + memcpy(&tmp_output, sout, sizeof(tmp_output)); + + /* Use temporary max size. */ + if (output->max_size != (uint64_t) -1ULL) { + tmp_output.max_size = output->max_size; + } + + /* Use temporary name. */ + if (*output->name != '\0') { + strncpy(tmp_output.name, output->name, + sizeof(tmp_output.name)); + } + + tmp_output.nb_snapshot = session->snapshot.nb_snapshot; + + ret = record_ust_snapshot(usess, &tmp_output, session, + wait, nb_streams); + if (ret != LTTNG_OK) { rcu_read_unlock(); goto error; } + snapshot_success = 1; } rcu_read_unlock(); } } -error: - if (tmp_sout) { - snapshot_output_destroy(tmp_sout); + if (snapshot_success) { + session->snapshot.nb_snapshot++; } + +error: return ret; }