diff options
Diffstat (limited to 'drivers/mtd/ubi')
-rw-r--r-- | drivers/mtd/ubi/scan.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 19dc5e04fd61..def0bf03d7fe 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -123,8 +123,8 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head, | |||
123 | * @ec: erase counter of the physical eraseblock | 123 | * @ec: erase counter of the physical eraseblock |
124 | * | 124 | * |
125 | * This function adds corrupted physical eraseblock @pnum to the 'corr' list. | 125 | * This function adds corrupted physical eraseblock @pnum to the 'corr' list. |
126 | * Returns zero in case of success and a negative error code in case of | 126 | * The corruption was presumably not caused by a power cut. Returns zero in |
127 | * failure. | 127 | * case of success and a negative error code in case of failure. |
128 | */ | 128 | */ |
129 | static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) | 129 | static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) |
130 | { | 130 | { |
@@ -751,6 +751,53 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, | |||
751 | } | 751 | } |
752 | 752 | ||
753 | /** | 753 | /** |
754 | * check_data_ff - make sure PEB contains only 0xFF data. | ||
755 | * @ubi: UBI device description object | ||
756 | * @vid_hrd: the (corrupted) VID header of this PEB | ||
757 | * @pnum: the physical eraseblock number to check | ||
758 | * | ||
759 | * This is a helper function which is used to distinguish between VID header | ||
760 | * corruptions caused by power cuts and other reasons. If the PEB contains only | ||
761 | * 0xFF bytes at the data area, the VID header is most probably corrupted | ||
762 | * because of a power cut (%0 is returned in this case). Otherwise, it was | ||
763 | * corrupted for some other reasons (%1 is returned in this case). A negative | ||
764 | * error code is returned if a read error occurred. | ||
765 | * | ||
766 | * If the corruption reason was a power cut, UBI can safely erase this PEB. | ||
767 | * Otherwise, it should preserve it to avoid possibly destroying important | ||
768 | * information. | ||
769 | */ | ||
770 | static int check_data_ff(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, | ||
771 | int pnum) | ||
772 | { | ||
773 | int err; | ||
774 | |||
775 | mutex_lock(&ubi->buf_mutex); | ||
776 | memset(ubi->peb_buf1, 0x00, ubi->leb_size); | ||
777 | |||
778 | err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start, | ||
779 | ubi->leb_size); | ||
780 | if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG) | ||
781 | return err; | ||
782 | |||
783 | if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) { | ||
784 | mutex_unlock(&ubi->buf_mutex); | ||
785 | return 0; | ||
786 | } | ||
787 | |||
788 | ubi_err("PEB %d contains corrupted VID header, and the data does not " | ||
789 | "contain all 0xFF, this may be a non-UBI PEB or a severe VID " | ||
790 | "header corruption which requires manual inspection", pnum); | ||
791 | ubi_dbg_dump_vid_hdr(vid_hdr); | ||
792 | dbg_msg("hexdump of PEB %d offset %d, length %d", | ||
793 | pnum, ubi->leb_start, ubi->leb_size); | ||
794 | ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | ||
795 | ubi->peb_buf1, ubi->leb_size, 1); | ||
796 | mutex_unlock(&ubi->buf_mutex); | ||
797 | return -EINVAL; | ||
798 | } | ||
799 | |||
800 | /** | ||
754 | * process_eb - read, check UBI headers, and add them to scanning information. | 801 | * process_eb - read, check UBI headers, and add them to scanning information. |
755 | * @ubi: UBI device description object | 802 | * @ubi: UBI device description object |
756 | * @si: scanning information | 803 | * @si: scanning information |
@@ -883,6 +930,31 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
883 | */ | 930 | */ |
884 | si->maybe_bad_peb_count += 1; | 931 | si->maybe_bad_peb_count += 1; |
885 | case UBI_IO_BAD_HDR: | 932 | case UBI_IO_BAD_HDR: |
933 | if (ec_err) | ||
934 | /* | ||
935 | * Both headers are corrupted. There is a possibility | ||
936 | * that this a valid UBI PEB which has corresponding | ||
937 | * LEB, but the headers are corrupted. However, it is | ||
938 | * impossible to distinguish it from a PEB which just | ||
939 | * contains garbage because a power cut during erase | ||
940 | * operation. So we just schedule this PEB for erasure. | ||
941 | */ | ||
942 | err = 0; | ||
943 | else | ||
944 | /* | ||
945 | * The EC was OK, but the VID header is corrupted. We | ||
946 | * have to check what is in the data area. | ||
947 | */ | ||
948 | err = check_data_ff(ubi, vidh, pnum); | ||
949 | if (!err) | ||
950 | /* This corruption is caused by a power cut */ | ||
951 | err = add_to_list(si, pnum, ec, 1, &si->erase); | ||
952 | else | ||
953 | /* This is an unexpected corruption */ | ||
954 | err = add_corrupted(si, pnum, ec); | ||
955 | if (err) | ||
956 | return err; | ||
957 | goto adjust_mean_ec; | ||
886 | case UBI_IO_FF_BITFLIPS: | 958 | case UBI_IO_FF_BITFLIPS: |
887 | err = add_to_list(si, pnum, ec, 1, &si->erase); | 959 | err = add_to_list(si, pnum, ec, 1, &si->erase); |
888 | if (err) | 960 | if (err) |