changeset 311:16de60f90faa

ecos-yaffs-nand.c: Correctly use ECC on YAFFS tags in yaffs2
author wry
date Fri, 18 Sep 2009 11:13:00 +0000
parents a097a8d2aa15
children 8678bc743892
files packages/fs/yaffs/current/ChangeLog packages/fs/yaffs/current/cdl/yaffs.cdl packages/fs/yaffs/current/doc/yaffs.sgml packages/fs/yaffs/current/src/ecos-yaffs-nand.c packages/fs/yaffs/current/src/ecos-yaffs-nand.h packages/fs/yaffs/current/src/ecos-yaffs.c packages/fs/yaffs/current/src/ecos-yaffs.h packages/fs/yaffs/current/src/yaffs_packedtags2.c packages/fs/yaffs/current/src/yaffs_tagscompat.c
diffstat 9 files changed, 99 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/packages/fs/yaffs/current/ChangeLog
+++ b/packages/fs/yaffs/current/ChangeLog
@@ -1,3 +1,11 @@
+2009-09-16  Ross Younger  <wry@ecoscentric.com>
+
+	* ecos-yaffs-nand.c: Correctly use ECC on YAFFS tags in yaffs2
+	filesystems when not in inbandTags mode (ref: 1000821)
+	* ecos-yaffs.c: Improve spare area size sanity checking on mount
+	* yaffs_packedtags2.c: Add framework (usually conditioned out)
+	to count ECC corrections within the spare area.
+
 2009-08-28  Ross Younger  <wry@ecoscentric.com>
 
 	* doc/yaffs.sgml: Bring explanations of CDL options up-to-date.
--- a/packages/fs/yaffs/current/cdl/yaffs.cdl
+++ b/packages/fs/yaffs/current/cdl/yaffs.cdl
@@ -70,6 +70,7 @@ cdl_package CYGPKG_FS_YAFFS {
     compile         yaffs_checkptrw.c       \
                     yaffs_guts.c            \
                     yaffs_nand.c            \
+                    yaffs_ecc.c             \
                     yaffs_packedtags1.c     \
                     yaffs_packedtags2.c     \
                     yaffs_tagscompat.c      \
--- a/packages/fs/yaffs/current/doc/yaffs.sgml
+++ b/packages/fs/yaffs/current/doc/yaffs.sgml
@@ -30,7 +30,7 @@
 
 <!-- }}} -->
 
-<!-- ### Uncomment to make a standalone book: 
+<!-- ### Uncomment to make a standalone book:
 <!DOCTYPE book  PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
 <book id="fs-yaffs-book">
     <bookinfo>
@@ -521,17 +521,60 @@ the heap's own overheads.)
 
 <sect1 id="yaffs-testing"><title>Testing</title>
 <para>
-YAFFS comes with a single test program, <filename>fops.c</filename>.
-This is believed to exercise all of the code paths (filesystem operations,
-file operations and directory operations) within the eCos-YAFFS
-adaptation layer.
+YAFFS is supplied with a number of test programs, some of which are have been
+adapted from tests for other filesystems in eCos.
 </para>
 
-<para>
-The test was originally designed to run on a synthetic NAND filesystem.
+<glosslist>
+<glossentry><glossterm>fops</glossterm><glossdef><para>
+This was the first basic test created for the port of the filesystem.
+It is believed to exercise all of the code paths (filesystem operations,
+file operations and directory operations) within the eCos-YAFFS
+adaptation layer.  </para> <para>
+This test was originally intended to run on a synthetic NAND filesystem.
 On real NAND chips, it deliberately omits the more stressful routines to
-avoid unduly damaging the hardware.
-</para>
+avoid undue wear on the hardware.
+</para></glossdef></glossentry>
+<glossentry><glossterm>yaffs1</glossterm><glossdef><para>
+A number of filesystem edge-case semantic tests, including 
+file and directory creation and deletion, 
+invalid open and rename operations, and
+removing nonexistent files and directories.
+</para></glossdef></glossentry>
+<glossentry><glossterm>yaffs2</glossterm><glossdef><para>
+Concurrent multi-threaded filesystem access and consistency checks.
+</para></glossdef></glossentry>
+<glossentry><glossterm>yaffs4</glossterm><glossdef><para>
+Semantic and edge-case testing - like yaffs1 - but with long file names.
+</para></glossdef></glossentry>
+<glossentry><glossterm>yaffs5</glossterm><glossdef><para>
+Tests that file reading and writing works over reasonably large files
+(up to 1Mbyte) with different I/O chunk sizes. Some operation timings
+are collected and reported, as is the data rate on large files.
+</para></glossdef></glossentry>
+<glossentry><glossterm>yaffs6</glossterm><glossdef><para>
+Semantic and edge-case testing - like yaffs1 - but with Cyrillic filenames
+in order to test UTF-8 correctness.
+</para></glossdef></glossentry>
+<glossentry><glossterm>mounttime</glossterm><glossdef><para>
+A simple benchmark which repeatedly mounts and unmounts the filesystem
+and measures how long this takes.
+You can optionally use the <filename>mkfiles</filename> routine - also
+present in the tests directory - to create many short files so you can 
+test performance on a loaded filesystem.
+</para></glossdef></glossentry>
+<glossentry><glossterm>hammer</glossterm><glossdef><para>
+A stress test designed to shake out corner cases.
+Repeatedly creates many files of varying sizes from multiple threads
+until the filesystem fills up, then verifies their contents and removes
+them. From time to time, all threads pause and the filesystem is
+unmounted and remounted. </para><para>This test is particularly useful when 
+combined with the bad block injection functionality provided by
+the synthetic NAND device. It has been used in this way by eCosCentric to 
+thoroughly test this package's stability under error conditions.
+<note><para>This test runs forever, until interrupted.</para></note>
+</para></glossdef></glossentry>
+</glosslist>
 </sect1>
 </chapter>
 
--- a/packages/fs/yaffs/current/src/ecos-yaffs-nand.c
+++ b/packages/fs/yaffs/current/src/ecos-yaffs-nand.c
@@ -73,9 +73,6 @@ int eyaffs_eraseBlockInNAND (struct yaff
     return rv==0 ? YAFFS_OK : YAFFS_FAIL;
 }
 
-// If writing a yaffs_PackedTags1, we store only its eight meaningful bytes 
-#define PACKEDTAGS1_OOBSIZE 8
-
 int eyaffs_writeChunkWithTagsToNAND (struct yaffs_DeviceStruct * dev,
         int chunkInNAND, const __u8 * data,
         const yaffs_ExtendedTags * tags)
@@ -120,9 +117,9 @@ int eyaffs_writeChunkWithTagsToNAND (str
             yaffs_PackTags2TagsPart(pt2tp, tags);
             rv = cyg_nand_write_page(part, chunkInNAND, data, dev->totalBytesPerChunk, 0, 0);
         } else {
-            yaffs_PackedTags2TagsPart pt;
-            yaffs_PackTags2TagsPart(&pt, tags);
-            rv = cyg_nand_write_page(part, chunkInNAND, data, dev->nDataBytesPerChunk, &pt, sizeof(yaffs_PackedTags2TagsPart));
+            yaffs_PackedTags2 pt;
+            yaffs_PackTags2(&pt, tags);
+            rv = cyg_nand_write_page(part, chunkInNAND, data, dev->nDataBytesPerChunk, &pt, PACKEDTAGS2_OOBSIZE);
         }
 #endif
     }
@@ -204,10 +201,10 @@ int eyaffs_readChunkWithTagsFromNAND (st
                 yaffs_UnpackTags2TagsPart(tags, pt2tp);
             }
         } else {
-            yaffs_PackedTags2TagsPart pt;
-            rv = cyg_nand_read_page(part, chunkInNAND, data, data ? dev->nDataBytesPerChunk : 0, &pt, sizeof(yaffs_PackedTags2TagsPart));
+            yaffs_PackedTags2 pt;
+            rv = cyg_nand_read_page(part, chunkInNAND, data, data ? dev->nDataBytesPerChunk : 0, &pt, tags ? PACKEDTAGS2_OOBSIZE : 0);
             if (tags)
-                yaffs_UnpackTags2TagsPart(tags, &pt);
+                yaffs_UnpackTags2(tags, &pt);
         }
 #endif
     }
--- a/packages/fs/yaffs/current/src/ecos-yaffs-nand.h
+++ b/packages/fs/yaffs/current/src/ecos-yaffs-nand.h
@@ -51,6 +51,10 @@
 #include "yaffs_guts.h" // extendedTags
 #include "devextras.h" // __u8 and __u32
 
+// If writing a yaffs_PackedTags1, we store only its eight meaningful bytes 
+#define PACKEDTAGS1_OOBSIZE 8
+#define PACKEDTAGS2_OOBSIZE sizeof(yaffs_PackedTags2)
+
 int eyaffs_eraseBlockInNAND (struct yaffs_DeviceStruct * dev, int blockInNAND);
 int eyaffs_initialiseNAND (struct yaffs_DeviceStruct * dev);
 // not mandatory:
