Merge tag 'upstream-3.4-rc1' of git://git.infradead.org/linux-ubi
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Mar 2012 16:25:31 +0000 (09:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 23 Mar 2012 16:25:31 +0000 (09:25 -0700)
Pull UBI changes from Artem Bityutskiy:
 - Reduce memory consumption
 - Fix picking unknown blocks
 - Fix error-path in 'ubi_scan()'
 - Minor clean-ups

* tag 'upstream-3.4-rc1' of git://git.infradead.org/linux-ubi:
  UBI: rename MOVE_CANCEL_BITFLIPS to MOVE_TARGET_BITFLIPS
  UBI: rename peb_buf1 to peb_buf
  UBI: reduce memory consumption
  UBI: fix eraseblock picking criteria
  UBI: fix documentation and improve readability
  UBI: fix error handling in ubi_scan()

drivers/mtd/ubi/build.c
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/wl.c

index 115749f20f9e5402d62785950092b05a4ec1206e..0fde9fc7d2e5415d032d57104694c9ef0e61f763 100644 (file)
@@ -945,12 +945,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
                goto out_free;
 
        err = -ENOMEM;
-       ubi->peb_buf1 = vmalloc(ubi->peb_size);
-       if (!ubi->peb_buf1)
-               goto out_free;
-
-       ubi->peb_buf2 = vmalloc(ubi->peb_size);
-       if (!ubi->peb_buf2)
+       ubi->peb_buf = vmalloc(ubi->peb_size);
+       if (!ubi->peb_buf)
                goto out_free;
 
        err = ubi_debugging_init_dev(ubi);
@@ -1029,8 +1025,7 @@ out_detach:
 out_debugging:
        ubi_debugging_exit_dev(ubi);
 out_free:
-       vfree(ubi->peb_buf1);
-       vfree(ubi->peb_buf2);
+       vfree(ubi->peb_buf);
        if (ref)
                put_device(&ubi->dev);
        else
@@ -1101,8 +1096,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
        vfree(ubi->vtbl);
        put_mtd_device(ubi->mtd);
        ubi_debugging_exit_dev(ubi);
-       vfree(ubi->peb_buf1);
-       vfree(ubi->peb_buf2);
+       vfree(ubi->peb_buf);
        ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
        put_device(&ubi->dev);
        return 0;
index cd26da8ad225b882d918188e46c6c2d38cccc803..2455d620d96b8a4c1ecc86def50d1bd580766ece 100644 (file)
@@ -529,18 +529,18 @@ retry:
 
        data_size = offset + len;
        mutex_lock(&ubi->buf_mutex);
-       memset(ubi->peb_buf1 + offset, 0xFF, len);
+       memset(ubi->peb_buf + offset, 0xFF, len);
 
        /* Read everything before the area where the write failure happened */
        if (offset > 0) {
-               err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
+               err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, offset);
                if (err && err != UBI_IO_BITFLIPS)
                        goto out_unlock;
        }
 
-       memcpy(ubi->peb_buf1 + offset, buf, len);
+       memcpy(ubi->peb_buf + offset, buf, len);
 
-       err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
+       err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
        if (err) {
                mutex_unlock(&ubi->buf_mutex);
                goto write_error;
@@ -979,7 +979,7 @@ static int is_error_sane(int err)
  * physical eraseblock @to. The @vid_hdr buffer may be changed by this
  * function. Returns:
  *   o %0 in case of success;
- *   o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, %MOVE_CANCEL_BITFLIPS, etc;
+ *   o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, %MOVE_TARGET_BITFLIPS, etc;
  *   o a negative error code in case of failure.
  */
 int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
@@ -1053,13 +1053,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
 
        /*
         * OK, now the LEB is locked and we can safely start moving it. Since
-        * this function utilizes the @ubi->peb_buf1 buffer which is shared
+        * this function utilizes the @ubi->peb_buf buffer which is shared
         * with some other functions - we lock the buffer by taking the
         * @ubi->buf_mutex.
         */
        mutex_lock(&ubi->buf_mutex);
        dbg_wl("read %d bytes of data", aldata_size);
-       err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size);
+       err = ubi_io_read_data(ubi, ubi->peb_buf, from, 0, aldata_size);
        if (err && err != UBI_IO_BITFLIPS) {
                ubi_warn("error %d while reading data from PEB %d",
                         err, from);
@@ -1079,10 +1079,10 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
         */
        if (vid_hdr->vol_type == UBI_VID_DYNAMIC)
                aldata_size = data_size =
-                       ubi_calc_data_len(ubi, ubi->peb_buf1, data_size);
+                       ubi_calc_data_len(ubi, ubi->peb_buf, data_size);
 
        cond_resched();
-       crc = crc32(UBI_CRC32_INIT, ubi->peb_buf1, data_size);
+       crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size);
        cond_resched();
 
        /*
@@ -1116,12 +1116,12 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                        if (is_error_sane(err))
                                err = MOVE_TARGET_RD_ERR;
                } else
-                       err = MOVE_CANCEL_BITFLIPS;
+                       err = MOVE_TARGET_BITFLIPS;
                goto out_unlock_buf;
        }
 
        if (data_size > 0) {
-               err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
+               err = ubi_io_write_data(ubi, ubi->peb_buf, to, 0, aldata_size);
                if (err) {
                        if (err == -EIO)
                                err = MOVE_TARGET_WR_ERR;
@@ -1134,8 +1134,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                 * We've written the data and are going to read it back to make
                 * sure it was written correctly.
                 */
