[PATCH] UBI: optimize vid-header IO read checks
Gupta, Pekon
pekon at ti.com
Thu May 16 02:38:35 EDT 2013
Hi,
Requesting feedbacks/comments on this one too ?
This should be independent of previous one..
with regards, pekon
> -----Original Message-----
> From: Gupta, Pekon
> Sent: Sunday, April 28, 2013 7:21 PM
> To: linux-mtd at lists.infradead.org
> Cc: Gupta, Pekon
> Subject: [PATCH] UBI: optimize vid-header IO read checks
>
> From: "Gupta, Pekon" <pekon at ti.com>
>
> This patch is extension of earlier patch
> 'UBI: optimize erase-header IO read checksUBI'
>
> During mounting of UBI device, ec_hdr and vid_hdr of all PEB are
> scanned.
> This patch tries to reduce the PEB scan time, by optimizing
> ubi_io_read_vid_hdr
> based on following analysis.
> --------------------------------------------------------------------------
> EC_HDR VID_HDR CONCLUSION NEXT STEP
> --------------------------------------------------------------------------
> valid valid PEB contains data map PEB to corresponding LEB
> valid blank PEB is free attach to free list
> valid invalid PEB may contain data try recovering data
>
> invalid valid PEB may contain data try recovering data
> invalid blank PEB is free[1] schedule for erasure
> invalid invalid underministic schedule for erasure
> --------------------------------------------------------------------------
>
> EC_HDR or VID_HDR may read 'invalid' due to following reasons:
> (a) contains non-UBI data.
> (b) block is completely erased.
> (b) header corrupted due to power-failure during program or erase
> operation.
> (c) header corrupted due to bitflips after program or erase operation.
>
> Signed-off-by: Gupta, Pekon <pekon at ti.com>
> ---
> drivers/mtd/ubi/io.c | 110 +++++++++++++++++++++++++++++++------
> --------------
> 1 file changed, 68 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
> index 0b9b0af..1446137 100644
> --- a/drivers/mtd/ubi/io.c
> +++ b/drivers/mtd/ubi/io.c
> @@ -532,7 +532,7 @@ static int nor_erase_prepare(struct ubi_device
> *ubi, int pnum)
> */
> err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
> if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 ==
> UBI_IO_BAD_HDR ||
> - err1 == UBI_IO_FF) {
> + err1 == UBI_IO_FF || err1 == UBI_IO_FF_BITFLIPS) {
> struct ubi_ec_hdr ec_hdr;
>
> err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
> @@ -829,7 +829,6 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi,
> int pnum,
> {
> int err;
> uint32_t crc;
> -
> dbg_io("write EC header to PEB %d", pnum);
> ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
>
> @@ -998,60 +997,87 @@ int ubi_io_read_vid_hdr(struct ubi_device
> *ubi, int pnum,
> p = (char *)vid_hdr - ubi->vid_hdr_shift;
> read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
> ubi->vid_hdr_alsize);
> - if (read_err && read_err != UBI_IO_BITFLIPS &&
> !mtd_is_eccerr(read_err))
> - return read_err;
> -
> - magic = be32_to_cpu(vid_hdr->magic);
> - if (magic != UBI_VID_HDR_MAGIC) {
> - if (mtd_is_eccerr(read_err))
> + switch (read_err) {
> + case -EBADMSG:
> + /* un-correctable bit-flips detected
> + * Case-1: hdr_crc != crc(vid_hdr)
> + * uncorrectable bit-flips detected within header
> region.
> + * header data cannot be trusted.
> + * Case-2: hdr_crc == crc(vid_hdr)
> + * uncorrectable bit-flip do not effect header
> region.
> + * header data can be parsed.
> + */
> + crc = crc32(UBI_CRC32_INIT, vid_hdr,
> UBI_VID_HDR_SIZE_CRC);
> + hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
> + if (hdr_crc == crc)
> + goto good_vid_hdr;
> + else
> return UBI_IO_BAD_HDR_EBADMSG;
> + break;
>
> - if (ubi_check_pattern(vid_hdr, 0xFF,
> UBI_VID_HDR_SIZE)) {
> + case 0:
> + case UBI_IO_BITFLIPS:
> + /* check whether this is UBI vid-hdr */
> + magic = be32_to_cpu(vid_hdr->magic);
> + if (magic == UBI_VID_HDR_MAGIC) {
> + /* check hdr-crc (data integrity check) */
> + crc = crc32(UBI_CRC32_INIT, vid_hdr,
> +
> UBI_VID_HDR_SIZE_CRC);
> + hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
> + if (hdr_crc == crc) {
> + goto good_vid_hdr;
> + } else {
> + if (verbose) {
> + ubi_warn("bad vid_hdr CRC at
> PEB %d",
> +
> pnum);
> + ubi_dump_vid_hdr(vid_hdr);
> + }
> + ubi_warn("bad vid_hdr CRC at PEB %d",
> pnum);
> + if (read_err)
> + return
> UBI_IO_BAD_HDR_EBADMSG;
> + else
> + return UBI_IO_BAD_HDR;
> + }
> +
> + /* BUT UNLIKE EC_HDR, we need to explicit check for
> + * vid-hdr(data) == all(0xFF) because vid_hdr is written
> only
> + * when PEB is mapped to LEB, Thus valid free PEB will still
> + * have blank vid_hdr.
> + */
> + } else if (ubi_check_pattern(vid_hdr, 0xFF,
> +
> UBI_VID_HDR_SIZE)) {
> if (verbose)
> - ubi_warn("no VID header found at PEB
> %d, only 0xFF bytes",
> - pnum);
> - dbg_bld("no VID header found at PEB %d, only
> 0xFF bytes",
> - pnum);
> - if (!read_err)
> - return UBI_IO_FF;
> - else
> - return UBI_IO_FF_BITFLIPS;
> - }
> + ubi_warn("No vid_hdr found at PEB %d",
> pnum);
> + dbg_bld("No vid_hdr found at PEB %d", pnum);
> + return (read_err) ? UBI_IO_FF_BITFLIPS :
> UBI_IO_FF;
>
> - if (verbose) {
> - ubi_warn("bad magic number at PEB %d: %08x
> instead of %08x",
> - pnum, magic, UBI_VID_HDR_MAGIC);
> - ubi_dump_vid_hdr(vid_hdr);
> + /* its a programmed page, but does not contain UBI
> vid_hdr */
> + } else {
> + if (verbose) {
> + ubi_warn("invalid vid_hdr at PEB %d",
> pnum);
> + ubi_dump_vid_hdr(vid_hdr);
> + }
> + dbg_bld("invalid vid_hdr at PEB %d", pnum);
> + return UBI_IO_BAD_HDR_EBADMSG;
> }
> - dbg_bld("bad magic number at PEB %d: %08x instead of
> %08x",
> - pnum, magic, UBI_VID_HDR_MAGIC);
> - return UBI_IO_BAD_HDR;
> - }
> -
> - crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
> - hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
> + break;
>
> - if (hdr_crc != crc) {
> - if (verbose) {
> - ubi_warn("bad CRC at PEB %d, calculated %#08x,
> read %#08x",
> - pnum, crc, hdr_crc);
> - ubi_dump_vid_hdr(vid_hdr);
> - }
> - dbg_bld("bad CRC at PEB %d, calculated %#08x, read
> %#08x",
> - pnum, crc, hdr_crc);
> - if (!read_err)
> - return UBI_IO_BAD_HDR;
> - else
> - return UBI_IO_BAD_HDR_EBADMSG;
> + default:
> + /* -EIO (may be incomplete page reads) */
> + return read_err;
> }
>
> +good_vid_hdr:
> err = validate_vid_hdr(ubi, vid_hdr);
> if (err) {
> ubi_err("validation failed for PEB %d", pnum);
> return -EINVAL;
> }
>
> - return read_err ? UBI_IO_BITFLIPS : 0;
> + if (read_err)
> + return UBI_IO_BITFLIPS;
> + else
> + return 0;
> }
>
> /**
> --
> 1.8.1
More information about the linux-mtd
mailing list