From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from yx-out-1718.google.com ([74.125.44.157]) by bombadil.infradead.org with esmtp (Exim 4.68 #1 (Red Hat Linux)) id 1Kke19-0004Jy-DR for linux-mtd@lists.infradead.org; Tue, 30 Sep 2008 12:07:52 +0000 Received: by yx-out-1718.google.com with SMTP id 3so1327400yxi.72 for ; Tue, 30 Sep 2008 05:07:50 -0700 (PDT) Message-ID: Date: Tue, 30 Sep 2008 20:07:50 +0800 From: "Jason Liu" To: apgmoorthy Subject: Re: [PATCH 1/2] [MTD] [JFFS2] MLC NAND support In-Reply-To: <001101c9222e$1914e6d0$3dd66c6b@sisodomain.com> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <30508484.52991221827822859.JavaMail.weblogic@epml16> <9c9fda240809212333n76fa6cc6jbf1025f4f272d3f4@mail.gmail.com> <001101c9222e$1914e6d0$3dd66c6b@sisodomain.com> Cc: linux-mtd@lists.infradead.org, Kyungmin Park , David.Woodhouse@intel.com List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Hi, I have looked into the log file. I notice the oops in the log file is the same i often meet with MLC nand after apply the patch JFFS2 doesn't use OOB at MLC NAND/OneNAND from Kyungmin Park, it seems that jffs2 file system may have serious issues. I have strong feeling that jffs2 files system is far from production level at least for MLC nand flash. David, do you have any comments? 2008/9/29 apgmoorthy : > Hi, > > In the earlier patch there was a typo , have rectified it and posting it > back. > > > Signed-off-by: Rajshekar H Payagond > --- > --- a/fs/jffs2/build.c 2008-09-16 20:48:12.000000000 +0530 > +++ b/fs/jffs2/build.c 2008-09-19 17:07:48.000000000 +0530 > @@ -330,7 +330,11 @@ int jffs2_do_mount_fs(struct jffs2_sb_in > int i; > int size; > > - c->free_size = c->flash_size; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) > + c->free_size = 0; > + else > + c->free_size = c->flash_size; > + > c->nr_blocks = c->flash_size / c->sector_size; > size = sizeof(struct jffs2_eraseblock) * c->nr_blocks; #ifndef > __ECOS @@ -346,7 +350,14 @@ int jffs2_do_mount_fs(struct jffs2_sb_in > for (i=0; inr_blocks; i++) { > INIT_LIST_HEAD(&c->blocks[i].list); > c->blocks[i].offset = i * c->sector_size; > - c->blocks[i].free_size = c->sector_size; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) { > + c->blocks[i].free_size = > + c->sector_size - c->wbuf_pagesize; > + c->blocks[i].used_size = c->wbuf_pagesize; > + c->free_size += c->blocks[i].free_size; > + c->used_size += c->blocks[i].used_size; > + } else > + c->blocks[i].free_size = c->sector_size; > } > > INIT_LIST_HEAD(&c->clean_list); > --- a/fs/jffs2/debug.c 2008-09-16 20:48:12.000000000 +0530 > +++ b/fs/jffs2/debug.c 2008-09-19 17:07:48.000000000 +0530 > @@ -307,6 +307,9 @@ __jffs2_dbg_acct_paranoia_check_nolock(s > uint32_t my_dirty_size = 0; > struct jffs2_raw_node_ref *ref2 = jeb->first_node; > > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) > + my_used_size = c->wbuf_pagesize; > + > while (ref2) { > uint32_t totlen = ref_totlen(c, jeb, ref2); > > --- a/fs/jffs2/erase.c 2008-09-16 20:48:12.000000000 +0530 > +++ b/fs/jffs2/erase.c 2008-09-19 17:07:48.000000000 +0530 > @@ -454,13 +454,21 @@ static void jffs2_mark_erased_block(stru > } > } > /* Everything else got zeroed before the erase */ > - jeb->free_size = c->sector_size; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) { > + jeb->free_size = c->sector_size - c->wbuf_pagesize; > + jeb->used_size = c->wbuf_pagesize; > + } else > + jeb->free_size = c->sector_size; > > mutex_lock(&c->erase_free_sem); > spin_lock(&c->erase_completion_lock); > > c->erasing_size -= c->sector_size; > - c->free_size += c->sector_size; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) { > + c->free_size += c->sector_size - c->wbuf_pagesize; > + c->used_size += c->wbuf_pagesize; > + } else > + c->free_size += c->sector_size; > > /* Account for cleanmarker now, if it's in-band */ > if (c->cleanmarker_size && !jffs2_cleanmarker_oob(c)) > --- a/fs/jffs2/gc.c 2008-09-16 20:48:12.000000000 +0530 > +++ b/fs/jffs2/gc.c 2008-09-23 21:36:56.000000000 +0530 > @@ -237,9 +237,17 @@ int jffs2_garbage_collect_pass(struct jf > D1(if (c->nextblock) > printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size > %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, > c->nextblock->used_size, c->nextblock->dirty_size, > c->nextblock->wasted_size, c->nextblock->free_size)); > > - if (!jeb->used_size) { > - mutex_unlock(&c->alloc_sem); > - goto eraseit; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) { > + if (jeb->used_size <= c->wbuf_pagesize) { > + mutex_unlock(&c->alloc_sem); > + goto eraseit; > + } > + > + } else{ > + if (!jeb->used_size) { > + mutex_unlock(&c->alloc_sem); > + goto eraseit; > + } > } > > raw = jeb->gc_node; > @@ -429,13 +437,30 @@ int jffs2_garbage_collect_pass(struct jf > spin_lock(&c->erase_completion_lock); > > eraseit: > - if (c->gcblock && !c->gcblock->used_size) { > - D1(printk(KERN_DEBUG "Block at 0x%08x completely obsoleted > by GC. Moving to erase_pending_list\n", c->gcblock->offset)); > - /* We're GC'ing an empty block? */ > - list_add_tail(&c->gcblock->list, &c->erase_pending_list); > - c->gcblock = NULL; > - c->nr_erasing_blocks++; > - jffs2_erase_pending_trigger(c); > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) { > + if (c->gcblock && (c->gcblock->used_size <= > c->wbuf_pagesize)) { > + D1(printk(KERN_DEBUG "Block at 0x%08x completely" > + " obsoleted by GC. Moving to > erase_pending_list\n" > + , c->gcblock->offset)); > + /* We're GC'ing an empty block? */ > + list_add_tail(&c->gcblock->list, > + &c->erase_pending_list); > + c->gcblock = NULL; > + c->nr_erasing_blocks++; > + jffs2_erase_pending_trigger(c); > + } > + } else{ > + if (c->gcblock && !c->gcblock->used_size) { > + D1(printk(KERN_DEBUG "Block at 0x%08x completely" > + " obsoleted by GC. Moving to > erase_pending_list\n" > + , c->gcblock->offset)); > + /* We're GC'ing an empty block? */ > + list_add_tail(&c->gcblock->list, > + &c->erase_pending_list); > + c->gcblock = NULL; > + c->nr_erasing_blocks++; > + jffs2_erase_pending_trigger(c); > + } > } > spin_unlock(&c->erase_completion_lock); > > --- a/fs/jffs2/nodelist.c 2008-09-16 20:48:12.000000000 +0530 > +++ b/fs/jffs2/nodelist.c 2008-09-19 17:07:48.000000000 +0530 > @@ -634,7 +634,11 @@ struct jffs2_raw_node_ref *jffs2_link_no > > if (!jeb->first_node) { > jeb->first_node = ref; > - BUG_ON(ref_offset(ref) != jeb->offset); > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) > + BUG_ON(ref_offset(ref) != > + jeb->offset + > c->wbuf_pagesize); > + else > + BUG_ON(ref_offset(ref) != jeb->offset); > } else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size > - jeb->free_size)) { > uint32_t last_len = ref_totlen(c, jeb, jeb->last_node); > > --- a/fs/jffs2/nodemgmt.c 2008-09-16 20:48:12.000000000 +0530 > +++ b/fs/jffs2/nodemgmt.c 2008-09-19 17:07:48.000000000 +0530 > @@ -362,16 +362,25 @@ static int jffs2_do_reserve_space(struct > } > > if (!jeb) { > - > ret = jffs2_find_nextblock(c); > if (ret) > return ret; > > jeb = c->nextblock; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) { > + if (jeb->free_size != c->sector_size - > + c->cleanmarker_size - c->wbuf_pagesize) { > + printk(KERN_WARNING "Eep. Block 0x%08x taken > from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); > + goto restart; > + } > + } > > - if (jeb->free_size != c->sector_size - c->cleanmarker_size) > { > - printk(KERN_WARNING "Eep. Block 0x%08x taken from > free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); > - goto restart; > + else{ > + if (jeb->free_size != c->sector_size - > + c->cleanmarker_size) { > + printk(KERN_WARNING "Eep. Block 0x%08x taken > from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); > + goto restart; > + } > } > } > /* OK, jeb (==c->nextblock) is now pointing at a block which > definitely has > --- a/fs/jffs2/scan.c 2008-09-16 20:48:12.000000000 +0530 > +++ b/fs/jffs2/scan.c 2008-09-19 17:07:48.000000000 +0530 > @@ -534,7 +534,10 @@ static int jffs2_scan_eraseblock (struct > } > } > > - buf_ofs = jeb->offset; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) > + buf_ofs = jeb->offset + c->wbuf_pagesize; > + else > + buf_ofs = jeb->offset; > > if (!buf_size) { > /* This is the XIP case -- we're reading _directly_ from the > flash chip */ @@ -582,7 +585,10 @@ static int jffs2_scan_eraseblock (struct > } > > /* Now ofs is a complete physical flash offset as it always was... > */ > - ofs += jeb->offset; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) > + ofs += jeb->offset + c->wbuf_pagesize; > + else > + ofs += jeb->offset; > > noise = 10; > > --- a/fs/jffs2/wbuf.c 2008-09-16 20:48:12.000000000 +0530 > +++ b/fs/jffs2/wbuf.c 2008-09-19 17:07:48.000000000 +0530 > @@ -873,6 +873,13 @@ int jffs2_flash_writev(struct jffs2_sb_i > vlen -= wbuf_retlen; > outvec_to += wbuf_retlen; > c->wbuf_ofs = outvec_to; > + if (c->mtd->flags == MTD_CAP_MLCNANDFLASH) { > + /* adjust write buffer offset, > + * else we get a non contiguous write bug > + */ > + if (!(c->wbuf_ofs % c->sector_size)) > + c->wbuf_ofs = 0xffffffff; > + } > donelen += wbuf_retlen; > v += wbuf_retlen; > } > --- a/include/mtd/mtd-abi.h 2008-09-16 20:48:12.000000000 +0530 > +++ b/include/mtd/mtd-abi.h 2008-09-23 22:09:18.000000000 +0530 > @@ -28,12 +28,14 @@ struct mtd_oob_buf { > #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ > #define MTD_NO_ERASE 0x1000 /* No erase necessary */ > #define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */ > +#define MTD_OOB_WRITEABLE 0x4000 > > // Some common devices / combinations of capabilities > #define MTD_CAP_ROM 0 > #define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | > MTD_NO_ERASE) > #define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE) > #define MTD_CAP_NANDFLASH (MTD_WRITEABLE | MTD_OOB_WRITEABLE) > +#define MTD_CAP_MLCNANDFLASH (MTD_WRITEABLE) > > /* ECC byte placement */ > #define MTD_NANDECC_OFF 0 // Switch off ECC (Not > recommended) > > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ >