Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 68480
b: refs/heads/master
c: a6bc432
h: refs/heads/master
v: v3
  • Loading branch information
David Woodhouse committed Jul 11, 2007
1 parent 10c9597 commit d140ad1
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ef53cb02ffee8ceb44ea75f778f77eace6b9c89a
refs/heads/master: a6bc432e296dfa1f05d4b586ca5ca3085a2d42d7
8 changes: 8 additions & 0 deletions trunk/fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,14 @@ config JFFS2_FS_WRITEBUFFER
- NOR flash with transparent ECC
- DataFlash

config JFFS2_FS_WBUF_VERIFY
bool "Verify JFFS2 write-buffer reads"
depends on JFFS2_FS_WRITEBUFFER
default n
help
This causes JFFS2 to read back every page written through the
write-buffer, and check for errors.

config JFFS2_SUMMARY
bool "JFFS2 summary support (EXPERIMENTAL)"
depends on JFFS2_FS && EXPERIMENTAL
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/jffs2/jffs2_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ struct jffs2_sb_info {

uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */

#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
unsigned char *wbuf_verify; /* read-back buffer for verification */
#endif
#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
unsigned char *wbuf; /* Write-behind buffer for NAND flash */
uint32_t wbuf_ofs;
Expand Down
73 changes: 63 additions & 10 deletions trunk/fs/jffs2/wbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,47 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info
return NULL;
}

#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
uint32_t ofs)
{
int ret;
size_t retlen;
char *eccstr;

ret = c->mtd->read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);
if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x failed: %d\n", c->wbuf_ofs, ret);
return ret;
} else if (retlen != c->wbuf_pagesize) {
printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x gave short read: %zd not %d.\n", ofs, retlen, c->wbuf_pagesize);
return -EIO;
}
if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize))
return 0;

if (ret == -EUCLEAN)
eccstr = "corrected";
else if (ret == -EBADMSG)
eccstr = "correction failed";
else
eccstr = "OK or unused";

printk(KERN_WARNING "Write verify error (ECC %s) at %08x. Wrote:\n",
eccstr, c->wbuf_ofs);
print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
c->wbuf, c->wbuf_pagesize, 0);

printk(KERN_WARNING "Read back:\n");
print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
c->wbuf_verify, c->wbuf_pagesize, 0);

return -EIO;
}
#else
#define jffs2_verify_write(c,b,o) (0)
#endif

/* Recover from failure to write wbuf. Recover the nodes up to the
* wbuf, not the one which we were starting to try to write. */

Expand Down Expand Up @@ -380,7 +421,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
rewrite_buf);

if (ret || retlen != towrite) {
if (ret || retlen != towrite || jffs2_verify_write(c, rewrite_buf, ofs)) {
/* Argh. We tried. Really we did. */
printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
kfree(buf);
Expand Down Expand Up @@ -587,15 +628,16 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)

ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);

if (ret || retlen != c->wbuf_pagesize) {
if (ret)
printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret);
else {
printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
retlen, c->wbuf_pagesize);
ret = -EIO;
}

if (ret) {
printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n", ret);
goto wfail;
} else if (retlen != c->wbuf_pagesize) {
printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
retlen, c->wbuf_pagesize);
ret = -EIO;
goto wfail;
} else if ((ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) {
wfail:
jffs2_wbuf_recover(c);

return ret;
Expand Down Expand Up @@ -1138,11 +1180,22 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
return -ENOMEM;
}

#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
if (!c->wbuf_verify) {
kfree(c->oobbuf);
kfree(c->wbuf);
return -ENOMEM;
}
#endif
return 0;
}

void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
{
#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
kfree(c->wbuf_verify);
#endif
kfree(c->wbuf);
kfree(c->oobbuf);
}
Expand Down

0 comments on commit d140ad1

Please sign in to comment.