From: Mathieu Desnoyers Date: Sat, 27 Sep 2014 21:29:12 +0000 (-0400) Subject: Implement PID tracking for kernel tracing X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=ccf10263bcd2ca4667b9e1fc4dab64a3c8d8c4d8 Implement PID tracking for kernel tracing Implement PID tracking (per-session) for kernel tracing. Only save/restore and MI are missing. Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- diff --git a/include/lttng/session.h b/include/lttng/session.h index c87efbd1d..7b1c8da6a 100644 --- a/include/lttng/session.h +++ b/include/lttng/session.h @@ -116,6 +116,26 @@ extern int lttng_list_sessions(struct lttng_session **sessions); extern int lttng_set_session_shm_path(const char *session_name, const char *shm_path); +/* + * Add PID to session tracker. + * + * A pid argument >= 0 adds the PID to the session tracker. + * A pid argument of -1 means "track all PIDs". + * + * Return 0 on success else a negative LTTng error code. + */ +extern int lttng_track_pid(struct lttng_handle *handle, int pid); + +/* + * Remove PID from session tracker. + * + * A pid argument >= 0 removes the PID from the session tracker. + * A pid argument of -1 means "untrack all PIDs". + * + * Return 0 on success else a negative LTTng error code. + */ +extern int lttng_untrack_pid(struct lttng_handle *handle, int pid); + #ifdef __cplusplus } #endif diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index bf6097b64..91ea88cb7 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -929,6 +929,90 @@ error: return ret; } +/* + * Command LTTNG_TRACK_PID processed by the client thread. + */ +int cmd_track_pid(struct ltt_session *session, int domain, int pid) +{ + int ret; + + rcu_read_lock(); + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + { + struct ltt_kernel_session *ksess; + + ksess = session->kernel_session; + + ret = kernel_track_pid(ksess, pid); + if (ret != LTTNG_OK) { + goto error; + } + + kernel_wait_quiescent(kernel_tracer_fd); + break; + } +#if 0 + case LTTNG_DOMAIN_UST: + case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: + case LTTNG_DOMAIN_UST_EXEC_NAME: + case LTTNG_DOMAIN_UST_PID: +#endif + default: + ret = LTTNG_ERR_UNKNOWN_DOMAIN; + goto error; + } + + ret = LTTNG_OK; + +error: + rcu_read_unlock(); + return ret; +} + +/* + * Command LTTNG_UNTRACK_PID processed by the client thread. + */ +int cmd_untrack_pid(struct ltt_session *session, int domain, int pid) +{ + int ret; + + rcu_read_lock(); + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + { + struct ltt_kernel_session *ksess; + + ksess = session->kernel_session; + + ret = kernel_untrack_pid(ksess, pid); + if (ret != LTTNG_OK) { + goto error; + } + + kernel_wait_quiescent(kernel_tracer_fd); + break; + } +#if 0 + case LTTNG_DOMAIN_UST: + case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN: + case LTTNG_DOMAIN_UST_EXEC_NAME: + case LTTNG_DOMAIN_UST_PID: +#endif + default: + ret = LTTNG_ERR_UNKNOWN_DOMAIN; + goto error; + } + + ret = LTTNG_OK; + +error: + rcu_read_unlock(); + return ret; +} + /* * Command LTTNG_ENABLE_CHANNEL processed by the client thread. * diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 7144690ca..869bc7009 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -37,9 +37,10 @@ int cmd_destroy_session(struct ltt_session *session, int wpipe); /* Channel commands */ int cmd_disable_channel(struct ltt_session *session, int domain, char *channel_name); - int cmd_enable_channel(struct ltt_session *session, struct lttng_domain *domain, struct lttng_channel *attr, int wpipe); +int cmd_track_pid(struct ltt_session *session, int domain, int pid); +int cmd_untrack_pid(struct ltt_session *session, int domain, int pid); /* Event commands */ int cmd_disable_event(struct ltt_session *session, int domain, diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 9464a84f0..4bb418949 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -367,6 +367,20 @@ int kernel_disable_syscall(const char *syscall_name, return kernctl_disable_syscall(channel->fd, syscall_name); } +int kernel_track_pid(struct ltt_kernel_session *session, int pid) +{ + DBG("Kernel track PID %d for session id %" PRIu64 ".", + pid, session->id); + return kernctl_track_pid(session->fd, pid); +} + +int kernel_untrack_pid(struct ltt_kernel_session *session, int pid) +{ + DBG("Kernel untrack PID %d for session id %" PRIu64 ".", + pid, session->id); + return kernctl_untrack_pid(session->fd, pid); +} + /* * Create kernel metadata, open from the kernel tracer and add it to the * kernel session. diff --git a/src/bin/lttng-sessiond/kernel.h b/src/bin/lttng-sessiond/kernel.h index 09c3ed992..3739bc999 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -45,6 +45,8 @@ int kernel_enable_syscall(const char *syscall_name, struct ltt_kernel_channel *channel); int kernel_disable_syscall(const char *syscall_name, struct ltt_kernel_channel *channel); +int kernel_track_pid(struct ltt_kernel_session *session, int pid); +int kernel_untrack_pid(struct ltt_kernel_session *session, int pid); int kernel_open_metadata(struct ltt_kernel_session *session); int kernel_open_metadata_stream(struct ltt_kernel_session *session); int kernel_open_channel_stream(struct ltt_kernel_channel *channel); diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 89ef3b092..21b4cf326 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -3252,6 +3252,20 @@ skip_domain: &cmd_ctx->lsm->u.channel.chan, kernel_poll_pipe[1]); break; } + case LTTNG_TRACK_PID: + { + ret = cmd_track_pid(cmd_ctx->session, + cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.pid_tracker.pid); + break; + } + case LTTNG_UNTRACK_PID: + { + ret = cmd_untrack_pid(cmd_ctx->session, + cmd_ctx->lsm->domain.type, + cmd_ctx->lsm->u.pid_tracker.pid); + break; + } case LTTNG_ENABLE_EVENT: { struct lttng_event_exclusion *exclusion = NULL; diff --git a/src/bin/lttng-sessiond/save.c b/src/bin/lttng-sessiond/save.c index c6fc33e7b..6cb220c2f 100644 --- a/src/bin/lttng-sessiond/save.c +++ b/src/bin/lttng-sessiond/save.c @@ -716,6 +716,8 @@ end: return ret; } +/* TODO: save/restore tracker pid */ + static int save_kernel_context(struct config_writer *writer, struct lttng_kernel_context *ctx) diff --git a/src/bin/lttng/Makefile.am b/src/bin/lttng/Makefile.am index ec04e4d7b..9f00caeae 100644 --- a/src/bin/lttng/Makefile.am +++ b/src/bin/lttng/Makefile.am @@ -15,6 +15,7 @@ lttng_SOURCES = command.h conf.c conf.h commands/start.c \ commands/snapshot.c \ commands/save.c \ commands/load.c \ + commands/track-untrack.c \ utils.c utils.h lttng.c lttng_LDADD = $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la \ diff --git a/src/bin/lttng/command.h b/src/bin/lttng/command.h index 3d4bbf8eb..a4f06d446 100644 --- a/src/bin/lttng/command.h +++ b/src/bin/lttng/command.h @@ -58,5 +58,7 @@ extern int cmd_disable_consumer(int argc, const char **argv); extern int cmd_snapshot(int argc, const char **argv); extern int cmd_save(int argc, const char **argv); extern int cmd_load(int argc, const char **argv); +extern int cmd_track(int argc, const char **argv); +extern int cmd_untrack(int argc, const char **argv); #endif /* _LTTNG_CMD_H */ diff --git a/src/bin/lttng/commands/track-untrack.c b/src/bin/lttng/commands/track-untrack.c new file mode 100644 index 000000000..52442cc13 --- /dev/null +++ b/src/bin/lttng/commands/track-untrack.c @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2011 - David Goulet + * Copyright (C) 2015 - Mathieu Desnoyers + * + * 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. + * + * 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 _GNU_SOURCE +#define _LGPL_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "../command.h" + +enum cmd_type { + CMD_TRACK, + CMD_UNTRACK, +}; + +static char *opt_session_name; +static int opt_kernel; +static int opt_userspace; +static int opt_all; +static char *opt_pid_string; +static int opt_pid; + +enum { + OPT_HELP = 1, + OPT_LIST_OPTIONS, + OPT_SESSION, + OPT_PID, +}; + +static struct poptOption long_options[] = { + /* { longName, shortName, argInfo, argPtr, value, descrip, argDesc, } */ + { "help", 'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0, }, + { "session", 's', POPT_ARG_STRING, &opt_session_name, OPT_SESSION, 0, 0, }, + { "kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0, }, + { "userspace", 'u', POPT_ARG_VAL, &opt_userspace, 1, 0, 0, }, + { "pid", 'p', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_pid_string, OPT_PID, 0, 0, }, + { "all", 'a', POPT_ARG_VAL, &opt_all, 1, 0, 0, }, + { "list-options", 0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, 0, 0, }, + { 0, 0, 0, 0, 0, 0, 0, }, +}; + +/* + * usage + */ +static void usage(FILE *ofp, const char *cmd_str) +{ + fprintf(ofp, "usage: lttng %s [-k|-u] [OPTIONS]\n", cmd_str); + fprintf(ofp, "\n"); + fprintf(ofp, "If no session is given (-s), the context is added to\n"); + fprintf(ofp, "the current sesssion. Exactly one domain (-k or -u)\n"); + fprintf(ofp, "must be specified.\n"); + fprintf(ofp, "\n"); + fprintf(ofp, "Options:\n"); + fprintf(ofp, " -h, --help Show this help.\n"); + fprintf(ofp, " --list-options Simple listing of options.\n"); + fprintf(ofp, " -s, --session NAME Apply to session name.\n"); + fprintf(ofp, " -k, --kernel Apply to the kernel tracer.\n"); + fprintf(ofp, " -u, --userspace Apply to the user-space tracer.\n"); + fprintf(ofp, " -p, --pid [PID] Process ID tracker. Leave PID empty when used with --all.\n"); + fprintf(ofp, " -a, --all All PIDs (use with --pid).\n"); + fprintf(ofp, "\n"); +} + +static +int parse_pid_string(const char *_pid_string, + int all, int **_pid_list, int *nr_pids) +{ + const char *one_pid_str; + char *iter; + int retval = CMD_SUCCESS; + int count = 0; + int *pid_list = NULL; + char *pid_string = NULL; + + if (all && _pid_string) { + ERR("An empty PID string is expected with --all"); + retval = CMD_ERROR; + goto error; + } + if (!all && !_pid_string) { + ERR("Please specify --all with an empty PID string"); + retval = CMD_ERROR; + goto error; + } + if (all) { + pid_list = zmalloc(sizeof(*_pid_list)); + if (!pid_list) { + ERR("Out of memory"); + retval = CMD_ERROR; + goto error; + } + /* Empty PID string means all PIDs */ + count = 1; + pid_list[0] = -1; + goto assign; + } + + pid_string = strdup(_pid_string); + if (!pid_string) { + ERR("Out of memory"); + retval = CMD_ERROR; + goto error; + } + + /* Count */ + one_pid_str = strtok_r(pid_string, ",", &iter); + while (one_pid_str != NULL) { + unsigned long v; + + v = strtoul(one_pid_str, NULL, 10); + if ((v == 0 && errno == EINVAL) + || (v == ULONG_MAX && errno == ERANGE)) { + ERR("Error parsing PID %s", one_pid_str); + retval = CMD_ERROR; + goto error; + } + if ((long) v > INT_MAX || (int) v < 0) { + ERR("Invalid PID value %ld", (long) v); + retval = CMD_ERROR; + goto error; + } + count++; + + /* For next loop */ + one_pid_str = strtok_r(NULL, ",", &iter); + } + + free(pid_string); + /* Identity of delimiter has been lost in first pass. */ + pid_string = strdup(_pid_string); + if (!pid_string) { + ERR("Out of memory"); + retval = CMD_ERROR; + goto error; + } + + /* Allocate */ + pid_list = zmalloc(count * sizeof(*pid_list)); + if (!pid_list) { + ERR("Out of memory"); + retval = CMD_ERROR; + goto error; + } + + /* Copy */ + count = 0; + one_pid_str = strtok_r(pid_string, ",", &iter); + while (one_pid_str != NULL) { + unsigned long v; + + v = strtoul(one_pid_str, NULL, 10); + pid_list[count++] = (int) v; + + /* For next loop */ + one_pid_str = strtok_r(NULL, ",", &iter); + } + +assign: + *nr_pids = count; + *_pid_list = pid_list; + goto end; /* SUCCESS */ + + /* ERROR */ +error: + free(pid_list); +end: + free(pid_string); + return retval; +} + +static +int track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str, + const char *session_name, const char *pid_string, + int all, struct mi_writer *writer) +{ + int ret, retval = CMD_SUCCESS, i; + int *pid_list = NULL; + int nr_pids; + struct lttng_domain dom; + struct lttng_handle *handle = NULL; + int (*lib_func)(struct lttng_handle *handle, int pid); + + switch (cmd_type) { + case CMD_TRACK: + lib_func = lttng_track_pid; + break; + case CMD_UNTRACK: + lib_func = lttng_untrack_pid; + break; + default: + ERR("Unknown command"); + retval = CMD_ERROR; + goto end; + } + + memset(&dom, 0, sizeof(dom)); + if (opt_kernel) { + dom.type = LTTNG_DOMAIN_KERNEL; + } else if (opt_userspace) { + dom.type = LTTNG_DOMAIN_UST; + } else { + print_missing_domain(); + ret = CMD_ERROR; + goto end; + } + + ret = parse_pid_string(pid_string, all, &pid_list, &nr_pids); + if (ret != CMD_SUCCESS) { + ERR("Error parsing PID string"); + usage(stderr, cmd_str); + retval = CMD_ERROR; + goto end; + } + + handle = lttng_create_handle(session_name, &dom); + if (handle == NULL) { + retval = CMD_ERROR; + goto end; + } + + if (writer) { + /* Open pids element */ + ret = mi_lttng_writer_open_element(writer, config_element_pids); + if (ret) { + retval = CMD_ERROR; + goto end; + } + } + + /* TODO: MI */ + for (i = 0; i < nr_pids; i++) { + DBG("%s PID %d", cmd_str, pid_list[i]); + ret = lib_func(handle, pid_list[i]); + if (ret) { + retval = CMD_ERROR; + goto end; + } + } + + if (writer) { + /* Close pids element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + retval = CMD_ERROR; + goto end; + } + } + + /* SUCCESS */ +end: + if (handle) { + lttng_destroy_handle(handle); + } + free(pid_list); + return retval; +} + +static +const char *get_mi_element_command(enum cmd_type cmd_type) +{ + switch (cmd_type) { + case CMD_TRACK: + return mi_lttng_element_command_track; + case CMD_UNTRACK: + return mi_lttng_element_command_untrack; + default: + return NULL; + } +} + +/* + * Add/remove tracker to/from session. + */ +static +int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str, + int argc, const char **argv) +{ + int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS; + int success = 1; + static poptContext pc; + char *session_name = NULL; + struct mi_writer *writer = NULL; + + if (argc < 1) { + usage(stderr, cmd_str); + ret = CMD_ERROR; + goto end; + } + + pc = poptGetContext(NULL, argc, argv, long_options, 0); + poptReadDefaultConfig(pc, 0); + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case OPT_HELP: + usage(stdout, cmd_str); + goto end; + case OPT_LIST_OPTIONS: + list_cmd_options(stdout, long_options); + goto end; + case OPT_SESSION: + case OPT_PID: + opt_pid = 1; + break; + default: + usage(stderr, cmd_str); + ret = CMD_UNDEFINED; + goto end; + } + } + + if (!(opt_userspace ^ opt_kernel)) { + ERR("Exactly one of -u or -k needs to be specified."); + usage(stderr, cmd_str); + ret = CMD_ERROR; + goto end; + } + + if (!opt_session_name) { + session_name = get_session_name(); + if (session_name == NULL) { + ret = CMD_ERROR; + goto end; + } + } else { + session_name = opt_session_name; + } + + /* Currently only PID tracker is supported */ + if (!opt_pid) { + ERR("Please specify at least one tracker with its expected arguments"); + usage(stderr, cmd_str); + ret = CMD_ERROR; + goto end; + } + + /* Mi check */ + if (lttng_opt_mi) { + writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi); + if (!writer) { + ret = CMD_ERROR; + goto end; + } + } + + if (writer) { + /* Open command element */ + ret = mi_lttng_writer_command_open(writer, + get_mi_element_command(cmd_type)); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Open output element */ + ret = mi_lttng_writer_open_element(writer, + mi_lttng_element_command_output); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } + + command_ret = track_untrack_pid(cmd_type, + cmd_str, session_name, opt_pid_string, + opt_all, writer); + if (command_ret) { + success = 0; + } + + /* Mi closing */ + if (writer) { + /* Close output element */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Success ? */ + ret = mi_lttng_writer_write_element_bool(writer, + mi_lttng_element_command_success, success); + if (ret) { + ret = CMD_ERROR; + goto end; + } + + /* Command element close */ + ret = mi_lttng_writer_command_close(writer); + if (ret) { + ret = CMD_ERROR; + goto end; + } + } + +end: + if (!opt_session_name) { + free(session_name); + } + + /* Mi clean-up */ + if (writer && mi_lttng_writer_destroy(writer)) { + /* Preserve original error code */ + ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL; + } + + /* Overwrite ret if an error occurred during track() */ + ret = command_ret ? command_ret : ret; + + poptFreeContext(pc); + return ret; +} + +int cmd_track(int argc, const char **argv) +{ + return cmd_track_untrack(CMD_TRACK, "track", argc, argv); +} + +int cmd_untrack(int argc, const char **argv) +{ + return cmd_track_untrack(CMD_UNTRACK, "untrack", argc, argv); +} diff --git a/src/bin/lttng/lttng.c b/src/bin/lttng/lttng.c index 8e5bb0fd4..13c77321e 100644 --- a/src/bin/lttng/lttng.c +++ b/src/bin/lttng/lttng.c @@ -85,6 +85,8 @@ static struct cmd_struct commands[] = { { "snapshot", cmd_snapshot}, { "save", cmd_save}, { "load", cmd_load}, + { "track", cmd_track}, + { "untrack", cmd_untrack}, { NULL, NULL} /* Array closure */ }; @@ -126,6 +128,8 @@ static void usage(FILE *ofp) fprintf(ofp, " view Start trace viewer\n"); fprintf(ofp, " save Save session configuration\n"); fprintf(ofp, " load Load session configuration\n"); + fprintf(ofp, " track Track specific system resources\n"); + fprintf(ofp, " untrack Untrack specific system resources\n"); fprintf(ofp, "\n"); fprintf(ofp, "Each command also has its own -h, --help option.\n"); fprintf(ofp, "\n"); diff --git a/src/common/config/config-session-abi.h b/src/common/config/config-session-abi.h index 1a1feec06..8cbff25f5 100644 --- a/src/common/config/config-session-abi.h +++ b/src/common/config/config-session-abi.h @@ -65,6 +65,8 @@ const char * const config_element_net_output; const char * const config_element_control_uri; const char * const config_element_data_uri; const char * const config_element_max_size; +const char * const config_element_pid; +const char * const config_element_pids; const char * const config_domain_type_kernel; const char * const config_domain_type_ust; diff --git a/src/common/config/config.c b/src/common/config/config.c index ece7cdb2a..d84e38b9f 100644 --- a/src/common/config/config.c +++ b/src/common/config/config.c @@ -115,6 +115,8 @@ const char * const config_element_net_output = "net_output"; const char * const config_element_control_uri = "control_uri"; const char * const config_element_data_uri = "data_uri"; const char * const config_element_max_size = "max_size"; +const char * const config_element_pid = "pid"; +const char * const config_element_pids = "pids"; const char * const config_domain_type_kernel = "KERNEL"; const char * const config_domain_type_ust = "UST"; diff --git a/src/common/kernel-ctl/kernel-ctl.c b/src/common/kernel-ctl/kernel-ctl.c index b223ceac8..7168c362c 100644 --- a/src/common/kernel-ctl/kernel-ctl.c +++ b/src/common/kernel-ctl/kernel-ctl.c @@ -217,6 +217,16 @@ end: return ret; } +int kernctl_track_pid(int fd, int pid) +{ + return ioctl(fd, LTTNG_KERNEL_SESSION_TRACK_PID, pid); +} + +int kernctl_untrack_pid(int fd, int pid) +{ + return ioctl(fd, LTTNG_KERNEL_SESSION_UNTRACK_PID, pid); +} + int kernctl_create_stream(int fd) { return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_STREAM, diff --git a/src/common/kernel-ctl/kernel-ctl.h b/src/common/kernel-ctl/kernel-ctl.h index d9e6c54a4..e854eba0e 100644 --- a/src/common/kernel-ctl/kernel-ctl.h +++ b/src/common/kernel-ctl/kernel-ctl.h @@ -59,6 +59,10 @@ int kernctl_disable_syscall(int fd, const char *syscall_name); int kernctl_syscall_mask(int fd, char **syscall_mask, uint32_t *nr_bits); +/* Process ID tracking can be applied to session FD */ +int kernctl_track_pid(int fd, int pid); +int kernctl_untrack_pid(int fd, int pid); + /* Buffer operations */ /* For mmap mode, readable without "get" operation */ diff --git a/src/common/kernel-ctl/kernel-ioctl.h b/src/common/kernel-ctl/kernel-ioctl.h index 927de6fd6..4050350ed 100644 --- a/src/common/kernel-ctl/kernel-ioctl.h +++ b/src/common/kernel-ctl/kernel-ioctl.h @@ -117,6 +117,10 @@ _IOW(0xF6, 0x55, struct lttng_kernel_channel) #define LTTNG_KERNEL_SESSION_START _IO(0xF6, 0x56) #define LTTNG_KERNEL_SESSION_STOP _IO(0xF6, 0x57) +#define LTTNG_KERNEL_SESSION_TRACK_PID \ + _IOR(0xF6, 0x58, int32_t) +#define LTTNG_KERNEL_SESSION_UNTRACK_PID \ + _IOR(0xF6, 0x59, int32_t) /* Channel FD ioctl */ #define LTTNG_KERNEL_STREAM _IO(0xF6, 0x62) diff --git a/src/common/mi-lttng.c b/src/common/mi-lttng.c index fed09854a..44ff56f1e 100644 --- a/src/common/mi-lttng.c +++ b/src/common/mi-lttng.c @@ -50,6 +50,8 @@ const char * const mi_lttng_element_command_snapshot_record = "record_snapshot"; const char * const mi_lttng_element_command_start = "start"; const char * const mi_lttng_element_command_stop = "stop"; const char * const mi_lttng_element_command_success = "success"; +const char * const mi_lttng_element_command_track = "track"; +const char * const mi_lttng_element_command_untrack = "untrack"; const char * const mi_lttng_element_command_version = "version"; /* Strings related to version command */ @@ -1238,6 +1240,9 @@ int mi_lttng_calibrate(struct mi_writer *writer, end: return ret; } + +/* TODO: mi tracker */ + LTTNG_HIDDEN int mi_lttng_context(struct mi_writer *writer, struct lttng_event_context *context, int is_open) diff --git a/src/common/mi-lttng.h b/src/common/mi-lttng.h index fd1ef936e..02c6b731e 100644 --- a/src/common/mi-lttng.h +++ b/src/common/mi-lttng.h @@ -73,6 +73,8 @@ const char * const mi_lttng_element_command_snapshot_record; const char * const mi_lttng_element_command_start; const char * const mi_lttng_element_command_stop; const char * const mi_lttng_element_command_success; +const char * const mi_lttng_element_command_track; +const char * const mi_lttng_element_command_untrack; const char * const mi_lttng_element_command_version; /* Strings related to version command */ diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 5078b522b..a56c914fc 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -91,8 +91,8 @@ enum lttcomm_sessiond_command { LTTNG_CREATE_SESSION_SNAPSHOT = 29, LTTNG_CREATE_SESSION_LIVE = 30, LTTNG_SAVE_SESSION = 31, - - /* Session daemon commands (cont.) */ + LTTNG_TRACK_PID = 32, + LTTNG_UNTRACK_PID = 33, LTTNG_SET_SESSION_SHM_PATH = 40, }; @@ -302,6 +302,9 @@ struct lttcomm_session_msg { struct { char shm_path[PATH_MAX]; } LTTNG_PACKED set_shm_path; + struct { + uint32_t pid; + } LTTNG_PACKED pid_tracker; } u; } LTTNG_PACKED; diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 4332881c6..c2210f48a 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1280,6 +1280,62 @@ int lttng_disable_channel(struct lttng_handle *handle, const char *name) return lttng_ctl_ask_sessiond(&lsm, NULL); } +/* + * Add PID to session tracker. + * Return 0 on success else a negative LTTng error code. + */ +int lttng_track_pid(struct lttng_handle *handle, int pid) +{ + struct lttcomm_session_msg lsm; + + /* + * NULL arguments are forbidden. No default values. + */ + if (handle == NULL) { + return -LTTNG_ERR_INVALID; + } + + memset(&lsm, 0, sizeof(lsm)); + + lsm.cmd_type = LTTNG_TRACK_PID; + lsm.u.pid_tracker.pid = pid; + + lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); + + lttng_ctl_copy_string(lsm.session.name, handle->session_name, + sizeof(lsm.session.name)); + + return lttng_ctl_ask_sessiond(&lsm, NULL); +} + +/* + * Remove PID from session tracker. + * Return 0 on success else a negative LTTng error code. + */ +int lttng_untrack_pid(struct lttng_handle *handle, int pid) +{ + struct lttcomm_session_msg lsm; + + /* + * NULL arguments are forbidden. No default values. + */ + if (handle == NULL) { + return -LTTNG_ERR_INVALID; + } + + memset(&lsm, 0, sizeof(lsm)); + + lsm.cmd_type = LTTNG_UNTRACK_PID; + lsm.u.pid_tracker.pid = pid; + + lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); + + lttng_ctl_copy_string(lsm.session.name, handle->session_name, + sizeof(lsm.session.name)); + + return lttng_ctl_ask_sessiond(&lsm, NULL); +} + /* * Lists all available tracepoints of domain. * Sets the contents of the events array.