-
-               err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
+               memset(ubi->peb_buf, 0xFF, aldata_size);
+               err = ubi_io_read_data(ubi, ubi->peb_buf, to, 0, aldata_size);
                if (err) {
                        if (err != UBI_IO_BITFLIPS) {
                                ubi_warn("error %d while reading data back "
@@ -1143,13 +1143,13 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
                                if (is_error_sane(err))
                                        err = MOVE_TARGET_RD_ERR;
                        } else
-                               err = MOVE_CANCEL_BITFLIPS;
+                               err = MOVE_TARGET_BITFLIPS;
                        goto out_unlock_buf;
                }
 
                cond_resched();
 
-               if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) {
+               if (crc != crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size)) {
                        ubi_warn("read data back from PEB %d and it is "
                                 "different", to);
                        err = -EINVAL;
index 5cde4e5ca3e542a38945be3d12f106b4c3853e80..43f1a0011a55cad9a9d876cff0241ecda9876ba3 100644 (file)
@@ -431,11 +431,11 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
                        goto out;
 
                /* Make sure the PEB contains only 0xFF bytes */
-               err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
+               err = ubi_io_read(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size);
                if (err)
                        goto out;
 
-               err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
+               err = ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->peb_size);
                if (err == 0) {
                        ubi_err("erased PEB %d, but a non-0xFF byte found",
                                pnum);
@@ -444,17 +444,17 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
                }
 
                /* Write a pattern and check it */
