summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-22 16:34:23 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-22 16:34:23 -0700
commit4f3a29dadaf999a273f1e7fe2476595d0283eef3 (patch)
tree3776499f6edc95a36533c7efe32a7b6038c88b61 /drivers/mtd/ubi
parent06d362931a530e0d48c1a9554a752da4ed240f0b (diff)
parent45aafd32996e27bfc4862654ff31231bdddbe200 (diff)
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
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r--drivers/mtd/ubi/Kconfig17
-rw-r--r--drivers/mtd/ubi/Kconfig.debug29
-rw-r--r--drivers/mtd/ubi/build.c6
-rw-r--r--drivers/mtd/ubi/debug.h4
-rw-r--r--drivers/mtd/ubi/eba.c10
-rw-r--r--drivers/mtd/ubi/io.c138
-rw-r--r--drivers/mtd/ubi/misc.c19
-rw-r--r--drivers/mtd/ubi/scan.c387
-rw-r--r--drivers/mtd/ubi/scan.h19
-rw-r--r--drivers/mtd/ubi/ubi.h29
-rw-r--r--drivers/mtd/ubi/vmt.c6
-rw-r--r--drivers/mtd/ubi/vtbl.c10
-rw-r--r--drivers/mtd/ubi/wl.c31
13 files changed, 419 insertions, 286 deletions
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index f702a163d8df..3cf193fb5e00 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 61f6e5e40458..fad4adc0fe2c 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 78ae89488a4f..5ebe280225d6 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 17a107129726..9eca95074bc2 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 fe74749e0dae..4be671815014 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 332f992f13d9..c2960ac9f39c 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 22ad31402945..ff2a65c37f69 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 69b52e9c9489..3c631863bf40 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;