]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/jffs2/background.c
Merge branch 'for-2.6.28' of git://linux-nfs.org/~bfields/linux
[linux-2.6-omap-h63xx.git] / fs / jffs2 / background.c
index 143c5530caf35ab48446cc3fbe38c6ace0fac41d..3cceef4ad2b7df413e98b8171cadf074de83ad2d 100644 (file)
@@ -23,8 +23,8 @@ static int jffs2_garbage_collect_thread(void *);
 void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
 {
        spin_lock(&c->erase_completion_lock);
-        if (c->gc_task && jffs2_thread_should_wake(c))
-                send_sig(SIGHUP, c->gc_task, 1);
+       if (c->gc_task && jffs2_thread_should_wake(c))
+               send_sig(SIGHUP, c->gc_task, 1);
        spin_unlock(&c->erase_completion_lock);
 }
 
@@ -84,19 +84,16 @@ static int jffs2_garbage_collect_thread(void *_c)
        set_freezable();
        for (;;) {
                allow_signal(SIGHUP);
-
+       again:
+               spin_lock(&c->erase_completion_lock);
                if (!jffs2_thread_should_wake(c)) {
                        set_current_state (TASK_INTERRUPTIBLE);
+                       spin_unlock(&c->erase_completion_lock);
                        D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n"));
-                       /* Yes, there's a race here; we checked jffs2_thread_should_wake()
-                          before setting current->state to TASK_INTERRUPTIBLE. But it doesn't
-                          matter - We don't care if we miss a wakeup, because the GC thread
-                          is only an optimisation anyway. */
                        schedule();
-               }
-
-               if (try_to_freeze())
-                       continue;
+               } else
+                       spin_unlock(&c->erase_completion_lock);
+                       
 
                /* This thread is purely an optimisation. But if it runs when
                   other things could be running, it actually makes things a
@@ -108,10 +105,13 @@ static int jffs2_garbage_collect_thread(void *_c)
 
                /* Put_super will send a SIGKILL and then wait on the sem.
                 */
-               while (signal_pending(current)) {
+               while (signal_pending(current) || freezing(current)) {
                        siginfo_t info;
                        unsigned long signr;
 
+                       if (try_to_freeze())
+                               goto again;
+
                        signr = dequeue_signal_lock(current, &current->blocked, &info);
 
                        switch(signr) {