Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
[safe/jmp/linux-2.6] / fs / jffs2 / erase.c
index 5e86f43..6286ad9 100644 (file)
@@ -68,7 +68,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
        instr->len = c->sector_size;
        instr->callback = jffs2_erase_callback;
        instr->priv = (unsigned long)(&instr[1]);
-       instr->fail_addr = 0xffffffff;
+       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
 
        ((struct erase_priv_struct *)instr->priv)->jeb = jeb;
        ((struct erase_priv_struct *)instr->priv)->c = c;
@@ -103,9 +103,10 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
        jffs2_erase_failed(c, jeb, bad_offset);
 }
 
-void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
+int jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
 {
        struct jffs2_eraseblock *jeb;
+       int work_done = 0;
 
        mutex_lock(&c->erase_free_sem);
 
@@ -121,6 +122,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
                        mutex_unlock(&c->erase_free_sem);
                        jffs2_mark_erased_block(c, jeb);
 
+                       work_done++;
                        if (!--count) {
                                D1(printk(KERN_DEBUG "Count reached. jffs2_erase_pending_blocks leaving\n"));
                                goto done;
@@ -157,6 +159,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
        mutex_unlock(&c->erase_free_sem);
  done:
        D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
+       return work_done;
 }
 
 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
@@ -165,17 +168,18 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblo
        mutex_lock(&c->erase_free_sem);
        spin_lock(&c->erase_completion_lock);
        list_move_tail(&jeb->list, &c->erase_complete_list);
+       /* Wake the GC thread to mark them clean */
+       jffs2_garbage_collect_trigger(c);
        spin_unlock(&c->erase_completion_lock);
        mutex_unlock(&c->erase_free_sem);
-       /* Ensure that kupdated calls us again to mark them clean */
-       jffs2_erase_pending_trigger(c);
+       wake_up(&c->erase_wait);
 }
 
 static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset)
 {
        /* For NAND, if the failure did not occur at the device level for a
           specific physical page, don't bother updating the bad block table. */
-       if (jffs2_cleanmarker_oob(c) && (bad_offset != 0xffffffff)) {
+       if (jffs2_cleanmarker_oob(c) && (bad_offset != (uint32_t)MTD_FAIL_ADDR_UNKNOWN)) {
                /* We had a device-level failure to erase.  Let's see if we've
                   failed too many times. */
                if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
@@ -209,7 +213,8 @@ static void jffs2_erase_callback(struct erase_info *instr)
        struct erase_priv_struct *priv = (void *)instr->priv;
 
        if(instr->state != MTD_ERASE_DONE) {
-               printk(KERN_WARNING "Erase at 0x%08x finished, but state != MTD_ERASE_DONE. State is 0x%x instead.\n", instr->addr, instr->state);
+               printk(KERN_WARNING "Erase at 0x%08llx finished, but state != MTD_ERASE_DONE. State is 0x%x instead.\n",
+                       (unsigned long long)instr->addr, instr->state);
                jffs2_erase_failed(priv->c, priv->jeb, instr->fail_addr);
        } else {
                jffs2_erase_succeeded(priv->c, priv->jeb);
@@ -269,19 +274,21 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
        D2({
                int i=0;
                struct jffs2_raw_node_ref *this;
-               printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG);
+               printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n");
 
                this = ic->nodes;
 
+               printk(KERN_DEBUG);
                while(this) {
-                       printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this));
+                       printk(KERN_CONT "0x%08x(%d)->",
+                              ref_offset(this), ref_flags(this));
                        if (++i == 5) {
-                               printk("\n" KERN_DEBUG);
+                               printk(KERN_DEBUG);
                                i=0;
                        }
                        this = this->next_in_ino;
                }
-               printk("\n");
+               printk(KERN_CONT "\n");
        });
 
        switch (ic->class) {
@@ -332,7 +339,8 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
        if (c->mtd->point) {
                unsigned long *wordebuf;
 
-               ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
+               ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size,
+                                   &retlen, &ebuf, NULL);
                if (ret) {
                        D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
                        goto do_flash_read;
@@ -340,7 +348,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
                if (retlen < c->sector_size) {
                        /* Don't muck about if it won't let us point to the whole erase sector */
                        D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
-                       c->mtd->unpoint(c->mtd, ebuf, jeb->offset, retlen);
+                       c->mtd->unpoint(c->mtd, jeb->offset, retlen);
                        goto do_flash_read;
                }
                wordebuf = ebuf-sizeof(*wordebuf);
@@ -349,7 +357,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
                   if (*++wordebuf != ~0)
                           break;
                } while(--retlen);
-               c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
+               c->mtd->unpoint(c->mtd, jeb->offset, c->sector_size);
                if (retlen) {
                        printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
                               *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
@@ -478,21 +486,14 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
        return;
 
 filebad:
-       mutex_lock(&c->erase_free_sem);
-       spin_lock(&c->erase_completion_lock);
-       /* Stick it on a list (any list) so erase_failed can take it
-          right off again.  Silly, but shouldn't happen often. */
-       list_move(&jeb->list, &c->erasing_list);
-       spin_unlock(&c->erase_completion_lock);
-       mutex_unlock(&c->erase_free_sem);
        jffs2_erase_failed(c, jeb, bad_offset);
        return;
 
 refile:
        /* Stick it back on the list from whence it came and come back later */
-       jffs2_erase_pending_trigger(c);
        mutex_lock(&c->erase_free_sem);
        spin_lock(&c->erase_completion_lock);
+       jffs2_garbage_collect_trigger(c);
        list_move(&jeb->list, &c->erase_complete_list);
        spin_unlock(&c->erase_completion_lock);
        mutex_unlock(&c->erase_free_sem);