Introduce PTRACE_O_DETACHED to mark the almost-detached engine as reusable for ptrace_reuse_engine().
Currently ptrace_reuse_engine() just checks ctx->resume == UTRACE_DETACH, but we are going to change ptrace_detach_task() to play with the tracee after setting ctx->resume == UTRACE_DETACH and thus we need another method to indicate that this engine is going to detach itself. Note that we set PTRACE_O_DETACHED after ptrace_wake_up()->utrace_control() and the possible new tracer does utrace_set_events() before it changes ctx->resume. This means that we do not need the barriers but can rely on utrace locking. Signed-off-by: Oleg Nesterov <o...@redhat.com> --- kernel/ptrace-utrace.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) --- kstub/kernel/ptrace-utrace.c~4_o_reusable 2010-09-20 03:53:31.000000000 +0200 +++ kstub/kernel/ptrace-utrace.c 2010-09-20 03:53:32.000000000 +0200 @@ -67,6 +67,7 @@ struct ptrace_context { #define PT_UTRACED 0x00001000 #define PTRACE_O_SYSEMU 0x100 +#define PTRACE_O_DETACHED 0x200 #define PTRACE_EVENT_SYSCALL (1 << 16) #define PTRACE_EVENT_SIGTRAP (2 << 16) @@ -128,7 +129,7 @@ ptrace_reuse_engine(struct task_struct * return engine; ctx = ptrace_context(engine); - if (unlikely(ctx->resume == UTRACE_DETACH)) { + if (unlikely(ctx->options == PTRACE_O_DETACHED)) { /* * Try to reuse this self-detaching engine. * The only caller which can hit this case is ptrace_attach(), @@ -264,12 +265,14 @@ static void ptrace_detach_task(struct ta bool voluntary = (sig >= 0); struct utrace_engine *engine = ptrace_lookup_engine(tracee); enum utrace_resume_action action = UTRACE_DETACH; + struct ptrace_context *ctx; if (unlikely(IS_ERR(engine))) return; + ctx = ptrace_context(engine); + if (sig) { - struct ptrace_context *ctx = ptrace_context(engine); switch (get_stop_event(ctx)) { case PTRACE_EVENT_SYSCALL: @@ -287,6 +290,10 @@ static void ptrace_detach_task(struct ta } ptrace_wake_up(tracee, engine, action, voluntary); + + if (action != UTRACE_DETACH) + ctx->options = PTRACE_O_DETACHED; + utrace_engine_put(engine); } @@ -774,7 +781,7 @@ void exit_ptrace(struct task_struct *tra static int ptrace_set_options(struct task_struct *tracee, struct utrace_engine *engine, long data) { - BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); + BUILD_BUG_ON(PTRACE_O_MASK & (PTRACE_O_SYSEMU | PTRACE_O_DETACHED)); ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;