X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fkernel.c;h=5d4f61451a53cf3d2d6cd8da21feeec086ad9e94;hp=154b2d62306df654d63a148ebf5005bc6d09218c;hb=4ce514c43483ba24fd935024da5b7aca681a7e52;hpb=6dc3064a30b0cc7cfa9fdd22da1963525dfb7388 diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 154b2d623..5d4f61451 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -754,6 +754,32 @@ void kernel_destroy_session(struct ltt_kernel_session *ksess) DBG("Tearing down kernel session"); + /* + * Destroy channels on the consumer if in no output mode because the + * streams are in *no* monitor mode so we have to send a command to clean + * them up or else they leaked. + */ + if (!ksess->output_traces) { + int ret; + struct consumer_socket *socket; + struct lttng_ht_iter iter; + + /* For each consumer socket. */ + cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter, + socket, node.node) { + struct ltt_kernel_channel *chan; + + /* For each channel, ask the consumer to destroy it. */ + cds_list_for_each_entry(chan, &ksess->channel_list.head, list) { + ret = kernel_consumer_destroy_channel(socket, chan); + if (ret < 0) { + /* Consumer is probably dead. Use next socket. */ + continue; + } + } + } + } + /* Close any relayd session */ consumer_output_send_destroy_relayd(ksess->consumer); @@ -793,15 +819,16 @@ void kernel_destroy_channel(struct ltt_kernel_channel *kchan) /* * Take a snapshot for a given kernel session. * - * Return 0 on success or else a negative value. + * Return 0 on success or else return a LTTNG_ERR code. */ int kernel_snapshot_record(struct ltt_kernel_session *ksess, - struct snapshot_output *output, int wait) + struct snapshot_output *output, int wait, unsigned int nb_streams) { - int ret, saved_metadata_fd; + int err, ret, saved_metadata_fd; struct consumer_socket *socket; struct lttng_ht_iter iter; struct ltt_kernel_metadata *saved_metadata; + uint64_t max_size_per_stream = 0; assert(ksess); assert(ksess->consumer); @@ -827,13 +854,17 @@ int kernel_snapshot_record(struct ltt_kernel_session *ksess, goto error_open_stream; } + if (output->max_size > 0 && nb_streams > 0) { + max_size_per_stream = output->max_size / nb_streams; + } + /* Send metadata to consumer and snapshot everything. */ cds_lfht_for_each_entry(ksess->consumer->socks->ht, &iter.iter, socket, node.node) { struct consumer_output *saved_output; struct ltt_kernel_channel *chan; /* Code flow error */ - assert(socket->fd >= 0); + assert(socket->fd); /* * Temporarly switch consumer output for our snapshot output. As long @@ -844,10 +875,9 @@ int kernel_snapshot_record(struct ltt_kernel_session *ksess, pthread_mutex_lock(socket->lock); /* This stream must not be monitored by the consumer. */ - ret = kernel_consumer_add_metadata(socket, ksess, 1); - ret = 0; + ret = kernel_consumer_add_metadata(socket, ksess, 0); pthread_mutex_unlock(socket->lock); - /* Put back the savec consumer output into the session. */ + /* Put back the saved consumer output into the session. */ ksess->consumer = saved_output; if (ret < 0) { ret = LTTNG_ERR_KERN_CONSUMER_FAIL; @@ -856,27 +886,53 @@ int kernel_snapshot_record(struct ltt_kernel_session *ksess, /* For each channel, ask the consumer to snapshot it. */ cds_list_for_each_entry(chan, &ksess->channel_list.head, list) { + if (max_size_per_stream && + chan->channel->attr.subbuf_size > max_size_per_stream) { + ret = LTTNG_ERR_INVALID; + DBG3("Kernel snapshot record maximum stream size %" PRIu64 + " is smaller than subbuffer size of %" PRIu64, + max_size_per_stream, chan->channel->attr.subbuf_size); + (void) kernel_consumer_destroy_metadata(socket, + ksess->metadata); + goto error_consumer; + } + + pthread_mutex_lock(socket->lock); ret = consumer_snapshot_channel(socket, chan->fd, output, 0, - ksess->uid, ksess->gid, wait); + ksess->uid, ksess->gid, + DEFAULT_KERNEL_TRACE_DIR, wait, + max_size_per_stream); + pthread_mutex_unlock(socket->lock); if (ret < 0) { ret = LTTNG_ERR_KERN_CONSUMER_FAIL; + (void) kernel_consumer_destroy_metadata(socket, + ksess->metadata); goto error_consumer; } } /* Snapshot metadata, */ + pthread_mutex_lock(socket->lock); ret = consumer_snapshot_channel(socket, ksess->metadata->fd, output, - 1, ksess->uid, ksess->gid, wait); + 1, ksess->uid, ksess->gid, + DEFAULT_KERNEL_TRACE_DIR, wait, max_size_per_stream); + pthread_mutex_unlock(socket->lock); if (ret < 0) { ret = LTTNG_ERR_KERN_CONSUMER_FAIL; goto error_consumer; } + + /* + * The metadata snapshot is done, ask the consumer to destroy it since + * it's not monitored on the consumer side. + */ + (void) kernel_consumer_destroy_metadata(socket, ksess->metadata); } error_consumer: /* Close newly opened metadata stream. It's now on the consumer side. */ - ret = close(ksess->metadata_stream_fd); - if (ret < 0) { + err = close(ksess->metadata_stream_fd); + if (err < 0) { PERROR("close snapshot kernel"); }