-               memset(ubi->peb_buf1, patterns[i], ubi->peb_size);
-               err = ubi_io_write(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
+               memset(ubi->peb_buf, patterns[i], ubi->peb_size);
+               err = ubi_io_write(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size);
                if (err)
                        goto out;
 
-               memset(ubi->peb_buf1, ~patterns[i], ubi->peb_size);
-               err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
+               memset(ubi->peb_buf, ~patterns[i], ubi->peb_size);
+               err = ubi_io_read(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size);
                if (err)
                        goto out;
 
-               err = ubi_check_pattern(ubi->peb_buf1, patterns[i],
+               err = ubi_check_pattern(ubi->peb_buf, patterns[i],
                                        ubi->peb_size);
                if (err == 0) {
                        ubi_err("pattern %x checking failed for PEB %d",
index 0cb17d936b5a46581ab6360c1b8307211b3c01c0..12c43b44f81578a4b78369e5140b66d34d26a188 100644 (file)
@@ -789,9 +789,9 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
        int err;
 
        mutex_lock(&ubi->buf_mutex);
-       memset(ubi->peb_buf1, 0x00, ubi->leb_size);
+       memset(ubi->peb_buf, 0x00, ubi->leb_size);
 
-       err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
+       err = ubi_io_read(ubi, ubi->peb_buf, pnum, ubi->leb_start,
                          ubi->leb_size);
        if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) {
                /*
@@ -808,7 +808,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
        if (err)
                goto out_unlock;
 
-       if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size))
+       if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size))
                goto out_unlock;
 
        ubi_err("PEB %d contains corrupted VID header, and the data does not "
@@ -818,7 +818,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
        dbg_msg("hexdump of PEB %d offset %d, length %d",
                pnum, ubi->leb_start, ubi->leb_size);
        ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-                              ubi->peb_buf1, ubi->leb_size, 1);
+                              ubi->peb_buf, ubi->leb_size, 1);
        err = 1;
 
 out_unlock:
@@ -1174,7 +1174,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
 
        ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
        if (!ech)
-               goto out_slab;
+               goto out_si;
 
        vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
        if (!vidh)
@@ -1235,8 +1235,6 @@ out_vidh:
        ubi_free_vid_hdr(ubi, vidh);
 out_ech:
        kfree(ech);
-out_slab:
-       kmem_cache_destroy(si->scan_leb_slab);
 out_si:
        ubi_scan_destroy_si(si);
        return ERR_PTR(err);
@@ -1325,7 +1323,9 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
                }
        }
 
-       kmem_cache_destroy(si->scan_leb_slab);
+       if (si->scan_leb_slab)
+               kmem_cache_destroy(si->scan_leb_slab);
+
        kfree(si);
 }
 
index d51d75d344462c1ec3b0ae657b423594f5857517..b162790790a99d58f5abe69a1eb4ea4030c7cf6a 100644 (file)
@@ -118,7 +118,7 @@ enum {
  *                     PEB
  * MOVE_TARGET_WR_ERR: canceled because there was a write error to the target
  *                     PEB
- * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the
+ * MOVE_TARGET_BITFLIPS: canceled because a bit-flip was detected in the
  *                       target PEB
  * MOVE_RETRY: retry scrubbing the PEB
  */
@@ -127,7 +127,7 @@ enum {
        MOVE_SOURCE_RD_ERR,
        MOVE_TARGET_RD_ERR,
        MOVE_TARGET_WR_ERR,
-       MOVE_CANCEL_BITFLIPS,
+       MOVE_TARGET_BITFLIPS,
        MOVE_RETRY,
 };
 
@@ -387,9 +387,8 @@ struct ubi_wl_entry;
  *                  time (MTD write buffer size)
  * @mtd: MTD device descriptor
  *
- * @peb_buf1: a buffer of PEB size used for different purposes
- * @peb_buf2: another buffer of PEB size used for different purposes
- * @buf_mutex: protects @peb_buf1 and @peb_buf2
+ * @peb_buf: a buffer of PEB size used for different purposes
+ * @buf_mutex: protects @peb_buf
  * @ckvol_mutex: serializes static volume checking when opening
  *
  * @dbg: debugging information for this UBI device
@@ -471,8 +470,7 @@ struct ubi_device {
        int max_write_size;
        struct mtd_info *mtd;
 
-       void *peb_buf1;
-       void *peb_buf2;
+       void *peb_buf;
        struct mutex buf_mutex;
        struct mutex ckvol_mutex;
 
index 0696e36b053939e878d0215aefe4f4598ba61ac3..7c1a9bf8ac869592e2697b1217bc9261197dc11b 100644 (file)
@@ -350,18 +350,19 @@ static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e)
 /**
  * find_wl_entry - find wear-leveling entry closest to certain erase counter.
  * @root: the RB-tree where to look for
- * @max: highest possible erase counter
+ * @diff: maximum possible difference from the smallest erase counter
  *
  * This function looks for a wear leveling entry with erase counter closest to
- * @max and less than @max.
+ * min + @diff, where min is the smallest erase counter.
  */
-static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max)
+static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int diff)
 {
        struct rb_node *p;
        struct ubi_wl_entry *e;
+       int max;
 
        e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
-       max += e->ec;
+       max = e->ec + diff;
 
        p = root->rb_node;
        while (p) {
@@ -389,7 +390,7 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max)
  */
 int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
 {
-       int err, medium_ec;
+       int err;
        struct ubi_wl_entry *e, *first, *last;
 
        ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
@@ -427,7 +428,7 @@ retry:
                 * For unknown data we pick a physical eraseblock with medium
                 * erase counter. But we by no means can pick a physical
                 * eraseblock with erase counter greater or equivalent than the
-                * lowest erase counter plus %WL_FREE_MAX_DIFF.
+                * lowest erase counter plus %WL_FREE_MAX_DIFF/2.
                 */
                first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
                                        u.rb);
@@ -436,10 +437,8 @@ retry:
                if (last->ec - first->ec < WL_FREE_MAX_DIFF)
                        e = rb_entry(ubi->free.rb_node,
                                        struct ubi_wl_entry, u.rb);
-               else {
-                       medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
-                       e = find_wl_entry(&ubi->free, medium_ec);
-               }
+               else
+                       e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
                break;
        case UBI_SHORTTERM:
                /*
@@ -799,7 +798,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
                        scrubbing = 1;
                        goto out_not_moved;
                }
-               if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR ||
+               if (err == MOVE_TARGET_BITFLIPS || err == MOVE_TARGET_WR_ERR ||
                    err == MOVE_TARGET_RD_ERR) {
                        /*
                         * Target PEB had bit-flips or write error - torture it.