Revert "writeback: fix WB_SYNC_NONE writeback from umount"
[safe/jmp/linux-2.6] / fs / jffs2 / nodemgmt.c
index 34a452b..694aa5b 100644 (file)
@@ -1,18 +1,15 @@
 /*
  * JFFS2 -- Journalling Flash File System, Version 2.
  *
- * Copyright (C) 2001-2003 Red Hat, Inc.
+ * Copyright © 2001-2007 Red Hat, Inc.
  *
  * Created by David Woodhouse <dwmw2@infradead.org>
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $
- *
  */
 
 #include <linux/kernel.h>
-#include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/compiler.h>
 #include <linux/sched.h> /* For cond_resched() */
  *     jffs2_reserve_space - request physical space to write nodes to flash
  *     @c: superblock info
  *     @minsize: Minimum acceptable size of allocation
- *     @ofs: Returned value of node offset
  *     @len: Returned value of allocation length
  *     @prio: Allocation type - ALLOC_{NORMAL,DELETION}
  *
  *     Requests a block of physical space on the flash. Returns zero for success
- *     and puts 'ofs' and 'len' into the appriopriate place, or returns -ENOSPC
- *     or other error if appropriate.
+ *     and puts 'len' into the appropriate place, or returns -ENOSPC or other 
+ *     error if appropriate. Doesn't return len since that's 
  *
  *     If it returns zero, jffs2_reserve_space() also downs the per-filesystem
  *     allocation semaphore, to prevent more than one allocation from being
@@ -40,9 +36,9 @@
  */
 
 static int jffs2_do_reserve_space(struct jffs2_sb_info *c,  uint32_t minsize,
-                                       uint32_t *ofs, uint32_t *len, uint32_t sumsize);
+                                 uint32_t *len, uint32_t sumsize);
 
-int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
                        uint32_t *len, int prio, uint32_t sumsize)
 {
        int ret = -EAGAIN;
@@ -51,7 +47,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
        minsize = PAD(minsize);
 
        D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize));
-       down(&c->alloc_sem);
+       mutex_lock(&c->alloc_sem);
 
        D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n"));
 
@@ -60,7 +56,6 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
        /* this needs a little more thought (true <tglx> :)) */
        while(ret == -EAGAIN) {
                while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) {
-                       int ret;
                        uint32_t dirty, avail;
 
                        /* calculate real dirty size
@@ -85,7 +80,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
                                          dirty, c->unchecked_size, c->sector_size));
 
                                spin_unlock(&c->erase_completion_lock);
-                               up(&c->alloc_sem);
+                               mutex_unlock(&c->alloc_sem);
                                return -ENOSPC;
                        }
 
@@ -108,11 +103,11 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
                                D1(printk(KERN_DEBUG "max. available size 0x%08x  < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n",
                                          avail, blocksneeded * c->sector_size));
                                spin_unlock(&c->erase_completion_lock);
-                               up(&c->alloc_sem);
+                               mutex_unlock(&c->alloc_sem);
                                return -ENOSPC;
                        }
 
-                       up(&c->alloc_sem);
+                       mutex_unlock(&c->alloc_sem);
 
                        D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n",
                                  c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size,
@@ -120,7 +115,22 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
                        spin_unlock(&c->erase_completion_lock);
 
                        ret = jffs2_garbage_collect_pass(c);
-                       if (ret)
+
+                       if (ret == -EAGAIN) {
+                               spin_lock(&c->erase_completion_lock);
+                               if (c->nr_erasing_blocks &&
+                                   list_empty(&c->erase_pending_list) &&
+                                   list_empty(&c->erase_complete_list)) {
+                                       DECLARE_WAITQUEUE(wait, current);
+                                       set_current_state(TASK_UNINTERRUPTIBLE);
+                                       add_wait_queue(&c->erase_wait, &wait);
+                                       D1(printk(KERN_DEBUG "%s waiting for erase to complete\n", __func__));
+                                       spin_unlock(&c->erase_completion_lock);
+
+                                       schedule();
+                               } else
+                                       spin_unlock(&c->erase_completion_lock);
+                       } else if (ret)
                                return ret;
 
                        cond_resched();
@@ -128,23 +138,25 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs
                        if (signal_pending(current))
                                return -EINTR;
 
-                       down(&c->alloc_sem);
+                       mutex_lock(&c->alloc_sem);
                        spin_lock(&c->erase_completion_lock);
                }
 
-               ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize);
+               ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
                if (ret) {
                        D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret));
                }
        }
        spin_unlock(&c->erase_completion_lock);
+       if (!ret)
+               ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
        if (ret)
-               up(&c->alloc_sem);
+               mutex_unlock(&c->alloc_sem);
        return ret;
 }
 
-int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
-                       uint32_t *len, uint32_t sumsize)
+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
+                          uint32_t *len, uint32_t sumsize)
 {
        int ret = -EAGAIN;
        minsize = PAD(minsize);
@@ -153,12 +165,15 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *
 
        spin_lock(&c->erase_completion_lock);
        while(ret == -EAGAIN) {
-               ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize);
+               ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
                if (ret) {
-                       D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
+                       D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
                }
        }
        spin_unlock(&c->erase_completion_lock);
+       if (!ret)
+               ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+
        return ret;
 }
 
@@ -168,6 +183,11 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *
 static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
 
+       if (c->nextblock == NULL) {
+               D1(printk(KERN_DEBUG "jffs2_close_nextblock: Erase block at 0x%08x has already been placed in a list\n",
+                 jeb->offset));
+               return;
+       }
        /* Check, if we have a dirty block now, or if it was dirty already */
        if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) {
                c->dirty_size += jeb->wasted_size;
@@ -207,10 +227,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
                        struct jffs2_eraseblock *ejeb;
 
                        ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list);
