No functional changes, move reuse/attach code into the new helpers. Microptimizations:
- check ->utrace_flags before trying to re-use the self-detaching engine - if ptrace_reuse_engine() finds engine and ->resume != UTRACE_DETACH, we can just return EPERM without trying UTRACE_ATTACH_CREATE. --- kernel/ptrace.c | 96 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 35 deletions(-) --- PU/kernel/ptrace.c~86_CLEANUP_ATTACH_REUSE 2009-10-13 14:15:48.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-13 17:36:05.000000000 +0200 @@ -421,6 +421,64 @@ static const struct utrace_engine_ops pt .release = ptrace_release, }; +static struct utrace_engine * +ptrace_reuse_engine(struct task_struct *tracee) +{ + struct utrace_engine *engine; + struct ptrace_context *context; + int err = -EPERM; + + engine = ptrace_lookup_engine(tracee); + if (IS_ERR(engine)) + return engine; + + context = ptrace_context(engine); + if (unlikely(context->resume == UTRACE_DETACH)) { + /* we rely on ->cred_guard_mutex */ + context->resume = UTRACE_RESUME; + /* make sure we don't race with ptrace_report_signal() */ + err = utrace_barrier(tracee, engine); + WARN_ON(!err != (engine->ops == &ptrace_utrace_ops)); + if (!err) + return engine; + } + + utrace_engine_put(engine); + return ERR_PTR(err); +} + +static struct utrace_engine * +ptrace_attach_engine(struct task_struct *tracee) +{ + struct utrace_engine *engine; + struct ptrace_context *context; + + if (unlikely(task_utrace_flags(tracee))) { + engine = ptrace_reuse_engine(tracee); + if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) + return engine; + } + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (unlikely(!context)) + return ERR_PTR(-ENOMEM); + + context->resume = UTRACE_RESUME; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, context); + if (unlikely(IS_ERR(engine))) { + if (engine != ERR_PTR(-ESRCH) && + engine != ERR_PTR(-ERESTARTNOINTR)) + engine = ERR_PTR(-EPERM); + kfree(context); + } + + return engine; +} + static inline int __ptrace_set_options(struct task_struct *target, struct utrace_engine *engine, unsigned long options) @@ -446,44 +504,12 @@ static inline int __ptrace_set_options(s */ static int ptrace_attach_task(struct task_struct *tracee, int options) { - struct ptrace_context *context; struct utrace_engine *engine; int err; - engine = ptrace_lookup_engine(tracee); - if (!IS_ERR(engine)) { - context = ptrace_context(engine); - if (context->resume == UTRACE_DETACH) { - /* we rely on ->cred_guard_mutex */ - context->resume = UTRACE_RESUME; - /* - * Make sure we don't race with ptrace_report_signal() - */ - err = utrace_barrier(tracee, engine); - if (!err) - goto finish; - } - utrace_engine_put(engine); - } - - context = kzalloc(sizeof(*context), GFP_KERNEL); - if (unlikely(!context)) - return -ENOMEM; - - context->resume = UTRACE_RESUME; - - engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | - UTRACE_ATTACH_EXCLUSIVE | - UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, context); - if (unlikely(IS_ERR(engine))) { - err = PTR_ERR(engine); - if (err != -ESRCH && err != -ERESTARTNOINTR) - err = -EPERM; - kfree(context); - return err; - } -finish: + engine = ptrace_attach_engine(tracee); + if (IS_ERR(engine)) + return PTR_ERR(engine); /* * It can fail only if the tracee is dead, the caller * must notice this before setting PT_PTRACED.