aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-04-30 06:02:33 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2010-06-04 04:30:44 -0400
commit0798cea8c2e1afee59686c51d27d0e96b05e42d1 (patch)
tree7bc5702e9bdeb37699f3cce0d4641d15676e74f2 /drivers/mtd/ubi
parent33789fb9d4470e27d18596c0966339e2ca8865a9 (diff)
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 <sebastian@breakpoint.cc> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Reviewed-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> Tested-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r--drivers/mtd/ubi/scan.c101
1 files changed, 82 insertions, 19 deletions
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,
760 bitflips = 1; 760 bitflips = 1;
761 } 761 }
762 762
763 si->is_empty = 0;
764
765 if (!ec_corr) { 763 if (!ec_corr) {
766 int image_seq; 764 int image_seq;
767 765
@@ -892,6 +890,85 @@ adjust_mean_ec:
892} 890}
893 891
894/** 892/**
893 * check_what_we_have - check what PEB were found by scanning.
894 * @ubi: UBI device description object
895 * @si: scanning information
896 *
897 * This is a helper function which takes a look what PEBs were found by
898 * scanning, and decides whether the flash is empty and should be formatted and
899 * whether there are too many corrupted PEBs and we should not attach this
900 * MTD device. Returns zero if we should proceed with attaching the MTD device,
901 * and %-EINVAL if we should not.
902 */
903static int check_what_we_have(const struct ubi_device *ubi,
904 struct ubi_scan_info *si)
905{
906 struct ubi_scan_leb *seb;
907 int max_corr;
908
909 max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
910 max_corr = max_corr / 20 ?: 8;
911
912 /*
913 * Few corrupted PEBs are not a problem and may be just a result of
914 * unclean reboots. However, many of them may indicate some problems
915 * with the flash HW or driver.
916 */
917 if (si->corr_peb_count >= 8) {
918 ubi_warn("%d PEBs are corrupted", si->corr_peb_count);
919 printk(KERN_WARNING "corrupted PEBs are:");
920 list_for_each_entry(seb, &si->corr, u.list)
921 printk(KERN_CONT " %d", seb->pnum);
922 printk(KERN_CONT "\n");
923
924 /*
925 * If too many PEBs are corrupted, we refuse attaching,
926 * otherwise, only print a warning.
927 */
928 if (si->corr_peb_count >= max_corr) {
929 ubi_err("too many corrupted PEBs, refusing this device");
930 return -EINVAL;
931 }
932 }
933
934 if (si->free_peb_count + si->used_peb_count +
935 si->alien_peb_count == 0) {
936 /* No UBI-formatted eraseblocks were found */
937 if (si->corr_peb_count == si->read_err_count &&
938 si->corr_peb_count < 8) {
939 /* No or just few corrupted PEBs, and all of them had a
940 * read error. We assume that those are bad PEBs, which
941 * were just not marked as bad so far.
942 *
943 * This piece of code basically tries to distinguish
944 * between the following 2 situations:
945 *
946 * 1. Flash is empty, but there are few bad PEBs, which
947 * are not marked as bad so far, and which were read
948 * with error. We want to go ahead and format this
949 * flash. While formating, the faulty PEBs will
950 * probably be marked as bad.
951 *
952 * 2. Flash probably contains non-UBI data and we do
953 * not want to format it and destroy possibly needed
954 * data (e.g., consider the case when the bootloader
955 * MTD partition was accidentally fed to UBI).
956 */
957 si->is_empty = 1;
958 ubi_msg("empty MTD device detected");
959 } else {
960 ubi_err("MTD device possibly contains non-UBI data, "
961 "refusing it");
962 return -EINVAL;
963 }
964 }
965
966 if (si->corr_peb_count >= 0)
967 ubi_msg("corrupted PEBs will be formatted");
968 return 0;
969}
970
971/**
895 * ubi_scan - scan an MTD device. 972 * ubi_scan - scan an MTD device.
896 * @ubi: UBI device description object 973 * @ubi: UBI device description object
897 * 974 *
@@ -915,7 +992,6 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
915 INIT_LIST_HEAD(&si->erase); 992 INIT_LIST_HEAD(&si->erase);
916 INIT_LIST_HEAD(&si->alien); 993 INIT_LIST_HEAD(&si->alien);
917 si->volumes = RB_ROOT; 994 si->volumes = RB_ROOT;
918 si->is_empty = 1;
919 995
920 err = -ENOMEM; 996 err = -ENOMEM;
921 ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); 997 ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
@@ -941,22 +1017,9 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
941 if (si->ec_count) 1017 if (si->ec_count)
942 si->mean_ec = div_u64(si->ec_sum, si->ec_count); 1018 si->mean_ec = div_u64(si->ec_sum, si->ec_count);
943 1019
944 if (si->is_empty) 1020 err = check_what_we_have(ubi, si);
945 ubi_msg("empty MTD device detected"); 1021 if (err)
946 1022 goto out_vidh;
947 /*
948 * Few corrupted PEBs are not a problem and may be just a result of
949 * unclean reboots. However, many of them may indicate some problems
950 * with the flash HW or driver. Print a warning in this case.
951 */
952 if (si->corr_peb_count >= 8 ||
953 si->corr_peb_count >= ubi->peb_count / 4) {
954 ubi_warn("%d PEBs are corrupted", si->corr_peb_count);
955 printk(KERN_WARNING "corrupted PEBs are:");
956 list_for_each_entry(seb, &si->corr, u.list)
957 printk(KERN_CONT " %d", seb->pnum);
958 printk(KERN_CONT "\n");
959 }
960 1023
961 /* 1024 /*
962 * In case of unknown erase counter we use the mean erase counter 1025 * In case of unknown erase counter we use the mean erase counter