UBIFS partition on NOR flash not mountable after power cut test

Anatolij Gustschin agust at denx.de
Fri Dec 3 06:15:37 EST 2010


On Thu, 02 Dec 2010 06:42:06 +0200
Artem Bityutskiy <dedekind1 at gmail.com> wrote:
...
> From 7ddb9cb80ab54d118e2a055ce7a35649070578b1 Mon Sep 17 00:00:00 2001
> From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> Date: Thu, 2 Dec 2010 06:34:01 +0200
> Subject: [PATCH] UBI: fix corrupted PEB detection for NOR flash
> 
> My new shiny code for corrupted PEB detection has NOR specific bug.
> We tread PEB as corrupted and preserve it, if
> 
> 1. EC header is OK.
> 2. VID header is corrupted.
> 3. data area is not "all 0xFFs"
> 
> In case of NOR we have 'nor_erase_prepare()' quirk, which invalidates
> the headers before erasing the PEB. And we invalidate first the VID
> header, and then the EC header. So if a power cut happens after we have
> invalidated the VID header, but before we have invalidated the EC
> header, we end up with a PEB which satisfies the above 3 conditions,
> and the scanning code will treat it as corrupted, and will print
> scary warnings, wrongly.
> 
> This patch fixes the issue by firt invalidating the EC header, then
> invalidating the VID header. In case of power cut inbetween, we still
> just lose the EC header, and UBI can deal with this situation gracefully.
> 
> This patch also adds one irrelevant comment about defining VID header
> buffer on stack.
> 
> Thanks to Anatolij Gustschin <agust at denx.de> for tracking this down.
> 
> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> Reported-by: Anatolij Gustschin <agust at denx.de>

Tested-by: Anatolij Gustschin <agust at denx.de>

> ---
>  drivers/mtd/ubi/io.c   |   37 ++++++++++++++++++++++++++++---------
>  drivers/mtd/ubi/scan.c |    4 ++++
>  2 files changed, 32 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
> index c2960ac..3839253 100644
> --- a/drivers/mtd/ubi/io.c
> +++ b/drivers/mtd/ubi/io.c
> @@ -480,12 +480,26 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
>  	size_t written;
>  	loff_t addr;
>  	uint32_t data = 0;
> +	/*
> +	 * Note, we cannot generally define VID header buffers on stack,
> +	 * because of the way we deal with these buffers (see the heder
> +	 * comment). But we know this is NOR-specific piece of code, so we can
> +	 * do this. But yes, this is error-prone and we should (pre-)allocate
> +	 * VID header buffer instead.
> +	 */
>  	struct ubi_vid_hdr vid_hdr;
>  
> -	addr = (loff_t)pnum * ubi->peb_size + ubi->vid_hdr_aloffset;
> +	/*
> +	 * Note, it is important to first invalidate the EC header, and then
> +	 * VID header. Otherwise a power cut may result in valid EC header and
> +	 * invalid VID header, then UBI will treat this PEB as corrupted and
> +	 * will try to preserve it, print scary warnings. See scan.c header
> +	 * comment for more information.
> +	 */
> +	addr = (loff_t)pnum * ubi->peb_size;
>  	err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
>  	if (!err) {
> -		addr -= ubi->vid_hdr_aloffset;
> +		addr += ubi->vid_hdr_aloffset;
>  		err = ubi->mtd->write(ubi->mtd, addr, 4, &written,
>  				      (void *)&data);
>  		if (!err)
> @@ -499,13 +513,18 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
>  	 * In this case we probably anyway have garbage in this PEB.
>  	 */
>  	err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
> -	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
> -		/*
> -		 * The VID header is corrupted, so we can safely erase this
> -		 * PEB and not afraid that it will be treated as a valid PEB in
> -		 * case of an unclean reboot.
> -		 */
> -		return 0;
> +	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) {
> +		struct ubi_ec_hdr ec_hdr;
> +
> +		err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
> +		if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
> +			/*
> +			 * The VID and EC headers are corrupted, so we can
> +			 * safely erase this PEB and not afraid that it will be
> +			 * treated as a valid PEB in case of an unclean reboot.
> +			 */
> +			return 0;
> +	}
>  
>  	/*
>  	 * The PEB contains a valid VID header, but we cannot invalidate it.
> diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
> index 3c63186..d4b1115 100644
> --- a/drivers/mtd/ubi/scan.c
> +++ b/drivers/mtd/ubi/scan.c
> @@ -951,6 +951,10 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
>  			 * impossible to distinguish it from a PEB which just
>  			 * contains garbage because of a power cut during erase
>  			 * operation. So we just schedule this PEB for erasure.
> +			 *
> +			 * Besides, in case of NOR flash, we deliberatly
> +			 * corrupt both headers because NOR flash erasure is
> +			 * slow and can start from the end.
>  			 */
>  			err = 0;
>  		else




More information about the linux-mtd mailing list