X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fkernel.c;h=d7c7984d201ba96c82d050eb71a48dca798c8e38;hp=53072f97187654dc37db1b6042f8100b375cbb70;hb=b8a1b0bd3964381c9ec6a8df26bd37cd7405a83f;hpb=3b9677124ab48bddc945ca67947c49b87b5853e0 diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 53072f971..d7c7984d2 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -1,18 +1,8 @@ /* - * Copyright (C) 2011 - David Goulet + * Copyright (C) 2011 David Goulet * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2 only, - * as published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _LGPL_SOURCE @@ -22,19 +12,29 @@ #include #include #include +#include #include #include #include #include #include - +#include +#include +#include +#include +#include + +#include "lttng-sessiond.h" +#include "lttng-syscall.h" #include "consumer.h" #include "kernel.h" #include "kernel-consumer.h" #include "kern-modules.h" #include "utils.h" #include "rotate.h" +#include "modprobe.h" +#include "tracker.h" /* * Key used to reference a channel between the sessiond and the consumer. This @@ -42,6 +42,10 @@ */ static uint64_t next_kernel_channel_key; +static const char *module_proc_lttng = "/proc/lttng"; + +static int kernel_tracer_fd = -1; + #include #include /* @@ -92,7 +96,7 @@ error: * Create a new kernel session, register it to the kernel tracer and add it to * the session daemon session. */ -int kernel_create_session(struct ltt_session *session, int tracer_fd) +int kernel_create_session(struct ltt_session *session) { int ret; struct ltt_kernel_session *lks; @@ -107,7 +111,7 @@ int kernel_create_session(struct ltt_session *session, int tracer_fd) } /* Kernel tracer session creation */ - ret = kernctl_create_session(tracer_fd); + ret = kernctl_create_session(kernel_tracer_fd); if (ret < 0) { PERROR("ioctl kernel create session"); goto error; @@ -126,6 +130,26 @@ int kernel_create_session(struct ltt_session *session, int tracer_fd) DBG("Kernel session created (fd: %d)", lks->fd); + /* + * This is necessary since the creation time is present in the session + * name when it is generated. + */ + if (session->has_auto_generated_name) { + ret = kernctl_session_set_name(lks->fd, DEFAULT_SESSION_NAME); + } else { + ret = kernctl_session_set_name(lks->fd, session->name); + } + if (ret) { + WARN("Could not set kernel session name for session %" PRIu64 " name: %s", + session->id, session->name); + } + + ret = kernctl_session_set_creation_time(lks->fd, session->creation_time); + if (ret) { + WARN("Could not set kernel session creation time for session %" PRIu64 " name: %s", + session->id, session->name); + } + return 0; error: @@ -651,120 +675,370 @@ error: return ret; } +static +struct process_attr_tracker *_kernel_get_process_attr_tracker( + struct ltt_kernel_session *session, + enum lttng_process_attr process_attr) +{ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + return session->tracker_pid; + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + return session->tracker_vpid; + case LTTNG_PROCESS_ATTR_USER_ID: + return session->tracker_uid; + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + return session->tracker_vuid; + case LTTNG_PROCESS_ATTR_GROUP_ID: + return session->tracker_gid; + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + return session->tracker_vgid; + default: + return NULL; + } +} -int kernel_track_pid(struct ltt_kernel_session *session, int pid) +const struct process_attr_tracker *kernel_get_process_attr_tracker( + struct ltt_kernel_session *session, + enum lttng_process_attr process_attr) +{ + return (const struct process_attr_tracker *) + _kernel_get_process_attr_tracker(session, process_attr); +} + +enum lttng_error_code kernel_process_attr_tracker_set_tracking_policy( + struct ltt_kernel_session *session, + enum lttng_process_attr process_attr, + enum lttng_tracking_policy policy) { int ret; + enum lttng_error_code ret_code = LTTNG_OK; + struct process_attr_tracker *tracker = + _kernel_get_process_attr_tracker(session, process_attr); + enum lttng_tracking_policy previous_policy; + + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + previous_policy = process_attr_tracker_get_tracking_policy(tracker); + ret = process_attr_tracker_set_tracking_policy(tracker, policy); + if (ret) { + ret_code = LTTNG_ERR_UNK; + goto end; + } - DBG("Kernel track PID %d for session id %" PRIu64 ".", - pid, session->id); - ret = kernctl_track_pid(session->fd, pid); - if (!ret) { - return LTTNG_OK; + if (previous_policy == policy) { + goto end; + } + + switch (policy) { + case LTTNG_TRACKING_POLICY_INCLUDE_ALL: + if (process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID) { + /* + * Maintain a special case for the process ID process + * attribute tracker as it was the only supported + * attribute prior to 2.12. + */ + ret = kernctl_track_pid(session->fd, -1); + } else { + ret = kernctl_track_id(session->fd, process_attr, -1); + } + break; + case LTTNG_TRACKING_POLICY_EXCLUDE_ALL: + case LTTNG_TRACKING_POLICY_INCLUDE_SET: + /* fall-through. */ + if (process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID) { + /* + * Maintain a special case for the process ID process + * attribute tracker as it was the only supported + * attribute prior to 2.12. + */ + ret = kernctl_untrack_pid(session->fd, -1); + } else { + ret = kernctl_untrack_id(session->fd, process_attr, -1); + } + break; + default: + abort(); } + /* kern-ctl error handling */ switch (-ret) { + case 0: + ret_code = LTTNG_OK; + break; case EINVAL: - return LTTNG_ERR_INVALID; + ret_code = LTTNG_ERR_INVALID; + break; case ENOMEM: - return LTTNG_ERR_NOMEM; + ret_code = LTTNG_ERR_NOMEM; + break; case EEXIST: - return LTTNG_ERR_PID_TRACKED; + ret_code = LTTNG_ERR_PROCESS_ATTR_EXISTS; + break; default: - return LTTNG_ERR_UNK; + ret_code = LTTNG_ERR_UNK; + break; } +end: + return ret_code; } -int kernel_untrack_pid(struct ltt_kernel_session *session, int pid) +enum lttng_error_code kernel_process_attr_tracker_inclusion_set_add_value( + struct ltt_kernel_session *session, + enum lttng_process_attr process_attr, + const struct process_attr_value *value) { - int ret; + int ret, integral_value; + enum lttng_error_code ret_code; + struct process_attr_tracker *tracker; + enum process_attr_tracker_status status; + + /* + * Convert process attribute tracker value to the integral + * representation required by the kern-ctl API. + */ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + integral_value = (int) value->value.pid; + break; + case LTTNG_PROCESS_ATTR_USER_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME) { + uid_t uid; + + ret_code = utils_user_id_from_name( + value->value.user_name, &uid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) uid; + } else { + integral_value = (int) value->value.uid; + } + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME) { + gid_t gid; + + ret_code = utils_group_id_from_name( + value->value.group_name, &gid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) gid; + } else { + integral_value = (int) value->value.gid; + } + break; + default: + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + tracker = _kernel_get_process_attr_tracker(session, process_attr); + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; + goto end; + } + + status = process_attr_tracker_inclusion_set_add_value(tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + switch (status) { + case PROCESS_ATTR_TRACKER_STATUS_EXISTS: + ret_code = LTTNG_ERR_PROCESS_ATTR_EXISTS; + break; + case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY: + ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY; + break; + case PROCESS_ATTR_TRACKER_STATUS_ERROR: + default: + ret_code = LTTNG_ERR_UNK; + break; + } + goto end; + } - DBG("Kernel untrack PID %d for session id %" PRIu64 ".", - pid, session->id); - ret = kernctl_untrack_pid(session->fd, pid); - if (!ret) { - return LTTNG_OK; + DBG("Kernel track %s %d for session id %" PRIu64, + lttng_process_attr_to_string(process_attr), + integral_value, session->id); + if (process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID) { + /* + * Maintain a special case for the process ID process attribute + * tracker as it was the only supported attribute prior to 2.12. + */ + ret = kernctl_track_pid(session->fd, integral_value); + } else { + ret = kernctl_track_id( + session->fd, process_attr, integral_value); } + if (ret == 0) { + ret_code = LTTNG_OK; + goto end; + } + + kernel_wait_quiescent(); + + /* kern-ctl error handling */ switch (-ret) { + case 0: + ret_code = LTTNG_OK; + break; case EINVAL: - return LTTNG_ERR_INVALID; + ret_code = LTTNG_ERR_INVALID; + break; case ENOMEM: - return LTTNG_ERR_NOMEM; - case ENOENT: - return LTTNG_ERR_PID_NOT_TRACKED; + ret_code = LTTNG_ERR_NOMEM; + break; + case EEXIST: + ret_code = LTTNG_ERR_PROCESS_ATTR_EXISTS; + break; default: - return LTTNG_ERR_UNK; + ret_code = LTTNG_ERR_UNK; + break; } + + /* Attempt to remove the value from the tracker. */ + status = process_attr_tracker_inclusion_set_remove_value( + tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + ERR("Failed to roll-back the tracking of kernel %s process attribute %d while handling a kern-ctl error", + lttng_process_attr_to_string(process_attr), + integral_value); + } +end: + return ret_code; } -ssize_t kernel_list_tracker_pids(struct ltt_kernel_session *session, - int **_pids) +enum lttng_error_code kernel_process_attr_tracker_inclusion_set_remove_value( + struct ltt_kernel_session *session, + enum lttng_process_attr process_attr, + const struct process_attr_value *value) { - int fd, ret; - int pid; - ssize_t nbmem, count = 0; - FILE *fp; - int *pids; + int ret, integral_value; + enum lttng_error_code ret_code; + struct process_attr_tracker *tracker; + enum process_attr_tracker_status status; - fd = kernctl_list_tracker_pids(session->fd); - if (fd < 0) { - PERROR("kernel tracker pids list"); - goto error; + /* + * Convert process attribute tracker value to the integral + * representation required by the kern-ctl API. + */ + switch (process_attr) { + case LTTNG_PROCESS_ATTR_PROCESS_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID: + integral_value = (int) value->value.pid; + break; + case LTTNG_PROCESS_ATTR_USER_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_USER_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_USER_NAME) { + uid_t uid; + + ret_code = utils_user_id_from_name( + value->value.user_name, &uid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) uid; + } else { + integral_value = (int) value->value.uid; + } + break; + case LTTNG_PROCESS_ATTR_GROUP_ID: + case LTTNG_PROCESS_ATTR_VIRTUAL_GROUP_ID: + if (value->type == LTTNG_PROCESS_ATTR_VALUE_TYPE_GROUP_NAME) { + gid_t gid; + + ret_code = utils_group_id_from_name( + value->value.group_name, &gid); + if (ret_code != LTTNG_OK) { + goto end; + } + integral_value = (int) gid; + } else { + integral_value = (int) value->value.gid; + } + break; + default: + ret_code = LTTNG_ERR_INVALID; + goto end; } - fp = fdopen(fd, "r"); - if (fp == NULL) { - PERROR("kernel tracker pids list fdopen"); - goto error_fp; + tracker = _kernel_get_process_attr_tracker(session, process_attr); + if (!tracker) { + ret_code = LTTNG_ERR_INVALID; + goto end; } - nbmem = KERNEL_TRACKER_PIDS_INIT_LIST_SIZE; - pids = zmalloc(sizeof(*pids) * nbmem); - if (pids == NULL) { - PERROR("alloc list pids"); - count = -ENOMEM; + status = process_attr_tracker_inclusion_set_remove_value( + tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + switch (status) { + case PROCESS_ATTR_TRACKER_STATUS_MISSING: + ret_code = LTTNG_ERR_PROCESS_ATTR_MISSING; + break; + case PROCESS_ATTR_TRACKER_STATUS_INVALID_TRACKING_POLICY: + ret_code = LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY; + break; + case PROCESS_ATTR_TRACKER_STATUS_ERROR: + default: + ret_code = LTTNG_ERR_UNK; + break; + } goto end; } - while (fscanf(fp, "process { pid = %u; };\n", &pid) == 1) { - if (count >= nbmem) { - int *new_pids; - size_t new_nbmem; - - new_nbmem = nbmem << 1; - DBG("Reallocating pids list from %zu to %zu entries", - nbmem, new_nbmem); - new_pids = realloc(pids, new_nbmem * sizeof(*new_pids)); - if (new_pids == NULL) { - PERROR("realloc list events"); - free(pids); - count = -ENOMEM; - goto end; - } - /* Zero the new memory */ - memset(new_pids + nbmem, 0, - (new_nbmem - nbmem) * sizeof(*new_pids)); - nbmem = new_nbmem; - pids = new_pids; - } - pids[count++] = pid; + DBG("Kernel track %s %d for session id %" PRIu64, + lttng_process_attr_to_string(process_attr), + integral_value, session->id); + if (process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID) { + /* + * Maintain a special case for the process ID process attribute + * tracker as it was the only supported attribute prior to 2.12. + */ + ret = kernctl_untrack_pid(session->fd, integral_value); + } else { + ret = kernctl_untrack_id( + session->fd, process_attr, integral_value); } + if (ret == 0) { + ret_code = LTTNG_OK; + goto end; + } + kernel_wait_quiescent(); - *_pids = pids; - DBG("Kernel list tracker pids done (%zd pids)", count); -end: - ret = fclose(fp); /* closes both fp and fd */ - if (ret) { - PERROR("fclose"); + /* kern-ctl error handling */ + switch (-ret) { + case 0: + ret_code = LTTNG_OK; + break; + case EINVAL: + ret_code = LTTNG_ERR_INVALID; + break; + case ENOMEM: + ret_code = LTTNG_ERR_NOMEM; + break; + case ENOENT: + ret_code = LTTNG_ERR_PROCESS_ATTR_MISSING; + break; + default: + ret_code = LTTNG_ERR_UNK; + break; } - return count; -error_fp: - ret = close(fd); - if (ret) { - PERROR("close"); + /* Attempt to add the value to the tracker. */ + status = process_attr_tracker_inclusion_set_add_value( + tracker, value); + if (status != PROCESS_ATTR_TRACKER_STATUS_OK) { + ERR("Failed to roll-back the tracking of kernel %s process attribute %d while handling a kern-ctl error", + lttng_process_attr_to_string(process_attr), + integral_value); } -error: - return -1; +end: + return ret_code; } /* @@ -836,9 +1110,10 @@ error: /* * Make a kernel wait to make sure in-flight probe have completed. */ -void kernel_wait_quiescent(int fd) +void kernel_wait_quiescent(void) { int ret; + int fd = kernel_tracer_fd; DBG("Kernel quiescent wait on %d", fd); @@ -997,7 +1272,7 @@ error: /* * Get the event list from the kernel tracer and return the number of elements. */ -ssize_t kernel_list_events(int tracer_fd, struct lttng_event **events) +ssize_t kernel_list_events(struct lttng_event **events) { int fd, ret; char *event; @@ -1007,7 +1282,7 @@ ssize_t kernel_list_events(int tracer_fd, struct lttng_event **events) assert(events); - fd = kernctl_tracepoint_list(tracer_fd); + fd = kernctl_tracepoint_list(kernel_tracer_fd); if (fd < 0) { PERROR("kernel tracepoint list"); goto error; @@ -1081,13 +1356,12 @@ error: /* * Get kernel version and validate it. */ -int kernel_validate_version(int tracer_fd, - struct lttng_kernel_tracer_version *version, +int kernel_validate_version(struct lttng_kernel_tracer_version *version, struct lttng_kernel_tracer_abi_version *abi_version) { int ret; - ret = kernctl_tracer_version(tracer_fd, version); + ret = kernctl_tracer_version(kernel_tracer_fd, version); if (ret < 0) { ERR("Failed to retrieve the lttng-modules version"); goto error; @@ -1099,7 +1373,7 @@ int kernel_validate_version(int tracer_fd, version->major, VERSION_MAJOR); goto error_version; } - ret = kernctl_tracer_abi_version(tracer_fd, abi_version); + ret = kernctl_tracer_abi_version(kernel_tracer_fd, abi_version); if (ret < 0) { ERR("Failed to retrieve lttng-modules ABI version"); goto error; @@ -1261,6 +1535,7 @@ enum lttng_error_code kernel_snapshot_record( struct lttng_ht_iter iter; struct ltt_kernel_metadata *saved_metadata; char *trace_path = NULL; + size_t consumer_path_offset = 0; assert(ksess); assert(ksess->consumer); @@ -1287,7 +1562,7 @@ enum lttng_error_code kernel_snapshot_record( } trace_path = setup_channel_trace_path(ksess->consumer, - DEFAULT_KERNEL_TRACE_DIR); + DEFAULT_KERNEL_TRACE_DIR, &consumer_path_offset); if (!trace_path) { status = LTTNG_ERR_INVALID; goto error; @@ -1310,7 +1585,7 @@ enum lttng_error_code kernel_snapshot_record( cds_list_for_each_entry(chan, &ksess->channel_list.head, list) { status = consumer_snapshot_channel(socket, chan->key, output, 0, ksess->uid, ksess->gid, - trace_path, wait, + &trace_path[consumer_path_offset], wait, nb_packets_per_stream); if (status != LTTNG_OK) { (void) kernel_consumer_destroy_metadata(socket, @@ -1321,7 +1596,8 @@ enum lttng_error_code kernel_snapshot_record( /* Snapshot metadata, */ status = consumer_snapshot_channel(socket, ksess->metadata->key, output, - 1, ksess->uid, ksess->gid, trace_path, wait, 0); + 1, ksess->uid, ksess->gid, &trace_path[consumer_path_offset], + wait, 0); if (status != LTTNG_OK) { goto error_consumer; } @@ -1372,12 +1648,12 @@ int kernel_syscall_mask(int chan_fd, char **syscall_mask, uint32_t *nr_bits) * Return 1 on success, 0 when feature is not supported, negative value in case * of errors. */ -int kernel_supports_ring_buffer_snapshot_sample_positions(int tracer_fd) +int kernel_supports_ring_buffer_snapshot_sample_positions(void) { int ret = 0; // Not supported by default struct lttng_kernel_tracer_abi_version abi; - ret = kernctl_tracer_abi_version(tracer_fd, &abi); + ret = kernctl_tracer_abi_version(kernel_tracer_fd, &abi); if (ret < 0) { ERR("Failed to retrieve lttng-modules ABI version"); goto error; @@ -1397,6 +1673,38 @@ error: return ret; } +/* + * Check for the support of the packet sequence number via abi version number. + * + * 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 ret = 0; // Not supported by default + struct lttng_kernel_tracer_abi_version abi; + + ret = kernctl_tracer_abi_version(kernel_tracer_fd, &abi); + if (ret < 0) { + ERR("Failed to retrieve lttng-modules ABI version"); + goto error; + } + + /* + * Packet sequence number was introduced in LTTng 2.8, + * lttng-modules ABI 2.1. + */ + if (abi.major >= 2 && abi.minor >= 1) { + /* Supported */ + ret = 1; + } else { + /* Not supported */ + ret = 0; + } +error: + return ret; +} + /* * Rotate a kernel session. * @@ -1426,7 +1734,7 @@ enum lttng_error_code kernel_rotate_session(struct ltt_session *session) socket, node.node) { struct ltt_kernel_channel *chan; - /* For each channel, ask the consumer to rotate it. */ + /* 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); @@ -1434,7 +1742,7 @@ enum lttng_error_code kernel_rotate_session(struct ltt_session *session) ksess->uid, ksess->gid, ksess->consumer, /* is_metadata_channel */ false); if (ret < 0) { - status = LTTNG_ERR_KERN_CONSUMER_FAIL; + status = LTTNG_ERR_ROTATION_FAIL_CONSUMER; goto error; } } @@ -1446,7 +1754,7 @@ enum lttng_error_code kernel_rotate_session(struct ltt_session *session) ksess->uid, ksess->gid, ksess->consumer, /* is_metadata_channel */ true); if (ret < 0) { - status = LTTNG_ERR_KERN_CONSUMER_FAIL; + status = LTTNG_ERR_ROTATION_FAIL_CONSUMER; goto error; } } @@ -1480,3 +1788,189 @@ error: rcu_read_unlock(); return ret; } + +/* + * Setup necessary data for kernel tracer action. + */ +LTTNG_HIDDEN +int init_kernel_tracer(void) +{ + int ret; + bool is_root = !getuid(); + + /* Modprobe lttng kernel modules */ + ret = modprobe_lttng_control(); + if (ret < 0) { + goto error; + } + + /* Open debugfs lttng */ + kernel_tracer_fd = open(module_proc_lttng, O_RDWR); + if (kernel_tracer_fd < 0) { + DBG("Failed to open %s", module_proc_lttng); + goto error_open; + } + + /* Validate kernel version */ + ret = kernel_validate_version(&kernel_tracer_version, + &kernel_tracer_abi_version); + if (ret < 0) { + goto error_version; + } + + ret = modprobe_lttng_data(); + if (ret < 0) { + goto error_modules; + } + + ret = kernel_supports_ring_buffer_snapshot_sample_positions(); + if (ret < 0) { + goto error_modules; + } + + if (ret < 1) { + WARN("Kernel tracer does not support buffer monitoring. " + "The monitoring timer of channels in the kernel domain " + "will be set to 0 (disabled)."); + } + + DBG("Kernel tracer fd %d", kernel_tracer_fd); + + ret = syscall_init_table(kernel_tracer_fd); + if (ret < 0) { + ERR("Unable to populate syscall table. Syscall tracing won't " + "work for this session daemon."); + } + return 0; + +error_version: + modprobe_remove_lttng_control(); + ret = close(kernel_tracer_fd); + if (ret) { + PERROR("close"); + } + kernel_tracer_fd = -1; + return LTTNG_ERR_KERN_VERSION; + +error_modules: + ret = close(kernel_tracer_fd); + if (ret) { + PERROR("close"); + } + +error_open: + modprobe_remove_lttng_control(); + +error: + WARN("No kernel tracer available"); + kernel_tracer_fd = -1; + if (!is_root) { + return LTTNG_ERR_NEED_ROOT_SESSIOND; + } else { + return LTTNG_ERR_KERN_NA; + } +} + +LTTNG_HIDDEN +void cleanup_kernel_tracer(void) +{ + int ret; + + DBG2("Closing kernel fd"); + if (kernel_tracer_fd >= 0) { + ret = close(kernel_tracer_fd); + if (ret) { + PERROR("close"); + } + kernel_tracer_fd = -1; + } + DBG("Unloading kernel modules"); + modprobe_remove_lttng_all(); + free(syscall_table); +} + +LTTNG_HIDDEN +bool kernel_tracer_is_initialized(void) +{ + return kernel_tracer_fd >= 0; +} + +/* + * Clear a kernel session. + * + * Return LTTNG_OK on success or else an LTTng error code. + */ +enum lttng_error_code kernel_clear_session(struct ltt_session *session) +{ + int ret; + enum lttng_error_code status = LTTNG_OK; + struct consumer_socket *socket; + struct lttng_ht_iter iter; + struct ltt_kernel_session *ksess = session->kernel_session; + + assert(ksess); + assert(ksess->consumer); + + 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; + } + } + + if (!ksess->metadata) { + /* + * Nothing to do for the metadata. + * This is a snapshot session. + * The metadata is genererated on the fly. + */ + 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; + } + } + + goto end; +error: + switch (-ret) { + case LTTCOMM_CONSUMERD_RELAYD_CLEAR_DISALLOWED: + status = LTTNG_ERR_CLEAR_RELAY_DISALLOWED; + break; + default: + status = LTTNG_ERR_CLEAR_FAIL_CONSUMER; + break; + } +end: + rcu_read_unlock(); + return status; +}