-                       list_del(&ejeb->list);
-                       list_add_tail(&ejeb->list, &c->erase_pending_list);
+                       list_move_tail(&ejeb->list, &c->erase_pending_list);
                        c->nr_erasing_blocks++;
-                       jffs2_erase_pending_trigger(c);
+                       jffs2_garbage_collect_trigger(c);
                        D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n",
                                  ejeb->offset));
                }
@@ -253,16 +272,23 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
 
        jffs2_sum_reset_collected(c->summary); /* reset collected summary */
 
+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
+       /* adjust write buffer offset, else we get a non contiguous write bug */
+       if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len)
+               c->wbuf_ofs = 0xffffffff;
+#endif
+
        D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset));
 
        return 0;
 }
 
 /* Called with alloc sem _and_ erase_completion_lock */
-static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize)
+static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+                                 uint32_t *len, uint32_t sumsize)
 {
        struct jffs2_eraseblock *jeb = c->nextblock;
-       uint32_t reserved_size;                         /* for summary information at the end of the jeb */
+       uint32_t reserved_size;                         /* for summary information at the end of the jeb */
        int ret;
 
  restart:
@@ -312,6 +338,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
                }
        } else {
                if (jeb && minsize > jeb->free_size) {
+                       uint32_t waste;
+
                        /* Skip the end of this block and file it as having some dirty space */
                        /* If there's a pending write to it, flush now */
 
@@ -324,10 +352,26 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
                                goto restart;
                        }
 
-                       c->wasted_size += jeb->free_size;
-                       c->free_size -= jeb->free_size;
-                       jeb->wasted_size += jeb->free_size;
-                       jeb->free_size = 0;
+                       spin_unlock(&c->erase_completion_lock);
+
+                       ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
+                       if (ret)
+                               return ret;
+                       /* Just lock it again and continue. Nothing much can change because
+                          we hold c->alloc_sem anyway. In fact, it's not entirely clear why
+                          we hold c->erase_completion_lock in the majority of this function...
+                          but that's a question for another (more caffeine-rich) day. */
+                       spin_lock(&c->erase_completion_lock);
+
+                       waste = jeb->free_size;
+                       jffs2_link_node_ref(c, jeb,
+                                           (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
+                                           waste, NULL);
+                       /* FIXME: that made it count as dirty. Convert to wasted */
+                       jeb->dirty_size -= waste;
+                       c->dirty_size -= waste;
+                       jeb->wasted_size += waste;
+                       c->wasted_size += waste;
 
                        jffs2_close_nextblock(c, jeb);
                        jeb = NULL;
@@ -349,7 +393,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
        }
        /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has
           enough space */
-       *ofs = jeb->offset + (c->sector_size - jeb->free_size);
        *len = jeb->free_size - reserved_size;
 
        if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size &&
@@ -365,7 +408,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
                spin_lock(&c->erase_completion_lock);
        }
 
-       D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs));
+       D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n",
+                 *len, jeb->offset + (c->sector_size - jeb->free_size)));
        return 0;
 }
 
@@ -381,30 +425,35 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin
  *     Must be called with the alloc_sem held.
  */
 
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new,
-                               uint32_t len, struct jffs2_inode_cache *ic)
+struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
+                                                      uint32_t ofs, uint32_t len,
+                                                      struct jffs2_inode_cache *ic)
 {
        struct jffs2_eraseblock *jeb;
+       struct jffs2_raw_node_ref *new;
 
-       jeb = &c->blocks[new->flash_offset / c->sector_size];
-#ifdef TEST_TOTLEN
-       new->__totlen = len;
-#endif
+       jeb = &c->blocks[ofs / c->sector_size];
 
-       D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len));
+       D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n",
+                 ofs & ~3, ofs & 3, len));
 #if 1
-       /* we could get some obsolete nodes after nextblock was refiled
-          in wbuf.c */
-       if ((c->nextblock || !ref_obsolete(new))
-           &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) {
-               printk(KERN_WARNING "argh. node added in wrong place\n");
-               jffs2_free_raw_node_ref(new);
-               return -EINVAL;
+       /* Allow non-obsolete nodes only to be added at the end of c->nextblock, 
+          if c->nextblock is set. Note that wbuf.c will file obsolete nodes
+          even after refiling c->nextblock */
+       if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
+           && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
+               printk(KERN_WARNING "argh. node added in wrong place at 0x%08x(%d)\n", ofs & ~3, ofs & 3);
+               if (c->nextblock)
+                       printk(KERN_WARNING "nextblock 0x%08x", c->nextblock->offset);
+               else
+                       printk(KERN_WARNING "No nextblock");
+               printk(", expected at %08x\n", jeb->offset + (c->sector_size - jeb->free_size));
+               return ERR_PTR(-EINVAL);
        }
 #endif
        spin_lock(&c->erase_completion_lock);
 
-       jffs2_link_node_ref(c, jeb, new, len, ic);
+       new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
 
        if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
                /* If it lives on the dirty_list, jffs2_reserve_space will put it there */
@@ -425,15 +474,17 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r
 
        spin_unlock(&c->erase_completion_lock);
 
-       return 0;
+       return new;
 }
 
 
 void jffs2_complete_reservation(struct jffs2_sb_info *c)
 {
        D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n"));
+       spin_lock(&c->erase_completion_lock);
        jffs2_garbage_collect_trigger(c);
-       up(&c->alloc_sem);
+       spin_unlock(&c->erase_completion_lock);
+       mutex_unlock(&c->alloc_sem);
 }
 
 static inline int on_list(struct list_head *obj, struct list_head *head)
@@ -459,7 +510,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        size_t retlen;
        uint32_t freed_len;
 
-       if(!ref) {
+       if(unlikely(!ref)) {
                printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
                return;
        }
@@ -482,7 +533,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                   any jffs2_raw_node_refs. So we don't need to stop erases from
                   happening, or protect against people holding an obsolete
                   jffs2_raw_node_ref without the erase_completion_lock. */
-               down(&c->erase_free_sem);
+               mutex_lock(&c->erase_free_sem);
        }
 
        spin_lock(&c->erase_completion_lock);
@@ -511,7 +562,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
 
        // Take care, that wasted size is taken into concern
        if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
-               D1(printk(KERN_DEBUG "Dirtying\n"));
+               D1(printk("Dirtying\n"));
                addedsize = freed_len;
                jeb->dirty_size += freed_len;
                c->dirty_size += freed_len;
@@ -533,7 +584,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                        }
                }
        } else {
-               D1(printk(KERN_DEBUG "Wasting\n"));
+               D1(printk("Wasting\n"));
                addedsize = 0;
                jeb->wasted_size += freed_len;
                c->wasted_size += freed_len;
@@ -574,7 +625,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                                D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n"));
                                list_add_tail(&jeb->list, &c->erase_pending_list);
                                c->nr_erasing_blocks++;
-                               jffs2_erase_pending_trigger(c);
+                               jffs2_garbage_collect_trigger(c);
                        } else {
                                /* Sometimes, however, we leave it elsewhere so it doesn't get
                                   immediately reused, and we spread the load a bit. */
@@ -612,7 +663,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
        /* The erase_free_sem is locked, and has been since before we marked the node obsolete
           and potentially put its eraseblock onto the erase_pending_list. Thus, we know that
           the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet
-          by jffs2_free_all_node_refs() in erase.c. Which is nice. */
+          by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */
 
        D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref)));
        ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
@@ -661,79 +712,43 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                spin_lock(&c->erase_completion_lock);
 
                ic = jffs2_raw_ref_to_ic(ref);
-               /* It seems we should never call jffs2_mark_node_obsolete() for
-                  XATTR nodes.... yet. Make sure we notice if/when we change
-                  that :) */
-               BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE);
                for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
                        ;
 
                *p = ref->next_in_ino;
                ref->next_in_ino = NULL;
 
-               if (ic->nodes == (void *)ic && ic->nlink == 0)
-                       jffs2_del_ino_cache(c, ic);
-
-               spin_unlock(&c->erase_completion_lock);
-       }
-
-
-       /* Merge with the next node in the physical list, if there is one
-          and if it's also obsolete and if it doesn't belong to any inode */
-       if (ref->next_phys && ref_obsolete(ref->next_phys) &&
-           !ref->next_phys->next_in_ino) {
-               struct jffs2_raw_node_ref *n = ref->next_phys;
-
-               spin_lock(&c->erase_completion_lock);
-
-#ifdef TEST_TOTLEN
-               ref->__totlen += n->__totlen;
+               switch (ic->class) {
+#ifdef CONFIG_JFFS2_FS_XATTR
+                       case RAWNODE_CLASS_XATTR_DATUM:
+                               jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
+                               break;
+                       case RAWNODE_CLASS_XATTR_REF:
+                               jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
+                               break;
 #endif
-               ref->next_phys = n->next_phys;
-                if (jeb->last_node == n) jeb->last_node = ref;
-               if (jeb->gc_node == n) {
-                       /* gc will be happy continuing gc on this node */
-                       jeb->gc_node=ref;
+                       default:
+                               if (ic->nodes == (void *)ic && ic->pino_nlink == 0)
+                                       jffs2_del_ino_cache(c, ic);
+                               break;
                }
                spin_unlock(&c->erase_completion_lock);
-
-               jffs2_free_raw_node_ref(n);
        }
 
-       /* Also merge with the previous node in the list, if there is one
-          and that one is obsolete */
-       if (ref != jeb->first_node ) {
-               struct jffs2_raw_node_ref *p = jeb->first_node;
-
-               spin_lock(&c->erase_completion_lock);
-
-               while (p->next_phys != ref)
-                       p = p->next_phys;
-
-               if (ref_obsolete(p) && !ref->next_in_ino) {
-#ifdef TEST_TOTLEN
-                       p->__totlen += ref->__totlen;
-#endif
-                       if (jeb->last_node == ref) {
-                               jeb->last_node = p;
-                       }
-                       if (jeb->gc_node == ref) {
-                               /* gc will be happy continuing gc on this node */
-                               jeb->gc_node=p;
-                       }
-                       p->next_phys = ref->next_phys;
-                       jffs2_free_raw_node_ref(ref);
-               }
-               spin_unlock(&c->erase_completion_lock);
-       }
  out_erase_sem:
-       up(&c->erase_free_sem);
+       mutex_unlock(&c->erase_free_sem);
 }
 
 int jffs2_thread_should_wake(struct jffs2_sb_info *c)
 {
        int ret = 0;
        uint32_t dirty;
+       int nr_very_dirty = 0;
+       struct jffs2_eraseblock *jeb;
+
+       if (!list_empty(&c->erase_complete_list) ||
+           !list_empty(&c->erase_pending_list))
+               return 1;
 
        if (c->unchecked_size) {
                D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n",
@@ -755,8 +770,18 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c)
                        (dirty > c->nospc_dirty_size))
                ret = 1;
 
-       D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n",
-                 c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no"));
+       list_for_each_entry(jeb, &c->very_dirty_list, list) {
+               nr_very_dirty++;
+               if (nr_very_dirty == c->vdirty_blocks_gctrigger) {
+                       ret = 1;
+                       /* In debug mode, actually go through and count them all */
+                       D1(continue);
+                       break;
+               }
+       }
+
+       D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x, vdirty_blocks %d: %s\n",
+                 c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, nr_very_dirty, ret?"yes":"no"));
 
        return ret;
 }