From 1f4c7592aae88726d6011da0d78698758d60b98e Mon Sep 17 00:00:00 2001 From: marty Date: Tue, 20 Sep 2005 22:46:17 +0000 Subject: [PATCH 01/16] Silly Marty, picked wrong guard for moduleconfig.h --- Makefile | 2 +- moduleconfig.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f9e7576..95bcf45 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ ifneq ($(KERNELRELEASE),) + EXTRA_CFLAGS += -DYAFFS_OUT_OF_TREE obj-m := yaffs2.o @@ -8,7 +9,6 @@ ifneq ($(KERNELRELEASE),) yaffs2-objs += yaffs_tagscompat.o yaffs_tagsvalidity.o else - KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) diff --git a/moduleconfig.h b/moduleconfig.h index a8684c3..2809701 100644 --- a/moduleconfig.h +++ b/moduleconfig.h @@ -1,7 +1,7 @@ #ifndef __YAFFS_CONFIG_H__ #define __YAFFS_CONFIG_H__ -#ifdef KBUILD_MODNAME +#ifdef YAFFS_OUT_OF_TREE #define CONFIG_YAFFS_FS #define CONFIG_YAFFS_YAFFS1 #define CONFIG_YAFFS_YAFFS2 -- 2.30.2 From ea7c7678c50a48bcb278e1233569f6a921dea0b5 Mon Sep 17 00:00:00 2001 From: charles Date: Tue, 20 Sep 2005 23:12:38 +0000 Subject: [PATCH 02/16] Improve ecc warnings --- yaffs_tagscompat.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/yaffs_tagscompat.c b/yaffs_tagscompat.c index 61880d5..2cf783e 100644 --- a/yaffs_tagscompat.c +++ b/yaffs_tagscompat.c @@ -10,7 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: yaffs_tagscompat.c,v 1.6 2005-08-11 02:33:03 marty Exp $ + * $Id: yaffs_tagscompat.c,v 1.7 2005-09-20 23:12:38 charles Exp $ */ #include "yaffs_guts.h" @@ -213,13 +213,13 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, if (eccResult1 > 0) { T(YAFFS_TRACE_ERROR, (TSTR - ("**>>ecc error fix performed on chunk %d:0" + ("**>>yaffs ecc error fix performed on chunk %d:0" TENDSTR), chunkInNAND)); dev->eccFixed++; } else if (eccResult1 < 0) { T(YAFFS_TRACE_ERROR, (TSTR - ("**>>ecc error unfixed on chunk %d:0" + ("**>>yaffs ecc error unfixed on chunk %d:0" TENDSTR), chunkInNAND)); dev->eccUnfixed++; } @@ -227,13 +227,13 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, if (eccResult2 > 0) { T(YAFFS_TRACE_ERROR, (TSTR - ("**>>ecc error fix performed on chunk %d:1" + ("**>>yaffs ecc error fix performed on chunk %d:1" TENDSTR), chunkInNAND)); dev->eccFixed++; } else if (eccResult2 < 0) { T(YAFFS_TRACE_ERROR, (TSTR - ("**>>ecc error unfixed on chunk %d:1" + ("**>>yaffs ecc error unfixed on chunk %d:1" TENDSTR), chunkInNAND)); dev->eccUnfixed++; } @@ -262,24 +262,24 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, if (nspare.eccres1 > 0) { T(YAFFS_TRACE_ERROR, (TSTR - ("**>>ecc error fix performed on chunk %d:0" + ("**>>mtd ecc error fix performed on chunk %d:0" TENDSTR), chunkInNAND)); } else if (nspare.eccres1 < 0) { T(YAFFS_TRACE_ERROR, (TSTR - ("**>>ecc error unfixed on chunk %d:0" + ("**>>mtd ecc error unfixed on chunk %d:0" TENDSTR), chunkInNAND)); } if (nspare.eccres2 > 0) { T(YAFFS_TRACE_ERROR, (TSTR - ("**>>ecc error fix performed on chunk %d:1" + ("**>>mtd ecc error fix performed on chunk %d:1" TENDSTR), chunkInNAND)); } else if (nspare.eccres2 < 0) { T(YAFFS_TRACE_ERROR, (TSTR - ("**>>ecc error unfixed on chunk %d:1" + ("**>>mtd ecc error unfixed on chunk %d:1" TENDSTR), chunkInNAND)); } -- 2.30.2 From 730a00c0527f2c63413598925b600af86b76db86 Mon Sep 17 00:00:00 2001 From: charles Date: Tue, 20 Sep 2005 23:14:14 +0000 Subject: [PATCH 03/16] Move comment --- yaffs_mtdif.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yaffs_mtdif.c b/yaffs_mtdif.c index 63f73f0..13cfdd9 100644 --- a/yaffs_mtdif.c +++ b/yaffs_mtdif.c @@ -14,7 +14,7 @@ */ const char *yaffs_mtdif_c_version = - "$Id: yaffs_mtdif.c,v 1.11 2005-09-20 05:23:41 charles Exp $"; + "$Id: yaffs_mtdif.c,v 1.12 2005-09-20 23:14:14 charles Exp $"; #include "yportenv.h" @@ -89,7 +89,8 @@ int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, __u8 *spareAsBytes = (__u8 *) spare; if (data && spare) { - if (dev->useNANDECC) { /* Careful, this call adds 2 ints */ + if (dev->useNANDECC) { + /* Careful, this call adds 2 ints */ /* to the end of the spare data. Calling function */ /* should allocate enough memory for spare, */ /* i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)]. */ -- 2.30.2 From ebbb972045bc371415021256d2a20c7b7af84457 Mon Sep 17 00:00:00 2001 From: charles Date: Wed, 21 Sep 2005 01:14:03 +0000 Subject: [PATCH 04/16] Fix problem introduced my mv over fix --- yaffs_fs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/yaffs_fs.c b/yaffs_fs.c index fcf111e..0a7c396 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -31,7 +31,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.30 2005-09-20 05:22:43 charles Exp $"; + "$Id: yaffs_fs.c,v 1.31 2005-09-21 01:14:03 charles Exp $"; extern const char *yaffs_guts_c_version; #include @@ -1133,8 +1133,10 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, yaffs_GrossUnlock(dev); if (retVal == YAFFS_OK) { - new_dentry->d_inode->i_nlink--; - mark_inode_dirty(new_dentry->d_inode); + if(target) { + new_dentry->d_inode->i_nlink--; + mark_inode_dirty(new_dentry->d_inode); + } return 0; } else { -- 2.30.2 From 831a8e85fb344ae8ef092fe12627e518d63fc009 Mon Sep 17 00:00:00 2001 From: marty Date: Wed, 21 Sep 2005 15:16:59 +0000 Subject: [PATCH 05/16] Added some documentation to moduleconfig.h and set it to match the Kconfig defaults. Updated Kconfig to force selection of YAFFS1 and YAFFS2 for now, until we straighten out the ifdefs so that one can be built when the other isn't. --- Kconfig | 2 ++ moduleconfig.h | 24 +++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Kconfig b/Kconfig index deb1c47..da516dd 100644 --- a/Kconfig +++ b/Kconfig @@ -5,6 +5,8 @@ config YAFFS_FS tristate "YAFFS2 file system support" default n + select YAFFS_YAFFS1 + select YAFFS_YAFFS2 help YAFFS2, or Yet Another Flash Filing System, is a filing system optimised for NAND Flash chips. diff --git a/moduleconfig.h b/moduleconfig.h index 2809701..e67c7bc 100644 --- a/moduleconfig.h +++ b/moduleconfig.h @@ -2,13 +2,31 @@ #define __YAFFS_CONFIG_H__ #ifdef YAFFS_OUT_OF_TREE + +/* DO NOT UNSET THESE THREE. YAFFS2 will not compile if you do. */ #define CONFIG_YAFFS_FS #define CONFIG_YAFFS_YAFFS1 #define CONFIG_YAFFS_YAFFS2 -#define CONFIG_YAFFS_DOES_ECC -#define CONFIG_YAFFS_ECC_WRONG_ORDER + +/* These options are independent of each other. Select those that matter. */ + +/* Default: Not selected */ +/* Meaning: Yaffs does its own ECC, rather than using MTD ECC */ +//#define CONFIG_YAFFS_DOES_ECC + +/* Default: Not selected */ +/* Meaning: ECC byte order is 'wrong'. Only meaningful if */ +/* CONFIG_YAFFS_DOES_ECC is set */ +//#define CONFIG_YAFFS_ECC_WRONG_ORDER + +/* Default: Selected */ +/* Meaning: Disables testing whether chunks are erased before writing to them*/ #define CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK + +/* Default: Selected */ +/* Meaning: Cache short names, taking more RAM, but faster look-ups */ #define CONFIG_YAFFS_SHORT_NAMES_IN_RAM -#endif /* KBUILD_MODNAME */ + +#endif /* YAFFS_OUT_OF_TREE */ #endif /* __YAFFS_CONFIG_H__ */ -- 2.30.2 From 64239466cac1b316650213aaa07c92f57c3e7861 Mon Sep 17 00:00:00 2001 From: charles Date: Fri, 7 Oct 2005 02:46:49 +0000 Subject: [PATCH 06/16] Add support for vmallocing large blockInfos --- yaffs_guts.c | 15 +++++++++++++-- yaffs_guts.h | 3 ++- yportenv.h | 7 ++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/yaffs_guts.c b/yaffs_guts.c index 90aba83..eafbaa9 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -13,7 +13,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.19 2005-09-20 05:08:50 charles Exp $"; + "$Id: yaffs_guts.c,v 1.20 2005-10-07 02:46:49 charles Exp $"; #include "yportenv.h" @@ -1747,6 +1747,12 @@ static int yaffs_InitialiseBlocks(yaffs_Device * dev, int nBlocks) /* Todo we're assuming the malloc will pass. */ dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); + if(!dev->blockInfo){ + dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo)); + dev->blockInfoAlt = 1; + } + else + dev->blockInfoAlt = 0; /* Set up dynamic blockinfo stuff. */ dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; @@ -1763,7 +1769,12 @@ static int yaffs_InitialiseBlocks(yaffs_Device * dev, int nBlocks) static void yaffs_DeinitialiseBlocks(yaffs_Device * dev) { - YFREE(dev->blockInfo); + if(dev->blockInfoAlt) + YFREE_ALT(dev->blockInfo); + else + YFREE(dev->blockInfo); + dev->blockInfoAlt = 0; + dev->blockInfo = NULL; YFREE(dev->chunkBits); dev->chunkBits = NULL; diff --git a/yaffs_guts.h b/yaffs_guts.h index 535a269..c5eee97 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -14,7 +14,7 @@ * * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. * - * $Id: yaffs_guts.h,v 1.14 2005-09-20 05:05:40 charles Exp $ + * $Id: yaffs_guts.h,v 1.15 2005-10-07 02:46:50 charles Exp $ */ #ifndef __YAFFS_GUTS_H__ @@ -561,6 +561,7 @@ struct yaffs_DeviceStruct { /* Block Info */ yaffs_BlockInfo *blockInfo; + int blockInfoAlt; /* was allocated using alternative strategy */ __u8 *chunkBits; /* bitmap of chunks in use */ int chunkBitmapStride; /* Number of bytes of chunkBits per block. * Must be consistent with nChunksPerBlock. diff --git a/yportenv.h b/yportenv.h index 0543383..240b6b9 100644 --- a/yportenv.h +++ b/yportenv.h @@ -15,7 +15,7 @@ * * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. * - * $Id: yportenv.h,v 1.8 2005-09-18 05:31:26 marty Exp $ + * $Id: yportenv.h,v 1.9 2005-10-07 02:46:50 charles Exp $ * */ @@ -37,6 +37,7 @@ #include #include #include +#include #define YCHAR char #define YUCHAR unsigned char @@ -55,6 +56,8 @@ /* #define YPRINTF(x) printk x */ #define YMALLOC(x) kmalloc(x,GFP_KERNEL) #define YFREE(x) kfree(x) +#define YMALLOC_ALT(x) vmalloc(x) +#define YFREE_ALT(x) vfree(x) #define YAFFS_ROOT_MODE 0666 #define YAFFS_LOSTNFOUND_MODE 0666 @@ -91,6 +94,8 @@ #define YMALLOC(x) malloc(x) #define YFREE(x) free(x) +#define YMALLOC_ALT(x) malloc(x) +#define YFREE_ALT(x) free(x) #define YCHAR char #define YUCHAR unsigned char -- 2.30.2 From f67d10d7a5a6d1cc7d1cb6eaada2522873ce5e99 Mon Sep 17 00:00:00 2001 From: charles Date: Fri, 7 Oct 2005 03:48:50 +0000 Subject: [PATCH 07/16] Improve YDI lookup and device prefic handling --- direct/dtest.c | 138 ++++++++++++++++++++++++++++++++++++++++---- direct/yaffscfg2k.c | 11 +++- direct/yaffsfs.c | 32 +++++++--- direct/ydirectenv.h | 4 +- 4 files changed, 163 insertions(+), 22 deletions(-) diff --git a/direct/dtest.c b/direct/dtest.c index 096ea7e..3679b25 100644 --- a/direct/dtest.c +++ b/direct/dtest.c @@ -855,6 +855,30 @@ int yaffs_scan_test(const char *path) } +void rename_over_test(const char *mountpt) +{ + int i; + char a[100]; + char b[100]; + + sprintf(a,"%s/a",mountpt); + sprintf(b,"%s/b",mountpt); + + yaffs_StartUp(); + + yaffs_mount(mountpt); + i = yaffs_open(a,O_CREAT | O_TRUNC | O_RDWR, 0); + yaffs_close(i); + i = yaffs_open(b,O_CREAT | O_TRUNC | O_RDWR, 0); + yaffs_close(i); + yaffs_rename(a,b); // rename over + yaffs_rename(b,a); // rename back again (not renaimng over) + yaffs_rename(a,b); // rename back again (not renaimng over) + + + yaffs_unmount(mountpt); + +} int resize_stress_test(const char *path) { @@ -1256,28 +1280,117 @@ void fill_disk_test(const char *mountpt) } -void rename_over_test(const char *mountpt) + + +void lookup_test(const char *mountpt) { int i; + int h; char a[100]; char b[100]; - sprintf(a,"%s/a",mountpt); - sprintf(b,"%s/b",mountpt); + + yaffs_DIR *d; + yaffs_dirent *de; + struct yaffs_stat s; + char str[100]; + + yaffs_StartUp(); + + yaffs_mount(mountpt); + + d = yaffs_opendir(mountpt); + + if(!d) + { + printf("opendir failed\n"); + } + else + { + + for(i = 0; (de = yaffs_readdir(d)) != NULL; i++) + { + printf("unlinking %s\n",de->d_name); + yaffs_unlink(de->d_name); + } + + printf("%d files deleted\n",i); + } + + + for(i = 0; i < 2000; i++){ + sprintf(a,"%s/%d",mountpt,i); + h = yaffs_open(a,O_CREAT | O_TRUNC | O_RDWR, 0); + yaffs_close(h); + } + + yaffs_rewinddir(d); + for(i = 0; (de = yaffs_readdir(d)) != NULL; i++) + { + printf("%d %s\n",i,de->d_name); + } + + printf("%d files listed\n\n\n",i); + + yaffs_rewinddir(d); + yaffs_readdir(d); + yaffs_readdir(d); + yaffs_readdir(d); + + for(i = 0; i < 2000; i++){ + sprintf(a,"%s/%d",mountpt,i); + yaffs_unlink(a); + } + + + yaffs_unmount(mountpt); + +} + +void freespace_test(const char *mountpt) +{ + int i; + int h; + char a[100]; + char b[100]; + + int f0; + int f1; + int f2; + int f3; + sprintf(a,"%s/aaa",mountpt); yaffs_StartUp(); yaffs_mount(mountpt); - i = yaffs_open(a,O_CREAT | O_TRUNC | O_RDWR, 0); - yaffs_close(i); - i = yaffs_open(b,O_CREAT | O_TRUNC | O_RDWR, 0); - yaffs_close(i); - yaffs_rename(a,b); + f0 = yaffs_freespace(mountpt); + + h = yaffs_open(a, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); + + for(i = 0; i < 100; i++) + yaffs_write(h,a,100); + + yaffs_close(h); + + f1 = yaffs_freespace(mountpt); + + yaffs_unlink(a); + + f2 = yaffs_freespace(mountpt); + yaffs_unmount(mountpt); + yaffs_mount(mountpt); + + f3 = yaffs_freespace(mountpt); + + printf("%d\n%d\n%d\n%d\n",f0, f1,f2,f3); + } + + void scan_deleted_files_test(const char *mountpt) { char fn[100]; @@ -1380,9 +1493,9 @@ void write_200k_file(const char *fn, const char *fdel, const char *fdel1) yaffs_unlink(fdel1); - } + void verify_200k_file(const char *fn) { int h1; @@ -1401,8 +1514,7 @@ void verify_200k_file(const char *fn) } } - yaffs_close(h1); - + yaffs_close(h1); } @@ -1462,7 +1574,9 @@ int main(int argc, char *argv[]) //long_test_on_path("/ram2k"); // long_test_on_path("/flash"); //fill_disk_test("/flash"); - rename_over_test("/flash"); + // rename_over_test("/flash"); + //lookup_test("/flash"); + freespace_test("/flash"); diff --git a/direct/yaffscfg2k.c b/direct/yaffscfg2k.c index 9c45524..e63411a 100644 --- a/direct/yaffscfg2k.c +++ b/direct/yaffscfg2k.c @@ -59,12 +59,19 @@ static yaffs_Device flashDev; static yaffs_Device ram2kDev; static yaffsfs_DeviceConfiguration yaffsfs_config[] = { - +#if 0 { "/ram", &ramDev}, { "/boot", &bootDev}, - { "/flash", &flashDev}, + { "/flash/", &flashDev}, + { "/ram2k", &ram2kDev}, + {(void *)0,(void *)0} +#else + { "/", &ramDev}, + { "/flash/boot", &bootDev}, + { "/flash/", &flashDev}, { "/ram2k", &ram2kDev}, {(void *)0,(void *)0} +#endif }; diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index 956df2c..4f06f9c 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -25,7 +25,7 @@ #endif -const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.6 2005-09-20 05:05:40 charles Exp $"; +const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.7 2005-10-07 03:48:50 charles Exp $"; // configurationList is the list of devices that are supported static yaffsfs_DeviceConfiguration *yaffsfs_configurationList; @@ -144,30 +144,47 @@ int yaffsfs_Match(char a, char b) // yaffsfs_FindDevice // yaffsfs_FindRoot // Scan the configuration list to find the root. +// Curveballs: Should match paths that end in '/' too +// Curveball2 Might have "/x/ and "/x/y". Need to return the longest match static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath) { yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList; const char *leftOver; const char *p; + yaffs_Device *retval = NULL; + int thisMatchLength; + int longestMatch = -1; + // Check all configs, choose the one that: + // 1) Actually matches a prefix (ie /a amd /abc will not match + // 2) Matches the longest. while(cfg && cfg->prefix && cfg->dev) { leftOver = path; p = cfg->prefix; - while(*p && *leftOver && yaffsfs_Match(*p,*leftOver)) + thisMatchLength = 0; + + while(*p && //unmatched part of prefix + strcmp(p,"/") && // the rest of the prefix is not / (to catch / at end) + *leftOver && + yaffsfs_Match(*p,*leftOver)) { p++; leftOver++; + thisMatchLength++; } - if(!*p && (!*leftOver || *leftOver == '/')) + if((!*p || strcmp(p,"/") == 0) && // end of prefix + (!*leftOver || *leftOver == '/') && // no more in this path name part + (thisMatchLength > longestMatch)) { // Matched prefix *restOfPath = (char *)leftOver; - return cfg->dev; + retval = cfg->dev; + longestMatch = thisMatchLength; } cfg++; } - return NULL; + return retval; } static yaffs_Object *yaffsfs_FindRoot(const char *path, char **restOfPath) @@ -1250,8 +1267,9 @@ yaffs_DIR *yaffs_opendir(const char *dirname) dir = (yaffs_DIR *)dsc; if(dsc) { + memset(dsc,0,sizeof(yaffsfs_DirectorySearchContext)); dsc->magic = YAFFS_MAGIC; - memset(dsc->name,0,NAME_MAX+1); + dsc->dirObj = obj; strncpy(dsc->name,dirname,NAME_MAX); INIT_LIST_HEAD(&dsc->others); @@ -1259,7 +1277,7 @@ yaffs_DIR *yaffs_opendir(const char *dirname) INIT_LIST_HEAD(&search_contexts); list_add(&dsc->others,&search_contexts); - } + yaffsfs_SetDirRewound(dsc); } } diff --git a/direct/ydirectenv.h b/direct/ydirectenv.h index 2b39af5..561c8b5 100644 --- a/direct/ydirectenv.h +++ b/direct/ydirectenv.h @@ -14,7 +14,7 @@ * * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. * - * $Id: ydirectenv.h,v 1.1 2005-07-03 05:48:11 charles Exp $ + * $Id: ydirectenv.h,v 1.2 2005-10-07 03:48:50 charles Exp $ * */ @@ -43,6 +43,8 @@ #define YMALLOC(x) malloc(x) #define YFREE(x) free(x) +#define YMALLOC_ALT(x) malloc(x) +#define YFREE_ALT(x) free(x) //#define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s)) -- 2.30.2 From 56f93d87556bc0802ea8d5b080d9e8265bc4e9c1 Mon Sep 17 00:00:00 2001 From: charles Date: Sun, 9 Oct 2005 07:55:00 +0000 Subject: [PATCH 08/16] Use vmalloc for large memory allocations --- yaffs_guts.c | 16 ++++++++++++++-- yaffs_guts.h | 5 +++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/yaffs_guts.c b/yaffs_guts.c index eafbaa9..4783f85 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -13,7 +13,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.20 2005-10-07 02:46:49 charles Exp $"; + "$Id: yaffs_guts.c,v 1.21 2005-10-09 07:55:00 charles Exp $"; #include "yportenv.h" @@ -1757,6 +1757,13 @@ static int yaffs_InitialiseBlocks(yaffs_Device * dev, int nBlocks) /* Set up dynamic blockinfo stuff. */ dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); + if(!dev->chunkBits){ + dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); + dev->chunkBitsAlt = 1; + } + else + dev->chunkBitsAlt = 0; + if (dev->blockInfo && dev->chunkBits) { memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo)); memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks); @@ -1776,7 +1783,12 @@ static void yaffs_DeinitialiseBlocks(yaffs_Device * dev) dev->blockInfoAlt = 0; dev->blockInfo = NULL; - YFREE(dev->chunkBits); + + if(dev->chunkBitsAlt) + YFREE_ALT(dev->chunkBits); + else + YFREE(dev->chunkBits); + dev->chunkBitsAlt = 0; dev->chunkBits = NULL; } diff --git a/yaffs_guts.h b/yaffs_guts.h index c5eee97..73375cc 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -14,7 +14,7 @@ * * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. * - * $Id: yaffs_guts.h,v 1.15 2005-10-07 02:46:50 charles Exp $ + * $Id: yaffs_guts.h,v 1.16 2005-10-09 07:55:00 charles Exp $ */ #ifndef __YAFFS_GUTS_H__ @@ -561,8 +561,9 @@ struct yaffs_DeviceStruct { /* Block Info */ yaffs_BlockInfo *blockInfo; - int blockInfoAlt; /* was allocated using alternative strategy */ __u8 *chunkBits; /* bitmap of chunks in use */ + unsigned blockInfoAlt:1; /* was allocated using alternative strategy */ + unsigned chunkBitsAlt:1; /* was allocated using alternative strategy */ int chunkBitmapStride; /* Number of bytes of chunkBits per block. * Must be consistent with nChunksPerBlock. */ -- 2.30.2 From 5fa110bde8233848e86ee328fe8082835becb025 Mon Sep 17 00:00:00 2001 From: charles Date: Thu, 13 Oct 2005 02:17:00 +0000 Subject: [PATCH 09/16] Throw out obsolete code --- yaffs_guts.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/yaffs_guts.c b/yaffs_guts.c index 4783f85..8a07775 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -13,7 +13,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.21 2005-10-09 07:55:00 charles Exp $"; + "$Id: yaffs_guts.c,v 1.22 2005-10-13 02:17:00 charles Exp $"; #include "yportenv.h" @@ -2660,14 +2660,6 @@ void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn) if (markNAND && bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->isYaffs2) { -#ifdef CONFIG_MTD_NAND_VERIFY_WRITE - - /* Read data before write, to ensure correct ecc - * if we're using MTD verification under Linux - */ - yaffs_ReadChunkFromNAND(dev, chunkId, NULL, &spare, 0); -#endif - yaffs_InitialiseTags(&tags); tags.chunkDeleted = 1; -- 2.30.2 From 070b41d99c4b50000f05a89e1e71882b7387810e Mon Sep 17 00:00:00 2001 From: marty Date: Thu, 27 Oct 2005 07:22:49 +0000 Subject: [PATCH 10/16] Patch from Todd Poyner (tpoynor@mvista.com) Return zero, not number of bytes written, for success (and non-zero for error) in the commit_write method. Some callers, notably the loopback mount driver, treat non-zero return as an error. --- yaffs_fs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/yaffs_fs.c b/yaffs_fs.c index 0a7c396..873de3e 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -31,7 +31,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.31 2005-09-21 01:14:03 charles Exp $"; + "$Id: yaffs_fs.c,v 1.32 2005-10-27 07:22:49 marty Exp $"; extern const char *yaffs_guts_c_version; #include @@ -604,9 +604,10 @@ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, } T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_commit_write returning %d\n", nWritten)); + (KERN_DEBUG "yaffs_commit_write returning %d\n", + nWritten == nBytes ? 0 : -1)); - return nWritten; + return nWritten == nBytes ? 0 : -1; } -- 2.30.2 From 549731ddfef7956f9c11c87697be04a075af953b Mon Sep 17 00:00:00 2001 From: marty Date: Thu, 27 Oct 2005 22:24:04 +0000 Subject: [PATCH 11/16] Patch from Sergey Kubushyn [ksi@koi8.net] Fix yaffs to return EINVALID rather than EPERM when mount fails. --- yaffs_fs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yaffs_fs.c b/yaffs_fs.c index 873de3e..14fd0b8 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -31,7 +31,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.32 2005-10-27 07:22:49 marty Exp $"; + "$Id: yaffs_fs.c,v 1.33 2005-10-27 22:24:04 marty Exp $"; extern const char *yaffs_guts_c_version; #include @@ -1493,7 +1493,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, int silent) { - return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -1; + return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL; } static struct super_block *yaffs_read_super(struct file_system_type *fs, @@ -1530,7 +1530,7 @@ static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, int silent) { - return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -1; + return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL; } static struct super_block *yaffs2_read_super(struct file_system_type *fs, -- 2.30.2 From afa20b9f76da4dfb1a0759ffdbedf61933f7d139 Mon Sep 17 00:00:00 2001 From: charles Date: Wed, 2 Nov 2005 06:45:24 +0000 Subject: [PATCH 12/16] Add first cut mkyaffs2image util --- utils/Makefile | 46 ++++ utils/mkyaffs2image.c | 522 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 568 insertions(+) create mode 100644 utils/Makefile create mode 100644 utils/mkyaffs2image.c diff --git a/utils/Makefile b/utils/Makefile new file mode 100644 index 0000000..5c1ee41 --- /dev/null +++ b/utils/Makefile @@ -0,0 +1,46 @@ +#Makefile for mkyaffs +# +# NB this is not yet suitable for putting into the kernel tree. +# YAFFS: Yet another FFS. A NAND-flash specific file system. +# +# Copyright (C) 2002 Aleph One Ltd. +# for Toby Churchill Ltd and Brightstar Engineering +# +# Created by Charles Manning +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. + +## Change or override KERNELDIR to your kernel + +#KERNELDIR = /usr/src/kernel-headers-2.4.18 + +CFLAGS = -I/usr/include -I.. -O2 -Wall -DCONFIG_YAFFS_UTIL +CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations +CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline + +## Change if you are using a cross-compiler +MAKETOOLS = + +CC=$(MAKETOOLS)gcc + +MKYAFFS2SOURCES = mkyaffs2image.c +MKYAFFS2LINKS = yaffs_ecc.c yaffs_packedtags2.c yaffs_tagsvalidity.c + +MKYAFFS2IMAGEOBJS = $(MKYAFFS2SOURCES:.c=.o) $(MKYAFFS2LINKS:.c=.o) + +all: mkyaffs2image + +$(MKYAFFS2IMAGEOBJS): %.o: %.c + $(CC) -c $(CFLAGS) $< -o $@ + +mkyaffs2image: $(MKYAFFS2IMAGEOBJS) + $(CC) -o $@ $(MKYAFFS2IMAGEOBJS) + +$(MKYAFFS2LINKS): + ln -s ../$@ $@ + + +clean: + rm -f $(MKYAFFS2IMAGEOBJS) core diff --git a/utils/mkyaffs2image.c b/utils/mkyaffs2image.c new file mode 100644 index 0000000..7649492 --- /dev/null +++ b/utils/mkyaffs2image.c @@ -0,0 +1,522 @@ +/* + * YAFFS: Yet another FFS. A NAND-flash specific file system. + * + * makeyaffsimage.c + * + * Makes a YAFFS file system image that can be used to load up a file system. + * + * Copyright (C) 2002 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * + * Nick Bane modifications flagged NCB + * + * Endian handling patches by James Ng. + * + * mkyaffs2image hacks by NCB + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "yaffs_ecc.h" +#include "yaffs_guts.h" + +#include "yaffs_tagsvalidity.h" +#include "yaffs_packedtags2.h" + +unsigned yaffs_traceMask=0; + +#define MAX_OBJECTS 10000 + +#define chunkSize 2048 +#define spareSize 64 + +const char * mkyaffsimage_c_version = "$Id: mkyaffs2image.c,v 1.1 2005-11-02 06:45:24 charles Exp $"; + + +typedef struct +{ + dev_t dev; + ino_t ino; + int obj; +} objItem; + + +static objItem obj_list[MAX_OBJECTS]; +static int n_obj = 0; +static int obj_id = YAFFS_NOBJECT_BUCKETS + 1; + +static int nObjects, nDirectories, nPages; + +static int outFile; + +static int error; + +static int convert_endian = 0; + +static int obj_compare(const void *a, const void * b) +{ + objItem *oa, *ob; + + oa = (objItem *)a; + ob = (objItem *)b; + + if(oa->dev < ob->dev) return -1; + if(oa->dev > ob->dev) return 1; + if(oa->ino < ob->ino) return -1; + if(oa->ino > ob->ino) return 1; + + return 0; +} + + +static void add_obj_to_list(dev_t dev, ino_t ino, int obj) +{ + if(n_obj < MAX_OBJECTS) + { + obj_list[n_obj].dev = dev; + obj_list[n_obj].ino = ino; + obj_list[n_obj].obj = obj; + n_obj++; + qsort(obj_list,n_obj,sizeof(objItem),obj_compare); + + } + else + { + // oops! not enough space in the object array + fprintf(stderr,"Not enough space in object array\n"); + exit(2); + } +} + + +static int find_obj_in_list(dev_t dev, ino_t ino) +{ + objItem *i = NULL; + objItem test; + + test.dev = dev; + test.ino = ino; + + if(n_obj > 0) + { + i = bsearch(&test,obj_list,n_obj,sizeof(objItem),obj_compare); + } + + if(i) + { + return i->obj; + } + return -1; +} + +/* This little function converts a little endian tag to a big endian tag. + * NOTE: The tag is not usable after this other than calculating the CRC + * with. + */ +static void little_to_big_endian(yaffs_Tags *tagsPtr) +{ +#if 0 // FIXME NCB + yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes. + yaffs_TagsUnion temp; + + memset(&temp, 0, sizeof(temp)); + // Ick, I hate magic numbers. + temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4); + temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4); + temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6); + temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6); + temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2); + temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2); + temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F); + temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6); + + // Now copy it back. + tags->asBytes[0] = temp.asBytes[0]; + tags->asBytes[1] = temp.asBytes[1]; + tags->asBytes[2] = temp.asBytes[2]; + tags->asBytes[3] = temp.asBytes[3]; + tags->asBytes[4] = temp.asBytes[4]; + tags->asBytes[5] = temp.asBytes[5]; + tags->asBytes[6] = temp.asBytes[6]; + tags->asBytes[7] = temp.asBytes[7]; +#endif +} + +static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) +{ + yaffs_ExtendedTags t; + yaffs_PackedTags2 pt; + + error = write(outFile,data,chunkSize); + if(error < 0) return error; + + yaffs_InitialiseTags(&t); + + t.chunkId = chunkId; +// t.serialNumber = 0; + t.serialNumber = 1; // **CHECK** + t.byteCount = nBytes; + t.objectId = objId; + + t.sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; + +// added NCB **CHECK** + t.chunkUsed = 1; + + if (convert_endian) + { + little_to_big_endian(&t); + } + + nPages++; + + yaffs_PackTags2(&pt,&t); + +// return write(outFile,&pt,sizeof(yaffs_PackedTags2)); + return write(outFile,&pt,spareSize); + +} + +#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \ + (((x) & 0x0000FF00) << 8 ) | \ + (((x) & 0x00FF0000) >> 8 ) | \ + (((x) & 0xFF000000) >> 24)) + +#define SWAP16(x) ((((x) & 0x00FF) << 8) | \ + (((x) & 0xFF00) >> 8)) + +// This one is easier, since the types are more standard. No funky shifts here. +static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh) +{ + oh->type = SWAP32(oh->type); // GCC makes enums 32 bits. + oh->parentObjectId = SWAP32(oh->parentObjectId); // int + oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness. + // name = skip. Char array. Not swapped. + oh->yst_mode = SWAP32(oh->yst_mode); +#ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case. + // In fact, WinCE would be *THE* place where this would be an issue! + oh->notForWinCE[0] = SWAP32(oh->notForWinCE[0]); + oh->notForWinCE[1] = SWAP32(oh->notForWinCE[1]); + oh->notForWinCE[2] = SWAP32(oh->notForWinCE[2]); + oh->notForWinCE[3] = SWAP32(oh->notForWinCE[3]); + oh->notForWinCE[4] = SWAP32(oh->notForWinCE[4]); +#else + // Regular POSIX. + oh->yst_uid = SWAP32(oh->yst_uid); + oh->yst_gid = SWAP32(oh->yst_gid); + oh->yst_atime = SWAP32(oh->yst_atime); + oh->yst_mtime = SWAP32(oh->yst_mtime); + oh->yst_ctime = SWAP32(oh->yst_ctime); +#endif + + oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that! + oh->equivalentObjectId = SWAP32(oh->equivalentObjectId); + // alias - char array. + oh->yst_rdev = SWAP32(oh->yst_rdev); + +#ifdef CONFIG_YAFFS_WINCE + oh->win_ctime[0] = SWAP32(oh->win_ctime[0]); + oh->win_ctime[1] = SWAP32(oh->win_ctime[1]); + oh->win_atime[0] = SWAP32(oh->win_atime[0]); + oh->win_atime[1] = SWAP32(oh->win_atime[1]); + oh->win_mtime[0] = SWAP32(oh->win_mtime[0]); + oh->win_mtime[1] = SWAP32(oh->win_mtime[1]); + oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); + oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); + oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); + oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); + oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); + oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); +#else + oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); + oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); + oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); + oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); + oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); + oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); + oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]); + oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]); + oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]); + oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]); + oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]); + oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]); +#endif +} + +static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias) +{ + __u8 bytes[chunkSize]; + + + yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes; + + memset(bytes,0xff,sizeof(bytes)); + + oh->type = t; + + oh->parentObjectId = parent; + + strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH); + + + if(t != YAFFS_OBJECT_TYPE_HARDLINK) + { + oh->yst_mode = s->st_mode; + oh->yst_uid = s->st_uid; +// NCB 12/9/02 oh->yst_gid = s->yst_uid; + oh->yst_gid = s->st_gid; + oh->yst_atime = s->st_atime; + oh->yst_mtime = s->st_mtime; + oh->yst_ctime = s->st_ctime; + oh->yst_rdev = s->st_rdev; + } + + if(t == YAFFS_OBJECT_TYPE_FILE) + { + oh->fileSize = s->st_size; + } + + if(t == YAFFS_OBJECT_TYPE_HARDLINK) + { + oh->equivalentObjectId = equivalentObj; + } + + if(t == YAFFS_OBJECT_TYPE_SYMLINK) + { + strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH); + } + + if (convert_endian) + { + object_header_little_to_big_endian(oh); + } + + return write_chunk(bytes,objId,0,0xffff); + +} + + +static int process_directory(int parent, const char *path) +{ + + DIR *dir; + struct dirent *entry; + + nDirectories++; + + dir = opendir(path); + + if(dir) + { + while((entry = readdir(dir)) != NULL) + { + + /* Ignore . and .. */ + if(strcmp(entry->d_name,".") && + strcmp(entry->d_name,"..")) + { + char full_name[500]; + struct stat stats; + int equivalentObj; + int newObj; + + sprintf(full_name,"%s/%s",path,entry->d_name); + + lstat(full_name,&stats); + + if(S_ISLNK(stats.st_mode) || + S_ISREG(stats.st_mode) || + S_ISDIR(stats.st_mode) || + S_ISFIFO(stats.st_mode) || + S_ISBLK(stats.st_mode) || + S_ISCHR(stats.st_mode) || + S_ISSOCK(stats.st_mode)) + { + + newObj = obj_id++; + nObjects++; + + printf("Object %d, %s is a ",newObj,full_name); + + /* We're going to create an object for it */ + if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0) + { + /* we need to make a hard link */ + printf("hard link to object %d\n",equivalentObj); + error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL); + } + else + { + + add_obj_to_list(stats.st_dev,stats.st_ino,newObj); + + if(S_ISLNK(stats.st_mode)) + { + + char symname[500]; + + memset(symname,0, sizeof(symname)); + + readlink(full_name,symname,sizeof(symname) -1); + + printf("symlink to \"%s\"\n",symname); + error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); + + } + else if(S_ISREG(stats.st_mode)) + { + printf("file, "); + error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL); + + if(error >= 0) + { + int h; + __u8 bytes[chunkSize]; + int nBytes; + int chunk = 0; + + h = open(full_name,O_RDONLY); + if(h >= 0) + { + memset(bytes,0xff,sizeof(bytes)); + while((nBytes = read(h,bytes,sizeof(bytes))) > 0) + { + chunk++; + write_chunk(bytes,newObj,chunk,nBytes); + memset(bytes,0xff,sizeof(bytes)); + } + if(nBytes < 0) + error = nBytes; + + printf("%d data chunks written\n",chunk); + } + else + { + perror("Error opening file"); + } + close(h); + + } + + } + else if(S_ISSOCK(stats.st_mode)) + { + printf("socket\n"); + error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); + } + else if(S_ISFIFO(stats.st_mode)) + { + printf("fifo\n"); + error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); + } + else if(S_ISCHR(stats.st_mode)) + { + printf("character device\n"); + error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); + } + else if(S_ISBLK(stats.st_mode)) + { + printf("block device\n"); + error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); + } + else if(S_ISDIR(stats.st_mode)) + { + printf("directory\n"); + error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL); +// NCB modified 10/9/2001 process_directory(1,full_name); + process_directory(newObj,full_name); + } + } + } + else + { + printf(" we don't handle this type\n"); + } + } + } + } + + return 0; + +} + + +int main(int argc, char *argv[]) +{ + struct stat stats; + + printf("mkyaffs2image: image building tool for YAFFS2 built "__DATE__"\n"); + + if(argc <= 3) + { + printf("usage: mkyaffs2image dir image_file [convert]\n"); + printf(" dir the directory tree to be converted\n"); + printf(" image_file the output file to hold the image\n"); + printf(" 'convert' produce a big-endian image from a little-endian machine\n"); + exit(1); + } + + if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert")))) + { + convert_endian = 1; + } + + if(stat(argv[1],&stats) < 0) + { + printf("Could not stat %s\n",argv[1]); + exit(1); + } + + if(!S_ISDIR(stats.st_mode)) + { + printf(" %s is not a directory\n",argv[1]); + exit(1); + } + + outFile = open(argv[2],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE); + + + if(outFile < 0) + { + printf("Could not open output file %s\n",argv[2]); + exit(1); + } + + printf("Processing directory %s into image file %s\n",argv[1],argv[2]); + error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL); + if(error) + error = process_directory(YAFFS_OBJECTID_ROOT,argv[1]); + + close(outFile); + + if(error < 0) + { + perror("operation incomplete"); + exit(1); + } + else + { + printf("Operation complete.\n" + "%d objects in %d directories\n" + "%d NAND pages\n",nObjects, nDirectories, nPages); + } + + close(outFile); + + exit(0); +} + -- 2.30.2 From af78eb35ef155fedf68b5ec3d99fbe195b0ac7c8 Mon Sep 17 00:00:00 2001 From: charles Date: Mon, 7 Nov 2005 07:13:33 +0000 Subject: [PATCH 13/16] Remove kernel version test --- yaffs_mtdif.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/yaffs_mtdif.c b/yaffs_mtdif.c index 13cfdd9..7dbf07a 100644 --- a/yaffs_mtdif.c +++ b/yaffs_mtdif.c @@ -14,7 +14,7 @@ */ const char *yaffs_mtdif_c_version = - "$Id: yaffs_mtdif.c,v 1.12 2005-09-20 23:14:14 charles Exp $"; + "$Id: yaffs_mtdif.c,v 1.13 2005-11-07 07:13:33 charles Exp $"; #include "yportenv.h" @@ -28,9 +28,7 @@ const char *yaffs_mtdif_c_version = static struct nand_oobinfo yaffs_oobinfo = { .useecc = 1, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)) .eccbytes = 6, -#endif .eccpos = {8, 9, 10, 13, 14, 15} }; -- 2.30.2 From 600cb55e4d937dd1f61d596b49a58ef11ddc01c9 Mon Sep 17 00:00:00 2001 From: charles Date: Mon, 7 Nov 2005 07:19:34 +0000 Subject: [PATCH 14/16] Change tracing flags --- yaffs_guts.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yaffs_guts.c b/yaffs_guts.c index 8a07775..1f36cea 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -13,7 +13,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.22 2005-10-13 02:17:00 charles Exp $"; + "$Id: yaffs_guts.c,v 1.23 2005-11-07 07:19:34 charles Exp $"; #include "yportenv.h" @@ -5325,7 +5325,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) int extraBits; int nBlocks; - T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR))); + T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR))); /* Check stuff that must be set */ @@ -5528,7 +5528,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) yaffs_VerifyFreeChunks(dev); - T(YAFFS_TRACE_ALWAYS, + T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); return YAFFS_OK; -- 2.30.2 From 8e45dc216be0b36eb0fd633543a2a184c81c5b9b Mon Sep 17 00:00:00 2001 From: charles Date: Mon, 14 Nov 2005 21:00:54 +0000 Subject: [PATCH 15/16] Apply 2.6.14 patches from Andre --- yaffs_fs.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/yaffs_fs.c b/yaffs_fs.c index 14fd0b8..02d6b82 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -31,7 +31,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.33 2005-10-27 22:24:04 marty Exp $"; + "$Id: yaffs_fs.c,v 1.34 2005-11-14 21:00:54 charles Exp $"; extern const char *yaffs_guts_c_version; #include @@ -152,7 +152,11 @@ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, static int yaffs_readlink(struct dentry *dentry, char __user * buffer, int buflen); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); +#else static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); +#endif static struct address_space_operations yaffs_file_address_operations = { .readpage = yaffs_readpage, @@ -243,7 +247,11 @@ static int yaffs_readlink(struct dentry *dentry, char __user * buffer, return ret; } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) +#else static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) +#endif { unsigned char *alias; int ret; @@ -256,11 +264,19 @@ static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) yaffs_GrossUnlock(dev); if (!alias) - return -ENOMEM; + { + ret = -ENOMEM; + goto out; + } ret = vfs_follow_link(nd, alias); kfree(alias); +out: +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + return ERR_PTR (ret); +#else return ret; +#endif } struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, @@ -398,6 +414,9 @@ static void yaffs_delete_inode(struct inode *inode) yaffs_DeleteFile(obj); yaffs_GrossUnlock(dev); } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + truncate_inode_pages (&inode->i_data, 0); +#endif clear_inode(inode); } -- 2.30.2 From ce988b0f03f8e930859563e59ea90bdc193d1c9f Mon Sep 17 00:00:00 2001 From: marty Date: Tue, 29 Nov 2005 20:54:32 +0000 Subject: [PATCH 16/16] Subject: [Yaffs] Avoid tagsEccUnfixed stats bump on mounting partially usedblock IIUC, yaffs1 compatibility mode checks tags ECCs and updates stats on tags ECC errors when scanning an unused chunk of a partially-allocated block at mount time. This causes a mildly alarming "tagsEccUnfixed..... 1" in /proc/yaffs. Suggested fix below. Signed-off-by: Todd Poynor --- yaffs_tagscompat.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/yaffs_tagscompat.c b/yaffs_tagscompat.c index 2cf783e..b51bccd 100644 --- a/yaffs_tagscompat.c +++ b/yaffs_tagscompat.c @@ -10,7 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: yaffs_tagscompat.c,v 1.7 2005-09-20 23:12:38 charles Exp $ + * $Id: yaffs_tagscompat.c,v 1.8 2005-11-29 20:54:32 marty Exp $ */ #include "yaffs_guts.h" @@ -455,20 +455,22 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, int deleted = (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0; - yaffs_GetTagsFromSpare(dev, &spare, &tags); - eTags->chunkDeleted = deleted; - eTags->objectId = tags.objectId; - eTags->chunkId = tags.chunkId; - eTags->byteCount = tags.byteCount; - eTags->serialNumber = tags.serialNumber; eTags->eccResult = eccResult; eTags->blockBad = 0; /* We're reading it */ /* therefore it is not a bad block */ - eTags->chunkUsed = (memcmp(&spareFF, &spare, sizeof(spareFF)) != 0) ? 1 : 0; + + if (eTags->chunkUsed) { + yaffs_GetTagsFromSpare(dev, &spare, &tags); + + eTags->objectId = tags.objectId; + eTags->chunkId = tags.chunkId; + eTags->byteCount = tags.byteCount; + eTags->serialNumber = tags.serialNumber; + } } return YAFFS_OK; -- 2.30.2