--- a/packages/fs/yaffs/current/src/ecos-yaffs.c
+++ b/packages/fs/yaffs/current/src/ecos-yaffs.c
@@ -588,14 +588,26 @@ static int eyaffs_mount    ( cyg_fstab_e
     if (NAND_BYTES_PER_PAGE(nand) == 512) {
 #ifdef CYGSEM_FS_YAFFS_SMALLPAGE_MODE_YAFFS1
         y->isYaffs2 = 0;
+        if (NAND_APPSPARE_PER_PAGE(nand) < PACKEDTAGS1_OOBSIZE) {
+            NAND_ERROR(nand,
+                    "Device has %d spare per page but YAFFS1 needs %d\n",
+                    NAND_APPSPARE_PER_PAGE(nand), PACKEDTAGS1_OOBSIZE);
+            EG(EINVAL);
+        }
 #else // CYGSEM_FS_YAFFS_SMALLPAGE_MODE_YAFFS2
         y->isYaffs2 = 1;
         // 512-byte page devices normally have 8-byte spare areas.
-        // This isn't big enough for YAFFS2 tags, which need 16.
+        // This isn't big enough for YAFFS2 tags, which need 25.
         y->inbandTags = 1;
 #endif
     } else {
         y->isYaffs2 = 1;
+        if (NAND_APPSPARE_PER_PAGE(nand) < PACKEDTAGS2_OOBSIZE) {
+            NAND_ERROR(nand,
+                    "Device has %d spare per page but YAFFS2 needs %d\n",
+                    NAND_APPSPARE_PER_PAGE(nand), PACKEDTAGS2_OOBSIZE);
+            EG(EINVAL);
+        }
     }
 
 #ifdef CYGSEM_FS_YAFFS_OMIT_YAFFS2_CODE
@@ -605,15 +617,6 @@ static int eyaffs_mount    ( cyg_fstab_e
     }
 #endif
 
-    // Sanity check: can our tags fit?
-    // Devices with page size 512 bytes normally have 8 appspare bytes,
-    // which isn't enough; they have to use either inbandTags or YAFFS1 mode.
-#define y2tagsize (sizeof(yaffs_PackedTags2TagsPart))
-    if (y->isYaffs2 && !y->inbandTags && (NAND_APPSPARE_PER_PAGE(nand) < y2tagsize)) {
-        NAND_ERROR(nand, "Device has %d spare per page, which is insufficient (need %d)\n", NAND_SPARE_PER_PAGE(nand), y2tagsize);
-        EG(EINVAL);
-    }
-
     y->eraseBlockInNAND = eyaffs_eraseBlockInNAND;
     y->initialiseNAND = eyaffs_initialiseNAND;
     y->deinitialiseNAND = eyaffs_deinitialiseNAND;
--- a/packages/fs/yaffs/current/src/ecos-yaffs.h
+++ b/packages/fs/yaffs/current/src/ecos-yaffs.h
@@ -65,8 +65,9 @@
  * use YAFFS's: */
 #define CONFIG_YAFFS_PROVIDE_DEFS
 
-/* Our NAND layer does ECC, so we won't use YAFFS's: */
-#define YAFFS_IGNORE_TAGS_ECC
+/* Our NAND layer does ECC, so we won't use YAFFS's - but we do need
+ * to use its internal ECC on the tags */
+//#define YAFFS_IGNORE_TAGS_ECC
 //#define CONFIG_YAFFS_DOES_ECC
 //#define CONFIG_YAFFS_ECC_WRONG_ORDER
 
--- a/packages/fs/yaffs/current/src/yaffs_packedtags2.c
+++ b/packages/fs/yaffs/current/src/yaffs_packedtags2.c
@@ -15,6 +15,13 @@
 #include "yportenv.h"
 #include "yaffs_tagsvalidity.h"
 
+#if 0
+// Used in conjunction with RANDOMLY_LOSE mode on the synth nand driver to
+// demonstrate that it is behaving as intended.
+#define COUNT_ECC_TAG_FIXES
+unsigned yaffs_tag_ecc_fixes = 0;
+#endif
+
 /* This code packs a set of extended tags into a binary structure for
  * NAND storage
  */
@@ -157,7 +164,6 @@ void yaffs_UnpackTags2TagsPart(yaffs_Ext
 
 }
 
-
 void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
 {
 
@@ -184,6 +190,9 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
 				break;
 			case 1:
 				eccResult = YAFFS_ECC_RESULT_FIXED;
+#ifdef COUNT_ECC_TAG_FIXES
+                ++yaffs_tag_ecc_fixes;
+#endif
 				break;
 			case -1:
 				eccResult = YAFFS_ECC_RESULT_UNFIXED;
--- a/packages/fs/yaffs/current/src/yaffs_tagscompat.c
+++ b/packages/fs/yaffs/current/src/yaffs_tagscompat.c
@@ -59,7 +59,7 @@ int yaffs_CountBits(__u8 x)
 
 void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)
 { 
-#ifdef YAFFS_IGNORE_TAGS_ECC
+#if 1
     YBUG(); // Should never get here if configured out..
 #else
 	yaffs_ECCCalculate(data, spare->ecc1);
@@ -199,7 +199,7 @@ static int yaffs_ReadChunkFromNAND(struc
 	}
 
 	if (!dev->useNANDECC) {
-#ifdef YAFFS_IGNORE_TAGS_ECC
+#if 1
         YBUG();
 #else
 		retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare);