From a5dfbb9db7ba31913657ed921006b13977b7b426 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 28 Jan 2015 09:50:07 -0500 Subject: [PATCH] Implement PID tracker content listing MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- include/lttng/session.h | 13 +++++ src/bin/lttng-sessiond/cmd.c | 51 +++++++++++++++++ src/bin/lttng-sessiond/cmd.h | 2 + src/bin/lttng-sessiond/kernel.c | 71 ++++++++++++++++++++++++ src/bin/lttng-sessiond/kernel.h | 3 + src/bin/lttng-sessiond/main.c | 33 +++++++++++ src/bin/lttng-sessiond/trace-ust.c | 44 +++++++++++++++ src/bin/lttng-sessiond/trace-ust.h | 9 ++- src/bin/lttng/commands/list.c | 48 ++++++++++++++++ src/common/kernel-ctl/kernel-ctl.c | 5 ++ src/common/kernel-ctl/kernel-ctl.h | 1 + src/common/kernel-ctl/kernel-ioctl.h | 1 + src/common/sessiond-comm/sessiond-comm.h | 1 + src/lib/lttng-ctl/lttng-ctl.c | 45 +++++++++++++++ 14 files changed, 326 insertions(+), 1 deletion(-) diff --git a/include/lttng/session.h b/include/lttng/session.h index 7b1c8da6a..302f0fc02 100644 --- a/include/lttng/session.h +++ b/include/lttng/session.h @@ -136,6 +136,19 @@ extern int lttng_track_pid(struct lttng_handle *handle, int pid); */ extern int lttng_untrack_pid(struct lttng_handle *handle, int pid); +/* + * List PIDs in the tracker. + * + * @enabled is set to whether the PID tracker is enabled. + * @pids is set to an allocated array of PIDs currently tracked. On + * success, @pids must be freed by the caller. + * @nr_pids is set to the number of entries contained by the @pids array. + * + * Returns 0 on success, else a negative LTTng error code. + */ +extern int lttng_list_tracker_pids(struct lttng_handle *handle, + int *enabled, int32_t **pids, size_t *nr_pids); + #ifdef __cplusplus } #endif diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index 9ae5cff39..4c1609fd2 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -1949,6 +1949,57 @@ ssize_t cmd_list_syscalls(struct lttng_event **events) return syscall_table_list(events); } +/* + * Command LTTNG_LIST_TRACKER_PIDS processed by the client thread. + * + * Called with session lock held. + */ +ssize_t cmd_list_tracker_pids(struct ltt_session *session, + int domain, int32_t **pids) +{ + int ret; + ssize_t nr_pids = 0; + + switch (domain) { + case LTTNG_DOMAIN_KERNEL: + { + struct ltt_kernel_session *ksess; + + ksess = session->kernel_session; + nr_pids = kernel_list_tracker_pids(ksess, pids); + if (nr_pids < 0) { + ret = LTTNG_ERR_KERN_LIST_FAIL; + goto error; + } + break; + } + case LTTNG_DOMAIN_UST: + { + struct ltt_ust_session *usess; + + usess = session->ust_session; + nr_pids = trace_ust_list_tracker_pids(usess, pids); + if (nr_pids < 0) { + ret = LTTNG_ERR_UST_LIST_FAIL; + goto error; + } + break; + } + case LTTNG_DOMAIN_LOG4J: + case LTTNG_DOMAIN_JUL: + case LTTNG_DOMAIN_PYTHON: + default: + ret = LTTNG_ERR_UND; + goto error; + } + + return nr_pids; + +error: + /* Return negative value to differentiate return code */ + return -ret; +} + /* * Command LTTNG_START_TRACE processed by the client thread. * diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 869bc7009..359d946a6 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -86,6 +86,8 @@ ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events); ssize_t cmd_snapshot_list_outputs(struct ltt_session *session, struct lttng_snapshot_output **outputs); ssize_t cmd_list_syscalls(struct lttng_event **events); +ssize_t cmd_list_tracker_pids(struct ltt_session *session, + int domain, int32_t **pids); int cmd_calibrate(int domain, struct lttng_calibrate *calibrate); int cmd_data_pending(struct ltt_session *session); diff --git a/src/bin/lttng-sessiond/kernel.c b/src/bin/lttng-sessiond/kernel.c index 4bb418949..59d86f45a 100644 --- a/src/bin/lttng-sessiond/kernel.c +++ b/src/bin/lttng-sessiond/kernel.c @@ -381,6 +381,77 @@ int kernel_untrack_pid(struct ltt_kernel_session *session, int pid) return kernctl_untrack_pid(session->fd, pid); } +ssize_t kernel_list_tracker_pids(struct ltt_kernel_session *session, + int **_pids) +{ + int fd, ret; + int pid; + ssize_t nbmem, count = 0; + FILE *fp; + int *pids; + + fd = kernctl_list_tracker_pids(session->fd); + if (fd < 0) { + PERROR("kernel tracker pids list"); + goto error; + } + + fp = fdopen(fd, "r"); + if (fp == NULL) { + PERROR("kernel tracker pids list fdopen"); + goto error_fp; + } + + nbmem = KERNEL_TRACKER_PIDS_INIT_LIST_SIZE; + pids = zmalloc(sizeof(*pids) * nbmem); + if (pids == NULL) { + PERROR("alloc list pids"); + count = -ENOMEM; + 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; + } + + *_pids = pids; + DBG("Kernel list tracker pids done (%zd pids)", count); +end: + ret = fclose(fp); /* closes both fp and fd */ + if (ret) { + PERROR("fclose"); + } + return count; + +error_fp: + ret = close(fd); + if (ret) { + PERROR("close"); + } +error: + return -1; +} + /* * 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 3739bc999..a2d19f143 100644 --- a/src/bin/lttng-sessiond/kernel.h +++ b/src/bin/lttng-sessiond/kernel.h @@ -30,6 +30,7 @@ * dynamic reallocation is performed. */ #define KERNEL_EVENT_INIT_LIST_SIZE 64 +#define KERNEL_TRACKER_PIDS_INIT_LIST_SIZE 64 int kernel_add_channel_context(struct ltt_kernel_channel *chan, struct ltt_kernel_context *ctx); @@ -66,5 +67,7 @@ int kernel_snapshot_record(struct ltt_kernel_session *ksess, int kernel_syscall_mask(int chan_fd, char **syscall_mask, uint32_t *nr_bits); int init_kernel_workarounds(void); +ssize_t kernel_list_tracker_pids(struct ltt_kernel_session *session, + int **_pids); #endif /* _LTT_KERNEL_CTL_H */ diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 966f60917..b2a8f555c 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -2960,6 +2960,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock, case LTTNG_LIST_CHANNELS: case LTTNG_LIST_EVENTS: case LTTNG_LIST_SYSCALLS: + case LTTNG_LIST_TRACKER_PIDS: break; default: /* Setup lttng message with no payload */ @@ -3495,6 +3496,38 @@ skip_domain: ret = LTTNG_OK; break; } + case LTTNG_LIST_TRACKER_PIDS: + { + int32_t *pids = NULL; + ssize_t nr_pids; + + nr_pids = cmd_list_tracker_pids(cmd_ctx->session, + cmd_ctx->lsm->domain.type, &pids); + if (nr_pids < 0) { + /* Return value is a negative lttng_error_code. */ + ret = -nr_pids; + goto error; + } + + /* + * Setup lttng message with payload size set to the event list size in + * bytes and then copy list into the llm payload. + */ + ret = setup_lttng_msg(cmd_ctx, sizeof(int32_t) * nr_pids); + if (ret < 0) { + free(pids); + goto setup_error; + } + + /* Copy event list into message payload */ + memcpy(cmd_ctx->llm->payload, pids, + sizeof(int) * nr_pids); + + free(pids); + + ret = LTTNG_OK; + break; + } case LTTNG_SET_CONSUMER_URI: { size_t nb_uri, len; diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c index e74ed62ba..2740d0f80 100644 --- a/src/bin/lttng-sessiond/trace-ust.c +++ b/src/bin/lttng-sessiond/trace-ust.c @@ -808,6 +808,50 @@ end: return retval; } +/* + * Called with session lock held. + */ +ssize_t trace_ust_list_tracker_pids(struct ltt_ust_session *session, + int32_t **_pids) +{ + struct ust_pid_tracker_node *tracker_node; + struct lttng_ht_iter iter; + unsigned long count, i = 0; + long approx[2]; + int32_t *pids; + int ret = 0; + + if (!session->pid_tracker.ht) { + /* Tracker disabled. Set first entry to -1. */ + pids = zmalloc(sizeof(*pids)); + if (!pids) { + ret = -1; + goto end; + } + pids[0] = -1; + *_pids = pids; + return 1; + } + + rcu_read_lock(); + cds_lfht_count_nodes(session->pid_tracker.ht->ht, + &approx[0], &count, &approx[1]); + pids = zmalloc(sizeof(*pids) * count); + if (!pids) { + ret = -1; + goto end; + } + cds_lfht_for_each_entry(session->pid_tracker.ht->ht, + &iter.iter, tracker_node, node.node) { + pids[i++] = tracker_node->node.key; + } + *_pids = pids; + ret = count; +end: + rcu_read_unlock(); + return ret; +} + /* * RCU safe free context structure. */ diff --git a/src/bin/lttng-sessiond/trace-ust.h b/src/bin/lttng-sessiond/trace-ust.h index ed1883c76..7d6426908 100644 --- a/src/bin/lttng-sessiond/trace-ust.h +++ b/src/bin/lttng-sessiond/trace-ust.h @@ -204,6 +204,9 @@ void trace_ust_destroy_event(struct ltt_ust_event *event); int trace_ust_track_pid(struct ltt_ust_session *session, int pid); int trace_ust_untrack_pid(struct ltt_ust_session *session, int pid); +ssize_t trace_ust_list_tracker_pids(struct ltt_ust_session *session, + int32_t **_pids); + #else /* HAVE_LIBLTTNG_UST_CTL */ static inline int trace_ust_ht_match_event(struct cds_lfht_node *node, @@ -295,7 +298,11 @@ int trace_ust_untrack_pid(struct ltt_ust_session *session, int pid) { return 0; } - +ssize_t trace_ust_list_tracker_pids(struct ltt_ust_session *session, + int32_t **_pids) +{ + return -1; +} #endif /* HAVE_LIBLTTNG_UST_CTL */ #endif /* _LTT_TRACE_UST_H */ diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c index aaa8f47a9..b8d0046aa 100644 --- a/src/bin/lttng/commands/list.c +++ b/src/bin/lttng/commands/list.c @@ -1246,6 +1246,37 @@ error_channels: return ret; } +/* + * List tracker PID(s) of session and domain. + */ +static int list_tracker_pids(void) +{ + int enabled, ret; + int *pids = NULL; + size_t nr_pids, i; + + ret = lttng_list_tracker_pids(handle, + &enabled, &pids, &nr_pids); + if (ret) { + return ret; + } + _MSG("PID tracker: [%s]", enabled ? "enabled" : "disabled"); + if (enabled) { + _MSG(", pids: ["); + + for (i = 0; i < nr_pids; i++) { + if (i) { + _MSG(","); + } + _MSG(" %d", pids[i]); + } + _MSG(" ]"); + } + _MSG("\n\n"); + free(pids); + return 0; +} + /* * Machine interface * Find the session with session_name as name @@ -1667,6 +1698,11 @@ int cmd_list(int argc, const char **argv) } + ret = list_tracker_pids(); + if (ret) { + goto end; + } + ret = list_channels(opt_channel); if (ret) { goto end; @@ -1754,6 +1790,18 @@ int cmd_list(int argc, const char **argv) continue; } + switch (domains[i].type) { + case LTTNG_DOMAIN_KERNEL: + case LTTNG_DOMAIN_UST: + ret = list_tracker_pids(); + if (ret) { + goto end; + } + break; + default: + break; + } + ret = list_channels(opt_channel); if (ret) { goto end; diff --git a/src/common/kernel-ctl/kernel-ctl.c b/src/common/kernel-ctl/kernel-ctl.c index 7168c362c..c6ff5c445 100644 --- a/src/common/kernel-ctl/kernel-ctl.c +++ b/src/common/kernel-ctl/kernel-ctl.c @@ -227,6 +227,11 @@ int kernctl_untrack_pid(int fd, int pid) return ioctl(fd, LTTNG_KERNEL_SESSION_UNTRACK_PID, pid); } +int kernctl_list_tracker_pids(int fd) +{ + return ioctl(fd, LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS); +} + 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 e854eba0e..5f2e014d1 100644 --- a/src/common/kernel-ctl/kernel-ctl.h +++ b/src/common/kernel-ctl/kernel-ctl.h @@ -62,6 +62,7 @@ int kernctl_syscall_mask(int fd, char **syscall_mask, /* 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); +int kernctl_list_tracker_pids(int fd); /* Buffer operations */ diff --git a/src/common/kernel-ctl/kernel-ioctl.h b/src/common/kernel-ctl/kernel-ioctl.h index 4050350ed..528c8082b 100644 --- a/src/common/kernel-ctl/kernel-ioctl.h +++ b/src/common/kernel-ctl/kernel-ioctl.h @@ -121,6 +121,7 @@ _IOR(0xF6, 0x58, int32_t) #define LTTNG_KERNEL_SESSION_UNTRACK_PID \ _IOR(0xF6, 0x59, int32_t) +#define LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS _IO(0xF6, 0x58) /* Channel FD ioctl */ #define LTTNG_KERNEL_STREAM _IO(0xF6, 0x62) diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index a56c914fc..1e51ae123 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -93,6 +93,7 @@ enum lttcomm_sessiond_command { LTTNG_SAVE_SESSION = 31, LTTNG_TRACK_PID = 32, LTTNG_UNTRACK_PID = 33, + LTTNG_LIST_TRACKER_PIDS = 34, LTTNG_SET_SESSION_SHM_PATH = 40, }; diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index c2210f48a..004b0cceb 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1990,6 +1990,51 @@ end: return ret; } +/* + * List PIDs in the tracker. + * + * @enabled is set to whether the PID tracker is enabled. + * @pids is set to an allocated array of PIDs currently tracked. On + * success, @pids must be freed by the caller. + * @nr_pids is set to the number of entries contained by the @pids array. + * + * Returns 0 on success, else a negative LTTng error code. + */ +int lttng_list_tracker_pids(struct lttng_handle *handle, + int *_enabled, int32_t **_pids, size_t *_nr_pids) +{ + int ret, enabled = 1; + struct lttcomm_session_msg lsm; + size_t nr_pids; + int32_t *pids; + + if (handle == NULL) { + return -LTTNG_ERR_INVALID; + } + + memset(&lsm, 0, sizeof(lsm)); + lsm.cmd_type = LTTNG_LIST_TRACKER_PIDS; + lttng_ctl_copy_string(lsm.session.name, handle->session_name, + sizeof(lsm.session.name)); + lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain); + + ret = lttng_ctl_ask_sessiond(&lsm, (void **) &pids); + if (ret < 0) { + return ret; + } + nr_pids = ret / sizeof(int32_t); + if (nr_pids == 1 && pids[0] == -1) { + free(pids); + pids = NULL; + enabled = 0; + nr_pids = 0; + } + *_enabled = enabled; + *_pids = pids; + *_nr_pids = nr_pids; + return 0; +} + /* * lib constructor */ -- 2.34.1