[JFFS2] printk warning fixes
[pandora-kernel.git] / fs / jffs2 / wbuf.c
index b9b7007..de718e3 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/crc32.h>
 #include <linux/mtd/nand.h>
 #include <linux/jiffies.h>
+#include <linux/sched.h>
 
 #include "nodelist.h"
 
@@ -956,44 +957,48 @@ exit:
        return ret;
 }
 
-#define NR_OOB_SCAN_PAGES      4
+#define NR_OOB_SCAN_PAGES 4
+
+/* For historical reasons we use only 12 bytes for OOB clean marker */
+#define OOB_CM_SIZE 12
+
+static const struct jffs2_unknown_node oob_cleanmarker =
+{
+       .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK),
+       .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
+       .totlen = cpu_to_je32(8)
+};
 
 /*
- * Check, if the out of band area is empty
+ * Check, if the out of band area is empty. This function knows about the clean
+ * marker and if it is present in OOB, treats the OOB as empty anyway.
  */
 int jffs2_check_oob_empty(struct jffs2_sb_info *c,
                          struct jffs2_eraseblock *jeb, int mode)
 {
-       int i, page, ret;
-       int oobsize = c->mtd->oobsize;
+       int i, ret;
+       int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
        struct mtd_oob_ops ops;
 
-       ops.len = NR_OOB_SCAN_PAGES * oobsize;
-       ops.ooblen = oobsize;
+       ops.mode = MTD_OOB_AUTO;
+       ops.ooblen = NR_OOB_SCAN_PAGES * c->oobavail;
        ops.oobbuf = c->oobbuf;
-       ops.ooboffs = 0;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
 
        ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
-       if (ret) {
-               D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
-                         "failed %d for block at %08x\n", ret, jeb->offset));
+       if (ret || ops.oobretlen != ops.ooblen) {
+               printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd"
+                               " bytes, read %zd bytes, error %d\n",
+                               jeb->offset, ops.ooblen, ops.oobretlen, ret);
+               if (!ret)
+                       ret = -EIO;
                return ret;
        }
 
-       if (ops.retlen < ops.len) {
-               D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
-                         "returned short read (%zd bytes not %d) for block "
-                         "at %08x\n", ops.retlen, ops.len, jeb->offset));
-               return -EIO;
-       }
-
-       /* Special check for first page */
-       for(i = 0; i < oobsize ; i++) {
-               /* Yeah, we know about the cleanmarker. */
-               if (mode && i >= c->fsdata_pos &&
-                   i < c->fsdata_pos + c->fsdata_len)
+       for(i = 0; i < ops.ooblen; i++) {
+               if (mode && i < cmlen)
+                       /* Yeah, we know about the cleanmarker */
                        continue;
 
                if (ops.oobbuf[i] != 0xFF) {
@@ -1003,113 +1008,63 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
                }
        }
 
-       /* we know, we are aligned :) */
-       for (page = oobsize; page < ops.len; page += sizeof(long)) {
-               long dat = *(long *)(&ops.oobbuf[page]);
-               if(dat != -1)
-                       return 1;
-       }
        return 0;
 }
 
 /*
- * Scan for a valid cleanmarker and for bad blocks
+ * Check for a valid cleanmarker.
+ * Returns: 0 if a valid cleanmarker was found
+ *          1 if no cleanmarker was found
+ *          negative error code if an error occurred
  */
-int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
-                                 struct jffs2_eraseblock *jeb)
+int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
+                                struct jffs2_eraseblock *jeb)
 {
-       struct jffs2_unknown_node n;
        struct mtd_oob_ops ops;
-       int oobsize = c->mtd->oobsize;
-       unsigned char *p,*b;
-       int i, ret;
-       size_t offset = jeb->offset;
-
-       /* Check first if the block is bad. */
-       if (c->mtd->block_isbad(c->mtd, offset)) {
-               D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker()"
-                          ": Bad block at %08x\n", jeb->offset));
-               return 2;
-       }
+       int ret, cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 
-       ops.len = oobsize;
-       ops.ooblen = oobsize;
+       ops.mode = MTD_OOB_AUTO;
+       ops.ooblen = cmlen;
        ops.oobbuf = c->oobbuf;
-       ops.ooboffs = 0;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
 
-       ret = c->mtd->read_oob(c->mtd, offset, &ops);
-       if (ret) {
-               D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-                          "Read OOB failed %d for block at %08x\n",
-                          ret, jeb->offset));
+       ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
+       if (ret || ops.oobretlen != ops.ooblen) {
+               printk(KERN_ERR "cannot read OOB for EB at %08x, requested %zd"
+                               " bytes, read %zd bytes, error %d\n",
+                               jeb->offset, ops.ooblen, ops.oobretlen, ret);
+               if (!ret)
+                       ret = -EIO;
                return ret;
        }
 
