Mercurial > yaffs-ecoscentric
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);
