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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTpxx+AAoJEKQekfcNnQGu8dQH/RWwKuq/SDqdqFrYM3y0MGtU GpWTzaTYfhoO7FE2zNx3JQtfu5Zg+KPzavecEQqYJGdUvd5lopo+GR4TYQ2GIDdA O4gBgXkxJjYCQ4x9INXf/U8Afd4tfCYSWik2zzWUZaJSLd6pMV/4XbqqZItZ7aqt bxWa7CgmSMHmfsO5a3xWzX0ybPCmYw/+G15CZDGguoazO1FU6oFAnKnr86PGhquH eIHzGAO7ka6k+hQwM1gzUi5vIN+OGBZ4HuJCFu/jqaJHMxW0lomL93Gruifk3l4v r2ierd0FjMSrV1BzCWRR+diWq8W0xwOUutFd1eG3fKlKHZJn4oZfiUHsZw65PFQ= =Idsk -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
b8e46d22dc
5 changed files with 63 additions and 16 deletions
|
@ -44,6 +44,12 @@
|
|||
#undef __field_ext
|
||||
#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
|
||||
#define __array(type, item, len) type item[len];
|
||||
|
||||
|
@ -122,6 +128,12 @@
|
|||
#undef __field_ext
|
||||
#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
|
||||
#define __array(type, item, len)
|
||||
|
||||
|
@ -315,9 +327,21 @@ static struct trace_event_functions ftrace_event_type_funcs_##call = { \
|
|||
if (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
|
||||
#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
|
||||
#define __array(type, item, len) \
|
||||
do { \
|
||||
|
@ -379,6 +403,12 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
|
|||
#undef __field_ext
|
||||
#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
|
||||
#define __array(type, item, len)
|
||||
|
||||
|
@ -550,6 +580,9 @@ static inline notrace int ftrace_get_offsets_##call( \
|
|||
#undef __field
|
||||
#define __field(type, item)
|
||||
|
||||
#undef __field_struct
|
||||
#define __field_struct(type, item)
|
||||
|
||||
#undef __array
|
||||
#define __array(type, item, len)
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <linux/tracepoint.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/ftrace_event.h>
|
||||
#include <linux/thread_info.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
|
@ -32,4 +33,18 @@ struct syscall_metadata {
|
|||
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 */
|
||||
|
|
|
@ -1487,7 +1487,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
|
|||
|
||||
total_forks++;
|
||||
spin_unlock(¤t->sighand->siglock);
|
||||
syscall_tracepoint_update(p);
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
|
||||
proc_fork_connector(p);
|
||||
cgroup_post_fork(p);
|
||||
if (clone_flags & CLONE_THREAD)
|
||||
|
|
|
@ -492,33 +492,29 @@ static int sys_tracepoint_refcount;
|
|||
|
||||
void syscall_regfunc(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct task_struct *g, *t;
|
||||
struct task_struct *p, *t;
|
||||
|
||||
if (!sys_tracepoint_refcount) {
|
||||
read_lock_irqsave(&tasklist_lock, flags);
|
||||
do_each_thread(g, t) {
|
||||
/* Skip kernel threads. */
|
||||
if (t->mm)
|
||||
set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
|
||||
} while_each_thread(g, t);
|
||||
read_unlock_irqrestore(&tasklist_lock, flags);
|
||||
read_lock(&tasklist_lock);
|
||||
for_each_process_thread(p, t) {
|
||||
set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
}
|
||||
sys_tracepoint_refcount++;
|
||||
}
|
||||
|
||||
void syscall_unregfunc(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct task_struct *g, *t;
|
||||
struct task_struct *p, *t;
|
||||
|
||||
sys_tracepoint_refcount--;
|
||||
if (!sys_tracepoint_refcount) {
|
||||
read_lock_irqsave(&tasklist_lock, flags);
|
||||
do_each_thread(g, t) {
|
||||
read_lock(&tasklist_lock);
|
||||
for_each_process_thread(p, t) {
|
||||
clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
|
||||
} while_each_thread(g, t);
|
||||
read_unlock_irqrestore(&tasklist_lock, flags);
|
||||
}
|
||||
read_unlock(&tasklist_lock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
* struct: This defines the way the data will be stored in the ring buffer.
|
||||
* There are currently two types of elements. __field and __array.
|
||||
* 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
|
||||
* type of elements in the array, the name of the field and the size
|
||||
* of the array.
|
||||
|
|
Loading…
Reference in a new issue