Commit b8e46d22 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'trace-fixes-v3.16-rc1-v2' of...

Merge tag 'trace-fixes-v3.16-rc1-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing cleanups and fixes from Steven Rostedt:
 "This includes three patches from Oleg Nesterov.  The first is a fix to
  a race condition that happens between enabling/disabling syscall
  tracepoints and new process creations (the check to go into the ptrace
  path for a process can be set when it shouldn't, or not set when it
  should).  Not a major bug but one that should be fixed and even
  applied to stable.

  The other two patches are cleanup/fixes that are not that critical,
  but for an -rc1 release would be nice to have.  They both deal with
  syscall tracepoints.

  It also includes a patch to introduce a new macro for the
  TRACE_EVENT() format called __field_struct().  Originally, __field()
  was used to record any variable into a trace event, but with the
  addition of setting the "is signed" attribute, the check causes
  anything but a primitive variable to fail to compile.  That is,
  structs and unions can't be used as they once were.  When the "is
  signed" check was introduce there were only primitive variables being
  recorded.  But that will change soon and it was reported that
  __field() causes build failures.

  To solve the __field() issue, __field_struct() is introduced to allow
  trace_events to be able to record complex types too"

* tag 'trace-fixes-v3.16-rc1-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  tracing: Add __field_struct macro for TRACE_EVENT()
  tracing: syscall_regfunc() should not skip kernel threads
  tracing: Change syscall_*regfunc() to check PF_KTHREAD and use for_each_process_thread()
  tracing: Fix syscall_*regfunc() vs copy_process() race
parents 10b5b536 4d4c9cc8
...@@ -44,6 +44,12 @@ ...@@ -44,6 +44,12 @@
#undef __field_ext #undef __field_ext
#define __field_ext(type, item, filter_type) type item; #define __field_ext(type, item, filter_type) type item;
#undef __field_struct
#define __field_struct(type, item) type item;
#undef __field_struct_ext
#define __field_struct_ext(type, item, filter_type) type item;
#undef __array #undef __array
#define __array(type, item, len) type item[len]; #define __array(type, item, len) type item[len];
...@@ -122,6 +128,12 @@ ...@@ -122,6 +128,12 @@
#undef __field_ext #undef __field_ext
#define __field_ext(type, item, filter_type) #define __field_ext(type, item, filter_type)
#undef __field_struct
#define __field_struct(type, item)
#undef __field_struct_ext
#define __field_struct_ext(type, item, filter_type)
#undef __array #undef __array
#define __array(type, item, len) #define __array(type, item, len)
...@@ -315,9 +327,21 @@ static struct trace_event_functions ftrace_event_type_funcs_##call = { \ ...@@ -315,9 +327,21 @@ static struct trace_event_functions ftrace_event_type_funcs_##call = { \
if (ret) \ if (ret) \
return ret; return ret;
#undef __field_struct_ext
#define __field_struct_ext(type, item, filter_type) \
ret = trace_define_field(event_call, #type, #item, \
offsetof(typeof(field), item), \
sizeof(field.item), \
0, filter_type); \
if (ret) \
return ret;
#undef __field #undef __field
#define __field(type, item) __field_ext(type, item, FILTER_OTHER) #define __field(type, item) __field_ext(type, item, FILTER_OTHER)
#undef __field_struct
#define __field_struct(type, item) __field_struct_ext(type, item, FILTER_OTHER)
#undef __array #undef __array
#define __array(type, item, len) \ #define __array(type, item, len) \
do { \ do { \
...@@ -379,6 +403,12 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \ ...@@ -379,6 +403,12 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
#undef __field_ext #undef __field_ext
#define __field_ext(type, item, filter_type) #define __field_ext(type, item, filter_type)
#undef __field_struct
#define __field_struct(type, item)
#undef __field_struct_ext
#define __field_struct_ext(type, item, filter_type)
#undef __array #undef __array
#define __array(type, item, len) #define __array(type, item, len)
...@@ -550,6 +580,9 @@ static inline notrace int ftrace_get_offsets_##call( \ ...@@ -550,6 +580,9 @@ static inline notrace int ftrace_get_offsets_##call( \
#undef __field #undef __field
#define __field(type, item) #define __field(type, item)
#undef __field_struct
#define __field_struct(type, item)
#undef __array #undef __array
#define __array(type, item, len) #define __array(type, item, len)
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/ftrace_event.h> #include <linux/ftrace_event.h>
#include <linux/thread_info.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
...@@ -32,4 +33,18 @@ struct syscall_metadata { ...@@ -32,4 +33,18 @@ struct syscall_metadata {
struct ftrace_event_call *exit_event; struct ftrace_event_call *exit_event;
}; };
#if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_HAVE_SYSCALL_TRACEPOINTS)
static inline void syscall_tracepoint_update(struct task_struct *p)
{
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
set_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT);
else
clear_tsk_thread_flag(p, TIF_SYSCALL_TRACEPOINT);
}
#else
static inline void syscall_tracepoint_update(struct task_struct *p)
{
}
#endif
#endif /* _TRACE_SYSCALL_H */ #endif /* _TRACE_SYSCALL_H */
...@@ -1487,7 +1487,9 @@ static struct task_struct *copy_process(unsigned long clone_flags, ...@@ -1487,7 +1487,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
total_forks++; total_forks++;
spin_unlock(&current->sighand->siglock); spin_unlock(&current->sighand->siglock);
syscall_tracepoint_update(p);
write_unlock_irq(&tasklist_lock); write_unlock_irq(&tasklist_lock);
proc_fork_connector(p); proc_fork_connector(p);
cgroup_post_fork(p); cgroup_post_fork(p);
if (clone_flags & CLONE_THREAD) if (clone_flags & CLONE_THREAD)
......
...@@ -492,33 +492,29 @@ static int sys_tracepoint_refcount; ...@@ -492,33 +492,29 @@ static int sys_tracepoint_refcount;
void syscall_regfunc(void) void syscall_regfunc(void)
{ {
unsigned long flags; struct task_struct *p, *t;
struct task_struct *g, *t;
if (!sys_tracepoint_refcount) { if (!sys_tracepoint_refcount) {
read_lock_irqsave(&tasklist_lock, flags); read_lock(&tasklist_lock);
do_each_thread(g, t) { for_each_process_thread(p, t) {
/* Skip kernel threads. */ set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
if (t->mm) }
set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT); read_unlock(&tasklist_lock);
} while_each_thread(g, t);
read_unlock_irqrestore(&tasklist_lock, flags);
} }
sys_tracepoint_refcount++; sys_tracepoint_refcount++;
} }
void syscall_unregfunc(void) void syscall_unregfunc(void)
{ {
unsigned long flags; struct task_struct *p, *t;
struct task_struct *g, *t;
sys_tracepoint_refcount--; sys_tracepoint_refcount--;
if (!sys_tracepoint_refcount) { if (!sys_tracepoint_refcount) {
read_lock_irqsave(&tasklist_lock, flags); read_lock(&tasklist_lock);
do_each_thread(g, t) { for_each_process_thread(p, t) {
clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT); clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
} while_each_thread(g, t); }
read_unlock_irqrestore(&tasklist_lock, flags); read_unlock(&tasklist_lock);
} }
} }
#endif #endif
...@@ -56,7 +56,8 @@ ...@@ -56,7 +56,8 @@
* struct: This defines the way the data will be stored in the ring buffer. * struct: This defines the way the data will be stored in the ring buffer.
* There are currently two types of elements. __field and __array. * There are currently two types of elements. __field and __array.
* a __field is broken up into (type, name). Where type can be any * a __field is broken up into (type, name). Where type can be any
* type but an array. * primitive type (integer, long or pointer). __field_struct() can
* be any static complex data value (struct, union, but not an array).
* For an array. there are three fields. (type, name, size). The * For an array. there are three fields. (type, name, size). The
* type of elements in the array, the name of the field and the size * type of elements in the array, the name of the field and the size
* of the array. * of the array.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment