All of lore.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.