diff options
author | Thomas Gleixner <tglx@cruncher.tec.linutronix.de> | 2006-05-29 08:56:39 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@cruncher.tec.linutronix.de> | 2006-05-29 09:06:51 -0400 |
commit | 9a1fcdfd4bee27c418424cac47abf7c049541297 (patch) | |
tree | 5baa5f1e1d1a296a319bf6a5a4b636668c107e00 /fs/jffs2 | |
parent | 8593fbc68b0df1168995de76d1af38eb62fd6b62 (diff) |
[MTD] NAND Signal that a bitflip was corrected by ECC
Return -EUCLEAN on read when a bitflip was detected and corrected, so the
clients can react and eventually copy the affected block to a spare one.
Make all in kernel users aware of the change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/jffs2')
-rw-r--r-- | fs/jffs2/wbuf.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 1195d06d4373..a7f153f79ecb 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
@@ -296,10 +296,11 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
296 | /* Do the read... */ | 296 | /* Do the read... */ |
297 | ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); | 297 | ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); |
298 | 298 | ||
299 | if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { | 299 | /* ECC recovered ? */ |
300 | /* ECC recovered */ | 300 | if ((ret == -EUCLEAN || ret == -EBADMSG) && |
301 | (retlen == c->wbuf_ofs - start)) | ||
301 | ret = 0; | 302 | ret = 0; |
302 | } | 303 | |
303 | if (ret || retlen != c->wbuf_ofs - start) { | 304 | if (ret || retlen != c->wbuf_ofs - start) { |
304 | printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n"); | 305 | printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n"); |
305 | 306 | ||
@@ -908,20 +909,21 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re | |||
908 | down_read(&c->wbuf_sem); | 909 | down_read(&c->wbuf_sem); |
909 | ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); | 910 | ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); |
910 | 911 | ||
911 | if ( (ret == -EBADMSG) && (*retlen == len) ) { | 912 | if ( (ret == -EBADMSG || ret == -EUCLEAN) && (*retlen == len) ) { |
912 | printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", | 913 | if (ret == -EBADMSG) |
913 | len, ofs); | 914 | printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx)" |
915 | " returned ECC error\n", len, ofs); | ||
914 | /* | 916 | /* |
915 | * We have the raw data without ECC correction in the buffer, maybe | 917 | * We have the raw data without ECC correction in the buffer, |
916 | * we are lucky and all data or parts are correct. We check the node. | 918 | * maybe we are lucky and all data or parts are correct. We |
917 | * If data are corrupted node check will sort it out. | 919 | * check the node. If data are corrupted node check will sort |
918 | * We keep this block, it will fail on write or erase and the we | 920 | * it out. We keep this block, it will fail on write or erase |
919 | * mark it bad. Or should we do that now? But we should give him a chance. | 921 | * and the we mark it bad. Or should we do that now? But we |
920 | * Maybe we had a system crash or power loss before the ecc write or | 922 | * should give him a chance. Maybe we had a system crash or |
921 | * a erase was completed. | 923 | * power loss before the ecc write or a erase was completed. |
922 | * So we return success. :) | 924 | * So we return success. :) |
923 | */ | 925 | */ |
924 | ret = 0; | 926 | ret = 0; |
925 | } | 927 | } |
926 | 928 | ||
927 | /* if no writebuffer available or write buffer empty, return */ | 929 | /* if no writebuffer available or write buffer empty, return */ |
@@ -943,7 +945,7 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re | |||
943 | orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ | 945 | orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ |
944 | if (orbf > len) /* is write beyond write buffer ? */ | 946 | if (orbf > len) /* is write beyond write buffer ? */ |
945 | goto exit; | 947 | goto exit; |
946 | lwbf = len - orbf; /* number of bytes to copy */ | 948 | lwbf = len - orbf; /* number of bytes to copy */ |
947 | if (lwbf > c->wbuf_len) | 949 | if (lwbf > c->wbuf_len) |
948 | lwbf = c->wbuf_len; | 950 | lwbf = c->wbuf_len; |
949 | } | 951 | } |