diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-04-30 06:02:33 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-06-04 04:30:44 -0400 |
commit | 0798cea8c2e1afee59686c51d27d0e96b05e42d1 (patch) | |
tree | 7bc5702e9bdeb37699f3cce0d4641d15676e74f2 /drivers/mtd/ubi | |
parent | 33789fb9d4470e27d18596c0966339e2ca8865a9 (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.c | 101 |
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 | */ | ||
903 | static 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 |