]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 Jul 2009 02:15:34 +0000 (19:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 11 Jul 2009 02:15:34 +0000 (19:15 -0700)
* 'linux-next' of git://git.infradead.org/ubi-2.6:
  UBI: fix compilation warnings
  UBI: fix NOR flash recovery
  UBI: nicify image sequence number handling
  UBI: add image sequence number to EC header
  UBI: remove bogus debugging checks
  UBI: add empty eraseblocks verification

drivers/mtd/ubi/build.c
drivers/mtd/ubi/debug.c
drivers/mtd/ubi/debug.h
drivers/mtd/ubi/io.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/scan.h
drivers/mtd/ubi/ubi-media.h
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/wl.c

index 286ed594e5a0ec01d87810c004e0511b78385477..e1f7d0a78b9d58e28a2b6c1fdad43423cddd3956 100644 (file)
@@ -657,6 +657,11 @@ static int io_init(struct ubi_device *ubi)
        if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
                ubi->bad_allowed = 1;
 
+       if (ubi->mtd->type == MTD_NORFLASH) {
+               ubi_assert(ubi->mtd->writesize == 1);
+               ubi->nor_flash = 1;
+       }
+
        ubi->min_io_size = ubi->mtd->writesize;
        ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
 
@@ -996,6 +1001,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
        ubi_msg("number of PEBs reserved for bad PEB handling: %d",
                ubi->beb_rsvd_pebs);
        ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
+       ubi_msg("image sequence number: %d", ubi->image_seq);
 
        /*
         * The below lock makes sure we do not race with 'ubi_thread()' which
index c0ed60e8ade978ca74091aed6a8e5b14f1a47e63..54b0186915fbf6ab6be8f845a4d942f7f2f277aa 100644 (file)
@@ -44,6 +44,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
               be32_to_cpu(ec_hdr->vid_hdr_offset));
        printk(KERN_DEBUG "\tdata_offset    %d\n",
               be32_to_cpu(ec_hdr->data_offset));
+       printk(KERN_DEBUG "\timage_seq      %d\n",
+              be32_to_cpu(ec_hdr->image_seq));
        printk(KERN_DEBUG "\thdr_crc        %#08x\n",
               be32_to_cpu(ec_hdr->hdr_crc));
        printk(KERN_DEBUG "erase counter header hexdump:\n");
index 13777e5beac93344ae759aa2ea0176c796e97d1d..a4da7a09b949b75f5e259837da31190b31874bbc 100644 (file)
@@ -93,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 #define UBI_IO_DEBUG 0
 #endif
 
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
+#else
+#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#endif
+
 #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
 #define DBG_DISABLE_BGT 1
 #else
@@ -167,6 +173,7 @@ static inline int ubi_dbg_is_erase_failure(void)
 #define ubi_dbg_is_bitflip()       0
 #define ubi_dbg_is_write_failure() 0
 #define ubi_dbg_is_erase_failure() 0
+#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
 
 #endif /* !CONFIG_MTD_UBI_DEBUG */
 #endif /* !__UBI_DEBUG_H__ */
index effaff28bab18ef4936c69cf354a4b8a11db17dd..4cb69925d8d968f9021626a6dd38933af94842ee 100644 (file)
@@ -98,17 +98,12 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
 static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
 static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
                                  const struct ubi_vid_hdr *vid_hdr);
-static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
-                                int len);
-static int paranoid_check_empty(struct ubi_device *ubi, int pnum);
 #else
 #define paranoid_check_not_bad(ubi, pnum) 0
 #define paranoid_check_peb_ec_hdr(ubi, pnum)  0
 #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr)  0
 #define paranoid_check_peb_vid_hdr(ubi, pnum) 0
 #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0
-#define paranoid_check_all_ff(ubi, pnum, offset, len) 0
-#define paranoid_check_empty(ubi, pnum) 0
 #endif
 
 /**
@@ -244,7 +239,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
                return err > 0 ? -EINVAL : err;
 
        /* The area we are writing to has to contain all 0xFF bytes */
-       err = paranoid_check_all_ff(ubi, pnum, offset, len);
+       err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
        if (err)
                return err > 0 ? -EINVAL : err;
 
@@ -271,8 +266,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
        addr = (loff_t)pnum * ubi->peb_size + offset;
        err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf);
        if (err) {
-               ubi_err("error %d while writing %d bytes to PEB %d:%d, written"
-                       " %zd bytes", err, len, pnum, offset, written);
+               ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
+                       "%zd bytes", err, len, pnum, offset, written);
                ubi_dbg_dump_stack();
        } else
                ubi_assert(written == len);
