From patchwork Tue Nov 11 05:31:32 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rohit X-Patchwork-Id: 8082 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D5861DDDD8 for ; Tue, 11 Nov 2008 16:27:16 +1100 (EST) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux)) id 1Kzlk5-0004Dp-6V; Tue, 11 Nov 2008 05:24:45 +0000 Received: from mailout1.samsung.com ([203.254.224.24]) by bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux)) id 1Kzljs-0004BT-7v for linux-mtd@lists.infradead.org; Tue, 11 Nov 2008 05:24:43 +0000 Received: from epmmp1 (mailout1.samsung.com [203.254.224.24]) by mailout1.samsung.com (iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004)) with ESMTP id <0KA500G4RLNVAW@mailout1.samsung.com> for linux-mtd@lists.infradead.org; Tue, 11 Nov 2008 14:23:55 +0900 (KST) Received: from localhost.localdomain ([107.108.214.120]) by mmp1.samsung.com (iPlanet Messaging Server 5.2 Patch 2 (built Jul 14 2004)) with ESMTPA id <0KA500INBLNRER@mmp1.samsung.com> for linux-mtd@lists.infradead.org; Tue, 11 Nov 2008 14:23:52 +0900 (KST) Date: Tue, 11 Nov 2008 11:01:32 +0530 From: Rohit Subject: [RFC] [PATCH 2/2] [MTDPARTS] Support erase regions with odd numbered blocks To: linux-mtd@lists.infradead.org Message-id: <491918B4.6040005@samsung.com> MIME-version: 1.0 User-Agent: Thunderbird 2.0.0.16 (X11/20080723) X-Spam-Score: -4.0 (----) X-Spam-Report: SpamAssassin version 3.2.5 on bombadil.infradead.org summary: Content analysis details: (-4.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -4.0 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [203.254.224.24 listed in list.dnswl.org] Cc: 'David Woodhouse' X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org An erroneous partition spanning across erase regions with odd number of blocks may go undetected. Examples are: 1. Region 0 has 1 block of 128KB, region 1 has blocks of 256KB. A partition with offset 0 and length 256KB (gets erase size 256KB) is invalid but passes all checks. 2. Region 0 has 1 block of 128KB, region 1 has 1 block of 256KB and region 2 has 128KB blocks. A partition with offset 0 and length 512KB (gets biggest erasesize ie 256KB) is invalid. Such a partition passes all checks. The patch checks if the portion of a partition present in each region is multiple of erase size of partition. Signed-off-by: Rohit Hagargundgi --- mtdpart.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) --- diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 3728913..f091943 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -425,7 +425,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, } if (master->numeraseregions > 1) { /* Deal with variable erase size stuff */ - int i, max = master->numeraseregions; + int i, rgn, max = master->numeraseregions; u32 end = slave->offset + slave->mtd.size; struct mtd_erase_region_info *regions = master->eraseregions; @@ -437,12 +437,35 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, i--; /* Pick biggest erasesize */ + rgn = i; for (; i < max && regions[i].offset < end; i++) { if (slave->mtd.erasesize < regions[i].erasesize) { slave->mtd.erasesize = regions[i].erasesize; } } BUG_ON(slave->mtd.erasesize == 0); + + if (slave->mtd.flags & MTD_WRITEABLE) { + /* If partition spans many erase regions, + * the partition portion present in each region + * should be multiple of biggest erase size + */ + unsigned portion_start, portion_end, region_end; + + for (i = rgn; i < max && regions[i].offset < end; i++) { + portion_start = max(regions[i].offset, slave->offset); + region_end = regions[i].offset + + regions[i].erasesize * regions[i].numblocks; + portion_end = min(end, region_end); + + if ((portion_end - portion_start) % slave->mtd.erasesize) { + slave->mtd.flags &= ~MTD_WRITEABLE; + printk(KERN_WARNING"mtd: partition \"%s\" is not erase block" + " aligned within erase region -- force read-only\n", part->name); + break; + } + } + } } else { /* Single erase size */ slave->mtd.erasesize = master->erasesize;