Patchwork [RFC,1/2,MTDPARTS] Support erase regions with odd numbered blocks

login
register
mail settings
Submitter Rohit
Date Nov. 11, 2008, 5:31 a.m.
Message ID <491918AC.4090502@samsung.com>
Download mbox | patch
Permalink /patch/8081/
State New
Headers show

Comments

Rohit - Nov. 11, 2008, 5:31 a.m.
Hi,

Currently add_one_partition in mtdpart.c does not handle erase regions
with odd number of blocks well. Some scenarios are :

     1. Region 0 has 3 blocks of 256KB. Region 1 has 512KB blocks.
	Partiton starting at offset 256KB and size 1MB turns read only.

     2. Region 0 has 3 blocks of 256KB. Region 1 has 512KB blocks.
	All partitions created on region 2 turn read only.

Every partition start offset should be multiple of partition erase size.
It is this condition which causes valid partitions to turn read-only.

The following patch is an attempt to allow such regions.
Is such a change to MTD core correct / acceptable?
Any suggestions are much appreciated.

Signed-off-by: Rohit Hagargundgi <h.rohit@samsung.com>
---
 mtdpart.c |   17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

---

Patch

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 3728913..5cdc345 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -320,6 +320,7 @@  static struct mtd_part *add_one_partition(struct mtd_info *master,
 		u_int32_t cur_offset)
 {
 	struct mtd_part *slave;
+	unsigned offset_checked = 0;
 
 	/* allocate the partition structure */
 	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
@@ -436,6 +437,20 @@  static struct mtd_part *add_one_partition(struct mtd_info *master,
 		/* The loop searched for the region _behind_ the first one */
 		i--;
 
+		if (slave->mtd.flags & MTD_WRITEABLE) {
+			/* A region starts on boundary of it's erase size.
+			 * Partition offset within region must align
+			 * on region's erase size
+			 */
+			if ((slave->offset - regions[i].offset) % regions[i].erasesize) {
+				slave->mtd.flags &= ~MTD_WRITEABLE;
+				printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an "
+					 "erase block boundary -- force read-only\n", part->name);
+			} else
+				/* Skip offset check below */
+				offset_checked = 1;
+		}
+
 		/* Pick biggest erasesize */
 		for (; i < max && regions[i].offset < end; i++) {
 			if (slave->mtd.erasesize < regions[i].erasesize) {
@@ -448,7 +463,7 @@  static struct mtd_part *add_one_partition(struct mtd_info *master,
 		slave->mtd.erasesize = master->erasesize;
 	}
 
-	if ((slave->mtd.flags & MTD_WRITEABLE) &&
+	if (!offset_checked && (slave->mtd.flags & MTD_WRITEABLE) &&
 	    (slave->offset % slave->mtd.erasesize)) {
 		/* Doesn't start on a boundary of major erase size */
 		/* FIXME: Let it be writable if it is on a boundary of