X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fkernel.cpp;h=5b4fc086bde52ce333f8cf72cf9f3d627b0cc000;hp=b4b8dab278caa8235e373d0f7b69aacacd062504;hb=HEAD;hpb=28ab034a2c3582d07d3423d2d746731f87d3969f diff --git a/src/bin/lttng-sessiond/kernel.cpp b/src/bin/lttng-sessiond/kernel.cpp index b4b8dab27..4cc51a279 100644 --- a/src/bin/lttng-sessiond/kernel.cpp +++ b/src/bin/lttng-sessiond/kernel.cpp @@ -16,7 +16,6 @@ #include "lttng-syscall.hpp" #include "modprobe.hpp" #include "notification-thread-commands.hpp" -#include "rotate.hpp" #include "sessiond-config.hpp" #include "tracker.hpp" #include "utils.hpp" @@ -25,9 +24,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -49,18 +50,71 @@ #include #include +namespace { /* * Key used to reference a channel between the sessiond and the consumer. This * is only read and updated with the session_list lock held. */ -static uint64_t next_kernel_channel_key; +uint64_t next_kernel_channel_key; -static const char *module_proc_lttng = "/proc/lttng"; +const char *module_proc_lttng = "/proc/lttng"; -static int kernel_tracer_fd = -1; -static int kernel_tracer_event_notifier_group_fd = -1; -static int kernel_tracer_event_notifier_group_notification_fd = -1; -static struct cds_lfht *kernel_token_to_event_notifier_rule_ht; +int kernel_tracer_fd = -1; +nonstd::optional kernel_tracer_status = nonstd::nullopt; +int kernel_tracer_event_notifier_group_fd = -1; +int kernel_tracer_event_notifier_group_notification_fd = -1; +struct cds_lfht *kernel_token_to_event_notifier_rule_ht; + +const char *kernel_tracer_status_to_str(lttng_kernel_tracer_status status) +{ + switch (status) { + case LTTNG_KERNEL_TRACER_STATUS_INITIALIZED: + return "LTTNG_KERNEL_TRACER_STATUS_INITIALIZED"; + case LTTNG_KERNEL_TRACER_STATUS_ERR_UNKNOWN: + return "LTTNG_KERNEL_TRACER_STATUS_ERR_UNKNOWN"; + case LTTNG_KERNEL_TRACER_STATUS_ERR_NEED_ROOT: + return "LTTNG_KERNEL_TRACER_STATUS_ERR_NEED_ROOT"; + case LTTNG_KERNEL_TRACER_STATUS_ERR_NOTIFIER: + return "LTTNG_KERNEL_TRACER_STATUS_ERR_NOTIFIER"; + case LTTNG_KERNEL_TRACER_STATUS_ERR_OPEN_PROC_LTTNG: + return "LTTNG_KERNEL_TRACER_STATUS_ERR_OPEN_PROC_LTTNG"; + case LTTNG_KERNEL_TRACER_STATUS_ERR_VERSION_MISMATCH: + return "LTTNG_KERNEL_TRACER_STATUS_ERR_VERSION_MISMATCH"; + case LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_UNKNOWN: + return "LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_UNKNOWN"; + case LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_MISSING: + return "LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_MISSING"; + case LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_SIGNATURE: + return "LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_SIGNATURE"; + } + + abort(); +} + +/* + * On some architectures, calling convention details are embedded in the symbol + * addresses. Uprobe requires a "clean" symbol offset (or at least, an address + * where an instruction boundary would be legal) to add + * instrumentation. sanitize_uprobe_offset implements that sanitization logic on + * a per-architecture basis. + */ +#if defined(__arm__) || defined(__aarch64__) +static inline uint64_t sanitize_uprobe_offset(uint64_t raw_offset) +{ + /* + * The least significant bit is used when branching to switch to thumb + * ISA. However, it's an invalid address for us; mask the least + * significant bit. + */ + return raw_offset &= ~0b1; +} +#else /* defined(__arm__) || defined(__aarch64__) */ +static inline uint64_t sanitize_uprobe_offset(uint64_t raw_offset) +{ + return raw_offset; +} +#endif +} /* namespace */ /* * Add context on a kernel channel. @@ -97,7 +151,7 @@ int kernel_add_channel_context(struct ltt_kernel_channel *chan, struct ltt_kerne end: cds_list_add_tail(&ctx->list, &chan->ctx_list); ctx->in_list = true; - ctx = NULL; + ctx = nullptr; error: if (ctx) { trace_kernel_destroy_context(ctx); @@ -118,7 +172,7 @@ int kernel_create_session(struct ltt_session *session) /* Allocate data structure */ lks = trace_kernel_create_session(); - if (lks == NULL) { + if (lks == nullptr) { ret = -1; goto error; } @@ -189,7 +243,7 @@ int kernel_create_channel(struct ltt_kernel_session *session, struct lttng_chann /* Allocate kernel channel */ lkc = trace_kernel_create_channel(chan); - if (lkc == NULL) { + if (lkc == nullptr) { goto error; } @@ -300,8 +354,8 @@ static int extract_userspace_probe_offset_function_elf( { int fd; int ret = 0; - const char *symbol = NULL; - const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; + const char *symbol = nullptr; + const struct lttng_userspace_probe_location_lookup_method *lookup = nullptr; enum lttng_userspace_probe_location_lookup_method_type lookup_method_type; LTTNG_ASSERT(lttng_userspace_probe_location_get_type(probe_location) == @@ -360,8 +414,8 @@ static int extract_userspace_probe_offset_tracepoint_sdt( uint32_t *offsets_count) { enum lttng_userspace_probe_location_lookup_method_type lookup_method_type; - const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; - const char *probe_name = NULL, *provider_name = NULL; + const struct lttng_userspace_probe_location_lookup_method *lookup = nullptr; + const char *probe_name = nullptr, *provider_name = nullptr; int ret = 0; int fd, i; @@ -428,7 +482,7 @@ static int userspace_probe_add_callsite(const struct lttng_userspace_probe_locat gid_t gid, int fd) { - const struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL; + const struct lttng_userspace_probe_location_lookup_method *lookup_method = nullptr; enum lttng_userspace_probe_location_lookup_method_type type; int ret; @@ -451,7 +505,7 @@ static int userspace_probe_add_callsite(const struct lttng_userspace_probe_locat goto end; } - callsite.u.uprobe.offset = offset; + callsite.u.uprobe.offset = sanitize_uprobe_offset(offset); ret = kernctl_add_callsite(fd, &callsite); if (ret) { WARN("Failed to add callsite to ELF userspace probe."); @@ -463,7 +517,7 @@ static int userspace_probe_add_callsite(const struct lttng_userspace_probe_locat case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: { int i; - uint64_t *offsets = NULL; + uint64_t *offsets = nullptr; uint32_t offsets_count; struct lttng_kernel_abi_event_callsite callsite; @@ -478,7 +532,7 @@ static int userspace_probe_add_callsite(const struct lttng_userspace_probe_locat goto end; } for (i = 0; i < offsets_count; i++) { - callsite.u.uprobe.offset = offsets[i]; + callsite.u.uprobe.offset = sanitize_uprobe_offset(offsets[i]); ret = kernctl_add_callsite(fd, &callsite); if (ret) { WARN("Failed to add callsite to SDT userspace probe"); @@ -507,7 +561,7 @@ static int userspace_probe_event_add_callsites(struct lttng_event *ev, int fd) { int ret; - const struct lttng_userspace_probe_location *location = NULL; + const struct lttng_userspace_probe_location *location = nullptr; LTTNG_ASSERT(ev); LTTNG_ASSERT(ev->type == LTTNG_EVENT_USERSPACE_PROBE); @@ -538,7 +592,7 @@ static int userspace_probe_event_rule_add_callsites(const struct lttng_event_rul int ret; enum lttng_event_rule_status status; enum lttng_event_rule_type event_rule_type; - const struct lttng_userspace_probe_location *location = NULL; + const struct lttng_userspace_probe_location *location = nullptr; LTTNG_ASSERT(rule); LTTNG_ASSERT(creds); @@ -691,7 +745,7 @@ int kernel_disable_channel(struct ltt_kernel_channel *chan) goto error; } - chan->enabled = 0; + chan->enabled = false; DBG("Kernel channel %s disabled (fd: %d, key: %" PRIu64 ")", chan->channel->name, chan->fd, @@ -718,7 +772,7 @@ int kernel_enable_channel(struct ltt_kernel_channel *chan) goto error; } - chan->enabled = 1; + chan->enabled = true; DBG("Kernel channel %s enabled (fd: %d, key: %" PRIu64 ")", chan->channel->name, chan->fd, @@ -752,7 +806,7 @@ int kernel_enable_event(struct ltt_kernel_event *event) goto error; } - event->enabled = 1; + event->enabled = true; DBG("Kernel event %s enabled (fd: %d)", event->event->name, event->fd); return 0; @@ -778,7 +832,7 @@ int kernel_disable_event(struct ltt_kernel_event *event) goto error; } - event->enabled = 0; + event->enabled = false; DBG("Kernel event %s disabled (fd: %d)", event->event->name, event->fd); return 0; @@ -796,9 +850,8 @@ static int kernel_disable_event_notifier_rule(struct ltt_kernel_event_notifier_r LTTNG_ASSERT(event); - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; cds_lfht_del(kernel_token_to_event_notifier_rule_ht, &event->ht_node); - rcu_read_unlock(); ret = kernctl_disable(event->fd); if (ret < 0) { @@ -808,7 +861,7 @@ static int kernel_disable_event_notifier_rule(struct ltt_kernel_event_notifier_r goto error; } - event->enabled = 0; + event->enabled = false; DBG("Disabled kernel event notifier: fd = %d, token = %" PRIu64, event->fd, event->token); error: @@ -833,7 +886,7 @@ _kernel_get_process_attr_tracker(struct ltt_kernel_session *session, case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: return session->tracker_vgid; default: - return NULL; + return nullptr; } } @@ -1180,13 +1233,13 @@ end: int kernel_open_metadata(struct ltt_kernel_session *session) { int ret; - struct ltt_kernel_metadata *lkm = NULL; + struct ltt_kernel_metadata *lkm = nullptr; LTTNG_ASSERT(session); /* Allocate kernel metadata */ lkm = trace_kernel_create_metadata(); - if (lkm == NULL) { + if (lkm == nullptr) { goto error; } @@ -1242,7 +1295,7 @@ error: /* * Make a kernel wait to make sure in-flight probe have completed. */ -void kernel_wait_quiescent(void) +void kernel_wait_quiescent() { int ret; int fd = kernel_tracer_fd; @@ -1338,7 +1391,7 @@ int kernel_open_channel_stream(struct ltt_kernel_channel *channel) while ((ret = kernctl_create_stream(channel->fd)) >= 0) { lks = trace_kernel_create_stream(channel->channel->name, channel->stream_count); - if (lks == NULL) { + if (lks == nullptr) { ret = close(ret); if (ret) { PERROR("close"); @@ -1418,7 +1471,7 @@ ssize_t kernel_list_events(struct lttng_event **events) } fp = fdopen(fd, "r"); - if (fp == NULL) { + if (fp == nullptr) { PERROR("kernel tracepoint list fdopen"); goto error_fp; } @@ -1429,7 +1482,7 @@ ssize_t kernel_list_events(struct lttng_event **events) */ nbmem = KERNEL_EVENT_INIT_LIST_SIZE; elist = calloc(nbmem); - if (elist == NULL) { + if (elist == nullptr) { PERROR("alloc list events"); count = -ENOMEM; goto end; @@ -1444,7 +1497,7 @@ ssize_t kernel_list_events(struct lttng_event **events) DBG("Reallocating event list from %zu to %zu bytes", nbmem, new_nbmem); new_elist = (lttng_event *) realloc(elist, new_nbmem * sizeof(struct lttng_event)); - if (new_elist == NULL) { + if (new_elist == nullptr) { PERROR("realloc list events"); free(event); free(elist); @@ -1534,7 +1587,7 @@ error: /* * Kernel work-arounds called at the start of sessiond main(). */ -int init_kernel_workarounds(void) +int init_kernel_workarounds() { int ret; FILE *fp; @@ -1571,7 +1624,7 @@ void kernel_destroy_session(struct ltt_kernel_session *ksess) { struct lttng_trace_chunk *trace_chunk; - if (ksess == NULL) { + if (ksess == nullptr) { DBG3("No kernel session when tearing down session"); return; } @@ -1590,7 +1643,8 @@ void kernel_destroy_session(struct ltt_kernel_session *ksess) struct lttng_ht_iter iter; /* For each consumer socket. */ - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; + cds_lfht_for_each_entry ( ksess->consumer->socks->ht, &iter.iter, socket, node.node) { struct ltt_kernel_channel *chan; @@ -1604,7 +1658,6 @@ void kernel_destroy_session(struct ltt_kernel_session *ksess) } } } - rcu_read_unlock(); } /* Close any relayd session */ @@ -1617,7 +1670,7 @@ void kernel_destroy_session(struct ltt_kernel_session *ksess) /* Teardown of data required by destroy notifiers. */ void kernel_free_session(struct ltt_kernel_session *ksess) { - if (ksess == NULL) { + if (ksess == nullptr) { return; } trace_kernel_free_session(ksess); @@ -1628,7 +1681,7 @@ void kernel_free_session(struct ltt_kernel_session *ksess) */ void kernel_destroy_channel(struct ltt_kernel_channel *kchan) { - struct ltt_kernel_session *ksess = NULL; + struct ltt_kernel_session *ksess = nullptr; LTTNG_ASSERT(kchan); LTTNG_ASSERT(kchan->channel); @@ -1667,7 +1720,7 @@ enum lttng_error_code kernel_snapshot_record(struct ltt_kernel_session *ksess, struct consumer_socket *socket; struct lttng_ht_iter iter; struct ltt_kernel_metadata *saved_metadata; - char *trace_path = NULL; + char *trace_path = nullptr; size_t consumer_path_offset = 0; LTTNG_ASSERT(ksess); @@ -1680,8 +1733,6 @@ enum lttng_error_code kernel_snapshot_record(struct ltt_kernel_session *ksess, saved_metadata = ksess->metadata; saved_metadata_fd = ksess->metadata_stream_fd; - rcu_read_lock(); - ret = kernel_open_metadata(ksess); if (ret < 0) { status = LTTNG_ERR_KERN_META_FAIL; @@ -1699,49 +1750,56 @@ enum lttng_error_code kernel_snapshot_record(struct ltt_kernel_session *ksess, status = LTTNG_ERR_INVALID; goto error; } - /* Send metadata to consumer and snapshot everything. */ - cds_lfht_for_each_entry (output->socks->ht, &iter.iter, socket, node.node) { - struct ltt_kernel_channel *chan; - pthread_mutex_lock(socket->lock); - /* This stream must not be monitored by the consumer. */ - ret = kernel_consumer_add_metadata(socket, ksess, 0); - pthread_mutex_unlock(socket->lock); - if (ret < 0) { - status = LTTNG_ERR_KERN_META_FAIL; - goto error_consumer; - } + { + /* Send metadata to consumer and snapshot everything. */ + lttng::urcu::read_lock_guard read_lock; + + cds_lfht_for_each_entry (output->socks->ht, &iter.iter, socket, node.node) { + struct ltt_kernel_channel *chan; + + pthread_mutex_lock(socket->lock); + /* This stream must not be monitored by the consumer. */ + ret = kernel_consumer_add_metadata(socket, ksess, 0); + pthread_mutex_unlock(socket->lock); + if (ret < 0) { + status = LTTNG_ERR_KERN_META_FAIL; + goto error_consumer; + } - /* For each channel, ask the consumer to snapshot it. */ - cds_list_for_each_entry (chan, &ksess->channel_list.head, list) { + /* For each channel, ask the consumer to snapshot it. */ + cds_list_for_each_entry (chan, &ksess->channel_list.head, list) { + status = + consumer_snapshot_channel(socket, + chan->key, + output, + 0, + &trace_path[consumer_path_offset], + nb_packets_per_stream); + if (status != LTTNG_OK) { + (void) kernel_consumer_destroy_metadata(socket, + ksess->metadata); + goto error_consumer; + } + } + + /* Snapshot metadata, */ status = consumer_snapshot_channel(socket, - chan->key, + ksess->metadata->key, output, - 0, + 1, &trace_path[consumer_path_offset], - nb_packets_per_stream); + 0); if (status != LTTNG_OK) { - (void) kernel_consumer_destroy_metadata(socket, ksess->metadata); goto error_consumer; } - } - /* Snapshot metadata, */ - status = consumer_snapshot_channel(socket, - ksess->metadata->key, - output, - 1, - &trace_path[consumer_path_offset], - 0); - if (status != LTTNG_OK) { - 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); } - - /* - * 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: @@ -1757,7 +1815,6 @@ error: /* Restore metadata state.*/ ksess->metadata = saved_metadata; ksess->metadata_stream_fd = saved_metadata_fd; - rcu_read_unlock(); free(trace_path); return status; } @@ -1799,7 +1856,7 @@ error: * Return 1 on success, 0 when feature is not supported, negative value in case * of errors. */ -int kernel_supports_ring_buffer_snapshot_sample_positions(void) +int kernel_supports_ring_buffer_snapshot_sample_positions() { /* * RING_BUFFER_SNAPSHOT_SAMPLE_POSITIONS was introduced in 2.3 @@ -1813,7 +1870,7 @@ int kernel_supports_ring_buffer_snapshot_sample_positions(void) * Return 1 on success, 0 when feature is not supported, negative value in case * of errors. */ -int kernel_supports_ring_buffer_packet_sequence_number(void) +int kernel_supports_ring_buffer_packet_sequence_number() { /* * Packet sequence number was introduced in LTTng 2.8, @@ -1828,7 +1885,7 @@ int kernel_supports_ring_buffer_packet_sequence_number(void) * Return 1 on success, 0 when feature is not supported, negative value in case * of errors. */ -int kernel_supports_event_notifiers(void) +int kernel_supports_event_notifiers() { /* * Event notifiers were introduced in LTTng 2.13, lttng-modules ABI 2.6. @@ -1854,45 +1911,47 @@ enum lttng_error_code kernel_rotate_session(struct ltt_session *session) DBG("Rotate kernel session %s started (session %" PRIu64 ")", session->name, session->id); - rcu_read_lock(); + { + /* + * Note that this loop will end after one iteration given that there is + * only one kernel consumer. + */ + lttng::urcu::read_lock_guard read_lock; + + cds_lfht_for_each_entry ( + ksess->consumer->socks->ht, &iter.iter, socket, node.node) { + struct ltt_kernel_channel *chan; - /* - * Note that this loop will end after one iteration given that there is - * only one kernel consumer. - */ - 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 rotate it. */ - cds_list_for_each_entry (chan, &ksess->channel_list.head, list) { - DBG("Rotate kernel channel %" PRIu64 ", session %s", - chan->key, - session->name); + /* For each channel, ask the consumer to rotate it. */ + cds_list_for_each_entry (chan, &ksess->channel_list.head, list) { + DBG("Rotate kernel channel %" PRIu64 ", session %s", + chan->key, + session->name); + ret = consumer_rotate_channel(socket, + chan->key, + ksess->consumer, + /* is_metadata_channel */ false); + if (ret < 0) { + status = LTTNG_ERR_ROTATION_FAIL_CONSUMER; + goto error; + } + } + + /* + * Rotate the metadata channel. + */ ret = consumer_rotate_channel(socket, - chan->key, + ksess->metadata->key, ksess->consumer, - /* is_metadata_channel */ false); + /* is_metadata_channel */ true); if (ret < 0) { status = LTTNG_ERR_ROTATION_FAIL_CONSUMER; goto error; } } - - /* - * Rotate the metadata channel. - */ - ret = consumer_rotate_channel(socket, - ksess->metadata->key, - ksess->consumer, - /* is_metadata_channel */ true); - if (ret < 0) { - status = LTTNG_ERR_ROTATION_FAIL_CONSUMER; - goto error; - } } error: - rcu_read_unlock(); return status; } @@ -1901,7 +1960,7 @@ enum lttng_error_code kernel_create_channel_subdirectories(const struct ltt_kern enum lttng_error_code ret = LTTNG_OK; enum lttng_trace_chunk_status chunk_status; - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; LTTNG_ASSERT(ksess->current_trace_chunk); /* @@ -1915,21 +1974,68 @@ enum lttng_error_code kernel_create_channel_subdirectories(const struct ltt_kern goto error; } error: - rcu_read_unlock(); return ret; } +/* + * Get current kernel tracer status + */ +enum lttng_kernel_tracer_status get_kernel_tracer_status() +{ + if (!kernel_tracer_status) { + return LTTNG_KERNEL_TRACER_STATUS_ERR_UNKNOWN; + } + + return *kernel_tracer_status; +} + +/* + * Sets the kernel tracer status based on the positive errno code + */ +void set_kernel_tracer_status_from_modules_ret(int code) +{ + switch (code) { + case ENOENT: + { + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_MISSING); + break; + } + case ENOKEY: + case EKEYEXPIRED: + case EKEYREVOKED: + case EKEYREJECTED: + { + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_SIGNATURE); + break; + } + default: + { + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_MODULES_UNKNOWN); + break; + } + } +} + /* * Setup necessary data for kernel tracer action. */ -int init_kernel_tracer(void) +int init_kernel_tracer() { int ret; bool is_root = !getuid(); + const auto log_status_on_exit = lttng::make_scope_exit([]() noexcept { + DBG_FMT("Kernel tracer status set to `{}`", + kernel_tracer_status_to_str(*kernel_tracer_status)); + }); + /* Modprobe lttng kernel modules */ ret = modprobe_lttng_control(); if (ret < 0) { + set_kernel_tracer_status_from_modules_ret(-ret); goto error; } @@ -1937,17 +2043,22 @@ int init_kernel_tracer(void) kernel_tracer_fd = open(module_proc_lttng, O_RDWR); if (kernel_tracer_fd < 0) { DBG("Failed to open %s", module_proc_lttng); + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_OPEN_PROC_LTTNG); goto error_open; } /* Validate kernel version */ ret = kernel_validate_version(&the_kernel_tracer_version, &the_kernel_tracer_abi_version); if (ret < 0) { + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_VERSION_MISMATCH); goto error_version; } ret = modprobe_lttng_data(); if (ret < 0) { + set_kernel_tracer_status_from_modules_ret(-ret); goto error_modules; } @@ -1964,6 +2075,8 @@ int init_kernel_tracer(void) ret = kernel_supports_event_notifiers(); if (ret < 0) { ERR("Failed to check for kernel tracer event notifier support"); + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_NOTIFIER); goto error_modules; } ret = kernel_create_event_notifier_group(&kernel_tracer_event_notifier_group_fd); @@ -1978,6 +2091,8 @@ int init_kernel_tracer(void) &kernel_tracer_event_notifier_group_notification_fd); if (error_code_ret != LTTNG_OK) { + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_NOTIFIER); goto error_modules; } @@ -1986,12 +2101,16 @@ int init_kernel_tracer(void) if (error_accounting_status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) { ERR("Failed to initialize event notifier error accounting for kernel tracer"); error_code_ret = LTTNG_ERR_EVENT_NOTIFIER_ERROR_ACCOUNTING; + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_NOTIFIER); goto error_modules; } kernel_token_to_event_notifier_rule_ht = cds_lfht_new( - DEFAULT_HT_SIZE, 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL); + DEFAULT_HT_SIZE, 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, nullptr); if (!kernel_token_to_event_notifier_rule_ht) { + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_NOTIFIER); goto error_token_ht; } } @@ -2007,6 +2126,8 @@ int init_kernel_tracer(void) "work for this session daemon."); } + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_INITIALIZED); return 0; error_version: @@ -2051,13 +2172,15 @@ error: WARN("No kernel tracer available"); kernel_tracer_fd = -1; if (!is_root) { + kernel_tracer_status = nonstd::optional( + LTTNG_KERNEL_TRACER_STATUS_ERR_NEED_ROOT); return LTTNG_ERR_NEED_ROOT_SESSIOND; } else { return LTTNG_ERR_KERN_NA; } } -void cleanup_kernel_tracer(void) +void cleanup_kernel_tracer() { DBG2("Closing kernel event notifier group notification file descriptor"); if (kernel_tracer_event_notifier_group_notification_fd >= 0) { @@ -2078,7 +2201,7 @@ void cleanup_kernel_tracer(void) } if (kernel_token_to_event_notifier_rule_ht) { - const int ret = cds_lfht_destroy(kernel_token_to_event_notifier_rule_ht, NULL); + const int ret = cds_lfht_destroy(kernel_token_to_event_notifier_rule_ht, nullptr); LTTNG_ASSERT(ret == 0); } @@ -2106,10 +2229,11 @@ void cleanup_kernel_tracer(void) kernel_tracer_fd = -1; } + kernel_tracer_status = nonstd::nullopt; free(syscall_table); } -bool kernel_tracer_is_initialized(void) +bool kernel_tracer_is_initialized() { return kernel_tracer_fd >= 0; } @@ -2132,49 +2256,52 @@ enum lttng_error_code kernel_clear_session(struct ltt_session *session) DBG("Clear kernel session %s (session %" PRIu64 ")", session->name, session->id); - rcu_read_lock(); - if (ksess->active) { ERR("Expecting inactive session %s (%" PRIu64 ")", session->name, session->id); status = LTTNG_ERR_FATAL; goto end; } - /* - * Note that this loop will end after one iteration given that there is - * only one kernel consumer. - */ - 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 clear it. */ - cds_list_for_each_entry (chan, &ksess->channel_list.head, list) { - DBG("Clear kernel channel %" PRIu64 ", session %s", - chan->key, - session->name); - ret = consumer_clear_channel(socket, chan->key); - if (ret < 0) { - goto error; + { + /* + * Note that this loop will end after one iteration given that there is + * only one kernel consumer. + */ + lttng::urcu::read_lock_guard read_lock; + + 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 clear it. */ + cds_list_for_each_entry (chan, &ksess->channel_list.head, list) { + DBG("Clear kernel channel %" PRIu64 ", session %s", + chan->key, + session->name); + ret = consumer_clear_channel(socket, chan->key); + if (ret < 0) { + goto error; + } + } + + if (!ksess->metadata) { + /* + * Nothing to do for the metadata. + * This is a snapshot session. + * The metadata is genererated on the fly. + */ + continue; } - } - if (!ksess->metadata) { /* - * Nothing to do for the metadata. - * This is a snapshot session. - * The metadata is genererated on the fly. + * Clear the metadata channel. + * Metadata channel is not cleared per se but we still need to + * perform a rotation operation on it behind the scene. */ - continue; - } - - /* - * Clear the metadata channel. - * Metadata channel is not cleared per se but we still need to - * perform a rotation operation on it behind the scene. - */ - ret = consumer_clear_channel(socket, ksess->metadata->key); - if (ret < 0) { - goto error; + ret = consumer_clear_channel(socket, ksess->metadata->key); + if (ret < 0) { + goto error; + } } } @@ -2189,7 +2316,6 @@ error: break; } end: - rcu_read_unlock(); return status; } @@ -2284,8 +2410,8 @@ static enum lttng_error_code kernel_create_event_notifier_rule( struct ltt_kernel_event_notifier_rule *event_notifier_rule; struct lttng_kernel_abi_event_notifier kernel_event_notifier = {}; unsigned int capture_bytecode_count = 0, i; - const struct lttng_condition *condition = NULL; - const struct lttng_event_rule *event_rule = NULL; + const struct lttng_condition *condition = nullptr; + const struct lttng_event_rule *event_rule = nullptr; enum lttng_condition_status cond_status; LTTNG_ASSERT(trigger); @@ -2392,7 +2518,7 @@ static enum lttng_error_code kernel_create_event_notifier_rule( lttng_condition_event_rule_matches_get_capture_bytecode_at_index(condition, i); - if (capture_bytecode == NULL) { + if (capture_bytecode == nullptr) { ERR("Unexpected NULL capture bytecode on condition"); error_code_ret = LTTNG_ERR_KERN_ENABLE_FAIL; goto capture_error; @@ -2422,11 +2548,12 @@ static enum lttng_error_code kernel_create_event_notifier_rule( } /* Add trigger to kernel token mapping in the hash table. */ - rcu_read_lock(); - cds_lfht_add(kernel_token_to_event_notifier_rule_ht, - hash_trigger(trigger), - &event_notifier_rule->ht_node); - rcu_read_unlock(); + { + lttng::urcu::read_lock_guard read_lock; + cds_lfht_add(kernel_token_to_event_notifier_rule_ht, + hash_trigger(trigger), + &event_notifier_rule->ht_node); + } DBG("Created kernel event notifier: name = '%s', fd = %d", kernel_event_notifier.event.name, @@ -2488,7 +2615,7 @@ enum lttng_error_code kernel_unregister_event_notifier(const struct lttng_trigge enum lttng_error_code error_code_ret; int ret; - rcu_read_lock(); + lttng::urcu::read_lock_guard read_lock; cds_lfht_lookup(kernel_token_to_event_notifier_rule_ht, hash_trigger(trigger), @@ -2515,12 +2642,11 @@ enum lttng_error_code kernel_unregister_event_notifier(const struct lttng_trigge error_code_ret = LTTNG_OK; error: - rcu_read_unlock(); return error_code_ret; } -int kernel_get_notification_fd(void) +int kernel_get_notification_fd() { return kernel_tracer_event_notifier_group_notification_fd; }