Allow the disabling of tags ECC
authorcharles <charles>
Wed, 14 Oct 2009 00:01:56 +0000 (00:01 +0000)
committercharles <charles>
Wed, 14 Oct 2009 00:01:56 +0000 (00:01 +0000)
Kconfig
direct/yaffs_fileem2k.c
direct/yaffs_ramem2k.c
moduleconfig.h
yaffs_fs.c
yaffs_guts.h
yaffs_mtdif2.c
yaffs_packedtags2.c
yaffs_packedtags2.h

diff --git a/Kconfig b/Kconfig
index c0e545b647b1c9e882dda2fdb9de89bb3737bdf2..1d3bb715e6e09ad4854dba7a43ca1e07ecb667a1 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -90,6 +90,18 @@ config YAFFS_AUTO_YAFFS2
 
          If unsure, say Y.
 
 
          If unsure, say Y.
 
+config YAFFS_DISABLE_TAGS_ECC
+       bool "Disable YAFFS from doing ECC on tags by default"
+       depends on YAFFS_FS && YAFFS_YAFFS2
+       default n
+       help
+         This defaults Yaffs to using its own ECC calculations on tags instead of
+         just relying on the MTD.
+         This behavior can also be overridden with tags_ecc_on and
+         tags_ecc_off mount options.
+
+         If unsure, say N.
+
 config YAFFS_DISABLE_LAZY_LOAD
        bool "Disable lazy loading"
        depends on YAFFS_YAFFS2
 config YAFFS_DISABLE_LAZY_LOAD
        bool "Disable lazy loading"
        depends on YAFFS_YAFFS2
index 105027602e8d74a4e07c7a170d2a794358471562..cfe992e0de674d0165dd9e31f139473f81b60ea2 100644 (file)
@@ -16,7 +16,7 @@
  * This is only intended as test code to test persistence etc.
  */
 
  * This is only intended as test code to test persistence etc.
  */
 
-const char *yaffs_flashif2_c_version = "$Id: yaffs_fileem2k.c,v 1.18 2009-01-16 02:26:56 charles Exp $";
+const char *yaffs_flashif2_c_version = "$Id: yaffs_fileem2k.c,v 1.19 2009-10-14 00:01:57 charles Exp $";
 
 
 #include "yportenv.h"
 
 
 #include "yportenv.h"
