From 33a39a3cd074931ab3a2eaff6eb8807091cf8172 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 4 Nov 2014 19:12:04 -0500 Subject: [PATCH] Implement syscall wildcard support Signed-off-by: Mathieu Desnoyers --- lttng-abi.c | 103 ++++++++++++++++++----------------------------- lttng-abi.h | 5 --- lttng-events.c | 43 +++++++++++++++++--- lttng-events.h | 5 +++ lttng-probes.c | 6 +-- lttng-syscalls.c | 28 ++++++++----- 6 files changed, 102 insertions(+), 88 deletions(-) diff --git a/lttng-abi.c b/lttng-abi.c index eaa2f63f..ede2ae79 100644 --- a/lttng-abi.c +++ b/lttng-abi.c @@ -929,74 +929,51 @@ int lttng_abi_create_event(struct file *channel_file, default: break; } - switch (event_param->instrumentation) { - default: - event_fd = lttng_get_unused_fd(); - if (event_fd < 0) { - ret = event_fd; - goto fd_error; - } - event_file = anon_inode_getfile("[lttng_event]", - <tng_event_fops, - NULL, O_RDWR); - if (IS_ERR(event_file)) { - ret = PTR_ERR(event_file); - goto file_error; - } - if (event_param->instrumentation == LTTNG_KERNEL_TRACEPOINT) { - struct lttng_enabler *enabler; - - if (event_param->name[strlen(event_param->name) - 1] == '*') { - enabler = lttng_enabler_create(LTTNG_ENABLER_WILDCARD, - event_param, channel); - } else { - enabler = lttng_enabler_create(LTTNG_ENABLER_NAME, - event_param, channel); - } - priv = enabler; + event_fd = lttng_get_unused_fd(); + if (event_fd < 0) { + ret = event_fd; + goto fd_error; + } + event_file = anon_inode_getfile("[lttng_event]", + <tng_event_fops, + NULL, O_RDWR); + if (IS_ERR(event_file)) { + ret = PTR_ERR(event_file); + goto file_error; + } + if (event_param->instrumentation == LTTNG_KERNEL_TRACEPOINT + || event_param->instrumentation == LTTNG_KERNEL_SYSCALL) { + struct lttng_enabler *enabler; + + if (event_param->name[strlen(event_param->name) - 1] == '*') { + enabler = lttng_enabler_create(LTTNG_ENABLER_WILDCARD, + event_param, channel); } else { - struct lttng_event *event; - - /* - * We tolerate no failure path after event creation. It - * will stay invariant for the rest of the session. - */ - event = lttng_event_create(channel, event_param, - NULL, NULL, - event_param->instrumentation); - WARN_ON_ONCE(!event); - if (IS_ERR(event)) { - ret = PTR_ERR(event); - goto event_error; - } - priv = event; + enabler = lttng_enabler_create(LTTNG_ENABLER_NAME, + event_param, channel); } - event_file->private_data = priv; - fd_install(event_fd, event_file); - /* The event holds a reference on the channel */ - atomic_long_inc(&channel_file->f_count); - break; - case LTTNG_KERNEL_SYSCALL: - ret = lttng_syscalls_register(channel, NULL); - if (ret) - goto fd_error; - event_fd = 0; - if (event_param->u.syscall.enable) { - ret = lttng_syscall_filter_enable(channel, - !strcmp(event_param->name, "*") ? - NULL : event_param->name); - if (ret) - goto fd_error; + priv = enabler; + } else { + struct lttng_event *event; - } else { - ret = lttng_syscall_filter_disable(channel, - !strcmp(event_param->name, "*") ? - NULL : event_param->name); - if (ret) - goto fd_error; + /* + * We tolerate no failure path after event creation. It + * will stay invariant for the rest of the session. + */ + event = lttng_event_create(channel, event_param, + NULL, NULL, + event_param->instrumentation); + WARN_ON_ONCE(!event); + if (IS_ERR(event)) { + ret = PTR_ERR(event); + goto event_error; } - break; + priv = event; } + event_file->private_data = priv; + fd_install(event_fd, event_file); + /* The event holds a reference on the channel */ + atomic_long_inc(&channel_file->f_count); return event_fd; event_error: diff --git a/lttng-abi.h b/lttng-abi.h index a2e34ff7..7239f76f 100644 --- a/lttng-abi.h +++ b/lttng-abi.h @@ -86,10 +86,6 @@ struct lttng_kernel_function_tracer { char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN]; } __attribute__((packed)); -struct lttng_kernel_syscall { - char enable; -} __attribute__((packed)); - /* * For syscall tracing, name = "*" means "enable all". */ @@ -105,7 +101,6 @@ struct lttng_kernel_event { struct lttng_kernel_kretprobe kretprobe; struct lttng_kernel_kprobe kprobe; struct lttng_kernel_function_tracer ftrace; - struct lttng_kernel_syscall syscall; char padding[LTTNG_KERNEL_EVENT_PADDING2]; } u; } __attribute__((packed)); diff --git a/lttng-events.c b/lttng-events.c index 3616e010..d09d4c2e 100644 --- a/lttng-events.c +++ b/lttng-events.c @@ -481,6 +481,7 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: + case LTTNG_KERNEL_SYSCALL: event_name = event_param->name; break; default: @@ -614,6 +615,7 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, WARN_ON_ONCE(!ret); break; case LTTNG_KERNEL_NOOP: + case LTTNG_KERNEL_SYSCALL: event->enabled = 1; event->registered = 0; event->desc = event_desc; @@ -711,6 +713,7 @@ int _lttng_event_unregister(struct lttng_event *event) ret = 0; break; case LTTNG_KERNEL_NOOP: + case LTTNG_KERNEL_SYSCALL: ret = 0; break; default: @@ -744,6 +747,7 @@ void _lttng_event_destroy(struct lttng_event *event) lttng_ftrace_destroy_private(event); break; case LTTNG_KERNEL_NOOP: + case LTTNG_KERNEL_SYSCALL: break; default: WARN_ON_ONCE(1); @@ -1025,6 +1029,8 @@ static int lttng_event_match_enabler(struct lttng_event *event, struct lttng_enabler *enabler) { + if (enabler->event_param.instrumentation != event->instrumentation) + return 0; if (lttng_desc_match_enabler(event->desc, enabler) && event->chan == enabler->chan) return 1; @@ -1046,13 +1052,8 @@ struct lttng_enabler_ref *lttng_event_enabler_ref(struct lttng_event *event, return NULL; } -/* - * Create struct lttng_event if it is missing and present in the list of - * tracepoint probes. - * Should be called with sessions mutex held. - */ static -void lttng_create_event_if_missing(struct lttng_enabler *enabler) +void lttng_create_tracepoint_if_missing(struct lttng_enabler *enabler) { struct lttng_session *session = enabler->chan->session; struct lttng_probe_desc *probe_desc; @@ -1109,6 +1110,36 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler) } } +static +void lttng_create_syscall_if_missing(struct lttng_enabler *enabler) +{ + int ret; + + ret = lttng_syscalls_register(enabler->chan, NULL); + WARN_ON_ONCE(ret); +} + +/* + * Create struct lttng_event if it is missing and present in the list of + * tracepoint probes. + * Should be called with sessions mutex held. + */ +static +void lttng_create_event_if_missing(struct lttng_enabler *enabler) +{ + switch (enabler->event_param.instrumentation) { + case LTTNG_KERNEL_TRACEPOINT: + lttng_create_tracepoint_if_missing(enabler); + break; + case LTTNG_KERNEL_SYSCALL: + lttng_create_syscall_if_missing(enabler); + break; + default: + WARN_ON_ONCE(1); + break; + } +} + /* * Create events associated with an enabler (if not already present), * and add backward reference from the event to the enabler. diff --git a/lttng-events.h b/lttng-events.h index 56744961..c360af0b 100644 --- a/lttng-events.h +++ b/lttng-events.h @@ -460,6 +460,11 @@ struct lttng_event *lttng_event_create(struct lttng_channel *chan, void *filter, const struct lttng_event_desc *event_desc, enum lttng_kernel_instrumentation itype); +struct lttng_event *_lttng_event_create(struct lttng_channel *chan, + struct lttng_kernel_event *event_param, + void *filter, + const struct lttng_event_desc *event_desc, + enum lttng_kernel_instrumentation itype); struct lttng_event *lttng_event_compat_old_create(struct lttng_channel *chan, struct lttng_kernel_old_event *old_event_param, void *filter, diff --git a/lttng-probes.c b/lttng-probes.c index d2723969..b5a7fc80 100644 --- a/lttng-probes.c +++ b/lttng-probes.c @@ -103,7 +103,7 @@ void lttng_lazy_probe_register(struct lttng_probe_desc *desc) /* We should be added at the head of the list */ list_add(&desc->head, probe_list); desc_added: - printk(KERN_DEBUG "just registered probe %s containing %u events\n", + pr_debug("LTTng: just registered probe %s containing %u events\n", desc->provider, desc->nr_events); } @@ -167,7 +167,7 @@ int lttng_probe_register(struct lttng_probe_desc *desc) } list_add(&desc->lazy_init_head, &lazy_probe_init); desc->lazy = 1; - printk(KERN_DEBUG "adding probe %s containing %u events to lazy registration list\n", + pr_debug("LTTng: adding probe %s containing %u events to lazy registration list\n", desc->provider, desc->nr_events); /* * If there is at least one active session, we need to register @@ -189,7 +189,7 @@ void lttng_probe_unregister(struct lttng_probe_desc *desc) list_del(&desc->head); else list_del(&desc->lazy_init_head); - printk(KERN_DEBUG "just unregistered probe %s\n", desc->provider); + pr_debug("LTTng: just unregistered probe %s\n", desc->provider); lttng_unlock_sessions(); } EXPORT_SYMBOL_GPL(lttng_probe_unregister); diff --git a/lttng-syscalls.c b/lttng-syscalls.c index ee09a041..2ddc9d12 100644 --- a/lttng-syscalls.c +++ b/lttng-syscalls.c @@ -666,7 +666,10 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) } } -/* noinline to diminish caller stack size */ +/* + * noinline to diminish caller stack size. + * Should be called with sessions lock held. + */ static int fill_table(const struct trace_syscall_entry *table, size_t table_len, struct lttng_event **chan_table, struct lttng_channel *chan, @@ -715,8 +718,8 @@ int fill_table(const struct trace_syscall_entry *table, size_t table_len, strncat(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN - strlen(ev.name) - 1); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan_table[i] = lttng_event_create(chan, &ev, filter, + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan_table[i] = _lttng_event_create(chan, &ev, filter, desc, ev.instrumentation); WARN_ON_ONCE(!chan_table[i]); if (IS_ERR(chan_table[i])) { @@ -732,6 +735,9 @@ int fill_table(const struct trace_syscall_entry *table, size_t table_len, return 0; } +/* + * Should be called with sessions lock held. + */ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) { struct lttng_kernel_event ev; @@ -779,8 +785,8 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) memset(&ev, 0, sizeof(ev)); strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan->sc_unknown = lttng_event_create(chan, &ev, filter, + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan->sc_unknown = _lttng_event_create(chan, &ev, filter, desc, ev.instrumentation); WARN_ON_ONCE(!chan->sc_unknown); @@ -796,8 +802,8 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) memset(&ev, 0, sizeof(ev)); strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan->sc_compat_unknown = lttng_event_create(chan, &ev, filter, + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan->sc_compat_unknown = _lttng_event_create(chan, &ev, filter, desc, ev.instrumentation); WARN_ON_ONCE(!chan->sc_unknown); @@ -813,8 +819,8 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) memset(&ev, 0, sizeof(ev)); strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan->compat_sc_exit_unknown = lttng_event_create(chan, &ev, + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan->compat_sc_exit_unknown = _lttng_event_create(chan, &ev, filter, desc, ev.instrumentation); WARN_ON_ONCE(!chan->compat_sc_exit_unknown); @@ -830,8 +836,8 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) memset(&ev, 0, sizeof(ev)); strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan->sc_exit_unknown = lttng_event_create(chan, &ev, filter, + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan->sc_exit_unknown = _lttng_event_create(chan, &ev, filter, desc, ev.instrumentation); WARN_ON_ONCE(!chan->sc_exit_unknown); if (IS_ERR(chan->sc_exit_unknown)) { -- 2.34.1