Personally I dislike the complications introduced by safe/unsafe modes of
utrace_reset().

And I think these complications are not needed. Let's return to the previous
discussion:

        > This case is not unlikely, for example ENGINE_STOP is cleared after 
the
        > previous wakeup. We are running, if ENGINE_STOP is set, UTRACE_STOP 
was
        > used and utrace_reset() was called after that. Otherwise, _perhaps_ it
        > was cleared by UTRACE_DETACH.

        What we want is to change things so that this case *is* unlikely.  That 
is,
        we really want to avoid any extra O(n) work such as utrace_reset calls. 
 It
        should never be common to do one of those we don't really want to do.

Yes! But with the recent changes mark_engine_wants_stop() adds ENGINE_STOP
to ->utrace_flags, this means the case when utrace_stop() calls utrace_reset()
is really unlikely.

So. Kill this (imho) awful "bool safe" argument. utrace_reset() must be always
safe. Instead,

        - change utrace_control(DETACH) to clear ENGINE_STOP from ->utrace_flags

        - change utrace_stop() to call utrace_reset() and re-check when there is
          no ENGINE_STOP in ->utrace_flags.

IOW, this partly re-rereverts 00932dbe24bd4273e6d723baa9342e7b3e248911

Signed-off-by: Oleg Nesterov <o...@redhat.com>
---

 kernel/utrace.c |   39 +++++++++++++++------------------------
 1 file changed, 15 insertions(+), 24 deletions(-)

--- __UTRACE/kernel/utrace.c~2_KILL_SAFE        2009-09-01 20:03:25.000000000 
+0200
+++ __UTRACE/kernel/utrace.c    2009-09-01 20:07:45.000000000 +0200
@@ -707,22 +707,17 @@ static void utrace_wakeup(struct task_st
  * some stale bits in @task->utrace_flags.  Clean them up and recompute the
  * flags.  Returns true if we're now fully detached.
  *
- * @safe is true if this is a safe point to touch the engine list,
- * i.e. @task is either current or known to be stopped.
- *
  * Called with @utrace->lock held, returns with it released.
  * After this returns, @utrace might be freed if everything detached.
  */
-static bool utrace_reset(struct task_struct *task, struct utrace *utrace,
-                        bool safe)
+static bool utrace_reset(struct task_struct *task, struct utrace *utrace)
        __releases(utrace->lock)
 {
        struct utrace_engine *engine, *next;
        unsigned long flags = 0;
        LIST_HEAD(detached);
 
-       if (safe)
-               splice_attaching(utrace);
+       splice_attaching(utrace);
 
        /*
         * Update the set of events of interest from the union
@@ -731,7 +726,7 @@ static bool utrace_reset(struct task_str
         * We'll collect them on the detached list.
         */
        list_for_each_entry_safe(engine, next, &utrace->attached, entry) {
-               if (safe && engine->ops == &utrace_detached_ops) {
+               if (engine->ops == &utrace_detached_ops) {
                        engine->ops = NULL;
                        list_move(&engine->entry, &detached);
                } else {
@@ -789,7 +784,7 @@ static void utrace_stop(struct task_stru
         * inside this function.  It should never be set on entry.
         */
        BUG_ON(utrace->stopped);
-
+relock:
        spin_lock(&utrace->lock);
 
        if (action == UTRACE_INTERRUPT) {
@@ -816,7 +811,9 @@ static void utrace_stop(struct task_stru
         * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH).
         */
        if (unlikely(!(task->utrace_flags & ENGINE_STOP))) {
-               spin_unlock(&utrace->lock);
+               utrace_reset(task, utrace);
+               if (task->utrace_flags & ENGINE_STOP)
+                       goto relock;
                return;
        }
 
@@ -1037,7 +1034,7 @@ int utrace_control(struct task_struct *t
                   enum utrace_resume_action action)
 {
        struct utrace *utrace;
-       bool reset, safe = false;
+       bool reset;
        int ret;
 
        if (unlikely(action > UTRACE_DETACH))
@@ -1074,7 +1071,7 @@ int utrace_control(struct task_struct *t
                        spin_unlock(&utrace->lock);
                        return ret;
                }
-               reset = safe = true;
+               reset = true;
        }
 
        switch (action) {
@@ -1086,6 +1083,9 @@ int utrace_control(struct task_struct *t
                break;
 
        case UTRACE_DETACH:
+               if (engine_wants_stop(engine))
+                       target->utrace_flags &= ~ENGINE_STOP;
+               mark_engine_detached(engine);
                reset = reset || utrace_do_stop(target, utrace);
                if (!reset) {
                        /*
@@ -1100,14 +1100,6 @@ int utrace_control(struct task_struct *t
                        if (utrace->reporting == engine)
                                ret = -EINPROGRESS;
                }
-               if (engine_wants_stop(engine)) {
-                       /*
-                        * We need utrace_reset() to check if anyone else
-                        * still wants this target to stay stopped.
-                        */
-                       reset = true;
-               }
-               mark_engine_detached(engine);
                break;
 
        case UTRACE_RESUME:
@@ -1211,8 +1203,7 @@ int utrace_control(struct task_struct *t
         * there is nothing more we need to do.
         */
        if (reset)
-               utrace_reset(target, utrace, safe || utrace->stopped ||
-                                               target == current);
+               utrace_reset(target, utrace);
        else
                spin_unlock(&utrace->lock);
 
@@ -1318,7 +1309,7 @@ static inline void finish_report_reset(s
 {
        if (unlikely(!report->takers || report->detaches)) {
                spin_lock(&utrace->lock);
-               if (utrace_reset(task, utrace, true))
+               if (utrace_reset(task, utrace))
                        report->action = UTRACE_RESUME;
        }
 }
@@ -1741,7 +1732,7 @@ void utrace_report_death(struct task_str
                 */
                utrace_reap(task, utrace);
        else
-               utrace_reset(task, utrace, true);
+               utrace_reset(task, utrace);
 }
 
 /*

Reply via email to