Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / md / bcache / closure.c
index 1841d0359bace765cc52acd6340bb96efb5aa2ee..7f12920c14f7ade2086e1f1813fd832e047a8699 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
+#include <linux/sched/debug.h>
 
 #include "closure.h"
 
@@ -18,10 +19,6 @@ static inline void closure_put_after_sub(struct closure *cl, int flags)
        BUG_ON(flags & CLOSURE_GUARD_MASK);
        BUG_ON(!r && (flags & ~CLOSURE_DESTRUCTOR));
 
-       /* Must deliver precisely one wakeup */
-       if (r == 1 && (flags & CLOSURE_SLEEPING))
-               wake_up_process(cl->task);
-
        if (!r) {
                if (cl->fn && !(flags & CLOSURE_DESTRUCTOR)) {
                        atomic_set(&cl->remaining,
@@ -100,28 +97,34 @@ bool closure_wait(struct closure_waitlist *waitlist, struct closure *cl)
 }
 EXPORT_SYMBOL(closure_wait);
 
-/**
- * closure_sync - sleep until a closure has nothing left to wait on
- *
- * Sleeps until the refcount hits 1 - the thread that's running the closure owns
- * the last refcount.
- */
-void closure_sync(struct closure *cl)
+struct closure_syncer {
+       struct task_struct      *task;
+       int                     done;
+};
+
+static void closure_sync_fn(struct closure *cl)
 {
-       while (1) {
-               __closure_start_sleep(cl);
-               closure_set_ret_ip(cl);
+       cl->s->done = 1;
+       wake_up_process(cl->s->task);
+}
 
-               if ((atomic_read(&cl->remaining) &
-                    CLOSURE_REMAINING_MASK) == 1)
-                       break;
+void __sched __closure_sync(struct closure *cl)
+{
+       struct closure_syncer s = { .task = current };
 
+       cl->s = &s;
+       continue_at(cl, closure_sync_fn, NULL);
+
+       while (1) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               if (s.done)
+                       break;
                schedule();
        }
 
-       __closure_end_sleep(cl);
+       __set_current_state(TASK_RUNNING);
 }
-EXPORT_SYMBOL(closure_sync);
+EXPORT_SYMBOL(__closure_sync);
 
 #ifdef CONFIG_BCACHE_CLOSURES_DEBUG
 
@@ -168,12 +171,10 @@ static int debug_seq_show(struct seq_file *f, void *data)
                           cl, (void *) cl->ip, cl->fn, cl->parent,
                           r & CLOSURE_REMAINING_MASK);
 
-               seq_printf(f, "%s%s%s%s\n",
+               seq_printf(f, "%s%s\n",
                           test_bit(WORK_STRUCT_PENDING_BIT,
                                    work_data_bits(&cl->work)) ? "Q" : "",
-                          r & CLOSURE_RUNNING  ? "R" : "",
-                          r & CLOSURE_STACK    ? "S" : "",
-                          r & CLOSURE_SLEEPING ? "Sl" : "");
+                          r & CLOSURE_RUNNING  ? "R" : "");
 
                if (r & CLOSURE_WAITING)
                        seq_printf(f, " W %pF\n",