UBI: use mtd->writebufsize to set minimal I/O unit size
authorAnatolij Gustschin <agust@denx.de>
Thu, 16 Dec 2010 22:42:19 +0000 (23:42 +0100)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Thu, 6 Jan 2011 15:36:00 +0000 (15:36 +0000)
Previously we used mtd->writesize field to set UBI's minimal
I/O unit size. This sometimes caused UBIFS recovery issues
when mounting an uncleanly unmounted UBIFS partition on NOR
flash since mtd->writesize is 1 byte for NOR flash. The
MTD CFI driver however often performs writing multiple
bytes in one programming operation using the chip's write
buffer. We have to use the size of this write buffer as
a minimal I/O unit size for UBI on NOR flash to fix the
observed UBIFS recovery issues.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
drivers/mtd/ubi/build.c

index 5ebe280..f49e49d 100644 (file)
@@ -672,7 +672,33 @@ static int io_init(struct ubi_device *ubi)
                ubi->nor_flash = 1;
        }
 
-       ubi->min_io_size = ubi->mtd->writesize;
+       /*
+        * Set UBI min. I/O size (@ubi->min_io_size). We use @mtd->writebufsize
+        * for these purposes, not @mtd->writesize. At the moment this does not
+        * matter for NAND, because currently @mtd->writebufsize is equivalent to
+        * @mtd->writesize for all NANDs. However, some CFI NOR flashes may
+        * have @mtd->writebufsize which is multiple of @mtd->writesize.
+        *
+        * The reason we use @mtd->writebufsize for @ubi->min_io_size is that
+        * UBI and UBIFS recovery algorithms rely on the fact that if there was
+        * an unclean power cut, then we can find offset of the last corrupted
+        * node, align the offset to @ubi->min_io_size, read the rest of the
+        * eraseblock starting from this offset, and check whether there are
+        * only 0xFF bytes. If yes, then we are probably dealing with a
+        * corruption caused by a power cut, if not, then this is probably some
+        * severe corruption.
+        *
+        * Thus, we have to use the maximum write unit size of the flash, which
+        * is @mtd->writebufsize, because @mtd->writesize is the minimum write
+        * size, not the maximum.
+        */
+       if (ubi->mtd->type == MTD_NANDFLASH)
+               ubi_assert(ubi->mtd->writebufsize == ubi->mtd->writesize);
+       else if (ubi->mtd->type == MTD_NORFLASH)
+               ubi_assert(ubi->mtd->writebufsize % ubi->mtd->writesize == 0);
+
+       ubi->min_io_size = ubi->mtd->writebufsize;
+
        ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
 
        /*