#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"
#include <common/sessiond-comm/sessiond-comm.hpp>
#include <common/trace-chunk.hpp>
#include <common/tracker.hpp>
+#include <common/urcu.hpp>
#include <common/utils.hpp>
#include <lttng/condition/event-rule-matches-internal.hpp>
static int kernel_tracer_event_notifier_group_notification_fd = -1;
static struct cds_lfht *kernel_token_to_event_notifier_rule_ht;
+namespace {
+/*
+ * 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.
*
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.");
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");
goto error;
}
- chan->enabled = 0;
+ chan->enabled = false;
DBG("Kernel channel %s disabled (fd: %d, key: %" PRIu64 ")",
chan->channel->name,
chan->fd,
goto error;
}
- chan->enabled = 1;
+ chan->enabled = true;
DBG("Kernel channel %s enabled (fd: %d, key: %" PRIu64 ")",
chan->channel->name,
chan->fd,
goto error;
}
- event->enabled = 1;
+ event->enabled = true;
DBG("Kernel event %s enabled (fd: %d)", event->event->name, event->fd);
return 0;
goto error;
}
- event->enabled = 0;
+ event->enabled = false;
DBG("Kernel event %s disabled (fd: %d)", event->event->name, event->fd);
return 0;
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) {
goto error;
}
- event->enabled = 0;
+ event->enabled = false;
DBG("Disabled kernel event notifier: fd = %d, token = %" PRIu64, event->fd, event->token);
error:
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;
}
}
}
- rcu_read_unlock();
}
/* Close any relayd session */
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;
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;
- /* For each channel, ask the consumer to snapshot it. */
- cds_list_for_each_entry (chan, &ksess->channel_list.head, list) {
+ 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) {
+ 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:
/* Restore metadata state.*/
ksess->metadata = saved_metadata;
ksess->metadata_stream_fd = saved_metadata_fd;
- rcu_read_unlock();
free(trace_path);
return status;
}
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;
}
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);
/*
goto error;
}
error:
- rcu_read_unlock();
return ret;
}
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;
+ }
}
}
break;
}
end:
- rcu_read_unlock();
return status;
}
}
/* 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,
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),
error_code_ret = LTTNG_OK;
error:
- rcu_read_unlock();
return error_code_ret;
}