#include <common/defaults.hpp>
#include <common/error.hpp>
#include <common/runas.hpp>
+#include <common/urcu.hpp>
#include <common/utils.hpp>
#include <lttng/save-internal.hpp>
+#include <fcntl.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
}
if (attr->extended.ptr) {
- struct lttng_channel_extended *ext = NULL;
+ struct lttng_channel_extended *ext = nullptr;
ext = (struct lttng_channel_extended *) attr->extended.ptr;
ret = config_writer_write_element_unsigned_int(
struct lttng_ust_abi_channel_attr *attr)
{
int ret;
- struct ltt_ust_channel *channel = NULL;
+ struct ltt_ust_channel *channel = nullptr;
ret = config_writer_write_element_string(writer,
config_element_overwrite_mode,
instrumentation_string = config_event_type_syscall;
break;
default:
- instrumentation_string = NULL;
+ instrumentation_string = nullptr;
}
return instrumentation_string;
context_type_string = config_event_context_vsgid;
break;
default:
- context_type_string = NULL;
+ context_type_string = nullptr;
}
return context_type_string;
* are stored as a node of type event_perf_context_type.
*/
default:
- context_type_string = NULL;
+ context_type_string = nullptr;
break;
}
buffer_type_string = config_buffer_type_global;
break;
default:
- buffer_type_string = NULL;
+ buffer_type_string = nullptr;
}
return buffer_type_string;
loglevel_type_string = config_loglevel_type_single;
break;
default:
- loglevel_type_string = NULL;
+ loglevel_type_string = nullptr;
}
return loglevel_type_string;
*/
addr = event->event->u.kprobe.addr;
offset = event->event->u.kprobe.offset;
- symbol_name = addr ? NULL : event->event->u.kprobe.symbol_name;
+ symbol_name = addr ? nullptr : event->event->u.kprobe.symbol_name;
break;
case LTTNG_KERNEL_ABI_KRETPROBE:
addr = event->event->u.kretprobe.addr;
offset = event->event->u.kretprobe.offset;
- symbol_name = addr ? NULL : event->event->u.kretprobe.symbol_name;
+ symbol_name = addr ? nullptr : event->event->u.kretprobe.symbol_name;
break;
default:
- LTTNG_ASSERT(1);
ERR("Unsupported kernel instrumentation type.");
ret = LTTNG_ERR_INVALID;
goto end;
static int save_kernel_events(struct config_writer *writer, struct ltt_kernel_channel *kchan)
{
int ret;
- struct ltt_kernel_event *event;
ret = config_writer_open_element(writer, config_element_events);
if (ret) {
goto end;
}
- cds_list_for_each_entry (event, &kchan->events_list.head, list) {
+ for (auto *event :
+ lttng::urcu::list_iteration_adapter<ltt_kernel_event, <t_kernel_event::list>(
+ kchan->events_list.head)) {
ret = save_kernel_event(writer, event);
if (ret != LTTNG_OK) {
goto end;
static int save_ust_events(struct config_writer *writer, struct lttng_ht *events)
{
int ret;
- struct ltt_ust_event *event;
- struct lttng_ht_node_str *node;
- struct lttng_ht_iter iter;
ret = config_writer_open_element(writer, config_element_events);
if (ret) {
goto end;
}
- rcu_read_lock();
- cds_lfht_for_each_entry (events->ht, &iter.iter, node, node) {
- event = lttng::utils::container_of(node, <t_ust_event::node);
-
+ for (auto *event : lttng::urcu::lfht_iteration_adapter<ltt_ust_event,
+ decltype(ltt_ust_event::node),
+ <t_ust_event::node>(*events->ht)) {
if (event->internal) {
/* Internal events must not be exposed to clients */
continue;
}
+
ret = save_ust_event(writer, event);
if (ret != LTTNG_OK) {
- rcu_read_unlock();
goto end;
}
}
- rcu_read_unlock();
/* /events */
ret = config_writer_close_element(writer);
static int save_agent_events(struct config_writer *writer, struct agent *agent)
{
int ret;
- struct lttng_ht_iter iter;
- struct lttng_ht_node_str *node;
ret = config_writer_open_element(writer, config_element_events);
if (ret) {
goto end;
}
- rcu_read_lock();
- cds_lfht_for_each_entry (agent->events->ht, &iter.iter, node, node) {
- struct agent_event *agent_event;
- struct ltt_ust_event fake_event;
-
- memset(&fake_event, 0, sizeof(fake_event));
- agent_event = lttng::utils::container_of(node, &agent_event::node);
+ for (struct agent_event *agent_event :
+ lttng::urcu::lfht_iteration_adapter<struct agent_event,
+ decltype(agent_event::node),
+ &agent_event::node>(*agent->events->ht)) {
+ ltt_ust_event fake_event;
/*
* Initialize a fake ust event to reuse the same serialization
*/
ret = init_ust_event_from_agent_event(&fake_event, agent_event);
if (ret != LTTNG_OK) {
- rcu_read_unlock();
goto end;
}
+
ret = save_ust_event(writer, &fake_event);
if (ret != LTTNG_OK) {
- rcu_read_unlock();
goto end;
}
}
- rcu_read_unlock();
/* /events */
ret = config_writer_close_element(writer);
static int save_kernel_contexts(struct config_writer *writer, struct ltt_kernel_channel *kchan)
{
int ret;
- struct ltt_kernel_context *ctx;
if (cds_list_empty(&kchan->ctx_list)) {
ret = LTTNG_OK;
goto end;
}
- cds_list_for_each_entry (ctx, &kchan->ctx_list, list) {
+ for (auto *ctx :
+ lttng::urcu::list_iteration_adapter<ltt_kernel_context, <t_kernel_context::list>(
+ kchan->ctx_list)) {
ret = save_kernel_context(writer, &ctx->ctx);
if (ret != LTTNG_OK) {
goto end;
static int save_ust_context(struct config_writer *writer, struct cds_list_head *ctx_list)
{
int ret;
- struct ltt_ust_context *ctx;
LTTNG_ASSERT(writer);
LTTNG_ASSERT(ctx_list);
goto end;
}
- cds_list_for_each_entry (ctx, ctx_list, list) {
+ for (auto *ctx :
+ lttng::urcu::list_iteration_adapter<ltt_ust_context, <t_ust_context::list>(
+ *ctx_list)) {
ret = config_writer_open_element(writer, config_element_context);
if (ret) {
ret = LTTNG_ERR_SAVE_IO_FAIL;
goto end;
}
} else {
- struct agent *agent = NULL;
+ struct agent *agent = nullptr;
agent = trace_ust_find_agent(session, ust_chan->domain);
if (!agent) {
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
-static int save_kernel_session(struct config_writer *writer, struct ltt_session *session)
+static int save_kernel_session(struct config_writer *writer, const ltt_session::locked_ref& session)
{
int ret;
- struct ltt_kernel_channel *kchan;
LTTNG_ASSERT(writer);
- LTTNG_ASSERT(session);
ret = config_writer_write_element_string(
writer, config_element_type, config_domain_type_kernel);
goto end;
}
- cds_list_for_each_entry (kchan, &session->kernel_session->channel_list.head, list) {
+ for (auto *kchan :
+ lttng::urcu::list_iteration_adapter<ltt_kernel_channel, <t_kernel_channel::list>(
+ session->kernel_session->channel_list.head)) {
ret = save_kernel_channel(writer, kchan);
if (ret != LTTNG_OK) {
goto end;
case LTTNG_DOMAIN_LOG4J:
str_dom = config_domain_type_log4j;
break;
+ case LTTNG_DOMAIN_LOG4J2:
+ str_dom = config_domain_type_log4j2;
+ break;
case LTTNG_DOMAIN_PYTHON:
str_dom = config_domain_type_python;
break;
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
static int save_process_attr_tracker(struct config_writer *writer,
- struct ltt_session *sess,
+ const ltt_session::locked_ref& session,
int domain,
enum lttng_process_attr process_attr)
{
const char *element_id_tracker, *element_target_id, *element_id;
const struct process_attr_tracker *tracker;
enum lttng_tracking_policy tracking_policy;
- struct lttng_process_attr_values *values = NULL;
+ struct lttng_process_attr_values *values = nullptr;
switch (process_attr) {
case LTTNG_PROCESS_ATTR_PROCESS_ID:
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
{
- tracker = kernel_get_process_attr_tracker(sess->kernel_session, process_attr);
+ tracker = kernel_get_process_attr_tracker(session->kernel_session, process_attr);
LTTNG_ASSERT(tracker);
break;
}
case LTTNG_DOMAIN_UST:
{
- tracker = trace_ust_get_process_attr_tracker(sess->ust_session, process_attr);
+ tracker = trace_ust_get_process_attr_tracker(session->ust_session, process_attr);
LTTNG_ASSERT(tracker);
break;
}
case LTTNG_DOMAIN_JUL:
case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_LOG4J2:
case LTTNG_DOMAIN_PYTHON:
default:
ret = LTTNG_ERR_UNSUPPORTED_DOMAIN;
if (tracking_policy == LTTNG_TRACKING_POLICY_INCLUDE_SET) {
unsigned int i, count;
- enum process_attr_tracker_status status =
+ const process_attr_tracker_status status =
process_attr_tracker_get_inclusion_set(tracker, &values);
if (status != PROCESS_ATTR_TRACKER_STATUS_OK) {
for (i = 0; i < count; i++) {
unsigned int integral_value = UINT_MAX;
- const char *name = NULL;
+ const char *name = nullptr;
const struct process_attr_value *value =
lttng_process_attr_tracker_values_get_at_index(values, i);
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
-static int
-save_process_attr_trackers(struct config_writer *writer, struct ltt_session *sess, int domain)
+static int save_process_attr_trackers(struct config_writer *writer,
+ const ltt_session::locked_ref& session,
+ int domain)
{
int ret;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_PROCESS_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_PROCESS_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
if (ret != LTTNG_OK) {
goto end;
}
- ret = save_process_attr_tracker(writer, sess, domain, LTTNG_PROCESS_ATTR_USER_ID);
+ ret = save_process_attr_tracker(
+ writer, session, domain, LTTNG_PROCESS_ATTR_USER_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
if (ret != LTTNG_OK) {
goto end;
}
- ret = save_process_attr_tracker(writer, sess, domain, LTTNG_PROCESS_ATTR_GROUP_ID);
+ ret = save_process_attr_tracker(
+ writer, session, domain, LTTNG_PROCESS_ATTR_GROUP_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
if (ret != LTTNG_OK) {
goto end;
}
break;
case LTTNG_DOMAIN_UST:
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID);
if (ret != LTTNG_OK) {
goto end;
}
ret = save_process_attr_tracker(
- writer, sess, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
+ writer, session, domain, LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID);
if (ret != LTTNG_OK) {
goto end;
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
static int save_ust_domain(struct config_writer *writer,
- struct ltt_session *session,
+ const ltt_session::locked_ref& session,
enum lttng_domain_type domain)
{
int ret;
- struct ltt_ust_channel *ust_chan;
const char *buffer_type_string;
- struct lttng_ht_node_str *node;
- struct lttng_ht_iter iter;
const char *config_domain_name;
LTTNG_ASSERT(writer);
- LTTNG_ASSERT(session);
ret = config_writer_open_element(writer, config_element_domain);
if (ret) {
goto end;
}
- rcu_read_lock();
- cds_lfht_for_each_entry (
- session->ust_session->domain_global.channels->ht, &iter.iter, node, node) {
- ust_chan = lttng::utils::container_of(node, <t_ust_channel::node);
+ for (auto *ust_chan : lttng::urcu::lfht_iteration_adapter<ltt_ust_channel,
+ decltype(ltt_ust_channel::node),
+ <t_ust_channel::node>(
+ *session->ust_session->domain_global.channels->ht)) {
if (domain == ust_chan->domain) {
ret = save_ust_channel(writer, ust_chan, session->ust_session);
if (ret != LTTNG_OK) {
- rcu_read_unlock();
goto end;
}
}
}
- rcu_read_unlock();
/* /channels */
ret = config_writer_close_element(writer);
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
-static int save_domains(struct config_writer *writer, struct ltt_session *session)
+static int save_domains(struct config_writer *writer, const ltt_session::locked_ref& session)
{
int ret = LTTNG_OK;
LTTNG_ASSERT(writer);
- LTTNG_ASSERT(session);
if (!session->kernel_session && !session->ust_session) {
goto end;
goto end;
}
+ ret = save_ust_domain(writer, session, LTTNG_DOMAIN_LOG4J2);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+
ret = save_ust_domain(writer, session, LTTNG_DOMAIN_PYTHON);
if (ret != LTTNG_OK) {
goto end;
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
static int save_snapshot_outputs(struct config_writer *writer, struct snapshot *snapshot)
{
- int ret;
- struct lttng_ht_iter iter;
- struct snapshot_output *output;
-
LTTNG_ASSERT(writer);
LTTNG_ASSERT(snapshot);
- ret = config_writer_open_element(writer, config_element_snapshot_outputs);
+ int ret = config_writer_open_element(writer, config_element_snapshot_outputs);
if (ret) {
ret = LTTNG_ERR_SAVE_IO_FAIL;
goto end;
}
- rcu_read_lock();
- cds_lfht_for_each_entry (snapshot->output_ht->ht, &iter.iter, output, node.node) {
+ for (auto *output : lttng::urcu::lfht_iteration_adapter<snapshot_output,
+ decltype(snapshot_output::node),
+ &snapshot_output::node>(
+ *snapshot->output_ht->ht)) {
ret = config_writer_open_element(writer, config_element_output);
if (ret) {
ret = LTTNG_ERR_SAVE_IO_FAIL;
goto end_unlock;
}
}
- rcu_read_unlock();
/* /snapshot_outputs */
ret = config_writer_close_element(writer);
end:
return ret;
end_unlock:
- rcu_read_unlock();
return ret;
}
/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
-static int save_session_output(struct config_writer *writer, struct ltt_session *session)
+static int save_session_output(struct config_writer *writer, const ltt_session::locked_ref& session)
{
int ret;
LTTNG_ASSERT(writer);
- LTTNG_ASSERT(session);
if ((session->snapshot_mode && session->snapshot.nb_output == 0) ||
(!session->snapshot_mode && !session->consumer)) {
}
static int save_session_rotation_schedules(struct config_writer *writer,
- struct ltt_session *session)
+ const ltt_session::locked_ref& session)
{
int ret;
*
* Return LTTNG_OK on success else a LTTNG_ERR* code.
*/
-static int save_session(struct ltt_session *session,
+static int save_session(const ltt_session::locked_ref& session,
struct lttng_save_session_attr *attr,
lttng_sock_cred *creds)
{
int ret, fd = -1;
char config_file_path[LTTNG_PATH_MAX];
size_t len;
- struct config_writer *writer = NULL;
+ struct config_writer *writer = nullptr;
size_t session_name_len;
const char *provided_path;
int file_open_flags = O_CREAT | O_WRONLY | O_TRUNC;
- LTTNG_ASSERT(session);
LTTNG_ASSERT(attr);
LTTNG_ASSERT(creds);
int cmd_save_sessions(struct lttng_save_session_attr *attr, lttng_sock_cred *creds)
{
- int ret;
- const char *session_name;
- struct ltt_session *session;
-
- session_lock_list();
+ const auto list_lock = lttng::sessiond::lock_session_list();
+ const auto session_name = lttng_save_session_attr_get_session_name(attr);
- session_name = lttng_save_session_attr_get_session_name(attr);
if (session_name) {
- session = session_find_by_name(session_name);
- if (!session) {
- ret = LTTNG_ERR_SESS_NOT_FOUND;
- goto end;
- }
-
- session_lock(session);
- ret = save_session(session, attr, creds);
- session_unlock(session);
- session_put(session);
- if (ret != LTTNG_OK) {
- goto end;
+ /*
+ * Mind the order of the declaration of list_lock vs session:
+ * the session list lock must always be released _after_ the release of
+ * a session's reference (the destruction of a ref/locked_ref) to ensure
+ * since the reference's release may unpublish the session from the list of
+ * sessions.
+ */
+ try {
+ const auto session = ltt_session::find_locked_session(session_name);
+ const auto save_ret = save_session(session, attr, creds);
+ if (save_ret != LTTNG_OK) {
+ return save_ret;
+ }
+ } catch (const lttng::sessiond::exceptions::session_not_found_error& ex) {
+ WARN_FMT("Failed to save session: {} {}", ex.what(), ex.source_location);
+ return LTTNG_ERR_SESS_NOT_FOUND;
}
} else {
struct ltt_session_list *list = session_get_list();
- cds_list_for_each_entry (session, &list->head, list) {
- if (!session_get(session)) {
- continue;
- }
- session_lock(session);
- ret = save_session(session, attr, creds);
- session_unlock(session);
- session_put(session);
+ for (auto raw_session_ptr :
+ lttng::urcu::list_iteration_adapter<ltt_session, <t_session::list>(
+ list->head)) {
+ auto session = [raw_session_ptr]() {
+ session_get(raw_session_ptr);
+ raw_session_ptr->lock();
+ return ltt_session::make_locked_ref(*raw_session_ptr);
+ }();
+ const auto save_ret = save_session(session, attr, creds);
+
/* Don't abort if we don't have the required permissions. */
- if (ret != LTTNG_OK && ret != LTTNG_ERR_EPERM) {
- goto end;
+ if (save_ret != LTTNG_OK && save_ret != LTTNG_ERR_EPERM) {
+ return save_ret;
}
}
}
- ret = LTTNG_OK;
-end:
- session_unlock_list();
- return ret;
+ return LTTNG_OK;
}