@@ -258,7 +258,7 @@ int yflash2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u
                        else
                        {
                                yaffs_PackedTags2 pt;
                        else
                        {
                                yaffs_PackedTags2 pt;
-                               yaffs_PackTags2(&pt,tags);
+                               yaffs_PackTags2(dev,&pt,tags);
                                __u8 * ptab = (__u8 *)&pt;
 
                                nRead = read(h,localBuffer,sizeof(pt));
                                __u8 * ptab = (__u8 *)&pt;
 
                                nRead = read(h,localBuffer,sizeof(pt));
@@ -336,7 +336,7 @@ int yflash2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u
                        else
                        {
                                yaffs_PackedTags2 pt;
                        else
                        {
                                yaffs_PackedTags2 pt;
-                               yaffs_PackTags2(&pt,tags);
+                               yaffs_PackTags2(dev,&pt,tags);
                                __u8 * ptab = (__u8 *)&pt;
 
                                nRead = read(h,localBuffer,sizeof(pt));
                                __u8 * ptab = (__u8 *)&pt;
 
                                nRead = read(h,localBuffer,sizeof(pt));
@@ -471,7 +471,7 @@ int yflash2_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *d
                        {
                                yaffs_PackedTags2 pt;
                                nread= read(h,&pt,sizeof(pt));
                        {
                                yaffs_PackedTags2 pt;
                                nread= read(h,&pt,sizeof(pt));
-                               yaffs_UnpackTags2(tags,&pt);
+                               yaffs_UnpackTags2(dev,tags,&pt);
 #ifdef SIMULATE_FAILURES
                                if((chunkInNAND >> 6) == 100) {
                                        if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
 #ifdef SIMULATE_FAILURES
                                if((chunkInNAND >> 6) == 100) {
                                        if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
index b496cc64befba775c35b2bf4e10b5a2e56cff0dd..767dceae262b7c8b923cff943bae8815311917c6 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 
  */
 
 
-const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.4 2008-05-05 07:58:58 charles Exp $";
+const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.5 2009-10-14 00:01:57 charles Exp $";
 
 #ifndef __KERNEL__
 #define CONFIG_YAFFS_RAM_ENABLED
 
 #ifndef __KERNEL__
 #define CONFIG_YAFFS_RAM_ENABLED
@@ -220,7 +220,7 @@ int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const
        {
                x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
                
        {
                x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
                
-               yaffs_PackTags2((yaffs_PackedTags2 *)x,tags);
+               yaffs_PackTags2(dev,(yaffs_PackedTags2 *)x,tags);
                        
        }
        
                        
        }
        
@@ -256,7 +256,7 @@ int nandemul2k_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8
        {
                x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
                
        {
                x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
                
-               yaffs_UnpackTags2(tags,(yaffs_PackedTags2 *)x);
+               yaffs_UnpackTags2(dev,tags,(yaffs_PackedTags2 *)x);
        }
 
        return YAFFS_OK;
        }
 
        return YAFFS_OK;
index a344baf372a3f69c26e8a13f95266d773272a6c1..99c9f6a66ef3e4e2b475e82941a0e1ff3e942d52 100644 (file)
 /* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
 /* #define CONFIG_YAFFS_DOES_ECC */
 
 /* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
 /* #define CONFIG_YAFFS_DOES_ECC */
 
+/* Default: Selected */
+/* Meaning: Yaffs does its own ECC on tags for packed tags rather than use mtd */
+#define CONFIG_YAFFS_DOES_TAGS_ECC
+
 /* Default: Not selected */
 /* Meaning: ECC byte order is 'wrong'.  Only meaningful if */
 /*          CONFIG_YAFFS_DOES_ECC is set */
 /* Default: Not selected */
 /* Meaning: ECC byte order is 'wrong'.  Only meaningful if */
 /*          CONFIG_YAFFS_DOES_ECC is set */
index 3fd94df12bab57878658836f06b4a0056ce0a7e8..a51dc20de633f900f25cf4ba5c8d993142956012 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 const char *yaffs_fs_c_version =
  */
 
 const char *yaffs_fs_c_version =
-    "$Id: yaffs_fs.c,v 1.83 2009-09-23 23:24:55 charles Exp $";
+    "$Id: yaffs_fs.c,v 1.84 2009-10-14 00:01:56 charles Exp $";
 extern const char *yaffs_guts_c_version;
 
 #include <linux/version.h>
 extern const char *yaffs_guts_c_version;
 
 #include <linux/version.h>
@@ -1812,6 +1812,8 @@ typedef struct {
        int skip_checkpoint_read;
        int skip_checkpoint_write;
        int no_cache;
        int skip_checkpoint_read;
        int skip_checkpoint_write;
        int no_cache;
+       int tags_ecc_on;
+       int tags_ecc_overridden;
 } yaffs_options;
 
 #define MAX_OPT_LEN 20
 } yaffs_options;
 
 #define MAX_OPT_LEN 20
@@ -1827,6 +1829,9 @@ static int yaffs_parse_options(yaffs_options *options, const char *options_str)
                memset(cur_opt, 0, MAX_OPT_LEN + 1);
                p = 0;
 
                memset(cur_opt, 0, MAX_OPT_LEN + 1);
                p = 0;
 
+               while(*options_str == ',')
+                       options_str++;
+
                while (*options_str && *options_str != ',') {
                        if (p < MAX_OPT_LEN) {
                                cur_opt[p] = *options_str;
                while (*options_str && *options_str != ',') {
                        if (p < MAX_OPT_LEN) {
                                cur_opt[p] = *options_str;
@@ -1837,7 +1842,13 @@ static int yaffs_parse_options(yaffs_options *options, const char *options_str)
 
                if (!strcmp(cur_opt, "inband-tags"))
                        options->inband_tags = 1;
 
                if (!strcmp(cur_opt, "inband-tags"))
                        options->inband_tags = 1;
-               else if (!strcmp(cur_opt, "no-cache"))
+               else if (!strcmp(cur_opt, "tags-ecc-off")){
+                       options->tags_ecc_on = 0;
+                       options->tags_ecc_overridden=1;
+               } else if (!strcmp(cur_opt, "tags-ecc-on")){
+                       options->tags_ecc_on = 1;
+                       options->tags_ecc_overridden = 1;
+               } else if (!strcmp(cur_opt, "no-cache"))
                        options->no_cache = 1;
                else if (!strcmp(cur_opt, "no-checkpoint-read"))
                        options->skip_checkpoint_read = 1;
                        options->no_cache = 1;
                else if (!strcmp(cur_opt, "no-checkpoint-read"))
                        options->skip_checkpoint_read = 1;
@@ -2053,6 +2064,12 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
        dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
        dev->inbandTags = options.inband_tags;
 
        dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
        dev->inbandTags = options.inband_tags;
 
+#ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC
+       dev->noTagsECC = 1;
+#endif
+       if(options.tags_ecc_overridden)
+               dev->noTagsECC = !options.tags_ecc_on;
+
        /* ... and the functions. */
        if (yaffsVersion == 2) {
                dev->writeChunkWithTagsToNAND =
        /* ... and the functions. */
        if (yaffsVersion == 2) {
                dev->writeChunkWithTagsToNAND =
@@ -2289,6 +2306,7 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev)
        buf +=
            sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
        buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
        buf +=
            sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
        buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
+       buf += sprintf(buf, "noTagsECC.......... %d\n", dev->noTagsECC);
        buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
        buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
 
        buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
        buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
 
index cb8d8ec788683b26b29b646faaf2d9bf1d4dae15..853fea60200bd1e5082dd4129e3fb19f712f632d 100644 (file)
@@ -557,7 +557,8 @@ struct yaffs_DeviceStruct {
 
        int useHeaderFileSize;  /* Flag to determine if we should use file sizes from the header */
 
 
        int useHeaderFileSize;  /* Flag to determine if we should use file sizes from the header */
 
-       int useNANDECC;         /* Flag to decide whether or not to use NANDECC */
+       int useNANDECC;         /* Flag to decide whether or not to use NANDECC on data (yaffs1) */
+       int noTagsECC;          /* Flag to decide whether or not to do ECC on packed tags (yaffs2) */ 
 
        void *genericDevice;    /* Pointer to device context
                                 * On an mtd this holds the mtd pointer.
 
        void *genericDevice;    /* Pointer to device context
                                 * On an mtd this holds the mtd pointer.
index 77504babb78112909b235c1ead8579f233e301c5..918f8de2b6aa95f6cd8a2fb5e363431fad27ea34 100644 (file)
@@ -14,7 +14,7 @@
 /* mtd interface for YAFFS2 */
 
 const char *yaffs_mtdif2_c_version =
 /* mtd interface for YAFFS2 */
 
 const char *yaffs_mtdif2_c_version =
-       "$Id: yaffs_mtdif2.c,v 1.23 2009-03-06 17:20:53 wookey Exp $";
+       "$Id: yaffs_mtdif2.c,v 1.24 2009-10-14 00:01:57 charles Exp $";
 
 #include "yportenv.h"
 
 
 #include "yportenv.h"
 
@@ -47,6 +47,9 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
 
        yaffs_PackedTags2 pt;
 
 
        yaffs_PackedTags2 pt;
 
+       int packed_tags_size = dev->noTagsECC ? sizeof(pt.t) : sizeof(pt);
+       void * packed_tags_ptr = dev->noTagsECC ? (void *) &pt.t : (void *)&pt;
+
        T(YAFFS_TRACE_MTD,
          (TSTR
           ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
        T(YAFFS_TRACE_MTD,
          (TSTR
           ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
@@ -66,22 +69,22 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
                pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
                yaffs_PackTags2TagsPart(pt2tp, tags);
        } else
                pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
                yaffs_PackTags2TagsPart(pt2tp, tags);
        } else
-               yaffs_PackTags2(&pt, tags);
+               yaffs_PackTags2(dev, &pt, tags);
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
        ops.mode = MTD_OOB_AUTO;
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
        ops.mode = MTD_OOB_AUTO;
-       ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
+       ops.ooblen = (dev->inbandTags) ? 0 : packed_tags_size;
        ops.len = dev->totalBytesPerChunk;
        ops.ooboffs = 0;
        ops.datbuf = (__u8 *)data;
        ops.len = dev->totalBytesPerChunk;
        ops.ooboffs = 0;
        ops.datbuf = (__u8 *)data;
-       ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
+       ops.oobbuf = (dev->inbandTags) ? NULL : packed_tags_ptr;
        retval = mtd->write_oob(mtd, addr, &ops);
 
 #else
        if (!dev->inbandTags) {
                retval =
                    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
        retval = mtd->write_oob(mtd, addr, &ops);
 
 #else
        if (!dev->inbandTags) {
                retval =
                    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
-                                  &dummy, data, (__u8 *) &pt, NULL);
+                                  &dummy, data, (__u8 *) packed_tags_ptr, NULL);
        } else {
                retval =
                    mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
        } else {
                retval =
                    mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
@@ -110,6 +113,9 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
 
        yaffs_PackedTags2 pt;
 
 
        yaffs_PackedTags2 pt;
 
+       int packed_tags_size = dev->noTagsECC ? sizeof(pt.t) : sizeof(pt);
+       void * packed_tags_ptr = dev->noTagsECC ? (void *) &pt.t: (void *)&pt;
+
        T(YAFFS_TRACE_MTD,
          (TSTR
           ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
        T(YAFFS_TRACE_MTD,
          (TSTR
           ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
@@ -132,8 +138,8 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
                                &dummy, data);
        else if (tags) {
                ops.mode = MTD_OOB_AUTO;
                                &dummy, data);
        else if (tags) {
                ops.mode = MTD_OOB_AUTO;
-               ops.ooblen = sizeof(pt);
-               ops.len = data ? dev->nDataBytesPerChunk : sizeof(pt);
+               ops.ooblen = packed_tags_size;
+               ops.len = data ? dev->nDataBytesPerChunk : packed_tags_size;
                ops.ooboffs = 0;
                ops.datbuf = data;
                ops.oobbuf = dev->spareBuffer;
                ops.ooboffs = 0;
                ops.datbuf = data;
                ops.oobbuf = dev->spareBuffer;
@@ -166,8 +172,8 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
                }
        } else {
                if (tags) {
                }
        } else {
                if (tags) {
-                       memcpy(&pt, dev->spareBuffer, sizeof(pt));
-                       yaffs_UnpackTags2(tags, &pt);
+                       memcpy(packed_tags_ptr, dev->spareBuffer, packed_tags_size);
+                       yaffs_UnpackTags2(dev, tags, &pt);
                }
        }
 
                }
        }
 
index a78c03c9d6ce368b3c8447d482c76252b32143e3..e0c55862d04597b26462aaadeda75a4b9387c384 100644 (file)
@@ -96,17 +96,14 @@ void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *ptt,
 }
 
 
 }
 
 
-void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t)
+void yaffs_PackTags2(yaffs_Device *dev, yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t)
 {
        yaffs_PackTags2TagsPart(&pt->t, t);
 
 {
        yaffs_PackTags2TagsPart(&pt->t, t);
 
-#ifndef YAFFS_IGNORE_TAGS_ECC
-       {
+       if(!dev->noTagsECC)
                yaffs_ECCCalculateOther((unsigned char *)&pt->t,
                                        sizeof(yaffs_PackedTags2TagsPart),
                                        &pt->ecc);
                yaffs_ECCCalculateOther((unsigned char *)&pt->t,
                                        sizeof(yaffs_PackedTags2TagsPart),
                                        &pt->ecc);
-       }
-#endif
 }
 
 
 }
 
 
@@ -158,27 +155,24 @@ void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t,
 }
 
 
 }
 
 
-void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
+void yaffs_UnpackTags2(yaffs_Device *dev, yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
 {
 
        yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
 
 {
 
        yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
 
-       if (pt->t.sequenceNumber != 0xFFFFFFFF) {
-               /* Page is in use */
-#ifndef YAFFS_IGNORE_TAGS_ECC
-               {
-                       yaffs_ECCOther ecc;
-                       int result;
-                       yaffs_ECCCalculateOther((unsigned char *)&pt->t,
-                                               sizeof
-                                               (yaffs_PackedTags2TagsPart),
-                                               &ecc);
-                       result =
-                           yaffs_ECCCorrectOther((unsigned char *)&pt->t,
-                                                 sizeof
-                                                 (yaffs_PackedTags2TagsPart),
-                                                 &pt->ecc, &ecc);
-                       switch (result) {
+       if (pt->t.sequenceNumber != 0xFFFFFFFF &&
+           !dev->noTagsECC){
+               /* Chunk is in use and we need to do ECC */
+               
+               yaffs_ECCOther ecc;
+               int result;
+               yaffs_ECCCalculateOther((unsigned char *)&pt->t,
+                                       sizeof(yaffs_PackedTags2TagsPart),
+                                       &ecc);
+               result = yaffs_ECCCorrectOther((unsigned char *)&pt->t,
+                                               sizeof(yaffs_PackedTags2TagsPart),
+                                               &pt->ecc, &ecc);
+               switch (result) {
                        case 0:
                                eccResult = YAFFS_ECC_RESULT_NO_ERROR;
                                break;
                        case 0:
                                eccResult = YAFFS_ECC_RESULT_NO_ERROR;
                                break;
@@ -190,9 +184,7 @@ void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
                                break;
                        default:
                                eccResult = YAFFS_ECC_RESULT_UNKNOWN;
                                break;
                        default:
                                eccResult = YAFFS_ECC_RESULT_UNKNOWN;
-                       }
                }
                }
-#endif
        }
 
        yaffs_UnpackTags2TagsPart(t, &pt->t);
        }
 
        yaffs_UnpackTags2TagsPart(t, &pt->t);
@@ -201,6 +193,5 @@ void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
 
        yaffs_DumpPackedTags2(pt);
        yaffs_DumpTags2(t);
 
        yaffs_DumpPackedTags2(pt);
        yaffs_DumpTags2(t);
-
 }
 
 }
 
index ec30f843bcbdbbd27ded4124c1c7ff713f60b81b..d90c6cbfd8218bc2f95083c5b6affc193c88ed85 100644 (file)
@@ -34,8 +34,8 @@ typedef struct {
 } yaffs_PackedTags2;
 
 /* Full packed tags with ECC, used for oob tags */
 } yaffs_PackedTags2;
 
 /* Full packed tags with ECC, used for oob tags */
-void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t);
-void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt);
+void yaffs_PackTags2(yaffs_Device *dev, yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t);
+void yaffs_UnpackTags2(yaffs_Device *dev, yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt);
 
 /* Only the tags part (no ECC for use with inband tags */
 void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *pt, const yaffs_ExtendedTags *t);
 
 /* Only the tags part (no ECC for use with inband tags */
 void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *pt, const yaffs_ExtendedTags *t);