From b8d29c8bf4afb63bf1ebad35d959348fe412dbb4 Mon Sep 17 00:00:00 2001 From: Francis Deslauriers Date: Thu, 23 Mar 2017 09:13:42 -0400 Subject: [PATCH] Add support for exclusion of kernel event Signed-off-by: Francis Deslauriers --- lttng-abi.c | 12 ++++++ lttng-abi.h | 7 ++++ lttng-events.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++- lttng-events.h | 12 ++++++ 4 files changed, 131 insertions(+), 2 deletions(-) diff --git a/lttng-abi.c b/lttng-abi.c index f2b207cb..7dec9dbc 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -1462,6 +1462,18 @@ long lttng_event_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (struct lttng_kernel_filter_bytecode __user *) arg); } + } + case LTTNG_KERNEL_EXCLUSION: + switch (*evtype) { + case LTTNG_TYPE_EVENT: + return -EINVAL; + case LTTNG_TYPE_ENABLER: + { + enabler = file->private_data; + return lttng_enabler_attach_exclusion(enabler, + (struct lttng_kernel_event_exclusion __user *) arg); + } + } default: return -ENOIOCTLCMD; diff --git a/lttng-abi.h b/lttng-abi.h index dac86584..bff80eea 100644 --- a/lttng-abi.h +++ b/lttng-abi.h @@ -173,6 +173,12 @@ struct lttng_kernel_filter_bytecode { uint64_t seqnum; char data[0]; } __attribute__((packed)); +#define LTTNG_KERNEL_EXCLUSION_PADDING 32 +struct lttng_kernel_event_exclusion { + uint32_t count; + char padding[LTTNG_KERNEL_EXCLUSION_PADDING]; + char names[LTTNG_KERNEL_SYM_NAME_LEN][0]; +} __attribute__((packed)); /* LTTng file descriptor ioctl */ #define LTTNG_KERNEL_SESSION _IO(0xF6, 0x45) @@ -224,6 +230,7 @@ struct lttng_kernel_filter_bytecode { /* Event FD ioctl */ #define LTTNG_KERNEL_FILTER _IO(0xF6, 0x90) +#define LTTNG_KERNEL_EXCLUSION _IO(0xF6, 0x91) /* LTTng-specific ioctls for the lib ringbuffer */ /* returns the timestamp begin of the current sub-buffer */ diff --git a/lttng-events.c b/lttng-events.c index 6aa994ca..fb734896 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -1144,7 +1144,7 @@ int lttng_session_list_tracker_pids(struct lttng_session *session) * Enabler management. */ static -int lttng_match_enabler_star_glob(const char *desc_name, +int lttng_match_event_pattern_star_glob(const char *desc_name, const char *pattern) { if (!strutils_star_glob_match(pattern, LTTNG_SIZE_MAX, @@ -1162,6 +1162,48 @@ int lttng_match_enabler_name(const char *desc_name, return 1; } +static +int lttng_match_enabler_exclusion(const char *desc_name, + struct lttng_enabler *enabler) +{ + struct lttng_excluder_node *excluder; + /** + * Iterate over the list of excluders of this enabler. If the + * event matches with an excluder, return 'do not enable' + */ + list_for_each_entry(excluder, &enabler->excluder_head, node) { + int count; + + for (count = 0; count < excluder->exclusion.count; count++) { + int len; + char *excluder_name; + + excluder_name = (char *) (excluder->exclusion.names) + + (count * LTTNG_KERNEL_SYM_NAME_LEN); + + len = strnlen(excluder_name, LTTNG_KERNEL_SYM_NAME_LEN); + + if (len <= 0) { + continue; + } + + /** + * If the event name matches with the exclusion, + * return 0 to signify that this event should _not_ be + * enabled + */ + if (lttng_match_event_pattern_star_glob(desc_name, excluder_name)) { + return 0; + } + } + } + /** + * If none of the exclusions match with the event name, + * return 1 to signify that this event should be enabled + */ + return 1; +} + static int lttng_desc_match_enabler(const struct lttng_event_desc *desc, struct lttng_enabler *enabler) @@ -1194,7 +1236,17 @@ int lttng_desc_match_enabler(const struct lttng_event_desc *desc, } switch (enabler->type) { case LTTNG_ENABLER_STAR_GLOB: - return lttng_match_enabler_star_glob(desc_name, enabler_name); + { + /** + * Return 'does not match' if the event name does not match with + * the enabler. + */ + if (!lttng_match_event_pattern_star_glob(desc_name, enabler_name)) { + return 0; + } + + return lttng_match_enabler_exclusion(desc_name, enabler); + } case LTTNG_ENABLER_NAME: return lttng_match_enabler_name(desc_name, enabler_name); default: @@ -1386,6 +1438,7 @@ struct lttng_enabler *lttng_enabler_create(enum lttng_enabler_type type, return NULL; enabler->type = type; INIT_LIST_HEAD(&enabler->filter_bytecode_head); + INIT_LIST_HEAD(&enabler->excluder_head); memcpy(&enabler->event_param, event_param, sizeof(enabler->event_param)); enabler->chan = chan; @@ -1447,6 +1500,45 @@ int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler, return ret; } +int lttng_enabler_attach_exclusion(struct lttng_enabler *enabler, + struct lttng_kernel_event_exclusion __user *exclusion) +{ + struct lttng_excluder_node *excluder_node; + uint32_t exclusion_count; + int ret; + + ret = get_user(exclusion_count, &exclusion->count); + if (ret) { + goto error; + } + + excluder_node = kzalloc(sizeof(*excluder_node) + + (exclusion_count * LTTNG_KERNEL_SYM_NAME_LEN), + GFP_KERNEL); + if (!excluder_node) { + ret = -ENOMEM; + goto error; + } + + ret = copy_from_user(&excluder_node->exclusion, exclusion, + sizeof(*exclusion) + (exclusion_count * LTTNG_KERNEL_SYM_NAME_LEN)); + if (ret) { + goto error_free; + } + + excluder_node->enabler = enabler; + excluder_node->exclusion.count = exclusion_count; + + list_add_tail(&excluder_node->node, &enabler->excluder_head); + lttng_session_lazy_sync_enablers(enabler->chan->session); + return 0; + +error_free: + kfree(excluder_node); +error: + return ret; +} + int lttng_enabler_attach_context(struct lttng_enabler *enabler, struct lttng_kernel_context *context_param) { @@ -1457,6 +1549,7 @@ static void lttng_enabler_destroy(struct lttng_enabler *enabler) { struct lttng_filter_bytecode_node *filter_node, *tmp_filter_node; + struct lttng_excluder_node *excluder_node, *tmp_excluder_node; /* Destroy filter bytecode */ list_for_each_entry_safe(filter_node, tmp_filter_node, @@ -1464,6 +1557,11 @@ void lttng_enabler_destroy(struct lttng_enabler *enabler) kfree(filter_node); } + list_for_each_entry_safe(excluder_node, tmp_excluder_node, + &enabler->excluder_head, node) { + kfree(excluder_node); + } + /* Destroy contexts */ lttng_destroy_context(enabler->ctx); diff --git a/lttng-events.h b/lttng-events.h index f55bf663..b71f11b1 100644 --- a/lttng-events.h +++ b/lttng-events.h @@ -258,6 +258,15 @@ struct lttng_filter_bytecode_node { */ struct lttng_kernel_filter_bytecode bc; }; +struct lttng_excluder_node { + struct list_head node; + struct lttng_enabler *enabler; + /* + * struct lttng_kernel_event_exclusion has var. sized array, must be + * last field. + */ + struct lttng_kernel_event_exclusion exclusion; +}; /* * Filter return value masks. @@ -340,6 +349,7 @@ struct lttng_enabler { struct list_head node; /* per-session list of enablers */ /* head list of struct lttng_ust_filter_bytecode_node */ struct list_head filter_bytecode_head; + struct list_head excluder_head; struct lttng_kernel_event event_param; struct lttng_channel *chan; @@ -655,6 +665,8 @@ static inline long lttng_channel_syscall_mask(struct lttng_channel *channel, void lttng_filter_sync_state(struct lttng_bytecode_runtime *runtime); int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler, struct lttng_kernel_filter_bytecode __user *bytecode); +int lttng_enabler_attach_exclusion(struct lttng_enabler *enabler, + struct lttng_kernel_event_exclusion __user *exclusion); void lttng_enabler_event_link_bytecode(struct lttng_event *event, struct lttng_enabler *enabler);