X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fkernel.c;h=154b2d62306df654d63a148ebf5005bc6d09218c;hp=69665058a0e098c0b7a2bbd9dc1042d6f7b25f0a;hb=6dc3064a30b0cc7cfa9fdd22da1963525dfb7388;hpb=57f272edb1b4ccb8869e3f5b69eb5461bcb56101 diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 69665058a..154b2d623 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -30,6 +30,7 @@ #include "consumer.h" #include "kernel.h" +#include "kernel-consumer.h" #include "kern-modules.h" /* @@ -788,3 +789,104 @@ void kernel_destroy_channel(struct ltt_kernel_channel *kchan) ksess->channel_count--; } } + +/* + * Take a snapshot for a given kernel session. + * + * Return 0 on success or else a negative value. + */ +int kernel_snapshot_record(struct ltt_kernel_session *ksess, + struct snapshot_output *output, int wait) +{ + int ret, saved_metadata_fd; + struct consumer_socket *socket; + struct lttng_ht_iter iter; + struct ltt_kernel_metadata *saved_metadata; + + assert(ksess); + assert(ksess->consumer); + assert(output); + + DBG("Kernel snapshot record started"); + + /* Save current metadata since the following calls will change it. */ + saved_metadata = ksess->metadata; + saved_metadata_fd = ksess->metadata_stream_fd; + + rcu_read_lock(); + + ret = kernel_open_metadata(ksess); + if (ret < 0) { + ret = LTTNG_ERR_KERN_META_FAIL; + goto error; + } + + ret = kernel_open_metadata_stream(ksess); + if (ret < 0) { + ret = LTTNG_ERR_KERN_META_FAIL; + goto error_open_stream; + } + + /* 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); + + /* + * Temporarly switch consumer output for our snapshot output. As long + * as the session lock is taken, this is safe. + */ + saved_output = ksess->consumer; + ksess->consumer = output->consumer; + + pthread_mutex_lock(socket->lock); + /* This stream must not be monitored by the consumer. */ + ret = kernel_consumer_add_metadata(socket, ksess, 1); + ret = 0; + pthread_mutex_unlock(socket->lock); + /* Put back the savec consumer output into the session. */ + ksess->consumer = saved_output; + if (ret < 0) { + ret = LTTNG_ERR_KERN_CONSUMER_FAIL; + goto error_consumer; + } + + /* For each channel, ask the consumer to snapshot it. */ + cds_list_for_each_entry(chan, &ksess->channel_list.head, list) { + ret = consumer_snapshot_channel(socket, chan->fd, output, 0, + ksess->uid, ksess->gid, wait); + if (ret < 0) { + ret = LTTNG_ERR_KERN_CONSUMER_FAIL; + goto error_consumer; + } + } + + /* Snapshot metadata, */ + ret = consumer_snapshot_channel(socket, ksess->metadata->fd, output, + 1, ksess->uid, ksess->gid, wait); + if (ret < 0) { + ret = LTTNG_ERR_KERN_CONSUMER_FAIL; + goto error_consumer; + } + } + +error_consumer: + /* Close newly opened metadata stream. It's now on the consumer side. */ + ret = close(ksess->metadata_stream_fd); + if (ret < 0) { + PERROR("close snapshot kernel"); + } + +error_open_stream: + trace_kernel_destroy_metadata(ksess->metadata); +error: + /* Restore metadata state.*/ + ksess->metadata = saved_metadata; + ksess->metadata_stream_fd = saved_metadata_fd; + + rcu_read_unlock(); + return ret; +}