diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 16:34:23 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 16:34:23 -0700 |
commit | 4f3a29dadaf999a273f1e7fe2476595d0283eef3 (patch) | |
tree | 3776499f6edc95a36533c7efe32a7b6038c88b61 | |
parent | 06d362931a530e0d48c1a9554a752da4ed240f0b (diff) | |
parent | 45aafd32996e27bfc4862654ff31231bdddbe200 (diff) | |
download | op-kernel-dev-4f3a29dadaf999a273f1e7fe2476595d0283eef3.zip op-kernel-dev-4f3a29dadaf999a273f1e7fe2476595d0283eef3.tar.gz |
Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6
* 'linux-next' of git://git.infradead.org/ubi-2.6:
UBI: tighten the corrupted PEB criteria
UBI: fix check_data_ff return code
UBI: remember copy_flag while scanning
UBI: preserve corrupted PEBs
UBI: add truly corrupted PEBs to corrupted list
UBI: introduce debugging helper function
UBI: make check_pattern function non-static
UBI: do not put eraseblocks to the corrupted list unnecessarily
UBI: separate out corrupted list
UBI: change cascade of ifs to switch statements
UBI: rename a local variable
UBI: handle bit-flips when no header found
UBI: remove duplicate IO error codes
UBI: rename IO error code
UBI: fix small 80 characters limit style issue
UBI: cleanup and simplify Kconfig
-rw-r--r-- | drivers/mtd/ubi/Kconfig | 17 | ||||
-rw-r--r-- | drivers/mtd/ubi/Kconfig.debug | 29 | ||||
-rw-r--r-- | drivers/mtd/ubi/build.c | 6 | ||||
-rw-r--r-- | drivers/mtd/ubi/debug.h | 4 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 10 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 138 | ||||
-rw-r--r-- | drivers/mtd/ubi/misc.c | 19 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.c | 387 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.h | 19 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 29 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 6 | ||||
-rw-r--r-- | drivers/mtd/ubi/vtbl.c | 10 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 31 |
13 files changed, 419 insertions, 286 deletions
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index f702a16..3cf193f 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig @@ -1,9 +1,5 @@ -menu "UBI - Unsorted block images" - depends on MTD - -config MTD_UBI - tristate "Enable UBI" - depends on MTD +menuconfig MTD_UBI + tristate "Enable UBI - Unsorted block images" select CRC32 help UBI is a software layer above MTD layer which admits of LVM-like @@ -12,11 +8,12 @@ config MTD_UBI capabilities. Please, consult the MTD web site for more details (www.linux-mtd.infradead.org). +if MTD_UBI + config MTD_UBI_WL_THRESHOLD int "UBI wear-leveling threshold" default 4096 range 2 65536 - depends on MTD_UBI help This parameter defines the maximum difference between the highest erase counter value and the lowest erase counter value of eraseblocks @@ -34,7 +31,6 @@ config MTD_UBI_BEB_RESERVE int "Percentage of reserved eraseblocks for bad eraseblocks handling" default 1 range 0 25 - depends on MTD_UBI help If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI reserves some amount of physical eraseblocks to handle new bad @@ -48,8 +44,6 @@ config MTD_UBI_BEB_RESERVE config MTD_UBI_GLUEBI tristate "MTD devices emulation driver (gluebi)" - default n - depends on MTD_UBI help This option enables gluebi - an additional driver which emulates MTD devices on top of UBI volumes: for each UBI volumes an MTD device is @@ -59,4 +53,5 @@ config MTD_UBI_GLUEBI software. source "drivers/mtd/ubi/Kconfig.debug" -endmenu + +endif # MTD_UBI diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug index 61f6e5e..fad4adc 100644 --- a/drivers/mtd/ubi/Kconfig.debug +++ b/drivers/mtd/ubi/Kconfig.debug @@ -1,94 +1,73 @@ comment "UBI debugging options" - depends on MTD_UBI config MTD_UBI_DEBUG bool "UBI debugging" depends on SYSFS - depends on MTD_UBI select DEBUG_FS select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL help This option enables UBI debugging. +if MTD_UBI_DEBUG + config MTD_UBI_DEBUG_MSG bool "UBI debugging messages" - depends on MTD_UBI_DEBUG - default n help This option enables UBI debugging messages. config MTD_UBI_DEBUG_PARANOID bool "Extra self-checks" - default n - depends on MTD_UBI_DEBUG help This option enables extra checks in UBI code. Note this slows UBI down significantly. config MTD_UBI_DEBUG_DISABLE_BGT bool "Do not enable the UBI background thread" - depends on MTD_UBI_DEBUG - default n help This option switches the background thread off by default. The thread may be also be enabled/disabled via UBI sysfs. config MTD_UBI_DEBUG_EMULATE_BITFLIPS bool "Emulate flash bit-flips" - depends on MTD_UBI_DEBUG - default n help This option emulates bit-flips with probability 1/50, which in turn causes scrubbing. Useful for debugging and stressing UBI. config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES bool "Emulate flash write failures" - depends on MTD_UBI_DEBUG - default n help This option emulates write failures with probability 1/100. Useful for debugging and testing how UBI handlines errors. config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES bool "Emulate flash erase failures" - depends on MTD_UBI_DEBUG - default n help This option emulates erase failures with probability 1/100. Useful for debugging and testing how UBI handlines errors. -menu "Additional UBI debugging messages" - depends on MTD_UBI_DEBUG +comment "Additional UBI debugging messages" config MTD_UBI_DEBUG_MSG_BLD bool "Additional UBI initialization and build messages" - default n - depends on MTD_UBI_DEBUG help This option enables detailed UBI initialization and device build debugging messages. config MTD_UBI_DEBUG_MSG_EBA bool "Eraseblock association unit messages" - default n - depends on MTD_UBI_DEBUG help This option enables debugging messages from the UBI eraseblock association unit. config MTD_UBI_DEBUG_MSG_WL bool "Wear-leveling unit messages" - default n - depends on MTD_UBI_DEBUG help This option enables debugging messages from the UBI wear-leveling unit. config MTD_UBI_DEBUG_MSG_IO bool "Input/output unit messages" - default n - depends on MTD_UBI_DEBUG help This option enables debugging messages from the UBI input/output unit. -endmenu # UBI debugging messages +endif # MTD_UBI_DEBUG diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 78ae894..5ebe280 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -95,8 +95,8 @@ DEFINE_MUTEX(ubi_devices_mutex); static DEFINE_SPINLOCK(ubi_devices_lock); /* "Show" method for files in '/<sysfs>/class/ubi/' */ -static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr, - char *buf) +static ssize_t ubi_version_show(struct class *class, + struct class_attribute *attr, char *buf) { return sprintf(buf, "%d\n", UBI_VERSION); } @@ -591,6 +591,7 @@ static int attach_by_scanning(struct ubi_device *ubi) ubi->bad_peb_count = si->bad_peb_count; ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count; + ubi->corr_peb_count = si->corr_peb_count; ubi->max_ec = si->max_ec; ubi->mean_ec = si->mean_ec; ubi_msg("max. sequence number: %llu", si->max_sqnum); @@ -972,6 +973,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); ubi_msg("number of good PEBs: %d", ubi->good_peb_count); ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); + ubi_msg("number of corrupted PEBs: %d", ubi->corr_peb_count); ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 17a1071..9eca950 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -57,6 +57,9 @@ void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type); void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len); +#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) \ + print_hex_dump(l, ps, pt, r, g, b, len, a) + #ifdef CONFIG_MTD_UBI_DEBUG_MSG /* General debugging messages */ #define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) @@ -172,6 +175,7 @@ static inline int ubi_dbg_is_erase_failure(void) #define ubi_dbg_dump_seb(seb, type) ({}) #define ubi_dbg_dump_mkvol_req(req) ({}) #define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({}) +#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) ({}) #define UBI_IO_DEBUG 0 #define DBG_DISABLE_BGT 0 diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index fe74749..4be67181 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -418,7 +418,7 @@ retry: * may try to recover data. FIXME: but this is * not implemented. */ - if (err == UBI_IO_BAD_HDR_READ || + if (err == UBI_IO_BAD_HDR_EBADMSG || err == UBI_IO_BAD_HDR) { ubi_warn("corrupted VID header at PEB " "%d, LEB %d:%d", pnum, vol_id, @@ -963,7 +963,7 @@ write_error: static int is_error_sane(int err) { if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR || - err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT) + err == UBI_IO_BAD_HDR_EBADMSG || err == -ETIMEDOUT) return 0; return 1; } @@ -1201,6 +1201,9 @@ static void print_rsvd_warning(struct ubi_device *ubi, ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d," " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level); + if (ubi->corr_peb_count) + ubi_warn("%d PEBs are corrupted and not used", + ubi->corr_peb_count); } /** @@ -1263,6 +1266,9 @@ 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); + if (ubi->corr_peb_count) + ubi_err("%d PEBs are corrupted and not used", + ubi->corr_peb_count); err = -ENOSPC; goto out_free; } diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 332f992..c2960ac 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -376,25 +376,6 @@ retry: return 0; } -/** - * check_pattern - check if buffer contains only a certain byte pattern. - * @buf: buffer to check - * @patt: the pattern to check - * @size: buffer size in bytes - * - * This function returns %1 in there are only @patt bytes in @buf, and %0 if - * something else was also found. - */ -static int check_pattern(const void *buf, uint8_t patt, int size) -{ - int i; - - for (i = 0; i < size; i++) - if (((const uint8_t *)buf)[i] != patt) - return 0; - return 1; -} - /* Patterns to write to a physical eraseblock when torturing it */ static uint8_t patterns[] = {0xa5, 0x5a, 0x0}; @@ -426,7 +407,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) if (err) goto out; - err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size); + err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size); if (err == 0) { ubi_err("erased PEB %d, but a non-0xFF byte found", pnum); @@ -445,7 +426,8 @@ static int torture_peb(struct ubi_device *ubi, int pnum) if (err) goto out; - err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size); + err = ubi_check_pattern(ubi->peb_buf1, patterns[i], + ubi->peb_size); if (err == 0) { ubi_err("pattern %x checking failed for PEB %d", patterns[i], pnum); @@ -517,7 +499,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) * In this case we probably anyway have garbage in this PEB. */ err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); - if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR) + if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) /* * The VID header is corrupted, so we can safely erase this * PEB and not afraid that it will be treated as a valid PEB in @@ -712,47 +694,47 @@ bad: * and corrected by the flash driver; this is harmless but may indicate that * this eraseblock may become bad soon (but may be not); * o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error); - * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty; + * o %UBI_IO_BAD_HDR_EBADMSG is the same as %UBI_IO_BAD_HDR, but there also was + * a data integrity error (uncorrectable ECC error in case of NAND); + * o %UBI_IO_FF if only 0xFF bytes were read (the PEB is supposedly empty) * o a negative error code in case of failure. */ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, struct ubi_ec_hdr *ec_hdr, int verbose) { - int err, read_err = 0; + int err, read_err; uint32_t crc, magic, hdr_crc; dbg_io("read EC header from PEB %d", pnum); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); - err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); - if (err) { - if (err != UBI_IO_BITFLIPS && err != -EBADMSG) - return err; + read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); + if (read_err) { + if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG) + return read_err; /* * We read all the data, but either a correctable bit-flip - * occurred, or MTD reported about some data integrity error, - * like an ECC error in case of NAND. The former is harmless, - * the later may mean that the read data is corrupted. But we - * have a CRC check-sum and we will detect this. If the EC - * header is still OK, we just report this as there was a - * bit-flip. + * occurred, or MTD reported a data integrity error + * (uncorrectable ECC error in case of NAND). The former is + * harmless, the later may mean that the read data is + * corrupted. But we have a CRC check-sum and we will detect + * this. If the EC header is still OK, we just report this as + * there was a bit-flip, to force scrubbing. */ - if (err == -EBADMSG) - read_err = UBI_IO_BAD_HDR_READ; } magic = be32_to_cpu(ec_hdr->magic); if (magic != UBI_EC_HDR_MAGIC) { - if (read_err) - return read_err; + if (read_err == -EBADMSG) + return UBI_IO_BAD_HDR_EBADMSG; /* * The magic field is wrong. Let's check if we have read all * 0xFF. If yes, this physical eraseblock is assumed to be * empty. */ - if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { + if (ubi_check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { /* The physical eraseblock is supposedly empty */ if (verbose) ubi_warn("no EC header found at PEB %d, " @@ -760,7 +742,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, else if (UBI_IO_DEBUG) dbg_msg("no EC header found at PEB %d, " "only 0xFF bytes", pnum); - return UBI_IO_PEB_EMPTY; + if (!read_err) + return UBI_IO_FF; + else + return UBI_IO_FF_BITFLIPS; } /* @@ -788,7 +773,11 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, } else if (UBI_IO_DEBUG) dbg_msg("bad EC header CRC at PEB %d, calculated " "%#08x, read %#08x", pnum, crc, hdr_crc); - return read_err ?: UBI_IO_BAD_HDR; + + if (!read_err) + return UBI_IO_BAD_HDR; + else + return UBI_IO_BAD_HDR_EBADMSG; } /* And of course validate what has just been read from the media */ @@ -975,22 +964,16 @@ bad: * * This function reads the volume identifier header from physical eraseblock * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read - * volume identifier header. The following codes may be returned: + * volume identifier header. The error codes are the same as in + * 'ubi_io_read_ec_hdr()'. * - * o %0 if the CRC checksum is correct and the header was successfully read; - * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected - * and corrected by the flash driver; this is harmless but may indicate that - * this eraseblock may become bad soon; - * o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC - * error detected); - * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID - * header there); - * o a negative error code in case of failure. + * Note, the implementation of this function is also very similar to + * 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'. */ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, struct ubi_vid_hdr *vid_hdr, int verbose) { - int err, read_err = 0; + int err, read_err; uint32_t crc, magic, hdr_crc; void *p; @@ -998,48 +981,29 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, ubi_assert(pnum >= 0 && pnum < ubi->peb_count); p = (char *)vid_hdr - ubi->vid_hdr_shift; - err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, + read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); - if (err) { - if (err != UBI_IO_BITFLIPS && err != -EBADMSG) - return err; - - /* - * We read all the data, but either a correctable bit-flip - * occurred, or MTD reported about some data integrity error, - * like an ECC error in case of NAND. The former is harmless, - * the later may mean the read data is corrupted. But we have a - * CRC check-sum and we will identify this. If the VID header is - * still OK, we just report this as there was a bit-flip. - */ - if (err == -EBADMSG) - read_err = UBI_IO_BAD_HDR_READ; - } + if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG) + return read_err; magic = be32_to_cpu(vid_hdr->magic); if (magic != UBI_VID_HDR_MAGIC) { - if (read_err) - return read_err; + if (read_err == -EBADMSG) + return UBI_IO_BAD_HDR_EBADMSG; - /* - * If we have read all 0xFF bytes, the VID header probably does - * not exist and the physical eraseblock is assumed to be free. - */ - if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { - /* The physical eraseblock is supposedly free */ + if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { if (verbose) ubi_warn("no VID header found at PEB %d, " "only 0xFF bytes", pnum); else if (UBI_IO_DEBUG) dbg_msg("no VID header found at PEB %d, " "only 0xFF bytes", pnum); - return UBI_IO_PEB_FREE; + if (!read_err) + return UBI_IO_FF; + else + return UBI_IO_FF_BITFLIPS; } - /* - * This is not a valid VID header, and these are not 0xFF - * bytes. Report that the header is corrupted. - */ if (verbose) { ubi_warn("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_VID_HDR_MAGIC); @@ -1061,20 +1025,18 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, } else if (UBI_IO_DEBUG) dbg_msg("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); - return read_err ?: UBI_IO_BAD_HDR; + if (!read_err) + return UBI_IO_BAD_HDR; + else + return UBI_IO_BAD_HDR_EBADMSG; } - /* Validate the VID header that we have just read */ err = validate_vid_hdr(ubi, vid_hdr); if (err) { ubi_err("validation failed for PEB %d", pnum); return -EINVAL; } - /* - * If there was a read error (%-EBADMSG), but the header CRC is still - * OK, report about a bit-flip to force scrubbing on this PEB. - */ return read_err ? UBI_IO_BITFLIPS : 0; } @@ -1383,7 +1345,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) goto error; } - err = check_pattern(ubi->dbg_peb_buf, 0xFF, len); + err = ubi_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, offset, len); diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c index 22ad314..ff2a65c 100644 --- a/drivers/mtd/ubi/misc.c +++ b/drivers/mtd/ubi/misc.c @@ -103,3 +103,22 @@ void ubi_calculate_reserved(struct ubi_device *ubi) if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS) ubi->beb_rsvd_level = MIN_RESEVED_PEBS; } + +/** + * ubi_check_pattern - check if buffer contains only a certain byte pattern. + * @buf: buffer to check + * @patt: the pattern to check + * @size: buffer size in bytes + * + * This function returns %1 in there are only @patt bytes in @buf, and %0 if + * something else was also found. + */ +int ubi_check_pattern(const void *buf, uint8_t patt, int size) +{ + int i; + + for (i = 0; i < size; i++) + if (((const uint8_t *)buf)[i] != patt) + return 0; + return 1; +} diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 69b52e9..3c63186 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -29,7 +29,7 @@ * objects which are kept in volume RB-tree with root at the @volumes field. * The RB-tree is indexed by the volume ID. * - * Found logical eraseblocks are represented by &struct ubi_scan_leb objects. + * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects. * These objects are kept in per-volume RB-trees with the root at the * corresponding &struct ubi_scan_volume object. To put it differently, we keep * an RB-tree of per-volume objects and each of these objects is the root of @@ -38,6 +38,33 @@ * Corrupted physical eraseblocks are put to the @corr list, free physical * eraseblocks are put to the @free list and the physical eraseblock to be * erased are put to the @erase list. + * + * UBI tries to distinguish between 2 types of corruptions. + * 1. Corruptions caused by power cuts. These are harmless and expected + * corruptions and UBI tries to handle them gracefully, without printing too + * many warnings and error messages. The idea is that we do not lose + * important data in these case - we may lose only the data which was being + * written to the media just before the power cut happened, and the upper + * layers (e.g., UBIFS) are supposed to handle these situations. UBI puts + * these PEBs to the head of the @erase list and they are scheduled for + * erasure. + * + * 2. Unexpected corruptions which are not caused by power cuts. During + * scanning, such PEBs are put to the @corr list and UBI preserves them. + * Obviously, this lessens the amount of available PEBs, and if at some + * point UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly + * informs about such PEBs every time the MTD device is attached. + * + * However, it is difficult to reliably distinguish between these types of + * corruptions and UBI's strategy is as follows. UBI assumes (2.) if the VID + * header is corrupted and the data area does not contain all 0xFFs, and there + * were not bit-flips or integrity errors while reading the data area. Otherwise + * UBI assumes (1.). The assumptions are: + * o if the data area contains only 0xFFs, there is no data, and it is safe + * to just erase this PEB. + * o if the data area has bit-flips and data integrity errors (ECC errors on + * NAND), it is probably a PEB which was being erased when power cut + * happened. */ #include <linux/err.h> @@ -62,26 +89,26 @@ static struct ubi_vid_hdr *vidh; * @si: scanning information * @pnum: physical eraseblock number to add * @ec: erase counter of the physical eraseblock + * @to_head: if not zero, add to the head of the list * @list: the list to add to * - * This function adds physical eraseblock @pnum to free, erase, corrupted or - * alien lists. Returns zero in case of success and a negative error code in - * case of failure. + * This function adds physical eraseblock @pnum to free, erase, or alien lists. + * If @to_head is not zero, PEB will be added to the head of the list, which + * basically means it will be processed first later. E.g., we add corrupted + * PEBs (corrupted due to power cuts) to the head of the erase list to make + * sure we erase them first and get rid of corruptions ASAP. This function + * returns zero in case of success and a negative error code in case of + * failure. */ -static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, +static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head, struct list_head *list) { struct ubi_scan_leb *seb; if (list == &si->free) { dbg_bld("add to free: PEB %d, EC %d", pnum, ec); - si->free_peb_count += 1; } else if (list == &si->erase) { dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); - si->erase_peb_count += 1; - } else if (list == &si->corr) { - dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); - si->corr_peb_count += 1; } else if (list == &si->alien) { dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); si->alien_peb_count += 1; @@ -94,7 +121,37 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, seb->pnum = pnum; seb->ec = ec; - list_add_tail(&seb->u.list, list); + if (to_head) + list_add(&seb->u.list, list); + else + list_add_tail(&seb->u.list, list); + return 0; +} + +/** + * add_corrupted - add a corrupted physical eraseblock. + * @si: scanning information + * @pnum: physical eraseblock number to add + * @ec: erase counter of the physical eraseblock + * + * This function adds corrupted physical eraseblock @pnum to the 'corr' list. + * The corruption was presumably not caused by a power cut. Returns zero in + * case of success and a negative error code in case of failure. + */ +static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) +{ + struct ubi_scan_leb *seb; + + dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); + + seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); + if (!seb) + return -ENOMEM; + + si->corr_peb_count += 1; + seb->pnum = pnum; + seb->ec = ec; + list_add(&seb->u.list, &si->corr); return 0; } @@ -258,8 +315,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, * created before sequence numbers support has been added. At * that times we used 32-bit LEB versions stored in logical * eraseblocks. That was before UBI got into mainline. We do not - * support these images anymore. Well, those images will work - * still work, but only if no unclean reboots happened. + * support these images anymore. Well, those images still work, + * but only if no unclean reboots happened. */ ubi_err("unsupported on-flash UBI format\n"); return -EINVAL; @@ -285,19 +342,25 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, return 1; } } else { - pnum = seb->pnum; + if (!seb->copy_flag) { + /* It is not a copy, so it is newer */ + dbg_bld("first PEB %d is newer, copy_flag is unset", + pnum); + return bitflips << 1; + } vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); if (!vh) return -ENOMEM; + pnum = seb->pnum; err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); if (err) { if (err == UBI_IO_BITFLIPS) bitflips = 1; else { dbg_err("VID of PEB %d header is bad, but it " - "was OK earlier", pnum); + "was OK earlier, err %d", pnum, err); if (err > 0) err = -EIO; @@ -305,14 +368,6 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, } } - if (!vh->copy_flag) { - /* It is not a copy, so it is newer */ - dbg_bld("first PEB %d is newer, copy_flag is unset", - pnum); - err = bitflips << 1; - goto out_free_vidh; - } - vid_hdr = vh; } @@ -463,18 +518,15 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, if (err) return err; - if (cmp_res & 4) - err = add_to_list(si, seb->pnum, seb->ec, - &si->corr); - else - err = add_to_list(si, seb->pnum, seb->ec, - &si->erase); + err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4, + &si->erase); if (err) return err; seb->ec = ec; seb->pnum = pnum; seb->scrub = ((cmp_res & 2) || bitflips); + seb->copy_flag = vid_hdr->copy_flag; seb->sqnum = sqnum; if (sv->highest_lnum == lnum) @@ -487,10 +539,8 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, * This logical eraseblock is older than the one found * previously. */ - if (cmp_res & 4) - return add_to_list(si, pnum, ec, &si->corr); - else - return add_to_list(si, pnum, ec, &si->erase); + return add_to_list(si, pnum, ec, cmp_res & 4, + &si->erase); } } @@ -510,8 +560,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, seb->ec = ec; seb->pnum = pnum; seb->lnum = lnum; - seb->sqnum = sqnum; seb->scrub = bitflips; + seb->copy_flag = vid_hdr->copy_flag; + seb->sqnum = sqnum; if (sv->highest_lnum <= lnum) { sv->highest_lnum = lnum; @@ -521,7 +572,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, sv->leb_count += 1; rb_link_node(&seb->u.rb, parent, p); rb_insert_color(&seb->u.rb, &sv->root); - si->used_peb_count += 1; return 0; } @@ -668,8 +718,8 @@ out_free: struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, struct ubi_scan_info *si) { - int err = 0, i; - struct ubi_scan_leb *seb; + int err = 0; + struct ubi_scan_leb *seb, *tmp_seb; if (!list_empty(&si->free)) { seb = list_entry(si->free.next, struct ubi_scan_leb, u.list); @@ -678,38 +728,86 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, return seb; } - for (i = 0; i < 2; i++) { - struct list_head *head; - struct ubi_scan_leb *tmp_seb; + /* + * We try to erase the first physical eraseblock from the erase list + * and pick it if we succeed, or try to erase the next one if not. And + * so forth. We don't want to take care about bad eraseblocks here - + * they'll be handled later. + */ + list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) { + if (seb->ec == UBI_SCAN_UNKNOWN_EC) + seb->ec = si->mean_ec; - if (i == 0) - head = &si->erase; - else - head = &si->corr; + err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1); + if (err) + continue; + seb->ec += 1; + list_del(&seb->u.list); + dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec); + return seb; + } + + ubi_err("no free eraseblocks"); + return ERR_PTR(-ENOSPC); +} + +/** + * check_corruption - check the data area of PEB. + * @ubi: UBI device description object + * @vid_hrd: the (corrupted) VID header of this PEB + * @pnum: the physical eraseblock number to check + * + * This is a helper function which is used to distinguish between VID header + * corruptions caused by power cuts and other reasons. If the PEB contains only + * 0xFF bytes in the data area, the VID header is most probably corrupted + * because of a power cut (%0 is returned in this case). Otherwise, it was + * probably corrupted for some other reasons (%1 is returned in this case). A + * negative error code is returned if a read error occurred. + * + * If the corruption reason was a power cut, UBI can safely erase this PEB. + * Otherwise, it should preserve it to avoid possibly destroying important + * information. + */ +static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, + int pnum) +{ + int err; + + mutex_lock(&ubi->buf_mutex); + memset(ubi->peb_buf1, 0x00, ubi->leb_size); + + err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start, + ubi->leb_size); + if (err == UBI_IO_BITFLIPS || err == -EBADMSG) { /* - * We try to erase the first physical eraseblock from the @head - * list and pick it if we succeed, or try to erase the - * next one if not. And so forth. We don't want to take care - * about bad eraseblocks here - they'll be handled later. + * Bit-flips or integrity errors while reading the data area. + * It is difficult to say for sure what type of corruption is + * this, but presumably a power cut happened while this PEB was + * erased, so it became unstable and corrupted, and should be + * erased. */ - list_for_each_entry_safe(seb, tmp_seb, head, u.list) { - if (seb->ec == UBI_SCAN_UNKNOWN_EC) - seb->ec = si->mean_ec; + return 0; + } - err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1); - if (err) - continue; + if (err) + return err; - seb->ec += 1; - list_del(&seb->u.list); - dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec); - return seb; - } + if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) { + mutex_unlock(&ubi->buf_mutex); + return 0; } - ubi_err("no eraseblocks found"); - return ERR_PTR(-ENOSPC); + ubi_err("PEB %d contains corrupted VID header, and the data does not " + "contain all 0xFF, this may be a non-UBI PEB or a severe VID " + "header corruption which requires manual inspection", pnum); + ubi_dbg_dump_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); + mutex_unlock(&ubi->buf_mutex); + return 1; } /** @@ -725,7 +823,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum) { long long uninitialized_var(ec); - int err, bitflips = 0, vol_id, ec_corr = 0; + int err, bitflips = 0, vol_id, ec_err = 0; dbg_bld("scan PEB %d", pnum); @@ -746,22 +844,37 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); if (err < 0) return err; - else if (err == UBI_IO_BITFLIPS) + switch (err) { + case 0: + break; + case UBI_IO_BITFLIPS: bitflips = 1; - else if (err == UBI_IO_PEB_EMPTY) - return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); - else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) { + break; + case UBI_IO_FF: + si->empty_peb_count += 1; + return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0, + &si->erase); + case UBI_IO_FF_BITFLIPS: + si->empty_peb_count += 1; + return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1, + &si->erase); + case UBI_IO_BAD_HDR_EBADMSG: + case UBI_IO_BAD_HDR: /* * We have to also look at the VID header, possibly it is not * corrupted. Set %bitflips flag in order to make this PEB be * moved and EC be re-created. */ - ec_corr = err; + ec_err = err; ec = UBI_SCAN_UNKNOWN_EC; bitflips = 1; + break; + default: + ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err); + return -EINVAL; } - if (!ec_corr) { + if (!ec_err) { int image_seq; /* Make sure UBI version is OK */ @@ -814,24 +927,67 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0); if (err < 0) return err; - else if (err == UBI_IO_BITFLIPS) + switch (err) { + case 0: + break; + case UBI_IO_BITFLIPS: bitflips = 1; - else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR || - (err == UBI_IO_PEB_FREE && ec_corr)) { - /* VID header is corrupted */ - if (err == UBI_IO_BAD_HDR_READ || - ec_corr == UBI_IO_BAD_HDR_READ) - si->read_err_count += 1; - err = add_to_list(si, pnum, ec, &si->corr); + break; + case UBI_IO_BAD_HDR_EBADMSG: + if (ec_err == UBI_IO_BAD_HDR_EBADMSG) + /* + * Both EC and VID headers are corrupted and were read + * with data integrity error, probably this is a bad + * PEB, bit it is not marked as bad yet. This may also + * be a result of power cut during erasure. + */ + si->maybe_bad_peb_count += 1; + case UBI_IO_BAD_HDR: + if (ec_err) + /* + * Both headers are corrupted. There is a possibility + * that this a valid UBI PEB which has corresponding + * LEB, but the headers are corrupted. However, it is + * impossible to distinguish it from a PEB which just + * contains garbage because of a power cut during erase + * operation. So we just schedule this PEB for erasure. + */ + err = 0; + else + /* + * The EC was OK, but the VID header is corrupted. We + * have to check what is in the data area. + */ + err = check_corruption(ubi, vidh, pnum); + + if (err < 0) + return err; + else if (!err) + /* This corruption is caused by a power cut */ + err = add_to_list(si, pnum, ec, 1, &si->erase); + else + /* This is an unexpected corruption */ + err = add_corrupted(si, pnum, ec); if (err) return err; goto adjust_mean_ec; - } else if (err == UBI_IO_PEB_FREE) { - /* No VID header - the physical eraseblock is free */ - err = add_to_list(si, pnum, ec, &si->free); + case UBI_IO_FF_BITFLIPS: + err = add_to_list(si, pnum, ec, 1, &si->erase); if (err) return err; goto adjust_mean_ec; + case UBI_IO_FF: + if (ec_err) + err = add_to_list(si, pnum, ec, 1, &si->erase); + else + err = add_to_list(si, pnum, ec, 0, &si->free); + if (err) + return err; + goto adjust_mean_ec; + default: + ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d", + err); + return -EINVAL; } vol_id = be32_to_cpu(vidh->vol_id); @@ -843,7 +999,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, case UBI_COMPAT_DELETE: ubi_msg("\"delete\" compatible internal volume %d:%d" " found, will remove it", vol_id, lnum); - err = add_to_list(si, pnum, ec, &si->erase); + err = add_to_list(si, pnum, ec, 1, &si->erase); if (err) return err; return 0; @@ -858,7 +1014,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, case UBI_COMPAT_PRESERVE: ubi_msg("\"preserve\" compatible internal volume %d:%d" " found", vol_id, lnum); - err = add_to_list(si, pnum, ec, &si->alien); + err = add_to_list(si, pnum, ec, 0, &si->alien); if (err) return err; return 0; @@ -870,7 +1026,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, } } - if (ec_corr) + if (ec_err) ubi_warn("valid VID header but corrupted EC header at PEB %d", pnum); err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips); @@ -878,7 +1034,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, return err; adjust_mean_ec: - if (!ec_corr) { + if (!ec_err) { si->ec_sum += ec; si->ec_count += 1; if (ec > si->max_ec) @@ -904,19 +1060,20 @@ adjust_mean_ec: static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) { struct ubi_scan_leb *seb; - int max_corr; + int max_corr, peb_count; - max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count; - max_corr = max_corr / 20 ?: 8; + peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count; + max_corr = peb_count / 20 ?: 8; /* - * Few corrupted PEBs are not a problem and may be just a result of + * Few corrupted PEBs is not a problem and may be just a result of * unclean reboots. However, many of them may indicate some problems * with the flash HW or driver. */ - if (si->corr_peb_count >= 8) { - ubi_warn("%d PEBs are corrupted", si->corr_peb_count); - printk(KERN_WARNING "corrupted PEBs are:"); + if (si->corr_peb_count) { + ubi_err("%d PEBs are corrupted and preserved", + si->corr_peb_count); + printk(KERN_ERR "Corrupted PEBs are:"); list_for_each_entry(seb, &si->corr, u.list) printk(KERN_CONT " %d", seb->pnum); printk(KERN_CONT "\n"); @@ -931,41 +1088,35 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) } } - if (si->free_peb_count + si->used_peb_count + - si->alien_peb_count == 0) { - /* No UBI-formatted eraseblocks were found */ - if (si->corr_peb_count == si->read_err_count && - si->corr_peb_count < 8) { - /* No or just few corrupted PEBs, and all of them had a - * read error. We assume that those are bad PEBs, which - * were just not marked as bad so far. - * - * This piece of code basically tries to distinguish - * between the following 2 situations: - * - * 1. Flash is empty, but there are few bad PEBs, which - * are not marked as bad so far, and which were read - * with error. We want to go ahead and format this - * flash. While formating, the faulty PEBs will - * probably be marked as bad. - * - * 2. Flash probably contains non-UBI data and we do - * not want to format it and destroy possibly needed - * data (e.g., consider the case when the bootloader - * MTD partition was accidentally fed to UBI). - */ + if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) { + /* + * All PEBs are empty, or almost all - a couple PEBs look like + * they may be bad PEBs which were not marked as bad yet. + * + * This piece of code basically tries to distinguish between + * the following situations: + * + * 1. Flash is empty, but there are few bad PEBs, which are not + * marked as bad so far, and which were read with error. We + * want to go ahead and format this flash. While formatting, + * the faulty PEBs will probably be marked as bad. + * + * 2. Flash contains non-UBI data and we do not want to format + * it and destroy possibly important information. + */ + if (si->maybe_bad_peb_count <= 2) { si->is_empty = 1; ubi_msg("empty MTD device detected"); - get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq)); + get_random_bytes(&ubi->image_seq, + sizeof(ubi->image_seq)); } else { - ubi_err("MTD device possibly contains non-UBI data, " - "refusing it"); + ubi_err("MTD device is not UBI-formatted and possibly " + "contains non-UBI data - refusing it"); return -EINVAL; } + } - if (si->corr_peb_count > 0) - ubi_msg("corrupted PEBs will be formatted"); return 0; } diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 2576a8d..a3264f0 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h @@ -30,6 +30,7 @@ * @pnum: physical eraseblock number * @lnum: logical eraseblock number * @scrub: if this physical eraseblock needs scrubbing + * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB) * @sqnum: sequence number * @u: unions RB-tree or @list links * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects @@ -42,7 +43,8 @@ struct ubi_scan_leb { int ec; int pnum; int lnum; - int scrub; + unsigned int scrub:1; + unsigned int copy_flag:1; unsigned long long sqnum; union { struct rb_node rb; @@ -91,14 +93,13 @@ struct ubi_scan_volume { * @erase: list of physical eraseblocks which have to be erased * @alien: list of physical eraseblocks which should not be used by UBI (e.g., * those belonging to "preserve"-compatible internal volumes) - * @used_peb_count: count of used PEBs * @corr_peb_count: count of PEBs in the @corr list - * @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was - * returned) - * @free_peb_count: count of PEBs in the @free list - * @erase_peb_count: count of PEBs in the @erase list + * @empty_peb_count: count of PEBs which are presumably empty (contain only + * 0xFF bytes) * @alien_peb_count: count of PEBs in the @alien list * @bad_peb_count: count of bad physical eraseblocks + * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked + * as bad yet, but which look like bad * @vols_found: number of volumes found during scanning * @highest_vol_id: highest volume ID * @is_empty: flag indicating whether the MTD device is empty or not @@ -119,13 +120,11 @@ struct ubi_scan_info { struct list_head free; struct list_head erase; struct list_head alien; - int used_peb_count; int corr_peb_count; - int read_err_count; - int free_peb_count; - int erase_peb_count; + int empty_peb_count; int alien_peb_count; int bad_peb_count; + int maybe_bad_peb_count; int vols_found; int highest_vol_id; int is_empty; diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 0359e0c..0b0149c 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -85,21 +85,26 @@ /* * Error codes returned by the I/O sub-system. * - * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only - * %0xFF bytes - * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a - * valid erase counter header, and the rest are %0xFF bytes + * UBI_IO_FF: the read region of flash contains only 0xFFs + * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a data + * integrity error reported by the MTD driver + * (uncorrectable ECC error in case of NAND) * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC) - * UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read - * error reported by the flash driver + * UBI_IO_BAD_HDR_EBADMSG: the same as %UBI_IO_BAD_HDR, but also there was a + * data integrity error reported by the MTD driver + * (uncorrectable ECC error in case of NAND) * UBI_IO_BITFLIPS: bit-flips were detected and corrected + * + * Note, it is probably better to have bit-flip and ebadmsg as flags which can + * be or'ed with other error code. But this is a big change because there are + * may callers, so it does not worth the risk of introducing a bug */ enum { - UBI_IO_PEB_EMPTY = 1, - UBI_IO_PEB_FREE, + UBI_IO_FF = 1, + UBI_IO_FF_BITFLIPS, UBI_IO_BAD_HDR, - UBI_IO_BAD_HDR_READ, - UBI_IO_BITFLIPS + UBI_IO_BAD_HDR_EBADMSG, + UBI_IO_BITFLIPS, }; /* @@ -356,6 +361,8 @@ struct ubi_wl_entry; * @peb_size: physical eraseblock size * @bad_peb_count: count of bad physical eraseblocks * @good_peb_count: count of good physical eraseblocks + * @corr_peb_count: count of corrupted physical eraseblocks (preserved and not + * used by UBI) * @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous * @max_erroneous: maximum allowed amount of erroneous physical eraseblocks * @min_io_size: minimal input/output unit size of the underlying MTD device @@ -442,6 +449,7 @@ struct ubi_device { int peb_size; int bad_peb_count; int good_peb_count; + int corr_peb_count; int erroneous_peb_count; int max_erroneous; int min_io_size; @@ -506,6 +514,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length); int ubi_check_volume(struct ubi_device *ubi, int vol_id); void ubi_calculate_reserved(struct ubi_device *ubi); +int ubi_check_pattern(const void *buf, uint8_t patt, int size); /* eba.c */ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index e42afab..c47620d 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -261,6 +261,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) /* Reserve physical eraseblocks */ if (vol->reserved_pebs > ubi->avail_pebs) { dbg_err("not enough PEBs, only %d available", ubi->avail_pebs); + if (ubi->corr_peb_count) + dbg_err("%d PEBs are corrupted and not used", + ubi->corr_peb_count); err = -ENOSPC; goto out_unlock; } @@ -527,6 +530,9 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) if (pebs > ubi->avail_pebs) { dbg_err("not enough PEBs: requested %d, available %d", pebs, ubi->avail_pebs); + if (ubi->corr_peb_count) + dbg_err("%d PEBs are corrupted and not used", + ubi->corr_peb_count); spin_unlock(&ubi->volumes_lock); err = -ENOSPC; goto out_free; diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 14c10be..fcdb7f6 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -366,7 +366,7 @@ write_error: * Probably this physical eraseblock went bad, try to pick * another one. */ - list_add_tail(&new_seb->u.list, &si->corr); + list_add(&new_seb->u.list, &si->erase); goto retry; } kfree(new_seb); @@ -662,9 +662,13 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, ubi->vol_count += 1; vol->ubi = ubi; - if (reserved_pebs > ubi->avail_pebs) + if (reserved_pebs > ubi->avail_pebs) { ubi_err("not enough PEBs, required %d, available %d", reserved_pebs, ubi->avail_pebs); + if (ubi->corr_peb_count) + ubi_err("%d PEBs are corrupted and not used", + ubi->corr_peb_count); + } ubi->rsvd_pebs += reserved_pebs; ubi->avail_pebs -= reserved_pebs; @@ -837,7 +841,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) return PTR_ERR(ubi->vtbl); } - ubi->avail_pebs = ubi->good_peb_count; + ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count; /* * The layout volume is OK, initialize the corresponding in-RAM data diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 97a4356..655bbbe 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -745,7 +745,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0); if (err && err != UBI_IO_BITFLIPS) { - if (err == UBI_IO_PEB_FREE) { + if (err == UBI_IO_FF) { /* * We are trying to move PEB without a VID header. UBI * always write VID headers shortly after the PEB was @@ -759,6 +759,16 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, dbg_wl("PEB %d has no VID header", e1->pnum); protect = 1; goto out_not_moved; + } else if (err == UBI_IO_FF_BITFLIPS) { + /* + * The same situation as %UBI_IO_FF, but bit-flips were + * detected. It is better to schedule this PEB for + * scrubbing. + */ + dbg_wl("PEB %d has no VID header but has bit-flips", + e1->pnum); + scrubbing = 1; + goto out_not_moved; } ubi_err("error %d while reading VID header from PEB %d", @@ -1468,22 +1478,6 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) ubi->lookuptbl[e->pnum] = e; } - list_for_each_entry(seb, &si->corr, u.list) { - cond_resched(); - - e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); - if (!e) - goto out_free; - - e->pnum = seb->pnum; - e->ec = seb->ec; - ubi->lookuptbl[e->pnum] = e; - if (schedule_erase(ubi, e, 0)) { - kmem_cache_free(ubi_wl_entry_slab, e); - goto out_free; - } - } - ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { cond_resched(); @@ -1510,6 +1504,9 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) if (ubi->avail_pebs < WL_RESERVED_PEBS) { ubi_err("no enough physical eraseblocks (%d, need %d)", ubi->avail_pebs, WL_RESERVED_PEBS); + if (ubi->corr_peb_count) + ubi_err("%d PEBs are corrupted and not used", + ubi->corr_peb_count); goto out_free; } ubi->avail_pebs -= WL_RESERVED_PEBS; |