>From b9207c3481acb395c36ca9e039dedaa440b6e881 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 22 Apr 2008 18:12:40 +0300 Subject: [PATCH] UBI: separate out header checking This is a preparation patch which separates out the checking stuff from the EC and VID read&check functions. This will be needed for the follow-up scanning improvement patch. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 250 +++++++++++++++++++++++++++++++------------------ drivers/mtd/ubi/ubi.h | 4 + 2 files changed, 164 insertions(+), 90 deletions(-) diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 4ac11df..f62728e 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -604,70 +604,38 @@ bad: } /** - * ubi_io_read_ec_hdr - read and check an erase counter header. + * ubi_io_check_ec_hdr - check an erase counter header. * @ubi: UBI device description object - * @pnum: physical eraseblock to read from - * @ec_hdr: a &struct ubi_ec_hdr object where to store the read erase counter - * header - * @verbose: be verbose if the header is corrupted or was not found + * @pnum: physical eraseblock the header was read from + * @ec_hdr: the header to check + * @verbose: be verbose if the header is corrupted * - * This function reads erase counter header from physical eraseblock @pnum and - * stores it in @ec_hdr. This function also checks CRC checksum of the read - * erase counter header. The following codes may be returned: + * This function check erase counter header which was read from physical + * eraseblock @pnum. The following codes may be returned: * * o %0 if the CRC checksum is correct and the header was successfully read; - * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected - * and corrected by the flash driver; this is harmless but may indicate that - * this eraseblock may become bad soon (but may be not); * o %UBI_IO_BAD_EC_HDR if the erase counter header is corrupted (a CRC error); * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty; * o a negative error code in case of failure. */ -int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, - struct ubi_ec_hdr *ec_hdr, int verbose) +int ubi_io_check_ec_hdr(struct ubi_device *ubi, int pnum, + const struct ubi_ec_hdr *ec_hdr, int verbose) { - int err, read_err = 0; uint32_t crc, magic, hdr_crc; - dbg_io("read EC header from PEB %d", pnum); - ubi_assert(pnum >= 0 && pnum < ubi->peb_count); - if (UBI_IO_DEBUG) - verbose = 1; - - err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); - if (err) { - if (err != UBI_IO_BITFLIPS && err != -EBADMSG) - return err; - - /* - * We read all the data, but either a correctable bit-flip - * occurred, or MTD reported about some data integrity error, - * like an ECC error in case of NAND. The former is harmless, - * the later may mean that the read data is corrupted. But we - * have a CRC check-sum and we will detect this. If the EC - * header is still OK, we just report this as there was a - * bit-flip. - */ - read_err = err; - } - magic = be32_to_cpu(ec_hdr->magic); if (magic != UBI_EC_HDR_MAGIC) { /* * The magic field is wrong. Let's check if we have read all * 0xFF. If yes, this physical eraseblock is assumed to be * empty. - * - * But if there was a read error, we do not test it for all - * 0xFFs. Even if it does contain all 0xFFs, this error - * indicates that something is still wrong with this physical - * eraseblock and we anyway cannot treat it as empty. */ - if (read_err != -EBADMSG && - check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { - /* The physical eraseblock is supposedly empty */ + if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { + int err; /* + * The physical eraseblock is supposedly empty. + * * The below is just a paranoid check, it has to be * compiled out if paranoid checks are disabled. */ @@ -675,7 +643,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, ubi->peb_size); if (err) return err > 0 ? UBI_IO_BAD_EC_HDR : err; - if (verbose) ubi_warn("no EC header found at PEB %d, " "only 0xFF bytes", pnum); @@ -691,6 +658,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, "%08x", pnum, magic, UBI_EC_HDR_MAGIC); ubi_dbg_dump_ec_hdr(ec_hdr); } + return UBI_IO_BAD_EC_HDR; } @@ -706,6 +674,72 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, return UBI_IO_BAD_EC_HDR; } + return 0; +} + +/** + * ubi_io_read_ec_hdr - read and check an erase counter header. + * @ubi: UBI device description object + * @pnum: physical eraseblock to read from + * @ec_hdr: a &struct ubi_ec_hdr object where to store the read erase counter + * header + * @verbose: be verbose if the header is corrupted or was not found + * + * This function reads erase counter header from physical eraseblock @pnum and + * stores it in @ec_hdr. This function also checks CRC checksum of the read + * erase counter header. The following codes may be returned: + * + * o %0 if the CRC checksum is correct and the header was successfully read; + * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected + * and corrected by the flash driver; this is harmless but may indicate that + * this eraseblock may become bad soon (but may be not); + * o %UBI_IO_BAD_EC_HDR if the erase counter header is corrupted (a CRC error); + * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty; + * o a negative error code in case of failure. + */ +int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, + struct ubi_ec_hdr *ec_hdr, int verbose) +{ + int err, read_err = 0; + + dbg_io("read EC header from PEB %d", pnum); + ubi_assert(pnum >= 0 && pnum < ubi->peb_count); + if (UBI_IO_DEBUG) + verbose = 1; + + err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); + if (err) { + if (err != UBI_IO_BITFLIPS && err != -EBADMSG) + return err; + + /* + * We read all the data, but either a correctable bit-flip + * occurred, or MTD reported about some data integrity error, + * like an ECC error in case of NAND. The former is harmless, + * the later may mean that the read data is corrupted. But we + * have a CRC check-sum and we will detect this. If the EC + * header is still OK, we just report this as there was a + * bit-flip. + */ + read_err = err; + } + + err = ubi_io_check_ec_hdr(ubi, pnum, ec_hdr, verbose); + if (err == UBI_IO_PEB_EMPTY && read_err) { + /* + * There was a read error, and the read data contains only + * 0xFFs. Do not treat this physical eraseblock as empty + * because the read error indicates that something is still + * wrong with it. + */ + if (verbose) + ubi_warn("PEB %d is supposedly empty, but there was " + "read a error (%d)", pnum, read_err); + return UBI_IO_BAD_EC_HDR; + } + if (err) + return err; + /* And of course validate what has just been read from the media */ err = validate_ec_hdr(ubi, ec_hdr); if (err) { @@ -876,73 +910,39 @@ bad: } /** - * ubi_io_read_vid_hdr - read and check a volume identifier header. + * ubi_io_check_vid_hdr - check a volume identifier header. * @ubi: UBI device description object - * @pnum: physical eraseblock number to read from - * @vid_hdr: &struct ubi_vid_hdr object where to store the read volume - * identifier header + * @pnum: physical eraseblock number the header was read from + * @vid_hdr: the header to check * @verbose: be verbose if the header is corrupted or wasn't found * - * This function reads the volume identifier header from physical eraseblock - * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read - * volume identifier header. The following codes may be returned: + * This function checks the volume identifier header @vid_hdr which was read + * from physical eraseblock @pnum. The following codes may be returned: * * o %0 if the CRC checksum is correct and the header was successfully read; - * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected - * and corrected by the flash driver; this is harmless but may indicate that - * this eraseblock may become bad soon; * o %UBI_IO_BAD_VID_HRD if the volume identifier header is corrupted (a CRC * error detected); * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID * header there); * o a negative error code in case of failure. */ -int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, - struct ubi_vid_hdr *vid_hdr, int verbose) +int ubi_io_check_vid_hdr(struct ubi_device *ubi, int pnum, + const struct ubi_vid_hdr *vid_hdr, int verbose) { - int err, read_err = 0; uint32_t crc, magic, hdr_crc; - void *p; - - dbg_io("read VID header from PEB %d", pnum); - ubi_assert(pnum >= 0 && pnum < ubi->peb_count); - if (UBI_IO_DEBUG) - verbose = 1; - - p = (char *)vid_hdr - ubi->vid_hdr_shift; - err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, - ubi->vid_hdr_alsize); - if (err) { - if (err != UBI_IO_BITFLIPS && err != -EBADMSG) - return err; - - /* - * We read all the data, but either a correctable bit-flip - * occurred, or MTD reported about some data integrity error, - * like an ECC error in case of NAND. The former is harmless, - * the later may mean the read data is corrupted. But we have a - * CRC check-sum and we will identify this. If the VID header is - * still OK, we just report this as there was a bit-flip. - */ - read_err = err; - } magic = be32_to_cpu(vid_hdr->magic); if (magic != UBI_VID_HDR_MAGIC) { /* * If we have read all 0xFF bytes, the VID header probably does * not exist and the physical eraseblock is assumed to be free. - * - * But if there was a read error, we do not test the data for - * 0xFFs. Even if it does contain all 0xFFs, this error - * indicates that something is still wrong with this physical - * eraseblock and it cannot be regarded as free. */ - if (read_err != -EBADMSG && - check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { - /* The physical eraseblock is supposedly free */ + if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { + int err; /* + * The physical eraseblock is supposedly free. + * * The below is just a paranoid check, it has to be * compiled out if paranoid checks are disabled. */ @@ -981,6 +981,76 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, return UBI_IO_BAD_VID_HDR; } + return 0; +} + +/** + * ubi_io_read_vid_hdr - read and check a volume identifier header. + * @ubi: UBI device description object + * @pnum: physical eraseblock number to read from + * @vid_hdr: &struct ubi_vid_hdr object where to store the read volume + * identifier header + * @verbose: be verbose if the header is corrupted or wasn't found + * + * This function reads the volume identifier header from physical eraseblock + * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read + * volume identifier header. The following codes may be returned: + * + * o %0 if the CRC checksum is correct and the header was successfully read; + * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected + * and corrected by the flash driver; this is harmless but may indicate that + * this eraseblock may become bad soon; + * o %UBI_IO_BAD_VID_HRD if the volume identifier header is corrupted (a CRC + * error detected); + * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID + * header there); + * o a negative error code in case of failure. + */ +int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, + struct ubi_vid_hdr *vid_hdr, int verbose) +{ + int err, read_err = 0; + void *p; + + dbg_io("read VID header from PEB %d", pnum); + ubi_assert(pnum >= 0 && pnum < ubi->peb_count); + if (UBI_IO_DEBUG) + verbose = 1; + + p = (char *)vid_hdr - ubi->vid_hdr_shift; + err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, + ubi->vid_hdr_alsize); + if (err) { + if (err != UBI_IO_BITFLIPS && err != -EBADMSG) + return err; + + /* + * We read all the data, but either a correctable bit-flip + * occurred, or MTD reported about some data integrity error, + * like an ECC error in case of NAND. The former is harmless, + * the later may mean the read data is corrupted. But we have a + * CRC check-sum and we will identify this. If the VID header is + * still OK, we just report this as there was a bit-flip. + */ + read_err = err; + } + + err = ubi_io_check_vid_hdr(ubi, pnum, vid_hdr, verbose); + if (err == UBI_IO_PEB_EMPTY && read_err) { + /* + * There was a read error, and the read data contains only + * 0xFFs. Do not treat this physical eraseblock as empty + * because the read error indicates that something is still + * wrong with it. + */ + if (verbose) + ubi_warn("PEB %d is supposedly empty, but there was a " + "read error (%d)", pnum, read_err); + return UBI_IO_BAD_VID_HDR; + } + if (err) + return err; + /* Validate the VID header that we have just read */ err = validate_vid_hdr(ubi, vid_hdr); if (err) { diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 28de80f..4e36028 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -496,10 +496,14 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture); int ubi_io_is_bad(const struct ubi_device *ubi, int pnum); int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum); +int ubi_io_check_ec_hdr(struct ubi_device *ubi, int pnum, + const struct ubi_ec_hdr *ec_hdr, int verbose); int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, struct ubi_ec_hdr *ec_hdr, int verbose); int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, struct ubi_ec_hdr *ec_hdr); +int ubi_io_check_vid_hdr(struct ubi_device *ubi, int pnum, + const struct ubi_vid_hdr *vid_hdr, int verbose); int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, struct ubi_vid_hdr *vid_hdr, int verbose); int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, -- 1.5.4.1