@@ -350,7 +345,7 @@ retry:
                return -EIO;
        }
 
-       err = paranoid_check_all_ff(ubi, pnum, 0, ubi->peb_size);
+       err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
        if (err)
                return err > 0 ? -EINVAL : err;
 
@@ -458,6 +453,54 @@ out:
        return err;
 }
 
+/**
+ * nor_erase_prepare - prepare a NOR flash PEB for erasure.
+ * @ubi: UBI device description object
+ * @pnum: physical eraseblock number to prepare
+ *
+ * NOR flash, or at least some of them, have peculiar embedded PEB erasure
+ * algorithm: the PEB is first filled with zeroes, then it is erased. And
+ * filling with zeroes starts from the end of the PEB. This was observed with
+ * Spansion S29GL512N NOR flash.
+ *
+ * This means that in case of a power cut we may end up with intact data at the
+ * beginning of the PEB, and all zeroes at the end of PEB. In other words, the
+ * EC and VID headers are OK, but a large chunk of data at the end of PEB is
+ * zeroed. This makes UBI mistakenly treat this PEB as used and associate it
+ * with an LEB, which leads to subsequent failures (e.g., UBIFS fails).
+ *
+ * This function is called before erasing NOR PEBs and it zeroes out EC and VID
+ * magic numbers in order to invalidate them and prevent the failures. Returns
+ * zero in case of success and a negative error code in case of failure.
+ */
+static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
+{
+       int err;
+       size_t written;
+       loff_t addr;
+       uint32_t data = 0;
+
+       addr = (loff_t)pnum * ubi->peb_size;
+       err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
+       if (err) {
+               ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
+                       "%zd bytes", err, pnum, 0, written);
+               ubi_dbg_dump_stack();
+               return err;
+       }
+
+       addr += ubi->vid_hdr_aloffset;
+       err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
+       if (err) {
+               ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
+                       "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written);
+               ubi_dbg_dump_stack();
+               return err;
+       }
+
+       return 0;
+}
+
 /**
  * ubi_io_sync_erase - synchronously erase a physical eraseblock.
  * @ubi: UBI device description object
@@ -489,6 +532,12 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
                return -EROFS;
        }
 
+       if (ubi->nor_flash) {
+               err = nor_erase_prepare(ubi, pnum);
+               if (err)
+                       return err;
+       }
+
        if (torture) {
                ret = torture_peb(ubi, pnum);
                if (ret < 0)
@@ -672,11 +721,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                if (read_err != -EBADMSG &&
                    check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
                        /* The physical eraseblock is supposedly empty */
-                       err = paranoid_check_all_ff(ubi, pnum, 0,
-                                                   ubi->peb_size);
-                       if (err)
-                               return err > 0 ? UBI_IO_BAD_EC_HDR : err;
-
                        if (verbose)
                                ubi_warn("no EC header found at PEB %d, "
                                         "only 0xFF bytes", pnum);
@@ -752,6 +796,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
        ec_hdr->version = UBI_VERSION;
        ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset);
        ec_hdr->data_offset = cpu_to_be32(ubi->leb_start);
+       ec_hdr->image_seq = cpu_to_be32(ubi->image_seq);
        crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
        ec_hdr->hdr_crc = cpu_to_be32(crc);
 
@@ -947,15 +992,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                if (read_err != -EBADMSG &&
                    check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
                        /* The physical eraseblock is supposedly free */
-
-                       /*
-                        * The below is just a paranoid check, it has to be
-                        * compiled out if paranoid checks are disabled.
-                        */
-                       err = paranoid_check_empty(ubi, pnum);
-                       if (err)
-                               return err > 0 ? UBI_IO_BAD_VID_HDR : err;
-
                        if (verbose)
                                ubi_warn("no VID header found at PEB %d, "
                                         "only 0xFF bytes", pnum);
@@ -1229,7 +1265,7 @@ exit:
 }
 
 /**
- * paranoid_check_all_ff - check that a region of flash is empty.
+ * ubi_dbg_check_all_ff - check that a region of flash is empty.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock number to check
  * @offset: the starting offset within the physical eraseblock to check
@@ -1239,8 +1275,7 @@ exit:
  * @offset of the physical eraseblock @pnum, %1 if not, and a negative error
  * code if an error occurred.
  */