-       if (ops.retlen < ops.len) {
-               D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-                           "Read OOB return short read (%zd bytes not %d) "
-                           "for block at %08x\n", ops.retlen, ops.len,
-                           jeb->offset));
-               return -EIO;
-       }
-
-       n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
-       n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-       n.totlen = cpu_to_je32 (8);
-       p = (unsigned char *) &n;
-       b = c->oobbuf + c->fsdata_pos;
-
-       for (i = c->fsdata_len; i; i--) {
-               if (*b++ != *p++)
-                       ret = 1;
-       }
-
-       D1(if (ret == 1) {
-               printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
-                      "Cleanmarker node not detected in block at %08x\n",
-                      offset);
-               printk(KERN_WARNING "OOB at %08zx was ", offset);
-               for (i=0; i < oobsize; i++)
-                       printk("%02x ", c->oobbuf[i]);
-               printk("\n");
-       });
-       return ret;
+       return !!memcmp(&oob_cleanmarker, c->oobbuf, cmlen);
 }
 
 int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
                                 struct jffs2_eraseblock *jeb)
 {
-       struct jffs2_unknown_node n;
-       int     ret;
+       int ret;
        struct mtd_oob_ops ops;
+       int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE);
 
-       n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
-       n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
-       n.totlen = cpu_to_je32(8);
-
-       ops.len = c->fsdata_len;
-       ops.ooblen = c->fsdata_len;;
-       ops.oobbuf = (uint8_t *)&n;
-       ops.ooboffs = c->fsdata_pos;
+       ops.mode = MTD_OOB_AUTO;
+       ops.ooblen = cmlen;
+       ops.oobbuf = (uint8_t *)&oob_cleanmarker;
+       ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
        ops.datbuf = NULL;
-       ops.mode = MTD_OOB_PLACE;
 
        ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops);
-
-       if (ret) {
-               D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
-                         "Write failed for block at %08x: error %d\n",
-                         jeb->offset, ret));
+       if (ret || ops.oobretlen != ops.ooblen) {
+               printk(KERN_ERR "cannot write OOB for EB at %08x, requested %zd"
+                               " bytes, read %zd bytes, error %d\n",
+                               jeb->offset, ops.ooblen, ops.oobretlen, ret);
+               if (!ret)
+                       ret = -EIO;
                return ret;
        }
-       if (ops.retlen != ops.len) {
-               D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
-                         "Short write for block at %08x: %zd not %d\n",
-                         jeb->offset, ops.retlen, ops.len));
-               return -EIO;
-       }
+
        return 0;
 }
 
@@ -1142,41 +1097,24 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
        return 1;
 }
 
-static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
+int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
 {
        struct nand_ecclayout *oinfo = c->mtd->ecclayout;
 
-       /* Do this only, if we have an oob buffer */
        if (!c->mtd->oobsize)
                return 0;
 
        /* Cleanmarker is out-of-band, so inline size zero */
        c->cleanmarker_size = 0;
 
-       /* Should we use autoplacement ? */
-       if (!oinfo) {
-               D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
+       if (!oinfo || oinfo->oobavail == 0) {
+               printk(KERN_ERR "inconsistent device description\n");
                return -EINVAL;
        }
 
-       D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
-       /* Get the position of the free bytes */
-       if (!oinfo->oobfree[0].length) {
-               printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep."
-                       " Autoplacement selected and no empty space in oob\n");
-               return -ENOSPC;
-       }
-       c->fsdata_pos = oinfo->oobfree[0].offset;
-       c->fsdata_len = oinfo->oobfree[0].length;
-       if (c->fsdata_len > 8)
-               c->fsdata_len = 8;
+       D1(printk(KERN_DEBUG "JFFS2 using OOB on NAND\n"));
 
-       return 0;
-}
-
-int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
-{
-       int res;
+       c->oobavail = oinfo->oobavail;
 
        /* Initialise write buffer */
        init_rwsem(&c->wbuf_sem);
@@ -1187,22 +1125,13 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
        if (!c->wbuf)
                return -ENOMEM;
 
-       c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->mtd->oobsize, GFP_KERNEL);
-       if (!c->oobbuf)
-               return -ENOMEM;
-
-       res = jffs2_nand_set_oobinfo(c);
-
-#ifdef BREAKME
-       if (!brokenbuf)
-               brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
-       if (!brokenbuf) {
+       c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->oobavail, GFP_KERNEL);
+       if (!c->oobbuf) {
                kfree(c->wbuf);
                return -ENOMEM;
        }
-       memset(brokenbuf, 0xdb, c->wbuf_pagesize);
-#endif
-       return res;
+
+       return 0;
 }
 
 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)