From 786d78318586cbdc8aec539fe5a4942490267fef Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 30 Apr 2010 16:50:22 +0300 Subject: UBI: simplify IO error codes We do not really need 2 separate error codes for indicating bad VID and bad EC headers (UBI_IO_BAD_EC_HDR, UBI_IO_BAD_VID_HDR), it is enough to have only one UBI_IO_BAD_HDR return code. This patch does not introduce any functional change, only some code simplification. Signed-off-by: Artem Bityutskiy Reviewed-by: Sebastian Andrzej Siewior Tested-by: Sebastian Andrzej Siewior --- drivers/mtd/ubi/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/ubi/scan.c') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index aed19f33b8f3..b878a7661f5a 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -745,7 +745,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, 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_EC_HDR) { + else if (err == 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 @@ -813,7 +813,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, return err; else if (err == UBI_IO_BITFLIPS) bitflips = 1; - else if (err == UBI_IO_BAD_VID_HDR || + else if (err == UBI_IO_BAD_HDR || (err == UBI_IO_PEB_FREE && ec_corr)) { /* VID header is corrupted */ err = add_to_list(si, pnum, ec, &si->corr); -- cgit v1.2.3 From eb89580e1a8388d206bf143c6c39d001095106ba Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 3 May 2010 09:04:39 +0300 Subject: UBI: introduce a new IO return code This patch introduces the %UBI_IO_BAD_HDR_READ return code for the I/O level function. We will use this code in order to distinguish between "corrupted header possibly because this is non-ubi data" and "corrupted header possibly because of real data corruption and ECC error". So far this patch does not introduce any functional change, just a preparation. This patch is pased on a patch from Sebastian Andrzej Siewior Signed-off-by: Artem Bityutskiy Reviewed-by: Sebastian Andrzej Siewior Tested-by: Sebastian Andrzej Siewior --- drivers/mtd/ubi/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/ubi/scan.c') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index b878a7661f5a..c45900744107 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -745,7 +745,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, 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) { + else if (err == UBI_IO_BAD_HDR_READ || err == 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 @@ -813,7 +813,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, return err; else if (err == UBI_IO_BITFLIPS) bitflips = 1; - else if (err == UBI_IO_BAD_HDR || + else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR || (err == UBI_IO_PEB_FREE && ec_corr)) { /* VID header is corrupted */ err = add_to_list(si, pnum, ec, &si->corr); -- cgit v1.2.3 From 33789fb9d4470e27d18596c0966339e2ca8865a9 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 30 Apr 2010 12:31:26 +0300 Subject: UBI: introduce eraseblock counter variables This is just a preparation patch which introduces several 'struct ubi_scan_info' fields which count eraseblocks of different types. This will be used later on to decide whether it is safe to format the flash or not. No functional changes so far. Signed-off-by: Artem Bityutskiy Reviewed-by: Sebastian Andrzej Siewior Tested-by: Sebastian Andrzej Siewior --- drivers/mtd/ubi/scan.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers/mtd/ubi/scan.c') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index c45900744107..a20f278d0c6c 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -72,16 +72,19 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, { struct ubi_scan_leb *seb; - if (list == &si->free) + if (list == &si->free) { dbg_bld("add to free: PEB %d, EC %d", pnum, ec); - else if (list == &si->erase) + si->free_peb_count += 1; + } else if (list == &si->erase) { dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); - else if (list == &si->corr) { + si->erase_peb_count += 1; + } else if (list == &si->corr) { dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); - si->corr_count += 1; - } else if (list == &si->alien) + si->corr_peb_count += 1; + } else if (list == &si->alien) { dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); - else + si->alien_peb_count += 1; + } else BUG(); seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); @@ -517,6 +520,7 @@ 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; } @@ -751,7 +755,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, * corrupted. Set %bitflips flag in order to make this PEB be * moved and EC be re-created. */ - ec_corr = 1; + ec_corr = err; ec = UBI_SCAN_UNKNOWN_EC; bitflips = 1; } @@ -816,6 +820,9 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, 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); if (err) return err; @@ -855,7 +862,6 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, err = add_to_list(si, pnum, ec, &si->alien); if (err) return err; - si->alien_peb_count += 1; return 0; case UBI_COMPAT_REJECT: @@ -943,8 +949,9 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) * unclean reboots. However, many of them may indicate some problems * with the flash HW or driver. Print a warning in this case. */ - if (si->corr_count >= 8 || si->corr_count >= ubi->peb_count / 4) { - ubi_warn("%d PEBs are corrupted", si->corr_count); + if (si->corr_peb_count >= 8 || + si->corr_peb_count >= ubi->peb_count / 4) { + ubi_warn("%d PEBs are corrupted", si->corr_peb_count); printk(KERN_WARNING "corrupted PEBs are:"); list_for_each_entry(seb, &si->corr, u.list) printk(KERN_CONT " %d", seb->pnum); -- cgit v1.2.3 From 0798cea8c2e1afee59686c51d27d0e96b05e42d1 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 30 Apr 2010 13:02:33 +0300 Subject: UBI: improve corrupted flash handling This patch improves the way UBI handles corrupted flash, or flash containing garbage or non-UBI data, which is the same from UBI POW. Namely, we do the following: * if 5% or more PEBs are corrupted, refuse the flash * if less than 5% PEBs are corrupted, do not refuse the flash and format these PEBs * if less than 8 PEBs are corrupted, format them silently, otherwise print a warning message. Reported-by: Sebastian Andrzej Siewior Signed-off-by: Artem Bityutskiy Reviewed-by: Sebastian Andrzej Siewior Tested-by: Sebastian Andrzej Siewior --- drivers/mtd/ubi/scan.c | 101 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 19 deletions(-) (limited to 'drivers/mtd/ubi/scan.c') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index a20f278d0c6c..6b7c0c4baf07 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -760,8 +760,6 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, bitflips = 1; } - si->is_empty = 0; - if (!ec_corr) { int image_seq; @@ -891,6 +889,85 @@ adjust_mean_ec: return 0; } +/** + * check_what_we_have - check what PEB were found by scanning. + * @ubi: UBI device description object + * @si: scanning information + * + * This is a helper function which takes a look what PEBs were found by + * scanning, and decides whether the flash is empty and should be formatted and + * whether there are too many corrupted PEBs and we should not attach this + * MTD device. Returns zero if we should proceed with attaching the MTD device, + * and %-EINVAL if we should not. + */ +static int check_what_we_have(const struct ubi_device *ubi, + struct ubi_scan_info *si) +{ + struct ubi_scan_leb *seb; + int max_corr; + + max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count; + max_corr = max_corr / 20 ?: 8; + + /* + * Few corrupted PEBs are 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:"); + list_for_each_entry(seb, &si->corr, u.list) + printk(KERN_CONT " %d", seb->pnum); + printk(KERN_CONT "\n"); + + /* + * If too many PEBs are corrupted, we refuse attaching, + * otherwise, only print a warning. + */ + if (si->corr_peb_count >= max_corr) { + ubi_err("too many corrupted PEBs, refusing this device"); + return -EINVAL; + } + } + + 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). + */ + si->is_empty = 1; + ubi_msg("empty MTD device detected"); + } else { + ubi_err("MTD device possibly contains non-UBI data, " + "refusing it"); + return -EINVAL; + } + } + + if (si->corr_peb_count >= 0) + ubi_msg("corrupted PEBs will be formatted"); + return 0; +} + /** * ubi_scan - scan an MTD device. * @ubi: UBI device description object @@ -915,7 +992,6 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) INIT_LIST_HEAD(&si->erase); INIT_LIST_HEAD(&si->alien); si->volumes = RB_ROOT; - si->is_empty = 1; err = -ENOMEM; ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); @@ -941,22 +1017,9 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) if (si->ec_count) si->mean_ec = div_u64(si->ec_sum, si->ec_count); - if (si->is_empty) - ubi_msg("empty MTD device detected"); - - /* - * Few corrupted PEBs are 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. Print a warning in this case. - */ - if (si->corr_peb_count >= 8 || - si->corr_peb_count >= ubi->peb_count / 4) { - ubi_warn("%d PEBs are corrupted", si->corr_peb_count); - printk(KERN_WARNING "corrupted PEBs are:"); - list_for_each_entry(seb, &si->corr, u.list) - printk(KERN_CONT " %d", seb->pnum); - printk(KERN_CONT "\n"); - } + err = check_what_we_have(ubi, si); + if (err) + goto out_vidh; /* * In case of unknown erase counter we use the mean erase counter -- cgit v1.2.3 From 095751a6e0838a712393a74eb0b7b6559dbdbe81 Mon Sep 17 00:00:00 2001 From: Matthieu CASTET Date: Thu, 3 Jun 2010 16:14:27 +0200 Subject: UBI: generate random image_seq when formatting MTD devices Generate random image_seq when attaching empty MTD device (kernel do the ubi formating). Signed-off-by: Matthieu CASTET Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/scan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/mtd/ubi/scan.c') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 6b7c0c4baf07..de7b2f1c4113 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "ubi.h" #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID @@ -956,6 +957,7 @@ static int check_what_we_have(const struct ubi_device *ubi, */ si->is_empty = 1; ubi_msg("empty MTD device detected"); + get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq)); } else { ubi_err("MTD device possibly contains non-UBI data, " "refusing it"); -- cgit v1.2.3 From f5d5b1f8c12a7637ee1145f2f00358eb375edb54 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 14 Jun 2010 08:15:39 +0300 Subject: UBI: fix error message and compilation warnings Fix the followong compilation warnings introduced by commit 095751a6e0838a712393a74eb0b7b6559dbdbe81: drivers/mtd/ubi/scan.c: In function 'check_what_we_have': drivers/mtd/ubi/scan.c:960: warning: passing argument 1 of 'get_random_bytes' discards qualifiers from pointer target type Fix the following compilation warnings introduced by commit 1a49af2ca019dcb4614c32f832bbcb814b61409c: drivers/mtd/ubi/io.c: In function 'ubi_io_read': drivers/mtd/ubi/io.c:153: warning: initialization makes integer from pointer without a cast drivers/mtd/ubi/io.c:170: warning: format '%s' expects type 'char *', but argument 5 has type 'int' drivers/mtd/ubi/io.c:177: warning: format '%zd' expects type 'signed size_t', but argument 7 has type 'int' drivers/mtd/ubi/io.c:177: warning: too many arguments for format Also, amend the ECC error code string and add brackets and whitespace there - this should make the message readable. Reported-by: Stephen Rothwell Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/scan.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mtd/ubi/scan.c') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index de7b2f1c4113..37855e55651f 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -901,8 +901,7 @@ adjust_mean_ec: * MTD device. Returns zero if we should proceed with attaching the MTD device, * and %-EINVAL if we should not. */ -static int check_what_we_have(const struct ubi_device *ubi, - struct ubi_scan_info *si) +static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) { struct ubi_scan_leb *seb; int max_corr; -- cgit v1.2.3 From 158132c9abbccce802def10e5ffaf044b266a6e1 Mon Sep 17 00:00:00 2001 From: Brijesh Singh Date: Wed, 16 Jun 2010 09:28:26 +0300 Subject: UBI: improve delete-compatible volumes handling When a delete-compatible volume is found, it is first added to the 'corr' list, which contains "corrupted" PEBs which should be erased, and then it is added to the used volumes tree. However, the second step should not be done. This does not cause problems in practice, because we never access delete-compattible volumes, but it is still not the right thing to do. [Artem: amended the commit message and few prints] Signed-off-by: Brijesh Singh Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/ubi/scan.c') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 37855e55651f..a86c04821368 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -842,11 +842,11 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, switch (vidh->compat) { case UBI_COMPAT_DELETE: ubi_msg("\"delete\" compatible internal volume %d:%d" - " found, remove it", vol_id, lnum); + " found, will remove it", vol_id, lnum); err = add_to_list(si, pnum, ec, &si->corr); if (err) return err; - break; + return 0; case UBI_COMPAT_RO: ubi_msg("read-only compatible internal volume %d:%d" -- cgit v1.2.3 From 7cdb996ee4d04b5bb2cd544b14e8eb91cfd7fe64 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 30 Jul 2010 16:31:38 +0300 Subject: UBI: do not print message about corruptes PEBs if we have none of them Currently UBI prints UBI: corrupted PEBs will be formatted even if there are not corrupted PEBs. Fix this. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/ubi/scan.c') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index a86c04821368..372a15ac9995 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -964,7 +964,7 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) } } - if (si->corr_peb_count >= 0) + if (si->corr_peb_count > 0) ubi_msg("corrupted PEBs will be formatted"); return 0; } -- cgit v1.2.3