-static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
-                                int len)
+int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
 {
        size_t read;
        int err;
@@ -1276,74 +1311,4 @@ error:
        return err;
 }
 
-/**
- * paranoid_check_empty - whether a PEB is empty.
- * @ubi: UBI device description object
- * @pnum: the physical eraseblock number to check
- *
- * This function makes sure PEB @pnum is empty, which means it contains only
- * %0xFF data bytes. Returns zero if the PEB is empty, %1 if not, and a
- * negative error code in case of failure.
- *
- * Empty PEBs have the EC header, and do not have the VID header. The caller of
- * this function should have already made sure the PEB does not have the VID
- * header. However, this function re-checks that, because it is possible that
- * the header and data has already been written to the PEB.
- *
- * Let's consider a possible scenario. Suppose there are 2 tasks - A and B.
- * Task A is in 'wear_leveling_worker()'. It is reading VID header of PEB X to
- * find which LEB it corresponds to. PEB X is currently unmapped, and has no
- * VID header. Task B is trying to write to PEB X.
- *
- * Task A: in 'ubi_io_read_vid_hdr()': reads the VID header from PEB X. The
- *         read data contain all 0xFF bytes;
- * Task B: writes VID header and some data to PEB X;
- * Task A: assumes PEB X is empty, calls 'paranoid_check_empty()'. And if we
- *         do not re-read the VID header, and do not cancel the checking if it
- *         is there, we fail.
- */
-static int paranoid_check_empty(struct ubi_device *ubi, int pnum)
-{
-       int err, offs = ubi->vid_hdr_aloffset, len = ubi->vid_hdr_alsize;
-       size_t read;
-       uint32_t magic;
-       const struct ubi_vid_hdr *vid_hdr;
-
-       mutex_lock(&ubi->dbg_buf_mutex);
-       err = ubi->mtd->read(ubi->mtd, offs, len, &read, ubi->dbg_peb_buf);
-       if (err && err != -EUCLEAN) {
-               ubi_err("error %d while reading %d bytes from PEB %d:%d, "
-                       "read %zd bytes", err, len, pnum, offs, read);
-               goto error;
-       }
-
-       vid_hdr = ubi->dbg_peb_buf;
-       magic = be32_to_cpu(vid_hdr->magic);
-       if (magic == UBI_VID_HDR_MAGIC)
-               /* The PEB contains VID header, so it is not empty */
-               goto out;
-
-       err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
-       if (err == 0) {
-               ubi_err("flash region at PEB %d:%d, length %d does not "
-                       "contain all 0xFF bytes", pnum, offs, len);
-               goto fail;
-       }
-
-out:
-       mutex_unlock(&ubi->dbg_buf_mutex);
-       return 0;
-
-fail:
-       ubi_err("paranoid check failed for PEB %d", pnum);
-       ubi_msg("hex dump of the %d-%d region", offs, offs + len);
-       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-                      ubi->dbg_peb_buf, len, 1);
-       err = 1;
-error:
-       ubi_dbg_dump_stack();
-       mutex_unlock(&ubi->dbg_buf_mutex);
-       return err;
-}
-
 #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
