Add support for SOFT_DISABLE to syscall events.

The original SOFT_DISABLE patches didn't add support for soft disable
of syscall events; this adds it and paves the way for future patches
allowing triggers to be added to syscall events, since triggers are
built on top of SOFT_DISABLE.

Because the trigger and SOFT_DISABLE bits are attached to the
ftrace_event_file associated with the event, pointers to the
ftrace_event_files associated with the event are added to the syscall
metadata entry for the event.

Signed-off-by: Tom Zanussi <[email protected]>
---
 include/linux/syscalls.h      |  2 ++
 include/trace/syscall.h       |  5 +++++
 kernel/trace/trace_syscalls.c | 28 ++++++++++++++++++++++++----
 3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 4147d70..b4c2afa 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -158,6 +158,8 @@ extern struct trace_event_functions 
exit_syscall_print_funcs;
                .args           = nb ? args_##sname : NULL,     \
                .enter_event    = &event_enter_##sname,         \
                .exit_event     = &event_exit_##sname,          \
+               .enter_file     = NULL, /* Filled in at boot */ \
+               .exit_file      = NULL, /* Filled in at boot */ \
                .enter_fields   = 
LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
        };                                                      \
        static struct syscall_metadata __used                   \
diff --git a/include/trace/syscall.h b/include/trace/syscall.h
index fed853f..ba24d3a 100644
--- a/include/trace/syscall.h
+++ b/include/trace/syscall.h
@@ -19,6 +19,8 @@
  * @enter_fields: list of fields for syscall_enter trace event
  * @enter_event: associated syscall_enter trace event
  * @exit_event: associated syscall_exit trace event
+ * @enter_file: associated syscall_enter ftrace event file
+ * @exit_file: associated syscall_exit ftrace event file
  */
 struct syscall_metadata {
        const char      *name;
@@ -30,6 +32,9 @@ struct syscall_metadata {
 
        struct ftrace_event_call *enter_event;
        struct ftrace_event_call *exit_event;
+
+       struct ftrace_event_file *enter_file;
+       struct ftrace_event_file *exit_file;
 };
 
 #endif /* _TRACE_SYSCALL_H */
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 8f2ac73..1d81881 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -319,6 +319,10 @@ static void ftrace_syscall_enter(void *data, struct 
pt_regs *regs, long id)
        if (!sys_data)
                return;
 
+       if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT,
+                    &sys_data->enter_file->flags))
+               return;
+
        size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args;
 
        buffer = tr->trace_buffer.buffer;
@@ -355,6 +359,10 @@ static void ftrace_syscall_exit(void *data, struct pt_regs 
*regs, long ret)
        if (!sys_data)
                return;
 
+       if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT,
+                    &sys_data->exit_file->flags))
+               return;
+
        buffer = tr->trace_buffer.buffer;
        event = trace_buffer_lock_reserve(buffer,
                        sys_data->exit_event->event.type, sizeof(*entry), 0, 0);
@@ -374,10 +382,12 @@ static int reg_event_syscall_enter(struct 
ftrace_event_file *file,
                                   struct ftrace_event_call *call)
 {
        struct trace_array *tr = file->tr;
+       struct syscall_metadata *meta;
        int ret = 0;
        int num;
 
-       num = ((struct syscall_metadata *)call->data)->syscall_nr;
+       meta = (struct syscall_metadata *)call->data;
+       num = meta->syscall_nr;
        if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
                return -ENOSYS;
        mutex_lock(&syscall_trace_lock);
@@ -386,6 +396,7 @@ static int reg_event_syscall_enter(struct ftrace_event_file 
*file,
        if (!ret) {
                set_bit(num, tr->enabled_enter_syscalls);
                tr->sys_refcount_enter++;
+               meta->enter_file = file;
        }
        mutex_unlock(&syscall_trace_lock);
        return ret;
@@ -395,14 +406,17 @@ static void unreg_event_syscall_enter(struct 
ftrace_event_file *file,
                                      struct ftrace_event_call *call)
 {
        struct trace_array *tr = file->tr;
+       struct syscall_metadata *meta;
        int num;
 
-       num = ((struct syscall_metadata *)call->data)->syscall_nr;
+       meta = (struct syscall_metadata *)call->data;
+       num = meta->syscall_nr;
        if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
                return;
        mutex_lock(&syscall_trace_lock);
        tr->sys_refcount_enter--;
        clear_bit(num, tr->enabled_enter_syscalls);
+       meta->enter_file = NULL;
        if (!tr->sys_refcount_enter)
                unregister_trace_sys_enter(ftrace_syscall_enter, tr);
        mutex_unlock(&syscall_trace_lock);
@@ -412,10 +426,12 @@ static int reg_event_syscall_exit(struct 
ftrace_event_file *file,
                                  struct ftrace_event_call *call)
 {
        struct trace_array *tr = file->tr;
+       struct syscall_metadata *meta;
        int ret = 0;
        int num;
 
-       num = ((struct syscall_metadata *)call->data)->syscall_nr;
+       meta = (struct syscall_metadata *)call->data;
+       num = meta->syscall_nr;
        if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
                return -ENOSYS;
        mutex_lock(&syscall_trace_lock);
@@ -424,6 +440,7 @@ static int reg_event_syscall_exit(struct ftrace_event_file 
*file,
        if (!ret) {
                set_bit(num, tr->enabled_exit_syscalls);
                tr->sys_refcount_exit++;
+               meta->exit_file = file;
        }
        mutex_unlock(&syscall_trace_lock);
        return ret;
@@ -433,14 +450,17 @@ static void unreg_event_syscall_exit(struct 
ftrace_event_file *file,
                                     struct ftrace_event_call *call)
 {
        struct trace_array *tr = file->tr;
+       struct syscall_metadata *meta;
        int num;
 
-       num = ((struct syscall_metadata *)call->data)->syscall_nr;
+       meta = (struct syscall_metadata *)call->data;
+       num = meta->syscall_nr;
        if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
                return;
        mutex_lock(&syscall_trace_lock);
        tr->sys_refcount_exit--;
        clear_bit(num, tr->enabled_exit_syscalls);
+       meta->exit_file = NULL;
        if (!tr->sys_refcount_exit)
                unregister_trace_sys_exit(ftrace_syscall_exit, tr);
        mutex_unlock(&syscall_trace_lock);
-- 
1.7.11.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to