[PATCH 3/3] nandwrite: fix/cleanup bad block skipping

Mike Crowe mac at mcrowe.com
Fri Jan 13 09:58:15 PST 2017


On Thursday 12 January 2017 at 11:28:28 +0100, David Oberhollenzer wrote:
> JFFS2 supports clustering erase blocks to virtual erase blocks.
> nandwrite supports this, but previously mixed up virtual and
> physical erase block numbers when checking for bad blocks.
> 
> This patch adds a function for checking if a virtual erase block
> is bad and replaces the broken mtd_is_bad loop.
> 
> Signed-off-by: David Oberhollenzer <david.oberhollenzer at sigma-star.at>
> ---
>  nand-utils/nandwrite.c | 57 ++++++++++++++++++++++++++------------------------
>  1 file changed, 30 insertions(+), 27 deletions(-)
> 
> diff --git a/nand-utils/nandwrite.c b/nand-utils/nandwrite.c
> index 22c741d..c7a53d1 100644
> --- a/nand-utils/nandwrite.c
> +++ b/nand-utils/nandwrite.c
> @@ -235,6 +235,20 @@ static void erase_buffer(void *buffer, size_t size)
>  		memset(buffer, kEraseByte, size);
>  }
>  
> +static int is_virt_block_bad(struct mtd_dev_info *mtd, int fd,
> +				long long offset)
> +{
> +	int i, ret = 0;
> +
> +	for (i = 0; i < blockalign; ++i) {
> +		ret = mtd_is_bad(mtd, fd, offset / mtd->eb_size + i);
> +		if (ret)
> +			break;
> +	}
> +
> +	return ret;
> +}
> +
>  /*
>   * Main program
>   */
> @@ -246,10 +260,8 @@ int main(int argc, char * const argv[])
>  	int ifd = -1;
>  	int pagelen;
>  	long long imglen = 0;
> -	bool baderaseblock = false;
>  	long long blockstart = -1;
>  	struct mtd_dev_info mtd;
> -	long long offs;
>  	int ret;
>  	bool failed = true;
>  	/* contains all the data read from the file so far for the current eraseblock */
> @@ -391,7 +403,6 @@ int main(int argc, char * const argv[])
>  		 */
>  		while (blockstart != (mtdoffset & (~ebsize_aligned + 1))) {
>  			blockstart = mtdoffset & (~ebsize_aligned + 1);
> -			offs = blockstart;
>  
>  			/*
>  			 * if writebuf == filebuf, we are rewinding so we must
> @@ -403,40 +414,32 @@ int main(int argc, char * const argv[])
>  				writebuf = filebuf;
>  			}
>  
> -			baderaseblock = false;
>  			if (!quiet)
>  				fprintf(stdout, "Writing data to block %lld at offset 0x%llx\n",
>  						 blockstart / ebsize_aligned, blockstart);
>  
> -			/* Check all the blocks in an erase block for bad blocks */
>  			if (noskipbad)
>  				continue;
>  
> -			do {
> -				ret = mtd_is_bad(&mtd, fd, offs / ebsize_aligned);
> -				if (ret < 0) {
> -					sys_errmsg("%s: MTD get bad block failed", mtd_device);
> -					goto closeall;
> -				} else if (ret == 1) {
> -					baderaseblock = true;
> -					if (!quiet)
> -						fprintf(stderr, "Bad block at %llx, %u block(s) "
> -								"from %llx will be skipped\n",
> -								offs, blockalign, blockstart);
> -				}
> +			ret = is_virt_block_bad(&mtd, fd, blockstart);
>  
> -				if (baderaseblock) {
> -					mtdoffset = blockstart + ebsize_aligned;
> -
> -					if (mtdoffset > mtd.size) {
> -						errmsg("too many bad blocks, cannot complete request");
> -						goto closeall;
> -					}
> -				}
> +			if (ret < 0) {
> +				sys_errmsg("%s: MTD get bad block failed", mtd_device);
> +				goto closeall;
> +			} else if (ret == 1) {
> +				if (!quiet)
> +					fprintf(stderr,
> +						"Bad block at %llx, %u block(s) "
> +						"will be skipped\n",
> +						blockstart, blockalign);
>  
> -				offs +=  ebsize_aligned / blockalign;
> -			} while (offs < blockstart + ebsize_aligned);
> +				mtdoffset = blockstart + ebsize_aligned;
>  
> +				if (mtdoffset > mtd.size) {
> +					errmsg("too many bad blocks, cannot complete request");
> +					goto closeall;
> +				}
> +			}
>  		}
>  
>  		/* Read more data from the input if there isn't enough in the buffer */
> -- 
> 2.10.2

I think that this change does probably fix the problems I raised in
http://lists.infradead.org/pipermail/linux-mtd/2017-January/071516.html and
its parents. I can't test it since we don't use virtual erase blocks.

It might be worth is_virt_block_bad checking that it has been passed a
multiple of ebsize_aligned. The caller in this patch is obviously aligned
(so hopefully the compiler would throw away such a check when it inlines
the static function) but that may not always be the case.

I will rebase my --skip-bad-blocks-to-start patch to make use of the new
function.

Thanks.

Mike.



More information about the linux-mtd mailing list