index c3d653ba5ca0153c45ccbfd21a6d106bfa1b6220..f60895ee0aebde9098e1f5251be0a38ecd6cf02f 100644 (file)
@@ -757,6 +757,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
        si->is_empty = 0;
 
        if (!ec_corr) {
+               int image_seq;
+
                /* Make sure UBI version is OK */
                if (ech->version != UBI_VERSION) {
                        ubi_err("this UBI version is %d, image version is %d",
@@ -778,6 +780,18 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                        ubi_dbg_dump_ec_hdr(ech);
                        return -EINVAL;
                }
+
+               image_seq = be32_to_cpu(ech->ec);
+               if (!si->image_seq_set) {
+                       ubi->image_seq = image_seq;
+                       si->image_seq_set = 1;
+               } else if (ubi->image_seq != image_seq) {
+                       ubi_err("bad image sequence number %d in PEB %d, "
+                               "expected %d", image_seq, pnum, ubi->image_seq);
+                       ubi_dbg_dump_ec_hdr(ech);
+                       return -EINVAL;
+               }
+
        }
 
        /* OK, we've done with the EC header, let's look at the VID header */
index 61df208e2f2077de860db28494e8639349368111..1017cf12def56253606168e3c2ad18af674b8eae 100644 (file)
@@ -102,6 +102,7 @@ struct ubi_scan_volume {
  * @mean_ec: mean erase counter value
  * @ec_sum: a temporary variable used when calculating @mean_ec
  * @ec_count: a temporary variable used when calculating @mean_ec
+ * @image_seq_set: indicates @ubi->image_seq is known
  *
  * This data structure contains the result of scanning and may be used by other
  * UBI sub-systems to build final UBI data structures, further error-recovery
@@ -124,6 +125,7 @@ struct ubi_scan_info {
        int mean_ec;
        uint64_t ec_sum;
        int ec_count;
+       int image_seq_set;
 };
 
 struct ubi_device;
index 8419fdccc79cbcbdadb639b8188c65eab18bd468..503ea9b273094670d0933baafbfbfb04ae6d88cd 100644 (file)
@@ -129,6 +129,7 @@ enum {
  * @ec: the erase counter
  * @vid_hdr_offset: where the VID header starts
  * @data_offset: where the user data start
+ * @image_seq: image sequence number
  * @padding2: reserved for future, zeroes
  * @hdr_crc: erase counter header CRC checksum
  *
@@ -144,6 +145,14 @@ enum {
  * volume identifier header and user data, relative to the beginning of the
  * physical eraseblock. These values have to be the same for all physical
  * eraseblocks.
+ *
+ * The @image_seq field is used to validate a UBI image that has been prepared
+ * for a UBI device. The @image_seq value can be any value, but it must be the
+ * same on all eraseblocks. UBI will ensure that all new erase counter headers
+ * also contain this value, and will check the value when scanning at start-up.
+ * One way to make use of @image_seq is to increase its value by one every time
+ * an image is flashed over an existing image, then, if the flashing does not
+ * complete, UBI will detect the error when scanning.
  */
 struct ubi_ec_hdr {
        __be32  magic;
@@ -152,7 +161,8 @@ struct ubi_ec_hdr {
        __be64  ec; /* Warning: the current limit is 31-bit anyway! */
        __be32  vid_hdr_offset;
        __be32  data_offset;
-       __u8    padding2[36];
+       __be32  image_seq;
+       __u8    padding2[32];
        __be32  hdr_crc;
 } __attribute__ ((packed));
 
index 28acd133c997987eedefe9c926313a4dd207ffb9..6a5fe963378367ab48f871cbd6893d56d4ed454e 100644 (file)
@@ -301,6 +301,7 @@ struct ubi_wl_entry;
  *                @vol->readers, @vol->writers, @vol->exclusive,
  *                @vol->ref_count, @vol->mapping and @vol->eba_tbl.
  * @ref_count: count of references on the UBI device
+ * @image_seq: image sequence number recorded on EC headers
  *
  * @rsvd_pebs: count of reserved physical eraseblocks
  * @avail_pebs: count of available physical eraseblocks
@@ -372,6 +373,7 @@ struct ubi_wl_entry;
  * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset
  * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
  *               not
+ * @nor_flash: non-zero if working on top of NOR flash
  * @mtd: MTD device descriptor
  *
  * @peb_buf1: a buffer of PEB size used for different purposes
@@ -390,6 +392,7 @@ struct ubi_device {
        struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT];
        spinlock_t volumes_lock;
        int ref_count;
+       int image_seq;
 
        int rsvd_pebs;
        int avail_pebs;
@@ -452,7 +455,8 @@ struct ubi_device {
        int vid_hdr_offset;
        int vid_hdr_aloffset;
        int vid_hdr_shift;
-       int bad_allowed;
+       unsigned int bad_allowed:1;
+       unsigned int nor_flash:1;
        struct mtd_info *mtd;
 
        void *peb_buf1;
index 2b2472300610f166eb897a53647436f4307c9456..600c7229d5cf21b0d959ca2d7c1a86ccc676e4af 100644 (file)
@@ -459,6 +459,14 @@ retry:
        dbg_wl("PEB %d EC %d", e->pnum, e->ec);
        prot_queue_add(ubi, e);
        spin_unlock(&ubi->wl_lock);
+
+       err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
+                                  ubi->peb_size - ubi->vid_hdr_aloffset);
+       if (err) {
+               ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
+               return err > 0 ? -EINVAL : err;
+       }
+
        return e->pnum;
 }