GIT 09ba2d5f14fa4f58bc2e53ed8159c5e38a3fb908 git://git.infradead.org/~dedekind/ubi-2.6.git#master commit Author: Artem Bityutskiy Date: Thu Dec 6 18:47:30 2007 +0200 UBI: add ubi_leb_map interface The idea of this interface belongs to Adrian Hunter. The interface is extremely useful when one has to have a guarantee that an LEB will contain all 0xFFs even in case of an unclean reboot. UBI does have an 'ubi_leb_erase()' call which may do this, but it is stupid and ineffecient, because it flushes whole queue. I should be re-worked to just be a pair of unmap, map calls. The user of the interfaci is UBIFS at the moment. Signed-off-by: Artem Bityutskiy commit 3514b674eb1eb698f9716c99485fc54c06700580 Author: Artem Bityutskiy Date: Tue Dec 4 21:36:12 2007 +0200 UBI: bugfix: allocate mandatory EBs first First allocate the necessary eraseblocks, then the optional ones. Otherwise it allocates all PEBs for bad EB handling, and fails on then following EBA LEB allocation. Reported-by: Adrian Hunter Signed-off-by: Artem Bityutskiy commit a5d8411fdc93cf6e8363ef3fed148920dc3f5527 Author: Artem Bityutskiy Date: Thu Oct 18 20:09:41 2007 +0300 UBI: fix error code in ubi_io_read() When NAND detects an ECC error, it returns -EBADMSG. It does not stop reading requested data if one page has an ECC error, it keeps going and reads all the requested data. If it fails to read all the data, it does not return -EBADMSG, but returns the error code which reflects the reason of the failure. But some drivers may have bugs (e.g., OneNAND had) and stop reading after the first ECC error, so it returns -EBADMSG. In turn, UBI propagates this up to the caller. The caller will treat this as "all the requested data was read, but there was an ECC error". So we change the error code to -EIO if it is -EBADMSG and the read length is less then the requested length. We also add an assertion, so if UBI debugging is enabled, UBI will bug. Pointed-to-by: Adrian Hunter Signed-off-by: Artem Bityutskiy drivers/mtd/ubi/eba.c | 31 +++++++++++++++++-------------- drivers/mtd/ubi/io.c | 10 ++++++++++ drivers/mtd/ubi/kapi.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/ubi.h | 1 + 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 880fa36..c87db07 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -656,11 +656,14 @@ retry: goto write_error; } - err = ubi_io_write_data(ubi, buf, pnum, offset, len); - if (err) { - ubi_warn("failed to write %d bytes at offset %d of LEB %d:%d, " - "PEB %d", len, offset, vol_id, lnum, pnum); - goto write_error; + if (len) { + err = ubi_io_write_data(ubi, buf, pnum, offset, len); + if (err) { + ubi_warn("failed to write %d bytes at offset %d of " + "LEB %d:%d, PEB %d", len, offset, vol_id, + lnum, pnum); + goto write_error; + } } vol->eba_tbl[lnum] = pnum; @@ -1168,6 +1171,15 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) } } + if (ubi->avail_pebs < EBA_RESERVED_PEBS) { + ubi_err("no enough physical eraseblocks (%d, need %d)", + ubi->avail_pebs, EBA_RESERVED_PEBS); + err = -ENOSPC; + goto out_free; + } + ubi->avail_pebs -= EBA_RESERVED_PEBS; + ubi->rsvd_pebs += EBA_RESERVED_PEBS; + if (ubi->bad_allowed) { ubi_calculate_reserved(ubi); @@ -1184,15 +1196,6 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) ubi->rsvd_pebs += ubi->beb_rsvd_pebs; } - if (ubi->avail_pebs < EBA_RESERVED_PEBS) { - ubi_err("no enough physical eraseblocks (%d, need %d)", - ubi->avail_pebs, EBA_RESERVED_PEBS); - err = -ENOSPC; - goto out_free; - } - ubi->avail_pebs -= EBA_RESERVED_PEBS; - ubi->rsvd_pebs += EBA_RESERVED_PEBS; - dbg_eba("EBA unit is initialized"); return 0; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 7c304ee..db3efde 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -173,6 +173,16 @@ retry: ubi_err("error %d while reading %d bytes from PEB %d:%d, " "read %zd bytes", err, len, pnum, offset, read); ubi_dbg_dump_stack(); + + /* + * The driver should never return -EBADMSG if it failed to read + * all the requested data. But some buggy drivers might do + * this, so we change it to -EIO. + */ + if (read != len && err == -EBADMSG) { + ubi_assert(0); + err = -EIO; + } } else { ubi_assert(len == read); diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 03c774f..e1ef802 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -547,6 +547,51 @@ int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum) EXPORT_SYMBOL_GPL(ubi_leb_unmap); /** + * ubi_leb_map - map logical erasblock to a physical eraseblock. + * @desc: volume descriptor + * @lnum: logical eraseblock number + * @dtype: expected data type + * + * This function maps an un-mapped logical eraseblock @lnum to a physical + * eraseblock. This means, that after a successfull invocation of this + * function the logical eraseblock @lnum will be empty (contain only %0xFF + * bytes) and be mapped to a physical eraseblock, even if an unclean reboot + * happens. + * + * This function returns zero in case of success, %-EBADF if the volume is + * damaged because of an interrupted update, %-EBADMSG if the logical + * eraseblock is already mapped, and other negative error codes in case of + * other failures. + */ +int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) +{ + struct ubi_volume *vol = desc->vol; + struct ubi_device *ubi = vol->ubi; + int vol_id = vol->vol_id; + + dbg_msg("unmap LEB %d:%d", vol_id, lnum); + + if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) + return -EROFS; + + if (lnum < 0 || lnum >= vol->reserved_pebs) + return -EINVAL; + + if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && + dtype != UBI_UNKNOWN) + return -EINVAL; + + if (vol->upd_marker) + return -EBADF; + + if (vol->eba_tbl[lnum] >= 0) + return -EBADMSG; + + return ubi_eba_write_leb(ubi, vol_id, lnum, NULL, 0, 0, dtype); +} +EXPORT_SYMBOL_GPL(ubi_leb_map); + +/** * ubi_is_mapped - check if logical eraseblock is mapped. * @desc: volume descriptor * @lnum: logical eraseblock number diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h index 3d967b6..c4abe03 100644 --- a/include/linux/mtd/ubi.h +++ b/include/linux/mtd/ubi.h @@ -167,6 +167,7 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, int len, int dtype); int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum); int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum); +int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype); int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum); /*