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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox