diff options
| -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) |
