From: Mathieu Desnoyers Date: Thu, 23 May 2019 19:11:50 +0000 (-0400) Subject: Fix: reintroduce lazy kernel modules load, fix empty syscall list X-Git-Tag: v2.11.0-rc3~18 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=32e10baa3513a50f5dca51193cd9c834a2e0c39a;p=lttng-tools.git Fix: reintroduce lazy kernel modules load, fix empty syscall list Up and including to lttng 2.10, if the lttng-modules are not available when the session daemon starts, an attempt is made to load them each time a command attempts to interact with the kernel domain. 2.11-rc introduces a change in behavior which removes this lazy initialization. This is an issue for distribution packaging (e.g. Ubuntu) where there is no strong dependency between lttng-tools and lttng-modules (because either are optional). So we can be unlucky and find ourselves in a situation where the modules are not available when the session daemon is launched at installation, but only afterwards. Re-introduce the lazy kernel module load behavior, since this is expected by users. Also, fix an issue with empty syscall list in those lazy initialization scenario by moving invocation of syscall_init_table() from main() to init_kernel_tracer(). While we are there, cleanup the following in session daemon: - move kernel_tracer_fd from globals.c to kernel.c. It becomes a static variable, - move module_proc_lttng from main.c to kernel.c, - move init_kernel_tracer() from main.c to kernel.c, - introduce kernel.c:cleanup_kernel_tracer(), invoke it from program cleanup, - introduce kernel_tracer_is_initialized() to check the state of kernel tracer initialization, - adapt kernel.c functions to use the static kernel_tracer_fd rather than expect it as parameter, - update syscall_init_table, invoked from kernel.c, to pass the kernel_tracer_fd as parameter. Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- diff --git a/src/bin/lttng-sessiond/client.c b/src/bin/lttng-sessiond/client.c index 02eac96e4..7b7642ea7 100644 --- a/src/bin/lttng-sessiond/client.c +++ b/src/bin/lttng-sessiond/client.c @@ -478,7 +478,7 @@ static int create_kernel_session(struct ltt_session *session) DBG("Creating kernel session"); - ret = kernel_create_session(session, kernel_tracer_fd); + ret = kernel_create_session(session); if (ret < 0) { ret = LTTNG_ERR_KERN_SESS_FAIL; goto error_create; @@ -879,6 +879,15 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int *sock, goto error; } + /* Kernel tracer check */ + if (!kernel_tracer_is_initialized()) { + /* Basically, load kernel tracer modules */ + ret = init_kernel_tracer(); + if (ret != 0) { + goto error; + } + } + /* Consumer is in an ERROR state. Report back to client */ if (uatomic_read(&kernel_consumerd_state) == CONSUMER_ERROR) { ret = LTTNG_ERR_NO_KERNCONSUMERD; diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 1b73978f2..82d920703 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -1252,7 +1252,7 @@ error: /* * Start a kernel session by opening all necessary streams. */ -static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe) +static int start_kernel_session(struct ltt_kernel_session *ksess) { int ret; struct ltt_kernel_channel *kchan; @@ -1304,7 +1304,7 @@ static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe) } /* Quiescent wait after starting trace */ - kernel_wait_quiescent(wpipe); + kernel_wait_quiescent(); ksess->active = 1; @@ -1336,7 +1336,7 @@ int cmd_disable_channel(struct ltt_session *session, goto error; } - kernel_wait_quiescent(kernel_tracer_fd); + kernel_wait_quiescent(); break; } case LTTNG_DOMAIN_UST: @@ -1394,7 +1394,7 @@ int cmd_track_pid(struct ltt_session *session, enum lttng_domain_type domain, goto error; } - kernel_wait_quiescent(kernel_tracer_fd); + kernel_wait_quiescent(); break; } case LTTNG_DOMAIN_UST: @@ -1445,7 +1445,7 @@ int cmd_untrack_pid(struct ltt_session *session, enum lttng_domain_type domain, goto error; } - kernel_wait_quiescent(kernel_tracer_fd); + kernel_wait_quiescent(); break; } case LTTNG_DOMAIN_UST: @@ -1525,7 +1525,7 @@ int cmd_enable_channel(struct ltt_session *session, switch (domain->type) { case LTTNG_DOMAIN_KERNEL: { - if (kernel_supports_ring_buffer_snapshot_sample_positions(kernel_tracer_fd) != 1) { + if (kernel_supports_ring_buffer_snapshot_sample_positions() != 1) { /* Sampling position of buffer is not supported */ WARN("Kernel tracer does not support buffer monitoring. " "Setting the monitor interval timer to 0 " @@ -1576,7 +1576,7 @@ int cmd_enable_channel(struct ltt_session *session, goto error; } - kernel_wait_quiescent(kernel_tracer_fd); + kernel_wait_quiescent(); break; } case LTTNG_DOMAIN_UST: @@ -1711,7 +1711,7 @@ int cmd_disable_event(struct ltt_session *session, goto error_unlock; } - kernel_wait_quiescent(kernel_tracer_fd); + kernel_wait_quiescent(); break; } case LTTNG_DOMAIN_UST: @@ -2161,7 +2161,7 @@ static int _cmd_enable_event(struct ltt_session *session, goto error; } - kernel_wait_quiescent(kernel_tracer_fd); + kernel_wait_quiescent(); break; } case LTTNG_DOMAIN_UST: @@ -2429,7 +2429,7 @@ ssize_t cmd_list_tracepoints(enum lttng_domain_type domain, switch (domain) { case LTTNG_DOMAIN_KERNEL: - nb_events = kernel_list_events(kernel_tracer_fd, events); + nb_events = kernel_list_events(events); if (nb_events < 0) { ret = LTTNG_ERR_KERN_LIST_FAIL; goto error; @@ -2609,7 +2609,7 @@ int cmd_start_trace(struct ltt_session *session) /* Kernel tracing */ if (ksession != NULL) { DBG("Start kernel tracing session %s", session->name); - ret = start_kernel_session(ksession, kernel_tracer_fd); + ret = start_kernel_session(ksession); if (ret != LTTNG_OK) { goto error; } @@ -2686,7 +2686,7 @@ int cmd_stop_trace(struct ltt_session *session) goto error; } - kernel_wait_quiescent(kernel_tracer_fd); + kernel_wait_quiescent(); /* Flush metadata after stopping (if exists) */ if (ksession->metadata_stream_fd >= 0) { diff --git a/src/bin/lttng-sessiond/globals.c b/src/bin/lttng-sessiond/globals.c index a8536afa3..ef57a960d 100644 --- a/src/bin/lttng-sessiond/globals.c +++ b/src/bin/lttng-sessiond/globals.c @@ -33,7 +33,6 @@ struct notification_thread_handle *notification_thread_handle; struct lttng_ht *agent_apps_ht_by_sock = NULL; -int kernel_tracer_fd = -1; struct lttng_kernel_tracer_version kernel_tracer_version; struct lttng_kernel_tracer_abi_version kernel_tracer_abi_version; diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 53072f971..b79503b7d 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -29,12 +30,15 @@ #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" /* * Key used to reference a channel between the sessiond and the consumer. This @@ -42,6 +46,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 +100,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 +115,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; @@ -836,9 +844,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 +1006,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 +1016,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 +1090,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 +1107,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; @@ -1372,12 +1380,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; @@ -1480,3 +1488,109 @@ 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; +} diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h index c822e8d76..0f1abd1d6 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -34,7 +34,7 @@ int kernel_add_channel_context(struct ltt_kernel_channel *chan, struct ltt_kernel_context *ctx); -int kernel_create_session(struct ltt_session *session, int tracer_fd); +int kernel_create_session(struct ltt_session *session); int kernel_create_channel(struct ltt_kernel_session *session, struct lttng_channel *chan); int kernel_create_event(struct lttng_event *ev, struct ltt_kernel_channel *channel, @@ -52,10 +52,9 @@ int kernel_flush_buffer(struct ltt_kernel_channel *channel); int kernel_metadata_flush_buffer(int fd); int kernel_start_session(struct ltt_kernel_session *session); int kernel_stop_session(struct ltt_kernel_session *session); -ssize_t kernel_list_events(int tracer_fd, struct lttng_event **event_list); -void kernel_wait_quiescent(int fd); -int kernel_validate_version(int tracer_fd, - struct lttng_kernel_tracer_version *kernel_tracer_version, +ssize_t kernel_list_events(struct lttng_event **event_list); +void kernel_wait_quiescent(void); +int kernel_validate_version(struct lttng_kernel_tracer_version *kernel_tracer_version, struct lttng_kernel_tracer_abi_version *kernel_tracer_abi_version); void kernel_destroy_session(struct ltt_kernel_session *ksess); void kernel_free_session(struct ltt_kernel_session *ksess); @@ -70,7 +69,10 @@ enum lttng_error_code kernel_rotate_session(struct ltt_session *session); int init_kernel_workarounds(void); ssize_t kernel_list_tracker_pids(struct ltt_kernel_session *session, int **_pids); -int kernel_supports_ring_buffer_snapshot_sample_positions(int tracer_fd); +int kernel_supports_ring_buffer_snapshot_sample_positions(void); +int init_kernel_tracer(void); +void cleanup_kernel_tracer(void); +bool kernel_tracer_is_initialized(void); enum lttng_error_code kernel_create_channel_subdirectories( const struct ltt_kernel_session *ksess); diff --git a/src/bin/lttng-sessiond/lttng-sessiond.h b/src/bin/lttng-sessiond/lttng-sessiond.h index 1cd9eeab6..8846262b6 100644 --- a/src/bin/lttng-sessiond/lttng-sessiond.h +++ b/src/bin/lttng-sessiond/lttng-sessiond.h @@ -75,7 +75,6 @@ extern const char default_home_dir[], default_global_apps_pipe[]; /* Set in main.c at boot time of the daemon */ -extern int kernel_tracer_fd; extern struct lttng_kernel_tracer_version kernel_tracer_version; extern struct lttng_kernel_tracer_abi_version kernel_tracer_abi_version; diff --git a/src/bin/lttng-sessiond/lttng-syscall.c b/src/bin/lttng-sessiond/lttng-syscall.c index b73f137b7..2a7d1eaa0 100644 --- a/src/bin/lttng-sessiond/lttng-syscall.c +++ b/src/bin/lttng-sessiond/lttng-syscall.c @@ -38,7 +38,7 @@ static size_t syscall_table_nb_entry; * Return 0 on success and the syscall table is allocated. On error, a negative * value is returned. */ -int syscall_init_table(void) +int syscall_init_table(int tracer_fd) { int ret, fd, err; size_t nbmem; @@ -51,7 +51,7 @@ int syscall_init_table(void) DBG3("Syscall init system call table"); - fd = kernctl_syscall_list(kernel_tracer_fd); + fd = kernctl_syscall_list(tracer_fd); if (fd < 0) { ret = fd; PERROR("kernelctl syscall list"); diff --git a/src/bin/lttng-sessiond/lttng-syscall.h b/src/bin/lttng-sessiond/lttng-syscall.h index a2708619c..50da7cc74 100644 --- a/src/bin/lttng-sessiond/lttng-syscall.h +++ b/src/bin/lttng-sessiond/lttng-syscall.h @@ -51,7 +51,7 @@ struct syscall { extern struct syscall *syscall_table; /* Use to list kernel system calls. */ -int syscall_init_table(void); +int syscall_init_table(int tracer_fd); ssize_t syscall_table_list(struct lttng_event **events); #endif /* LTTNG_SYSCALL_H */ diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index f698fae4c..5f99bdbf6 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -61,7 +61,6 @@ #include "event.h" #include "kernel.h" #include "kernel-consumer.h" -#include "modprobe.h" #include "shm.h" #include "ust-ctl.h" #include "ust-consumer.h" @@ -75,7 +74,6 @@ #include "notification-thread.h" #include "notification-thread-commands.h" #include "rotation-thread.h" -#include "lttng-syscall.h" #include "agent.h" #include "ht-cleanup.h" #include "sessiond-config.h" @@ -155,8 +153,6 @@ static int apps_cmd_notify_pipe[2] = { -1, -1 }; */ static struct ust_cmd_queue ust_cmd_queue; -static const char *module_proc_lttng = "/proc/lttng"; - /* * Section name to look for in the daemon configuration file. */ @@ -340,16 +336,7 @@ static void sessiond_cleanup(void) wait_consumer(&ustconsumer32_data); if (is_root && !config.no_kernel) { - DBG2("Closing kernel fd"); - if (kernel_tracer_fd >= 0) { - ret = close(kernel_tracer_fd); - if (ret) { - PERROR("close"); - } - } - DBG("Unloading kernel modules"); - modprobe_remove_lttng_all(); - free(syscall_table); + cleanup_kernel_tracer(); } /* @@ -371,81 +358,6 @@ static void sessiond_cleanup_options(void) run_as_destroy_worker(); } -/* - * Setup necessary data for kernel tracer action. - */ -static int init_kernel_tracer(void) -{ - int ret; - - /* 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_fd, &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( - kernel_tracer_fd); - 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); - 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; - } -} - static int string_match(const char *str1, const char *str2) { return (str1 && str2) && !strcmp(str1, str2); @@ -1641,14 +1553,6 @@ int main(int argc, char **argv) /* Setup kernel tracer */ if (!config.no_kernel) { init_kernel_tracer(); - if (kernel_tracer_fd >= 0) { - ret = syscall_init_table(); - if (ret < 0) { - ERR("Unable to populate syscall table. " - "Syscall tracing won't work " - "for this session daemon."); - } - } } /* Set ulimit for open files */ diff --git a/src/bin/lttng-sessiond/notification-thread-events.c b/src/bin/lttng-sessiond/notification-thread-events.c index 052689a0e..bdbac0c40 100644 --- a/src/bin/lttng-sessiond/notification-thread-events.c +++ b/src/bin/lttng-sessiond/notification-thread-events.c @@ -1860,8 +1860,7 @@ int condition_is_supported(struct lttng_condition *condition) * buffers. Therefore, we reject triggers that require that * mechanism to be available to be evaluated. */ - ret = kernel_supports_ring_buffer_snapshot_sample_positions( - kernel_tracer_fd); + ret = kernel_supports_ring_buffer_snapshot_sample_positions(); break; } default: