Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

UBI: add truly corrupted PEBs to corrupted list

Start using the 'corr' list and add there PEBs which look truly corrupted,
which means they have corrupted VID header and the data which follows the
corrupted header does not contain all 0xFF bytes.

At the moment, this does not change UBI functionality much because these
PEBs will be erase when scanning finishes. But the plan is to teach UBI
preserving them.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>

+74 -2
+74 -2
drivers/mtd/ubi/scan.c
··· 123 123 * @ec: erase counter of the physical eraseblock 124 124 * 125 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 127 - * failure. 126 + * The corruption was presumably not caused by a power cut. Returns zero in 127 + * case of success and a negative error code in case of failure. 128 128 */ 129 129 static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) 130 130 { ··· 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 801 * process_eb - read, check UBI headers, and add them to scanning information. 755 802 * @ubi: UBI device description object 756 803 * @si: scanning information ··· 930 883 */ 931 884 si->maybe_bad_peb_count += 1; 932 885 case UBI_IO_BAD_HDR: 886 + if (ec_err) 887 + /* 888 + * Both headers are corrupted. There is a possibility 889 + * that this a valid UBI PEB which has corresponding 890 + * LEB, but the headers are corrupted. However, it is 891 + * impossible to distinguish it from a PEB which just 892 + * contains garbage because a power cut during erase 893 + * operation. So we just schedule this PEB for erasure. 894 + */ 895 + err = 0; 896 + else 897 + /* 898 + * The EC was OK, but the VID header is corrupted. We 899 + * have to check what is in the data area. 900 + */ 901 + err = check_data_ff(ubi, vidh, pnum); 902 + if (!err) 903 + /* This corruption is caused by a power cut */ 904 + err = add_to_list(si, pnum, ec, 1, &si->erase); 905 + else 906 + /* This is an unexpected corruption */ 907 + err = add_corrupted(si, pnum, ec); 908 + if (err) 909 + return err; 910 + goto adjust_mean_ec; 933 911 case UBI_IO_FF_BITFLIPS: 934 912 err = add_to_list(si, pnum, ec, 1, &si->erase); 935 913 if (err)