All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pantelis Antoniou <panto@intracom.gr>
To: David Woodhouse <dwmw2@infradead.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	linux-mtd@lists.infradead.org
Subject: [PATCH] Any RO filesystem on NAND
Date: Thu, 06 May 2004 10:07:31 +0300	[thread overview]
Message-ID: <4099E433.6050604@intracom.gr> (raw)

[-- 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(-)

                 reply	other threads:[~2004-05-06  7:19 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4099E433.6050604@intracom.gr \
    --to=panto@intracom.gr \
    --cc=dwmw2@infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.