public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH] Any RO filesystem on NAND
@ 2004-05-06  7:07 Pantelis Antoniou
  0 siblings, 0 replies; only message in thread
From: Pantelis Antoniou @ 2004-05-06  7:07 UTC (permalink / raw)
  To: David Woodhouse, Thomas Gleixner, linux-mtd

[-- Attachment #1: Type: text/plain, Size: 208 bytes --]

Hello.

The following patch implements any RO filesystem on MTD devices like
NANDs with bad blocks.

It is a modification for the mtd-block device when the partition/device 
is read only.

Regards

Pantelis


[-- Attachment #2: block_ro.diff --]
[-- Type: text/x-patch, Size: 3385 bytes --]

diff -ruN mtd-original/drivers/mtd/mtdblock.c mtd-work/drivers/mtd/mtdblock.c
--- mtd-original/drivers/mtd/mtdblock.c	2003-10-05 01:00:04.000000000 +0300
+++ mtd-work/drivers/mtd/mtdblock.c	2004-05-06 10:00:21.347152520 +0300
@@ -26,6 +26,11 @@
 	unsigned long cache_offset;
 	unsigned int cache_size;
 	enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
+
+	/* block map for RO */
+	int		*block_map;
+	int		 block_top;
+	int		 block_scantop;
 } *mtdblks[MAX_MTD_DEVICES];
 
 /*
@@ -190,6 +195,71 @@
 	return 0;
 }
 
+static unsigned long map_block(struct mtdblk_dev *mtdblk, unsigned long pos)
+{
+	struct mtd_info *mtd = mtdblk->mtd;
+	int i, block;
+
+	/* only for read-only devices with OOB info and bad block checking */
+	if ((mtd->flags & MTD_WRITEABLE) == MTD_WRITEABLE ||
+			(mtd->flags & MTD_OOB) == 0 || mtd->block_isbad == NULL ||
+			mtd->erasesize == 0)
+		return pos;
+
+	/* first time in */
+	if (mtdblk->block_map == NULL) {
+		mtdblk->block_top = mtd->size / mtd->erasesize;
+		mtdblk->block_map = kmalloc(sizeof(*mtdblk->block_map) * mtdblk->block_top, GFP_KERNEL);
+		if (mtdblk->block_map == NULL) {
+			printk (KERN_WARNING "mtd: block_map(): unable to allocate block map\n");
+			return (unsigned long)-1;
+		}
+		for (i = 0; i < mtdblk->block_top; i++)
+			mtdblk->block_map[i] = -1;
+
+		for (i = 0; i < mtdblk->block_top; i++)
+			if ((*mtd->block_isbad)(mtd, i * mtd->erasesize) == 0)
+				break;
+
+		if (i >= mtdblk->block_top) {
+			printk (KERN_WARNING "mtd: block_map(): all blocks bad?!\n");
+			return (unsigned long)-1;
+		}
+		mtdblk->block_scantop = 0;
+		mtdblk->block_map[0] = i;
+
+		DEBUG(0, "mtdblk: map %d -> %d\n", mtdblk->block_scantop, mtdblk->block_map[mtdblk->block_scantop]);
+	}
+
+	block = (int)(pos / mtd->erasesize);
+	if ((unsigned int)block >= (unsigned int)mtdblk->block_top) {
+		printk (KERN_WARNING "mtd: block_map(): requested block too large!\n");
+		return (unsigned long)-1;
+	}
+
+	/* scan for bad block up to where we want */
+	while (block >= mtdblk->block_scantop) {
+		/* find a non bad block */
+		for (i = mtdblk->block_map[mtdblk->block_scantop] + 1; i < mtdblk->block_top; i++)
+			if ((*mtd->block_isbad)(mtd, i * mtd->erasesize) == 0)
+				break;
+
+		/* exchausted ? */
+		if (i >= mtdblk->block_top) {
+			printk (KERN_WARNING "mtd: block_map(): no more good blocks\n");
+			return (unsigned long)-1;
+		}
+
+		mtdblk->block_map[++mtdblk->block_scantop] = i;
+		DEBUG(0, "mtdblk: map %d -> %d\n", mtdblk->block_scantop, mtdblk->block_map[mtdblk->block_scantop]);
+	}
+
+	/* get the mapped block */
+	block = mtdblk->block_map[block];
+
+	/* form actual position */
+	return ((unsigned long)block * mtd->erasesize) | (pos & (mtd->erasesize - 1));
+}
 
 static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, 
 			   int len, char *buf)
@@ -222,11 +292,17 @@
 		    mtdblk->cache_offset == sect_start) {
 			memcpy (buf, mtdblk->cache_data + offset, size);
 		} else {
-			ret = MTD_READ (mtd, pos, size, &retlen, buf);
-			if (ret)
-				return ret;
-			if (retlen != size)
-				return -EIO;
+			pos = map_block(mtdblk, pos);
+			if (pos == (unsigned long)-1) {
+				memset(buf, 0xff, size);
+				retlen = size;
+			} else {
+				ret = MTD_READ (mtd, pos, size, &retlen, buf);
+				if (ret)
+					return ret;
+				if (retlen != size)
+					return -EIO;
+			}
 		}
 
 		buf += size;


[-- Attachment #3: block_ro.diffstat --]
[-- Type: text/plain, Size: 132 bytes --]

 mtdblock.c |   86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 81 insertions(+), 5 deletions(-)

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-05-06  7:19 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-06  7:07 [PATCH] Any RO filesystem on NAND Pantelis Antoniou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox