[PATCH] MTD: mtdconcat NAND/Sibley support

Jörn Engel joern at wohnheim.fh-wedel.de
Wed Apr 26 11:51:16 EDT 2006


On Wed, 26 April 2006 15:36:08 +0400, Belyakov, Alexander wrote:
> 
> diff -uNr a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
> --- a/drivers/mtd/mtdconcat.c	2006-04-07 20:56:47.000000000 +0400
> +++ b/drivers/mtd/mtdconcat.c	2006-04-26 15:26:21.000000000 +0400
> @@ -141,6 +141,97 @@
>  }
>  
>  static int
> +concat_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned
> long count, 
> +		loff_t to, size_t * retlen)
> +{
> +	int i, page, len, total_len, ret = 0, written = 0, cnt = 0,
> towrite;
> +	u_char *bufstart;
> +	char* data_poi;
> +	char* data_buf;
> +	loff_t write_offset;
> +	int rl_wr;
> +	u_int32_t pagesize;
> +
> +	if (mtd->flags & MTD_PROGRAM_REGIONS) {
> +		pagesize = MTD_PROGREGION_SIZE(mtd);
> +	} else {
> +		pagesize = mtd->oobblock;
> +	}

Take a look at my tree:
http://git.infradead.org/?p=users/joern/mtd-2.6.git;a=summary

Once writesize is in, this part can just go.

> +	data_buf = kmalloc(pagesize, GFP_KERNEL);

Allocation can fail.

> +	/* Preset written len for early exit */
> +	*retlen = 0;
> +
> +	/* Calculate total length of data */
> +	total_len = 0;
> +	for (i = 0; i < count; i++)
> +		total_len += (int) vecs[i].iov_len;
> +
> +	/* Do not allow write past end of page */
> +	if ((to + total_len) > mtd->size) {
> +		kfree(data_buf);

Move the allocation below this check instead.

> +		return -EINVAL;
> +	}
> +
> +	/* Setup start page */
> +	page = ((int) to) / pagesize;

If you have to cast, at least take uint32_t, as mtd->size has that
type as well.

> +	towrite = (page + 1) * pagesize - to;
> +	write_offset = to;
> +	written = 0;
> +	
> +	/* Loop until all iovecs' data has been written */
> +	len = 0;
> +	while (len < total_len) {
> +    		bufstart = (u_char *)vecs->iov_base;

Why the cast?  Can't bufstart be a void*?

> +		bufstart += written;
> +		data_poi = bufstart;
> +
> +    		/* If the given tuple is >= reet of page then
> +		 * write it out from the iov
> +		 */
> +		if ( (vecs->iov_len-written) >= towrite) {
> +			ret = mtd->write(mtd, write_offset, towrite,
> &rl_wr, data_poi);
> +			if(ret)

Documentation/CodingStyle requires a space here.

> +	    			break;
> +			len += towrite;
> +			page ++;
> +			write_offset = page * pagesize;
> +			towrite = pagesize;
> +			written += towrite;
> +			if (vecs->iov_len  == written) {
> +				vecs ++;
> +				written = 0;
> +			}
> +		} else {
> +			cnt = 0;
> +			while (cnt < towrite ) {
> +				data_buf[cnt++] = ((u_char *)
> vecs->iov_base)[written++];
> +				if (vecs->iov_len == written ) {
> +					if((cnt+len) == total_len )
> +						break;
> +					vecs ++;
> +					written = 0;
> +				}
> +			}
> +			data_poi = data_buf;
> +			ret = mtd->write(mtd, write_offset, cnt, &rl_wr,
> data_poi);
> +			if (ret)
> +				break;
> +			len += cnt;
> +			page ++;
> +			write_offset = page * pagesize;
> +			towrite = pagesize;
> +		}
> +	}
> +
> +	if(retlen)
> +		*retlen = len;
> +	kfree(data_buf);
> +	return ret;
> +}
> +
> +static int
>  concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
>  		size_t * retlen, u_char * buf, u_char * eccbuf,
>  		struct nand_oobinfo *oobsel)
> @@ -251,6 +342,123 @@
>  }
>  
>  static int
> +concat_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
> unsigned long count, 
> +		loff_t to, size_t * retlen, u_char *eccbuf, struct
> nand_oobinfo *oobsel)
> +{
> +	int i, page, len, total_len, ret = 0, written = 0, cnt = 0,
> towrite;
> +	u_char *bufstart;
> +	char* data_poi;
> +	char* data_buf;
> +	loff_t write_offset;
> +	int rl_wr;
> +	u_int32_t pagesize;
> +
> +	if (mtd->flags & MTD_PROGRAM_REGIONS) {
> +		pagesize = MTD_PROGREGION_SIZE(mtd);
> +	} else {
> +		pagesize = mtd->oobblock;
> +	}

Again.

> +	data_buf = kmalloc(pagesize, GFP_KERNEL);

Again.

> +	if (!(mtd->flags & MTD_WRITEABLE))
> +		return -EROFS;
> +
> +	/* Preset written len for early exit */
> +	*retlen = 0;
> +
> +	/* Calculate total length of data */
> +	total_len = 0;
> +	for (i = 0; i < count; i++)
> +		total_len += (int) vecs[i].iov_len;
> +
> +	/* check if no data is going to be written */
> +	if (!total_len) {
> +		kfree(data_buf);

Again.

I'll stop reading here.  These two functions look fairly similar so
there might be some duplicated code you can move into a common helper.

Once you have the above fixed up and checked all the code for similar
problems, I'll take another look.

Jörn

-- 
Simplicity is prerequisite for reliability.
-- Edsger W. Dijkstra




More information about the linux-mtd mailing list