diff options
27 files changed, 0 insertions, 10446 deletions
diff --git a/fs/yaffs2/Kconfig b/fs/yaffs2/Kconfig deleted file mode 100644 index 272df72..0000000 --- a/fs/yaffs2/Kconfig +++ /dev/null @@ -1,176 +0,0 @@ -# -# YAFFS file system configurations -# - -config YAFFS_FS - tristate "YAFFS2 file system support" - default n - depends on MTD - select YAFFS_YAFFS1 - select YAFFS_YAFFS2 - help - YAFFS2, or Yet Another Flash Filing System, is a filing system - optimised for NAND Flash chips. - - To compile the YAFFS2 file system support as a module, choose M - here: the module will be called yaffs2. - - If unsure, say N. - - Further information on YAFFS2 is available at - <http://www.aleph1.co.uk/yaffs/>. - -config YAFFS_YAFFS1 - bool "512 byte / page devices" - depends on YAFFS_FS - default y - help - Enable YAFFS1 support -- yaffs for 512 byte / page devices - - Not needed for 2K-page devices. - - If unsure, say Y. - -config YAFFS_9BYTE_TAGS - bool "Use older-style on-NAND data format with pageStatus byte" - depends on YAFFS_YAFFS1 - default n - help - - Older-style on-NAND data format has a "pageStatus" byte to record - chunk/page state. This byte is zero when the page is discarded. - Choose this option if you have existing on-NAND data using this - format that you need to continue to support. New data written - also uses the older-style format. Note: Use of this option - generally requires that MTD's oob layout be adjusted to use the - older-style format. See notes on tags formats and MTD versions - in yaffs_mtdif1.c. - - If unsure, say N. - -config YAFFS_DOES_ECC - bool "Lets Yaffs do its own ECC" - depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS - default n - help - This enables Yaffs to use its own ECC functions instead of using - the ones from the generic MTD-NAND driver. - - If unsure, say N. - -config YAFFS_ECC_WRONG_ORDER - bool "Use the same ecc byte order as Steven Hill's nand_ecc.c" - depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS - default n - help - This makes yaffs_ecc.c use the same ecc byte order as Steven - Hill's nand_ecc.c. If not set, then you get the same ecc byte - order as SmartMedia. - - If unsure, say N. - -config YAFFS_YAFFS2 - bool "2048 byte (or larger) / page devices" - depends on YAFFS_FS - default y - help - Enable YAFFS2 support -- yaffs for >= 2K bytes per page devices - - If unsure, say Y. - -config YAFFS_AUTO_YAFFS2 - bool "Autoselect yaffs2 format" - depends on YAFFS_YAFFS2 - default y - help - Without this, you need to explicitely use yaffs2 as the file - system type. With this, you can say "yaffs" and yaffs or yaffs2 - will be used depending on the device page size (yaffs on - 512-byte page devices, yaffs2 on 2K page devices). - - If unsure, say Y. - -config YAFFS_DISABLE_LAZY_LOAD - bool "Disable lazy loading" - depends on YAFFS_YAFFS2 - default n - help - "Lazy loading" defers loading file details until they are - required. This saves mount time, but makes the first look-up - a bit longer. - - Lazy loading will only happen if enabled by this option being 'n' - and if the appropriate tags are available, else yaffs2 will - automatically fall back to immediate loading and do the right - thing. - - Lazy laoding will be required by checkpointing. - - Setting this to 'y' will disable lazy loading. - - If unsure, say N. - -config YAFFS_CHECKPOINT_RESERVED_BLOCKS - int "Reserved blocks for checkpointing" - depends on YAFFS_YAFFS2 - default 10 - help - Give the number of Blocks to reserve for checkpointing. - Checkpointing saves the state at unmount so that mounting is - much faster as a scan of all the flash to regenerate this state - is not needed. These Blocks are reserved per partition, so if - you have very small partitions the default (10) may be a mess - for you. You can set this value to 0, but that does not mean - checkpointing is disabled at all. There only won't be any - specially reserved blocks for checkpointing, so if there is - enough free space on the filesystem, it will be used for - checkpointing. - - If unsure, leave at default (10), but don't wonder if there are - always 2MB used on your large page device partition (10 x 2k - pagesize). When using small partitions or when being very small - on space, you probably want to set this to zero. - -config YAFFS_DISABLE_WIDE_TNODES - bool "Turn off wide tnodes" - depends on YAFFS_FS - default n - help - Wide tnodes are only used for NAND arrays >=32MB for 512-byte - page devices and >=128MB for 2k page devices. They use slightly - more RAM but are faster since they eliminate chunk group - searching. - - Setting this to 'y' will force tnode width to 16 bits and save - memory but make large arrays slower. - - If unsure, say N. - -config YAFFS_ALWAYS_CHECK_CHUNK_ERASED - bool "Force chunk erase check" - depends on YAFFS_FS - default n - help - Normally YAFFS only checks chunks before writing until an erased - chunk is found. This helps to detect any partially written - chunks that might have happened due to power loss. - - Enabling this forces on the test that chunks are erased in flash - before writing to them. This takes more time but is potentially - a bit more secure. - - Suggest setting Y during development and ironing out driver - issues etc. Suggest setting to N if you want faster writing. - - If unsure, say Y. - -config YAFFS_SHORT_NAMES_IN_RAM - bool "Cache short names in RAM" - depends on YAFFS_FS - default y - help - If this config is set, then short names are stored with the - yaffs_Object. This costs an extra 16 bytes of RAM per object, - but makes look-ups faster. - - If unsure, say Y. diff --git a/fs/yaffs2/Makefile b/fs/yaffs2/Makefile deleted file mode 100644 index 538aec4..0000000 --- a/fs/yaffs2/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# Main Makefile for YAFFS -# -# -# YAFFS: Yet Another Flash File System. A NAND-flash specific file system. -# -# Copyright (C) 2002-2007 Aleph One Ltd. -# for Toby Churchill Ltd and Brightstar Engineering -# -# Created by Charles Manning <charles@aleph1.co.uk> -# -# 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. - - -ifneq ($(KERNELRELEASE),) - EXTRA_CFLAGS += -DYAFFS_OUT_OF_TREE - - obj-m := yaffs2.o - - yaffs2-objs := yaffs_mtdif.o yaffs_mtdif2.o - yaffs2-objs += yaffs_mtdif1.o yaffs_packedtags1.o - yaffs2-objs += yaffs_ecc.o yaffs_fs.o yaffs_guts.o - yaffs2-objs += yaffs_packedtags2.o yaffs_qsort.o - yaffs2-objs += yaffs_tagscompat.o yaffs_tagsvalidity.o - yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o - -else - KERNELDIR ?= /lib/modules/$(shell uname -r)/build - PWD := $(shell pwd) - -modules default: - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules - -mi modules_install: - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install - -clean: - $(MAKE) -C $(KERNELDIR) M=$(PWD) clean -endif diff --git a/fs/yaffs2/Makefile.kernel b/fs/yaffs2/Makefile.kernel deleted file mode 100644 index 382ee61..0000000 --- a/fs/yaffs2/Makefile.kernel +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for the linux YAFFS filesystem routines. -# - -obj-$(CONFIG_YAFFS_FS) += yaffs.o - -yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o -yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o -yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o -yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o diff --git a/fs/yaffs2/README-linux-patch b/fs/yaffs2/README-linux-patch deleted file mode 100644 index 3bdf26c..0000000 --- a/fs/yaffs2/README-linux-patch +++ /dev/null @@ -1,20 +0,0 @@ -To build YAFFS in the Linux kernel tree you need to run the patch-ker.sh -script from the yaffs source directory, giving your choice as to whether -you wish to copy (c) or link (l) the code and the path to your kernel -sources, e.g: - -./patch-ker.sh c /usr/src/linux - -This will copy the yaffs files into fs/yaffs2 and modify the Kconfig -and Makefiles in the fs directory. - -./patch-ker.sh l /usr/src/linux - -This does the same as the above but makes symbolic links instead. - -After you've run the script, go back to your normal kernel making procedure -and configure the yaffs settings you want. - -Prolems? Contact the yaffs mailing list: - -http://www.aleph1.co.uk/mailman/listinfo/yaffs diff --git a/fs/yaffs2/direct/dtest.c b/fs/yaffs2/direct/dtest.c deleted file mode 100644 index a9156ca..0000000 --- a/fs/yaffs2/direct/dtest.c +++ /dev/null @@ -1,2282 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * 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. - */ - -/* -* Test code for the "direct" interface. -*/ - -/* XXX U-BOOT XXX */ -#include <common.h> - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> - -#include "yaffsfs.h" - -void dumpDir(const char *dname); - -char xx[600]; - -void copy_in_a_file(char *yaffsName,char *inName) -{ - int inh,outh; - unsigned char buffer[100]; - int ni,no; - inh = open(inName,O_RDONLY); - outh = yaffs_open(yaffsName, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); - - while((ni = read(inh,buffer,100)) > 0) - { - no = yaffs_write(outh,buffer,ni); - if(ni != no) - { - printf("problem writing yaffs file\n"); - } - - } - - yaffs_close(outh); - close(inh); -} - -void make_a_file(char *yaffsName,char bval,int sizeOfFile) -{ - int outh; - int i; - unsigned char buffer[100]; - - outh = yaffs_open(yaffsName, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); - - memset(buffer,bval,100); - - do{ - i = sizeOfFile; - if(i > 100) i = 100; - sizeOfFile -= i; - - yaffs_write(outh,buffer,i); - - } while (sizeOfFile > 0); - - - yaffs_close(outh); - -} - -void make_pattern_file(char *fn,int size) -{ - int outh; - int marker; - int i; - outh = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); - yaffs_lseek(outh,size-1,SEEK_SET); - yaffs_write(outh,"A",1); - - for(i = 0; i < size; i+=256) - { - marker = ~i; - yaffs_lseek(outh,i,SEEK_SET); - yaffs_write(outh,&marker,sizeof(marker)); - } - yaffs_close(outh); - -} - -int check_pattern_file(char *fn) -{ - int h; - int marker; - int i; - int size; - int ok = 1; - - h = yaffs_open(fn, O_RDWR,0); - size = yaffs_lseek(h,0,SEEK_END); - - for(i = 0; i < size; i+=256) - { - yaffs_lseek(h,i,SEEK_SET); - yaffs_read(h,&marker,sizeof(marker)); - ok = (marker == ~i); - if(!ok) - { - printf("pattern check failed on file %s, size %d at position %d. Got %x instead of %x\n", - fn,size,i,marker,~i); - } - } - yaffs_close(h); - return ok; -} - - - - - -int dump_file_data(char *fn) -{ - int h; - int marker; - int i = 0; - int size; - int ok = 1; - unsigned char b; - - h = yaffs_open(fn, O_RDWR,0); - - - printf("%s\n",fn); - while(yaffs_read(h,&b,1)> 0) - { - printf("%02x",b); - i++; - if(i > 32) - { - printf("\n"); - i = 0;; - } - } - printf("\n"); - yaffs_close(h); - return ok; -} - - - -void dump_file(const char *fn) -{ - int i; - int size; - int h; - - h = yaffs_open(fn,O_RDONLY,0); - if(h < 0) - { - printf("*****\nDump file %s does not exist\n",fn); - } - else - { - size = yaffs_lseek(h,0,SEEK_SET); - printf("*****\nDump file %s size %d\n",fn,size); - for(i = 0; i < size; i++) - { - - } - } -} - -void create_file_of_size(const char *fn,int syze) -{ - int h; - int n; - - char xx[200]; - - int iterations = (syze + strlen(fn) -1)/ strlen(fn); - - h = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); - - while (iterations > 0) - { - sprintf(xx,"%s %8d",fn,iterations); - yaffs_write(h,xx,strlen(xx)); - iterations--; - } - yaffs_close (h); -} - -void verify_file_of_size(const char *fn,int syze) -{ - int h; - int n; - - char xx[200]; - char yy[200]; - int l; - - int iterations = (syze + strlen(fn) -1)/ strlen(fn); - - h = yaffs_open(fn, O_RDONLY, S_IREAD | S_IWRITE); - - while (iterations > 0) - { - sprintf(xx,"%s %8d",fn,iterations); - l = strlen(xx); - - yaffs_read(h,yy,l); - yy[l] = 0; - - if(strcmp(xx,yy)){ - printf("=====>>>>> verification of file %s failed near position %d\n",fn,yaffs_lseek(h,0,SEEK_CUR)); - } - iterations--; - } - yaffs_close (h); -} - -void create_resized_file_of_size(const char *fn,int syze1,int reSyze, int syze2) -{ - int h; - int n; - - - int iterations; - - h = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); - - iterations = (syze1 + strlen(fn) -1)/ strlen(fn); - while (iterations > 0) - { - yaffs_write(h,fn,strlen(fn)); - iterations--; - } - - yaffs_truncate(h,reSyze); - - yaffs_lseek(h,0,SEEK_SET); - iterations = (syze2 + strlen(fn) -1)/ strlen(fn); - while (iterations > 0) - { - yaffs_write(h,fn,strlen(fn)); - iterations--; - } - - yaffs_close (h); -} - - -void do_some_file_stuff(const char *path) -{ - - char fn[100]; - - sprintf(fn,"%s/%s",path,"f1"); - create_file_of_size(fn,10000); - - sprintf(fn,"%s/%s",path,"fdel"); - create_file_of_size(fn,10000); - yaffs_unlink(fn); - - sprintf(fn,"%s/%s",path,"f2"); - - create_resized_file_of_size(fn,10000,3000,4000); -} - -void yaffs_backward_scan_test(const char *path) -{ - char fn[100]; - - yaffs_StartUp(); - - yaffs_mount(path); - - do_some_file_stuff(path); - - sprintf(fn,"%s/ddd",path); - - yaffs_mkdir(fn,0); - - do_some_file_stuff(fn); - - yaffs_unmount(path); - - yaffs_mount(path); -} - -char xxzz[2000]; - - -void yaffs_device_flush_test(const char *path) -{ - char fn[100]; - int h; - int i; - - yaffs_StartUp(); - - yaffs_mount(path); - - do_some_file_stuff(path); - - // Open and add some data to a few files - for(i = 0; i < 10; i++) { - - sprintf(fn,"%s/ff%d",path,i); - - h = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IWRITE | S_IREAD); - yaffs_write(h,xxzz,2000); - yaffs_write(h,xxzz,2000); - } - yaffs_unmount(path); - - yaffs_mount(path); -} - - - -void short_scan_test(const char *path, int fsize, int niterations) -{ - int i; - char fn[100]; - - sprintf(fn,"%s/%s",path,"f1"); - - yaffs_StartUp(); - for(i = 0; i < niterations; i++) - { - printf("\n*****************\nIteration %d\n",i); - yaffs_mount(path); - printf("\nmount: Directory look-up of %s\n",path); - dumpDir(path); - make_a_file(fn,1,fsize); - yaffs_unmount(path); - } -} - - - -void scan_pattern_test(const char *path, int fsize, int niterations) -{ - int i; - int j; - char fn[3][100]; - int result; - - sprintf(fn[0],"%s/%s",path,"f0"); - sprintf(fn[1],"%s/%s",path,"f1"); - sprintf(fn[2],"%s/%s",path,"f2"); - - yaffs_StartUp(); - - for(i = 0; i < niterations; i++) - { - printf("\n*****************\nIteration %d\n",i); - yaffs_mount(path); - printf("\nmount: Directory look-up of %s\n",path); - dumpDir(path); - for(j = 0; j < 3; j++) - { - result = dump_file_data(fn[j]); - result = check_pattern_file(fn[j]); - make_pattern_file(fn[j],fsize); - result = dump_file_data(fn[j]); - result = check_pattern_file(fn[j]); - } - yaffs_unmount(path); - } -} - -void fill_disk(char *path,int nfiles) -{ - int h; - int n; - int result; - int f; - - char str[50]; - - for(n = 0; n < nfiles; n++) - { - sprintf(str,"%s/%d",path,n); - - h = yaffs_open(str, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); - - printf("writing file %s handle %d ",str, h); - - while ((result = yaffs_write(h,xx,600)) == 600) - { - f = yaffs_freespace(path); - } - result = yaffs_close(h); - printf(" close %d\n",result); - } -} - -void fill_disk_and_delete(char *path, int nfiles, int ncycles) -{ - int i,j; - char str[50]; - int result; - - for(i = 0; i < ncycles; i++) - { - printf("@@@@@@@@@@@@@@ cycle %d\n",i); - fill_disk(path,nfiles); - - for(j = 0; j < nfiles; j++) - { - sprintf(str,"%s/%d",path,j); - result = yaffs_unlink(str); - printf("unlinking file %s, result %d\n",str,result); - } - } -} - - -void fill_files(char *path,int flags, int maxIterations,int siz) -{ - int i; - int j; - char str[50]; - int h; - - i = 0; - - do{ - sprintf(str,"%s/%d",path,i); - h = yaffs_open(str, O_CREAT | O_TRUNC | O_RDWR,S_IREAD | S_IWRITE); - yaffs_close(h); - - if(h >= 0) - { - for(j = 0; j < siz; j++) - { - yaffs_write(h,str,1); - } - } - - if( flags & 1) - { - yaffs_unlink(str); - } - i++; - } while(h >= 0 && i < maxIterations); - - if(flags & 2) - { - i = 0; - do{ - sprintf(str,"%s/%d",path,i); - printf("unlink %s\n",str); - i++; - } while(yaffs_unlink(str) >= 0); - } -} - -void leave_unlinked_file(char *path,int maxIterations,int siz) -{ - int i; - char str[50]; - int h; - - i = 0; - - do{ - sprintf(str,"%s/%d",path,i); - printf("create %s\n",str); - h = yaffs_open(str, O_CREAT | O_TRUNC | O_RDWR,S_IREAD | S_IWRITE); - if(h >= 0) - { - yaffs_unlink(str); - } - i++; - } while(h < 0 && i < maxIterations); - - if(h >= 0) - { - for(i = 0; i < siz; i++) - { - yaffs_write(h,str,1); - } - } - - printf("Leaving file %s open\n",str); - -} - -void dumpDirFollow(const char *dname) -{ - yaffs_DIR *d; - yaffs_dirent *de; - struct yaffs_stat s; - char str[100]; - - d = yaffs_opendir(dname); - - if(!d) - { - printf("opendir failed\n"); - } - else - { - while((de = yaffs_readdir(d)) != NULL) - { - sprintf(str,"%s/%s",dname,de->d_name); - - yaffs_stat(str,&s); - - printf("%s length %d mode %X ",de->d_name,(int)s.st_size,s.st_mode); - switch(s.st_mode & S_IFMT) - { - case S_IFREG: printf("data file"); break; - case S_IFDIR: printf("directory"); break; - case S_IFLNK: printf("symlink -->"); - if(yaffs_readlink(str,str,100) < 0) - printf("no alias"); - else - printf("\"%s\"",str); - break; - default: printf("unknown"); break; - } - - printf("\n"); - } - - yaffs_closedir(d); - } - printf("\n"); - - printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname)); - -} - - -void dump_directory_tree_worker(const char *dname,int recursive) -{ - yaffs_DIR *d; - yaffs_dirent *de; - struct yaffs_stat s; - char str[1000]; - - d = yaffs_opendir(dname); - - if(!d) - { - printf("opendir failed\n"); - } - else - { - while((de = yaffs_readdir(d)) != NULL) - { - sprintf(str,"%s/%s",dname,de->d_name); - - yaffs_lstat(str,&s); - - printf("%s inode %d obj %x length %d mode %X ",str,s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode); - switch(s.st_mode & S_IFMT) - { - case S_IFREG: printf("data file"); break; - case S_IFDIR: printf("directory"); break; - case S_IFLNK: printf("symlink -->"); - if(yaffs_readlink(str,str,100) < 0) - printf("no alias"); - else - printf("\"%s\"",str); - break; - default: printf("unknown"); break; - } - - printf("\n"); - - if((s.st_mode & S_IFMT) == S_IFDIR && recursive) - dump_directory_tree_worker(str,1); - - } - - yaffs_closedir(d); - } - -} - -static void dump_directory_tree(const char *dname) -{ - dump_directory_tree_worker(dname,1); - printf("\n"); - printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname)); -} - -void dumpDir(const char *dname) -{ dump_directory_tree_worker(dname,0); - printf("\n"); - printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname)); -} - - -static void PermissionsCheck(const char *path, mode_t tmode, int tflags,int expectedResult) -{ - int fd; - - if(yaffs_chmod(path,tmode)< 0) printf("chmod failed\n"); - - fd = yaffs_open(path,tflags,0); - - if((fd >= 0) != (expectedResult > 0)) - { - printf("Permissions check %x %x %d failed\n",tmode,tflags,expectedResult); - } - else - { - printf("Permissions check %x %x %d OK\n",tmode,tflags,expectedResult); - } - - - yaffs_close(fd); - - -} - -int long_test(int argc, char *argv[]) -{ - - int f; - int r; - char buffer[20]; - - char str[100]; - - int h; - mode_t temp_mode; - struct yaffs_stat ystat; - - yaffs_StartUp(); - - yaffs_mount("/boot"); - yaffs_mount("/data"); - yaffs_mount("/flash"); - yaffs_mount("/ram"); - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - printf("\nDirectory look-up of /data\n"); - dumpDir("/data"); - printf("\nDirectory look-up of /flash\n"); - dumpDir("/flash"); - - //leave_unlinked_file("/flash",20000,0); - //leave_unlinked_file("/data",20000,0); - - leave_unlinked_file("/ram",20,0); - - - f = yaffs_open("/boot/b1", O_RDONLY,0); - - printf("open /boot/b1 readonly, f=%d\n",f); - - f = yaffs_open("/boot/b1", O_CREAT,S_IREAD | S_IWRITE); - - printf("open /boot/b1 O_CREAT, f=%d\n",f); - - - r = yaffs_write(f,"hello",1); - printf("write %d attempted to write to a read-only file\n",r); - - r = yaffs_close(f); - - printf("close %d\n",r); - - f = yaffs_open("/boot/b1", O_RDWR,0); - - printf("open /boot/b1 O_RDWR,f=%d\n",f); - - - r = yaffs_write(f,"hello",2); - printf("write %d attempted to write to a writeable file\n",r); - r = yaffs_write(f,"world",3); - printf("write %d attempted to write to a writeable file\n",r); - - r= yaffs_lseek(f,0,SEEK_END); - printf("seek end %d\n",r); - memset(buffer,0,20); - r = yaffs_read(f,buffer,10); - printf("read %d \"%s\"\n",r,buffer); - r= yaffs_lseek(f,0,SEEK_SET); - printf("seek set %d\n",r); - memset(buffer,0,20); - r = yaffs_read(f,buffer,10); - printf("read %d \"%s\"\n",r,buffer); - memset(buffer,0,20); - r = yaffs_read(f,buffer,10); - printf("read %d \"%s\"\n",r,buffer); - - // Check values reading at end. - // A read past end of file should return 0 for 0 bytes read. - - r= yaffs_lseek(f,0,SEEK_END); - r = yaffs_read(f,buffer,10); - printf("read at end returned %d\n",r); - r= yaffs_lseek(f,500,SEEK_END); - r = yaffs_read(f,buffer,10); - printf("read past end returned %d\n",r); - - r = yaffs_close(f); - - printf("close %d\n",r); - - copy_in_a_file("/boot/yyfile","xxx"); - - // Create a file with a long name - - copy_in_a_file("/boot/file with a long name","xxx"); - - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - - // Check stat - r = yaffs_stat("/boot/file with a long name",&ystat); - - // Check rename - - r = yaffs_rename("/boot/file with a long name","/boot/r1"); - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - - // Check unlink - r = yaffs_unlink("/boot/r1"); - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - - // Check mkdir - - r = yaffs_mkdir("/boot/directory1",0); - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - printf("\nDirectory look-up of /boot/directory1\n"); - dumpDir("/boot/directory1"); - - // add a file to the directory - copy_in_a_file("/boot/directory1/file with a long name","xxx"); - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - printf("\nDirectory look-up of /boot/directory1\n"); - dumpDir("/boot/directory1"); - - // Attempt to delete directory (should fail) - - r = yaffs_rmdir("/boot/directory1"); - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - printf("\nDirectory look-up of /boot/directory1\n"); - dumpDir("/boot/directory1"); - - // Delete file first, then rmdir should work - r = yaffs_unlink("/boot/directory1/file with a long name"); - r = yaffs_rmdir("/boot/directory1"); - - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - printf("\nDirectory look-up of /boot/directory1\n"); - dumpDir("/boot/directory1"); - -#if 0 - fill_disk_and_delete("/boot",20,20); - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); -#endif - - yaffs_symlink("yyfile","/boot/slink"); - - yaffs_readlink("/boot/slink",str,100); - printf("symlink alias is %s\n",str); - - - - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - printf("\nDirectory look-up of /boot (using stat instead of lstat)\n"); - dumpDirFollow("/boot"); - printf("\nDirectory look-up of /boot/directory1\n"); - dumpDir("/boot/directory1"); - - h = yaffs_open("/boot/slink",O_RDWR,0); - - printf("file length is %d\n",(int)yaffs_lseek(h,0,SEEK_END)); - - yaffs_close(h); - - yaffs_unlink("/boot/slink"); - - - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - - // Check chmod - - yaffs_stat("/boot/yyfile",&ystat); - temp_mode = ystat.st_mode; - - yaffs_chmod("/boot/yyfile",0x55555); - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - - yaffs_chmod("/boot/yyfile",temp_mode); - printf("\nDirectory look-up of /boot\n"); - dumpDir("/boot"); - - // Permission checks... - PermissionsCheck("/boot/yyfile",0, O_WRONLY,0); - PermissionsCheck("/boot/yyfile",0, O_RDONLY,0); - PermissionsCheck("/boot/yyfile",0, O_RDWR,0); - - PermissionsCheck("/boot/yyfile",S_IREAD, O_WRONLY,0); - PermissionsCheck("/boot/yyfile",S_IREAD, O_RDONLY,1); - PermissionsCheck("/boot/yyfile",S_IREAD, O_RDWR,0); - - PermissionsCheck("/boot/yyfile",S_IWRITE, O_WRONLY,1); - PermissionsCheck("/boot/yyfile",S_IWRITE, O_RDONLY,0); - PermissionsCheck("/boot/yyfile",S_IWRITE, O_RDWR,0); - - PermissionsCheck("/boot/yyfile",S_IREAD | S_IWRITE, O_WRONLY,1); - PermissionsCheck("/boot/yyfile",S_IREAD | S_IWRITE, O_RDONLY,1); - PermissionsCheck("/boot/yyfile",S_IREAD | S_IWRITE, O_RDWR,1); - - yaffs_chmod("/boot/yyfile",temp_mode); - - //create a zero-length file and unlink it (test for scan bug) - - h = yaffs_open("/boot/zlf",O_CREAT | O_TRUNC | O_RDWR,0); - yaffs_close(h); - - yaffs_unlink("/boot/zlf"); - - - yaffs_DumpDevStruct("/boot"); - - fill_disk_and_delete("/boot",20,20); - - yaffs_DumpDevStruct("/boot"); - - fill_files("/boot",1,10000,0); - fill_files("/boot",1,10000,5000); - fill_files("/boot",2,10000,0); - fill_files("/boot",2,10000,5000); - - leave_unlinked_file("/data",20000,0); - leave_unlinked_file("/data",20000,5000); - leave_unlinked_file("/data",20000,5000); - leave_unlinked_file("/data",20000,5000); - leave_unlinked_file("/data",20000,5000); - leave_unlinked_file("/data",20000,5000); - - yaffs_DumpDevStruct("/boot"); - yaffs_DumpDevStruct("/data"); - - - - return 0; - -} - -int huge_directory_test_on_path(char *path) -{ - - yaffs_DIR *d; - yaffs_dirent *de; - struct yaffs_stat s; - - int f; - int i; - int r; - int total = 0; - int lastTotal = 0; - char buffer[20]; - - char str[100]; - char name[100]; - char name2[100]; - - int h; - mode_t temp_mode; - struct yaffs_stat ystat; - - yaffs_StartUp(); - - yaffs_mount(path); - - // Create a large number of files - - for(i = 0; i < 2000; i++) - { - sprintf(str,"%s/%d",path,i); - - f = yaffs_open(str,O_CREAT,S_IREAD | S_IWRITE); - yaffs_close(f); - } - - - - d = yaffs_opendir(path); - i = 0; - if (d) { - while((de = yaffs_readdir(d)) != NULL) { - if (total >lastTotal+100*9*1024||(i & 1023)==0){ - printf("files = %d, total = %d\n",i, total); - lastTotal = total; - } - i++; - sprintf(str,"%s/%s",path,de->d_name); - yaffs_lstat(str,&s); - switch(s.st_mode & S_IFMT){ - case S_IFREG: - //printf("data file"); - total += s.st_size; - break; - } - } - - yaffs_closedir(d); - } - - return 0; -} - -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) -{ - int a,b,i,j; - int x; - int r; - char aname[100]; - char bname[100]; - - char abuffer[1000]; - char bbuffer[1000]; - - yaffs_StartUp(); - - yaffs_mount(path); - - sprintf(aname,"%s%s",path,"/a"); - sprintf(bname,"%s%s",path,"/b"); - - memset(abuffer,'a',1000); - memset(bbuffer,'b',1000); - - a = yaffs_open(aname, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - b = yaffs_open(bname, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - - printf(" %s %d %s %d\n",aname,a,bname,b); - - x = 0; - - for(j = 0; j < 100; j++) - { - yaffs_lseek(a,0,SEEK_END); - - - for(i = 0; i <20000; i++) - { - //r = yaffs_lseek(b,i,SEEK_SET); - //r = yaffs_write(b,bbuffer,1000); - - if(x & 0x16) - { - // shrink - int syz = yaffs_lseek(a,0,SEEK_END); - - syz -= 500; - if(syz < 0) syz = 0; - yaffs_truncate(a,syz); - - } - else - { - //expand - r = yaffs_lseek(a,i * 500,SEEK_SET); - r = yaffs_write(a,abuffer,1000); - } - x++; - - } - } - - return 0; - -} - - -int resize_stress_test_no_grow_complex(const char *path,int iters) -{ - int a,b,i,j; - int x; - int r; - char aname[100]; - char bname[100]; - - char abuffer[1000]; - char bbuffer[1000]; - - yaffs_StartUp(); - - yaffs_mount(path); - - sprintf(aname,"%s%s",path,"/a"); - sprintf(bname,"%s%s",path,"/b"); - - memset(abuffer,'a',1000); - memset(bbuffer,'b',1000); - - a = yaffs_open(aname, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - b = yaffs_open(bname, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - - printf(" %s %d %s %d\n",aname,a,bname,b); - - x = 0; - - for(j = 0; j < iters; j++) - { - yaffs_lseek(a,0,SEEK_END); - - - for(i = 0; i <20000; i++) - { - //r = yaffs_lseek(b,i,SEEK_SET); - //r = yaffs_write(b,bbuffer,1000); - - if(!(x%20)) - { - // shrink - int syz = yaffs_lseek(a,0,SEEK_END); - - while(syz > 4000) - { - - syz -= 2050; - if(syz < 0) syz = 0; - yaffs_truncate(a,syz); - syz = yaffs_lseek(a,0,SEEK_END); - printf("shrink to %d\n",syz); - } - - - } - else - { - //expand - r = yaffs_lseek(a,500,SEEK_END); - r = yaffs_write(a,abuffer,1000); - } - x++; - - - } - printf("file size is %d\n",yaffs_lseek(a,0,SEEK_END)); - - } - - return 0; - -} - -int resize_stress_test_no_grow(const char *path,int iters) -{ - int a,b,i,j; - int x; - int r; - char aname[100]; - char bname[100]; - - char abuffer[1000]; - char bbuffer[1000]; - - yaffs_StartUp(); - - yaffs_mount(path); - - sprintf(aname,"%s%s",path,"/a"); - sprintf(bname,"%s%s",path,"/b"); - - memset(abuffer,'a',1000); - memset(bbuffer,'b',1000); - - a = yaffs_open(aname, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - b = yaffs_open(bname, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - - printf(" %s %d %s %d\n",aname,a,bname,b); - - x = 0; - - for(j = 0; j < iters; j++) - { - yaffs_lseek(a,0,SEEK_END); - - - for(i = 0; i <20000; i++) - { - //r = yaffs_lseek(b,i,SEEK_SET); - //r = yaffs_write(b,bbuffer,1000); - - if(!(x%20)) - { - // shrink - int syz = yaffs_lseek(a,0,SEEK_END); - - while(syz > 4000) - { - - syz -= 2050; - if(syz < 0) syz = 0; - yaffs_truncate(a,syz); - syz = yaffs_lseek(a,0,SEEK_END); - printf("shrink to %d\n",syz); - } - - - } - else - { - //expand - r = yaffs_lseek(a,-500,SEEK_END); - r = yaffs_write(a,abuffer,1000); - } - x++; - - - } - printf("file size is %d\n",yaffs_lseek(a,0,SEEK_END)); - - } - - return 0; - -} - -int directory_rename_test(void) -{ - int r; - yaffs_StartUp(); - - yaffs_mount("/ram"); - yaffs_mkdir("/ram/a",0); - yaffs_mkdir("/ram/a/b",0); - yaffs_mkdir("/ram/c",0); - - printf("\nDirectory look-up of /ram\n"); - dumpDir("/ram"); - dumpDir("/ram/a"); - dumpDir("/ram/a/b"); - - printf("Do rename (should fail)\n"); - - r = yaffs_rename("/ram/a","/ram/a/b/d"); - printf("\nDirectory look-up of /ram\n"); - dumpDir("/ram"); - dumpDir("/ram/a"); - dumpDir("/ram/a/b"); - - printf("Do rename (should not fail)\n"); - - r = yaffs_rename("/ram/c","/ram/a/b/d"); - printf("\nDirectory look-up of /ram\n"); - dumpDir("/ram"); - dumpDir("/ram/a"); - dumpDir("/ram/a/b"); - - - return 1; - -} - -int cache_read_test(void) -{ - int a,b,c; - int i; - int sizeOfFiles = 500000; - char buffer[100]; - - yaffs_StartUp(); - - yaffs_mount("/boot"); - - make_a_file("/boot/a",'a',sizeOfFiles); - make_a_file("/boot/b",'b',sizeOfFiles); - - a = yaffs_open("/boot/a",O_RDONLY,0); - b = yaffs_open("/boot/b",O_RDONLY,0); - c = yaffs_open("/boot/c", O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE); - - do{ - i = sizeOfFiles; - if (i > 100) i = 100; - sizeOfFiles -= i; - yaffs_read(a,buffer,i); - yaffs_read(b,buffer,i); - yaffs_write(c,buffer,i); - } while(sizeOfFiles > 0); - - - - return 1; - -} - -int cache_bypass_bug_test(void) -{ - // This test reporoduces a bug whereby YAFFS caching *was* buypassed - // resulting in erroneous reads after writes. - // This bug has been fixed. - - int a; - int i; - char buffer1[1000]; - char buffer2[1000]; - - memset(buffer1,0,sizeof(buffer1)); - memset(buffer2,0,sizeof(buffer2)); - - yaffs_StartUp(); - - yaffs_mount("/boot"); - - // Create a file of 2000 bytes. - make_a_file("/boot/a",'X',2000); - - a = yaffs_open("/boot/a",O_RDWR, S_IREAD | S_IWRITE); - - // Write a short sequence to the file. - // This will go into the cache. - yaffs_lseek(a,0,SEEK_SET); - yaffs_write(a,"abcdefghijklmnopqrstuvwxyz",20); - - // Read a short sequence from the file. - // This will come from the cache. - yaffs_lseek(a,0,SEEK_SET); - yaffs_read(a,buffer1,30); - - // Read a page size sequence from the file. - yaffs_lseek(a,0,SEEK_SET); - yaffs_read(a,buffer2,512); - - printf("buffer 1 %s\n",buffer1); - printf("buffer 2 %s\n",buffer2); - - if(strncmp(buffer1,buffer2,20)) - { - printf("Cache bypass bug detected!!!!!\n"); - } - - - return 1; -} - - -int free_space_check(void) -{ - int f; - - yaffs_StartUp(); - yaffs_mount("/boot"); - fill_disk("/boot/",2); - f = yaffs_freespace("/boot"); - - printf("%d free when disk full\n",f); - return 1; -} - -int truncate_test(void) -{ - int a; - int r; - int i; - int l; - - char y[10]; - - yaffs_StartUp(); - yaffs_mount("/boot"); - - yaffs_unlink("/boot/trunctest"); - - a = yaffs_open("/boot/trunctest", O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - - yaffs_write(a,"abcdefghijklmnopqrstuvwzyz",26); - - yaffs_truncate(a,3); - l= yaffs_lseek(a,0,SEEK_END); - - printf("truncated length is %d\n",l); - - yaffs_lseek(a,5,SEEK_SET); - yaffs_write(a,"1",1); - - yaffs_lseek(a,0,SEEK_SET); - - r = yaffs_read(a,y,10); - - printf("read %d bytes:",r); - - for(i = 0; i < r; i++) printf("[%02X]",y[i]); - - printf("\n"); - - return 0; - -} - - - - - -void fill_disk_test(const char *mountpt) -{ - int i; - yaffs_StartUp(); - - for(i = 0; i < 5; i++) - { - yaffs_mount(mountpt); - fill_disk_and_delete(mountpt,100,i+1); - yaffs_unmount(mountpt); - } - -} - - - -void lookup_test(const char *mountpt) -{ - int i; - int h; - char a[100]; - char b[100]; - - - 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 link_test(const char *mountpt) -{ - int i; - int h; - char a[100]; - char b[100]; - char c[100]; - - int f0; - int f1; - int f2; - int f3; - sprintf(a,"%s/aaa",mountpt); - sprintf(b,"%s/bbb",mountpt); - sprintf(c,"%s/ccc",mountpt); - - yaffs_StartUp(); - - yaffs_mount(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); - - yaffs_unlink(b); - yaffs_unlink(c); - yaffs_link(a,b); - yaffs_link(a,c); - yaffs_unlink(b); - yaffs_unlink(c); - yaffs_unlink(a); - - - yaffs_unmount(mountpt); - yaffs_mount(mountpt); - - printf("link test done\n"); - -} - -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); - - 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 simple_rw_test(const char *mountpt) -{ - int i; - int h; - char a[100]; - - int x; - int result; - - sprintf(a,"%s/aaa",mountpt); - - yaffs_StartUp(); - - yaffs_mount(mountpt); - - yaffs_unlink(a); - - h = yaffs_open(a,O_CREAT| O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - - for(i = 100000;i < 200000; i++){ - result = yaffs_write(h,&i,sizeof(i)); - - if(result != 4) - { - printf("write error\n"); - exit(1); - } - } - - //yaffs_close(h); - - // h = yaffs_open(a,O_RDWR, S_IREAD | S_IWRITE); - - - yaffs_lseek(h,0,SEEK_SET); - - for(i = 100000; i < 200000; i++){ - result = yaffs_read(h,&x,sizeof(x)); - - if(result != 4 || x != i){ - printf("read error %d %x %x\n",i,result,x); - } - } - - printf("Simple rw test passed\n"); - - - -} - - -void scan_deleted_files_test(const char *mountpt) -{ - char fn[100]; - char sub[100]; - - const char *p; - - int i; - int j; - int k; - int h; - - sprintf(sub,"%s/sdir",mountpt); - yaffs_StartUp(); - - for(j = 0; j < 10; j++) - { - printf("\n\n>>>>>>> Run %d <<<<<<<<<<<<<\n\n",j); - yaffs_mount(mountpt); - yaffs_mkdir(sub,0); - - - p = (j & 0) ? mountpt: sub; - - for(i = 0; i < 100; i++) - { - sprintf(fn,"%s/%d",p,i); - - if(i & 1) - { - h = yaffs_open(fn,O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - for(k = 0; k < 1000; k++) - yaffs_write(h,fn,100); - yaffs_close(h); - } - else - yaffs_mkdir(fn,0); - } - - for(i = 0; i < 10; i++) - { - sprintf(fn,"%s/%d",p,i); - if(i & 1) - yaffs_unlink(fn); - else - yaffs_rmdir(fn); - - } - - yaffs_unmount(mountpt); - } - - - - -} - - -void write_10k(int h) -{ - int i; - const char *s="0123456789"; - for(i = 0; i < 1000; i++) - yaffs_write(h,s,10); - -} -void write_200k_file(const char *fn, const char *fdel, const char *fdel1) -{ - int h1; - int i; - int offs; - - h1 = yaffs_open(fn, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - - for(i = 0; i < 100000; i+= 10000) - { - write_10k(h1); - } - - offs = yaffs_lseek(h1,0,SEEK_CUR); - if( offs != 100000) - { - printf("Could not write file\n"); - } - - yaffs_unlink(fdel); - for(i = 0; i < 100000; i+= 10000) - { - write_10k(h1); - } - - offs = yaffs_lseek(h1,0,SEEK_CUR); - if( offs != 200000) - { - printf("Could not write file\n"); - } - - yaffs_close(h1); - yaffs_unlink(fdel1); - -} - - -void verify_200k_file(const char *fn) -{ - int h1; - int i; - char x[11]; - const char *s="0123456789"; - int errCount = 0; - - h1 = yaffs_open(fn, O_RDONLY, 0); - - for(i = 0; i < 200000 && errCount < 10; i+= 10) - { - yaffs_read(h1,x,10); - if(strncmp(x,s,10) != 0) - { - printf("File %s verification failed at %d\n",fn,i); - errCount++; - } - } - if(errCount >= 10) - printf("Too many errors... aborted\n"); - - yaffs_close(h1); - -} - - -void check_resize_gc_bug(const char *mountpt) -{ - - char a[30]; - char b[30]; - char c[30]; - - int i; - - sprintf(a,"%s/a",mountpt); - sprintf(b,"%s/b",mountpt); - sprintf(c,"%s/c",mountpt); - - - - - yaffs_StartUp(); - yaffs_mount(mountpt); - yaffs_unlink(a); - yaffs_unlink(b); - - for(i = 0; i < 50; i++) - { - printf("A\n");write_200k_file(a,"",c); - printf("B\n");verify_200k_file(a); - printf("C\n");write_200k_file(b,a,c); - printf("D\n");verify_200k_file(b); - yaffs_unmount(mountpt); - yaffs_mount(mountpt); - printf("E\n");verify_200k_file(a); - printf("F\n");verify_200k_file(b); - } - -} - - -void multi_mount_test(const char *mountpt,int nmounts) -{ - - char a[30]; - char b[30]; - char c[30]; - - int i; - int j; - - sprintf(a,"%s/a",mountpt); - - yaffs_StartUp(); - - for(i = 0; i < nmounts; i++){ - int h0; - int h1; - int len0; - int len1; - - static char xx[1000]; - - printf("############### Iteration %d Start\n",i); - if(1 || i == 0 || i == 5) - yaffs_mount(mountpt); - - dump_directory_tree(mountpt); - - - yaffs_mkdir(a,0); - - sprintf(xx,"%s/0",a); - h0 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - - sprintf(xx,"%s/1",a); - h1 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - - for(j = 0; j < 200; j++){ - yaffs_write(h0,xx,1000); - yaffs_write(h1,xx,1000); - } - - len0 = yaffs_lseek(h0,0,SEEK_END); - len1 = yaffs_lseek(h1,0,SEEK_END); - - yaffs_lseek(h0,0,SEEK_SET); - yaffs_lseek(h1,0,SEEK_SET); - - for(j = 0; j < 200; j++){ - yaffs_read(h0,xx,1000); - yaffs_read(h1,xx,1000); - } - - - yaffs_truncate(h0,0); - yaffs_close(h0); - yaffs_close(h1); - - printf("########### %d\n",i); - dump_directory_tree(mountpt); - - if(1 || i == 4 || i == nmounts -1) - yaffs_unmount(mountpt); - } -} - - -void small_mount_test(const char *mountpt,int nmounts) -{ - - char a[30]; - char b[30]; - char c[30]; - - int i; - int j; - - int h0; - int h1; - int len0; - int len1; - int nread; - - sprintf(a,"%s/a",mountpt); - - yaffs_StartUp(); - - - - for(i = 0; i < nmounts; i++){ - - static char xx[1000]; - - printf("############### Iteration %d Start\n",i); - if(1 || i == 0 || i == 5) - yaffs_mount(mountpt); - - dump_directory_tree(mountpt); - - yaffs_mkdir(a,0); - - sprintf(xx,"%s/0",a); - if(i ==0){ - - h0 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - for(j = 0; j < 130; j++) - yaffs_write(h0,xx,1000); - yaffs_close(h0); - } - - h0 = yaffs_open(xx,O_RDONLY,0); - - sprintf(xx,"%s/1",a); - h1 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - - while((nread = yaffs_read(h0,xx,1000)) > 0) - yaffs_write(h1,xx,nread); - - - len0 = yaffs_lseek(h0,0,SEEK_END); - len1 = yaffs_lseek(h1,0,SEEK_END); - - yaffs_lseek(h0,0,SEEK_SET); - yaffs_lseek(h1,0,SEEK_SET); - - for(j = 0; j < 200; j++){ - yaffs_read(h0,xx,1000); - yaffs_read(h1,xx,1000); - } - - yaffs_close(h0); - yaffs_close(h1); - - printf("########### %d\n",i); - dump_directory_tree(mountpt); - - if(1 || i == 4 || i == nmounts -1) - yaffs_unmount(mountpt); - } -} - - -int early_exit; - -void small_overwrite_test(const char *mountpt,int nmounts) -{ - - char a[30]; - char b[30]; - char c[30]; - - int i; - int j; - - int h0; - int h1; - int len0; - int len1; - int nread; - - sprintf(a,"%s/a",mountpt); - - yaffs_StartUp(); - - - - for(i = 0; i < nmounts; i++){ - - static char xx[8000]; - - printf("############### Iteration %d Start\n",i); - if(1) - yaffs_mount(mountpt); - - dump_directory_tree(mountpt); - - yaffs_mkdir(a,0); - - sprintf(xx,"%s/0",a); - h0 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - sprintf(xx,"%s/1",a); - h1 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - - for(j = 0; j < 1000000; j+=1000){ - yaffs_truncate(h0,j); - yaffs_lseek(h0,j,SEEK_SET); - yaffs_write(h0,xx,7000); - yaffs_write(h1,xx,7000); - - if(early_exit) - exit(0); - } - - yaffs_close(h0); - - printf("########### %d\n",i); - dump_directory_tree(mountpt); - - if(1) - yaffs_unmount(mountpt); - } -} - - -void yaffs_touch(const char *fn) -{ - yaffs_chmod(fn, S_IREAD | S_IWRITE); -} - -void checkpoint_fill_test(const char *mountpt,int nmounts) -{ - - char a[50]; - char b[50]; - char c[50]; - - int i; - int j; - int h; - - sprintf(a,"%s/a",mountpt); - - - - - yaffs_StartUp(); - - for(i = 0; i < nmounts; i++){ - printf("############### Iteration %d Start\n",i); - yaffs_mount(mountpt); - dump_directory_tree(mountpt); - yaffs_mkdir(a,0); - - sprintf(b,"%s/zz",a); - - h = yaffs_open(b,O_CREAT | O_RDWR,S_IREAD |S_IWRITE); - - - while(yaffs_write(h,c,50) == 50){} - - yaffs_close(h); - - for(j = 0; j < 2; j++){ - printf("touch %d\n",j); - yaffs_touch(b); - yaffs_unmount(mountpt); - yaffs_mount(mountpt); - } - - dump_directory_tree(mountpt); - yaffs_unmount(mountpt); - } -} - - -int make_file2(const char *name1, const char *name2,int syz) -{ - - char xx[2500]; - int i; - int h1=-1,h2=-1; - int n = 1; - - - if(name1) - h1 = yaffs_open(name1,O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - if(name2) - h2 = yaffs_open(name2,O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); - - while(syz > 0 && n > 0){ - i = (syz > 2500) ? 2500 : syz; - n = yaffs_write(h1,xx,i); - n = yaffs_write(h2,xx,i); - syz -= 500; - } - yaffs_close(h1); - yaffs_close(h2); - -} - - -extern void SetCheckpointReservedBlocks(int n); - -void checkpoint_upgrade_test(const char *mountpt,int nmounts) -{ - - char a[50]; - char b[50]; - char c[50]; - char d[50]; - - int i; - int j; - int h; - - sprintf(a,"%s/a",mountpt); - - - - - printf("Create start condition\n"); - yaffs_StartUp(); - SetCheckpointReservedBlocks(0); - yaffs_mount(mountpt); - yaffs_mkdir(a,0); - sprintf(b,"%s/zz",a); - sprintf(c,"%s/xx",a); - make_file2(b,c,2000000); - sprintf(d,"%s/aa",a); - make_file2(d,NULL,500000000); - dump_directory_tree(mountpt); - - printf("Umount/mount attempt full\n"); - yaffs_unmount(mountpt); - - SetCheckpointReservedBlocks(10); - yaffs_mount(mountpt); - - printf("unlink small file\n"); - yaffs_unlink(c); - dump_directory_tree(mountpt); - - printf("Umount/mount attempt\n"); - yaffs_unmount(mountpt); - yaffs_mount(mountpt); - - for(j = 0; j < 500; j++){ - printf("***** touch %d\n",j); - dump_directory_tree(mountpt); - yaffs_touch(b); - yaffs_unmount(mountpt); - yaffs_mount(mountpt); - } - - for(j = 0; j < 500; j++){ - printf("***** touch %d\n",j); - dump_directory_tree(mountpt); - yaffs_touch(b); - yaffs_unmount(mountpt); - yaffs_mount(mountpt); - } -} - -void huge_array_test(const char *mountpt,int n) -{ - - char a[50]; - - - int i; - int j; - int h; - - int fnum; - - sprintf(a,"mount point %s",mountpt); - - - - yaffs_StartUp(); - - yaffs_mount(mountpt); - - while(n>0){ - n--; - fnum = 0; - printf("\n\n START run\n\n"); - while(yaffs_freespace(mountpt) > 25000000){ - sprintf(a,"%s/file%d",mountpt,fnum); - fnum++; - printf("create file %s\n",a); - create_file_of_size(a,10000000); - printf("verifying file %s\n",a); - verify_file_of_size(a,10000000); - } - - printf("\n\n verification/deletion\n\n"); - - for(i = 0; i < fnum; i++){ - sprintf(a,"%s/file%d",mountpt,i); - printf("verifying file %s\n",a); - verify_file_of_size(a,10000000); - printf("deleting file %s\n",a); - yaffs_unlink(a); - } - printf("\n\n done \n\n"); - - - } -} - - -void random_write(int h) -{ - static char buffer[12000]; - int n; - - n = random() & 0x1FFF; - yaffs_write(h,buffer,n); -} - -void random_seek(int h) -{ - int n; - n = random() & 0xFFFFF; - yaffs_lseek(h,n,SEEK_SET); -} - -void random_truncate(int h, char * name) -{ - int n; - int flen; - n = random() & 0xFFFFF; - flen = yaffs_lseek(h,0,SEEK_END); - if(n > flen) - n = flen / 2; - yaffs_truncate(name,n); - yaffs_lseek(h,n,SEEK_SET); -} - - -#define NSMALLFILES 10 -void random_small_file_test(const char *mountpt,int iterations) -{ - - char a[NSMALLFILES][50]; - - - int i; - int n; - int j; - int h[NSMALLFILES]; - int r; - int fnum; - - - yaffs_StartUp(); - - yaffs_mount(mountpt); - - for(i = 0; i < NSMALLFILES; i++){ - h[i]=-1; - strcpy(a[i],""); - } - - for(n = 0; n < iterations; n++){ - - for(i = 0; i < NSMALLFILES; i++) { - r = random(); - - if(strlen(a[i]) == 0){ - sprintf(a[i],"%s/%dx%d",mountpt,n,i); - h[i] = yaffs_open(a,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - } - - if(h[i] < -1) - printf("Could not open yaffs file %d %d error %d\n",n,i,h[i]); - else { - r = r & 7; - switch(r){ - case 0: - case 1: - case 2: - random_write(h[i]); - break; - case 3: - random_truncate(h[i],a[i]); - break; - case 4: - case 5: random_seek(h[i]); - break; - case 6: - yaffs_close(h[i]); - h[i] = -1; - break; - case 7: - yaffs_close(h[i]); - yaffs_unlink(a[i]); - strcpy(a[i],""); - h[i] = -1; - } - } - } - - } - - for(i = 0; i < NSMALLFILES; i++) - yaffs_close(h[i]); - - yaffs_unmount(mountpt); -} - - - -int main(int argc, char *argv[]) -{ - //return long_test(argc,argv); - - //return cache_read_test(); - - resize_stress_test_no_grow("/flash/flash",20); - - //huge_directory_test_on_path("/ram2k"); - - //yaffs_backward_scan_test("/flash/flash"); - // yaffs_device_flush_test("/flash/flash"); - - - //scan_pattern_test("/flash",10000,10); - //short_scan_test("/flash/flash",40000,200); - //small_mount_test("/flash/flash",1000); - //small_overwrite_test("/flash/flash",1000); - //checkpoint_fill_test("/flash/flash",20); - // random_small_file_test("/flash/flash",10000); - // huge_array_test("/flash/flash",10); - - - - - //long_test_on_path("/ram2k"); - // long_test_on_path("/flash"); - //simple_rw_test("/flash/flash"); - //fill_disk_test("/flash/flash"); - // rename_over_test("/flash"); - //lookup_test("/flash"); - //freespace_test("/flash/flash"); - - //link_test("/flash/flash"); - - - - - // cache_bypass_bug_test(); - - //free_space_check(); - - //check_resize_gc_bug("/flash"); - - return 0; - -} diff --git a/fs/yaffs2/direct/fsx_test/Makefile b/fs/yaffs2/direct/fsx_test/Makefile deleted file mode 100644 index 1927865..0000000 --- a/fs/yaffs2/direct/fsx_test/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# Makefile for YAFFS direct test -# -# -# YAFFS: Yet another Flash File System. A NAND-flash specific file system. -# -# Copyright (C) 2003 Aleph One Ltd. -# -# -# Created by Charles Manning <charles@aleph1.co.uk> -# -# 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. -# -# NB Warning this Makefile does not include header dependencies. -# -# $Id: Makefile,v 1.1 2007/10/16 00:46:33 charles Exp $ - -#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC - -CFLAGS = -Wall -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -g $(EXTRA_COMPILE_FLAGS) -DNO_Y_INLINE -CFLAGS+= -fstack-check -O0 - -#CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -#CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline - - -FSXTESTOBJS = yaffs_fsx.o yaffscfg2k.o yaffs_ecc.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \ - yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ - yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ - yaffs_checkptrw.o yaffs_qsort.o \ -# yaffs_checkptrwtest.o\ - - -BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o - -#ALLOBJS = dtest.o nand_ecc.o yaffscfg.o yaffs_fileem.o yaffsfs.o yaffs_ramdisk.o bootldtst.o yboot.o yaffs_ramem2k.o - -ALLOBJS = $(FSXTESTOBJS) $(BOOTTESTOBJS) - -YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \ - yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h yaffs_nandemul2k.h \ - yaffs_nand.c yaffs_nand.h \ - yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ - yaffs_qsort.c yaffs_qsort.h - -YAFFSDIRECTSYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h \ - yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \ - yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c - - - -#all: fsxtest boottest - -all: fsxtest - -$(ALLOBJS): %.o: %.c - gcc -c $(CFLAGS) $< -o $@ - -$(YAFFSSYMLINKS): - ln -s ../../$@ $@ - -$(YAFFSDIRECTSYMLINKS): - ln -s ../$@ $@ - -fsxtest: $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) $(FSXTESTOBJS) - gcc -o $@ $(FSXTESTOBJS) - - -boottest: $(SYMLINKS) $(BOOTTESTOBJS) - gcc -o $@ $(BOOTTESTOBJS) - - -clean: - rm -f $(ALLOBJS) core diff --git a/fs/yaffs2/direct/fsx_test/README b/fs/yaffs2/direct/fsx_test/README deleted file mode 100644 index 725ab07..0000000 --- a/fs/yaffs2/direct/fsx_test/README +++ /dev/null @@ -1,7 +0,0 @@ -NB THis directory uses a hacked version of fsx.c which is released under -Apple Public Source License. - -From what I have been able to determine, it is legally OK to release a hacked -version for the purposes of testing. - -If anyone knows otherwise, please contact me: manningc2@actrix.gen.nz diff --git a/fs/yaffs2/direct/fsx_test/yaffs_fsx.c b/fs/yaffs2/direct/fsx_test/yaffs_fsx.c deleted file mode 100644 index 1e110b9..0000000 --- a/fs/yaffs2/direct/fsx_test/yaffs_fsx.c +++ /dev/null @@ -1,1007 +0,0 @@ -/* - * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.2 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - * - * WARNING--WARNING--WARNING - * This is not the original fsx.c. It has been modified to run with - * yaffs direct. Seek out the original fsx.c if you want to do anything - * else. - * - * - * - * File: fsx.c - * Author: Avadis Tevanian, Jr. - * - * File system exerciser. - * - * Rewrite and enhancements 1998-2001 Conrad Minshall -- conrad@mac.com - * - * Various features from Joe Sokol, Pat Dirks, and Clark Warner. - * - * Small changes to work under Linux -- davej@suse.de - * - * Sundry porting patches from Guy Harris 12/2001 - * - * Checks for mmap last-page zero fill. - * - * Modified heavily by Charles Manning to exercise via the - * yaffs direct interface. - * - */ - -#include <sys/types.h> -#include <sys/stat.h> -#ifdef _UWIN -# include <sys/param.h> -# include <limits.h> -# include <time.h> -# include <strings.h> -#endif -#include <fcntl.h> -#include <sys/mman.h> -#ifndef MAP_FILE -# define MAP_FILE 0 -#endif -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdarg.h> -#include <errno.h> - -#include "yaffsfs.h" - -#define NUMPRINTCOLUMNS 32 /* # columns of data to print on each line */ - -/* - * A log entry is an operation and a bunch of arguments. - */ - -struct log_entry { - int operation; - int args[3]; -}; - -#define LOGSIZE 1000 - -struct log_entry oplog[LOGSIZE]; /* the log */ -int logptr = 0; /* current position in log */ -int logcount = 0; /* total ops */ - -/* - * Define operations - */ - -#define OP_READ 1 -#define OP_WRITE 2 -#define OP_TRUNCATE 3 -#define OP_CLOSEOPEN 4 -#define OP_MAPREAD 5 -#define OP_MAPWRITE 6 -#define OP_SKIPPED 7 - -int page_size; -int page_mask; - -char *original_buf; /* a pointer to the original data */ -char *good_buf; /* a pointer to the correct data */ -char *temp_buf; /* a pointer to the current data */ -char *fname; /* name of our test file */ -int fd; /* fd for our test file */ - -off_t file_size = 0; -off_t biggest = 0; -char state[256]; -unsigned long testcalls = 0; /* calls to function "test" */ - -unsigned long simulatedopcount = 0; /* -b flag */ -int closeprob = 0; /* -c flag */ -int debug = 0; /* -d flag */ -unsigned long debugstart = 0; /* -D flag */ -unsigned long maxfilelen = 256 * 1024; /* -l flag */ -int sizechecks = 1; /* -n flag disables them */ -int maxoplen = 64 * 1024; /* -o flag */ -int quiet = 0; /* -q flag */ -unsigned long progressinterval = 0; /* -p flag */ -int readbdy = 1; /* -r flag */ -int style = 0; /* -s flag */ -int truncbdy = 1; /* -t flag */ -int writebdy = 1; /* -w flag */ -long monitorstart = -1; /* -m flag */ -long monitorend = -1; /* -m flag */ -int lite = 0; /* -L flag */ -long numops = -1; /* -N flag */ -int randomoplen = 1; /* -O flag disables it */ -int seed = 1; /* -S flag */ - -int mapped_writes = 0; /* yaffs direct does not support mmapped files */ -int mapped_reads = 0; - -int fsxgoodfd = 0; -FILE * fsxlogf = NULL; -int badoff = -1; -int closeopen = 0; - - -void -vwarnc(code, fmt, ap) - int code; - const char *fmt; - va_list ap; -{ - fprintf(stderr, "fsx: "); - if (fmt != NULL) { - vfprintf(stderr, fmt, ap); - fprintf(stderr, ": "); - } - fprintf(stderr, "%s\n", strerror(code)); -} - - -void -warn(const char * fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vwarnc(errno, fmt, ap); - va_end(ap); -} - - -void -prt(char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vfprintf(stdout, fmt, args); - if (fsxlogf) - vfprintf(fsxlogf, fmt, args); - va_end(args); -} - -void -prterr(char *prefix) -{ - prt("%s%s%s\n", prefix, prefix ? ": " : "", strerror(errno)); -} - - -void -log4(int operation, int arg0, int arg1, int arg2) -{ - struct log_entry *le; - - le = &oplog[logptr]; - le->operation = operation; - if (closeopen) - le->operation = ~ le->operation; - le->args[0] = arg0; - le->args[1] = arg1; - le->args[2] = arg2; - logptr++; - logcount++; - if (logptr >= LOGSIZE) - logptr = 0; -} - - -void -logdump(void) -{ - int i, count, down; - struct log_entry *lp; - - prt("LOG DUMP (%d total operations):\n", logcount); - if (logcount < LOGSIZE) { - i = 0; - count = logcount; - } else { - i = logptr; - count = LOGSIZE; - } - for ( ; count > 0; count--) { - int opnum; - - opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE; - prt("%d(%d mod 256): ", opnum, opnum%256); - lp = &oplog[i]; - if ((closeopen = lp->operation < 0)) - lp->operation = ~ lp->operation; - - switch (lp->operation) { - case OP_MAPREAD: - prt("MAPREAD\t0x%x thru 0x%x\t(0x%x bytes)", - lp->args[0], lp->args[0] + lp->args[1] - 1, - lp->args[1]); - if (badoff >= lp->args[0] && badoff < - lp->args[0] + lp->args[1]) - prt("\t***RRRR***"); - break; - case OP_MAPWRITE: - prt("MAPWRITE 0x%x thru 0x%x\t(0x%x bytes)", - lp->args[0], lp->args[0] + lp->args[1] - 1, - lp->args[1]); - if (badoff >= lp->args[0] && badoff < - lp->args[0] + lp->args[1]) - prt("\t******WWWW"); - break; - case OP_READ: - prt("READ\t0x%x thru 0x%x\t(0x%x bytes)", - lp->args[0], lp->args[0] + lp->args[1] - 1, - lp->args[1]); - if (badoff >= lp->args[0] && - badoff < lp->args[0] + lp->args[1]) - prt("\t***RRRR***"); - break; - case OP_WRITE: - prt("WRITE\t0x%x thru 0x%x\t(0x%x bytes)", - lp->args[0], lp->args[0] + lp->args[1] - 1, - lp->args[1]); - if (lp->args[0] > lp->args[2]) - prt(" HOLE"); - else if (lp->args[0] + lp->args[1] > lp->args[2]) - prt(" EXTEND"); - if ((badoff >= lp->args[0] || badoff >=lp->args[2]) && - badoff < lp->args[0] + lp->args[1]) - prt("\t***WWWW"); - break; - case OP_TRUNCATE: - down = lp->args[0] < lp->args[1]; - prt("TRUNCATE %s\tfrom 0x%x to 0x%x", - down ? "DOWN" : "UP", lp->args[1], lp->args[0]); - if (badoff >= lp->args[!down] && - badoff < lp->args[!!down]) - prt("\t******WWWW"); - break; - case OP_SKIPPED: - prt("SKIPPED (no operation)"); - break; - default: - prt("BOGUS LOG ENTRY (operation code = %d)!", - lp->operation); - } - if (closeopen) - prt("\n\t\tCLOSE/OPEN"); - prt("\n"); - i++; - if (i == LOGSIZE) - i = 0; - } -} - - -void -save_buffer(char *buffer, off_t bufferlength, int fd) -{ - off_t ret; - ssize_t byteswritten; - - if (fd <= 0 || bufferlength == 0) - return; - - if (bufferlength > SSIZE_MAX) { - prt("fsx flaw: overflow in save_buffer\n"); - exit(67); - } - if (lite) { - off_t size_by_seek = yaffs_lseek(fd, (off_t)0, SEEK_END); - if (size_by_seek == (off_t)-1) - prterr("save_buffer: lseek eof"); - else if (bufferlength > size_by_seek) { - warn("save_buffer: .fsxgood file too short... will save 0x%llx bytes instead of 0x%llx\n", (unsigned long long)size_by_seek, - (unsigned long long)bufferlength); - bufferlength = size_by_seek; - } - } - - ret = yaffs_lseek(fd, (off_t)0, SEEK_SET); - if (ret == (off_t)-1) - prterr("save_buffer: lseek 0"); - - byteswritten = yaffs_write(fd, buffer, (size_t)bufferlength); - if (byteswritten != bufferlength) { - if (byteswritten == -1) - prterr("save_buffer write"); - else - warn("save_buffer: short write, 0x%x bytes instead of 0x%llx\n", - (unsigned)byteswritten, - (unsigned long long)bufferlength); - } -} - - -void -report_failure(int status) -{ - logdump(); - - if (fsxgoodfd) { - if (good_buf) { - save_buffer(good_buf, file_size, fsxgoodfd); - prt("Correct content saved for comparison\n"); - prt("(maybe hexdump \"%s\" vs \"%s.fsxgood\")\n", - fname, fname); - } - close(fsxgoodfd); - } - prt("Exiting with %d\n",status); - exit(status); -} - - -#define short_at(cp) ((unsigned short)((*((unsigned char *)(cp)) << 8) | \ - *(((unsigned char *)(cp)) + 1))) - -void -check_buffers(unsigned offset, unsigned size) -{ - unsigned char c, t; - unsigned i = 0; - unsigned n = 0; - unsigned op = 0; - unsigned bad = 0; - - if (memcmp(good_buf + offset, temp_buf, size) != 0) { - prt("READ BAD DATA: offset = 0x%x, size = 0x%x\n", - offset, size); - prt("OFFSET\tGOOD\tBAD\tRANGE\n"); - while (size > 0) { - c = good_buf[offset]; - t = temp_buf[i]; - if (c != t) { - if (n == 0) { - bad = short_at(&temp_buf[i]); - prt("0x%5x\t0x%04x\t0x%04x", offset, - short_at(&good_buf[offset]), bad); - op = temp_buf[offset & 1 ? i+1 : i]; - } - n++; - badoff = offset; - } - offset++; - i++; - size--; - } - if (n) { - prt("\t0x%5x\n", n); - if (bad) - prt("operation# (mod 256) for the bad data may be %u\n", ((unsigned)op & 0xff)); - else - prt("operation# (mod 256) for the bad data unknown, check HOLE and EXTEND ops\n"); - } else - prt("????????????????\n"); - report_failure(110); - } -} - - -void -check_size(void) -{ - struct yaffs_stat statbuf; - off_t size_by_seek; - - if (yaffs_fstat(fd, &statbuf)) { - prterr("check_size: fstat"); - statbuf.st_size = -1; - } - size_by_seek = yaffs_lseek(fd, (off_t)0, SEEK_END); - if (file_size != statbuf.st_size || file_size != size_by_seek) { - prt("Size error: expected 0x%llx stat 0x%llx seek 0x%llx\n", - (unsigned long long)file_size, - (unsigned long long)statbuf.st_size, - (unsigned long long)size_by_seek); - report_failure(120); - } -} - - -void -check_trunc_hack(void) -{ - struct yaffs_stat statbuf; - - yaffs_truncate(fd, (off_t)0); - yaffs_truncate(fd, (off_t)100000); - yaffs_fstat(fd, &statbuf); - if (statbuf.st_size != (off_t)100000) { - prt("no extend on truncate! not posix!\n"); - exit(130); - } - yaffs_truncate(fd, (off_t)0); -} - - -void -doread(unsigned offset, unsigned size) -{ - off_t ret; - unsigned iret; - - offset -= offset % readbdy; - if (size == 0) { - if (!quiet && testcalls > simulatedopcount) - prt("skipping zero size read\n"); - log4(OP_SKIPPED, OP_READ, offset, size); - return; - } - if (size + offset > file_size) { - if (!quiet && testcalls > simulatedopcount) - prt("skipping seek/read past end of file\n"); - log4(OP_SKIPPED, OP_READ, offset, size); - return; - } - - log4(OP_READ, offset, size, 0); - - if (testcalls <= simulatedopcount) - return; - - if (!quiet && ((progressinterval && - testcalls % progressinterval == 0) || - (debug && - (monitorstart == -1 || - (offset + size > monitorstart && - (monitorend == -1 || offset <= monitorend)))))) - prt("%lu read\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls, - offset, offset + size - 1, size); - ret = yaffs_lseek(fd, (off_t)offset, SEEK_SET); - if (ret == (off_t)-1) { - prterr("doread: lseek"); - report_failure(140); - } - iret = yaffs_read(fd, temp_buf, size); - if (iret != size) { - if (iret == -1) - prterr("doread: read"); - else - prt("short read: 0x%x bytes instead of 0x%x\n", - iret, size); - report_failure(141); - } - check_buffers(offset, size); -} - - - - - -void -gendata(char *original_buf, char *good_buf, unsigned offset, unsigned size) -{ - while (size--) { - good_buf[offset] = testcalls % 256; - if (offset % 2) - good_buf[offset] += original_buf[offset]; - offset++; - } -} - - -void -dowrite(unsigned offset, unsigned size) -{ - off_t ret; - unsigned iret; - - offset -= offset % writebdy; - if (size == 0) { - if (!quiet && testcalls > simulatedopcount) - prt("skipping zero size write\n"); - log4(OP_SKIPPED, OP_WRITE, offset, size); - return; - } - - log4(OP_WRITE, offset, size, file_size); - - gendata(original_buf, good_buf, offset, size); - if (file_size < offset + size) { - if (file_size < offset) - memset(good_buf + file_size, '\0', offset - file_size); - file_size = offset + size; - if (lite) { - warn("Lite file size bug in fsx!"); - report_failure(149); - } - } - - if (testcalls <= simulatedopcount) - return; - - if (!quiet && ((progressinterval && - testcalls % progressinterval == 0) || - (debug && - (monitorstart == -1 || - (offset + size > monitorstart && - (monitorend == -1 || offset <= monitorend)))))) - prt("%lu write\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls, - offset, offset + size - 1, size); - ret = yaffs_lseek(fd, (off_t)offset, SEEK_SET); - if (ret == (off_t)-1) { - prterr("dowrite: lseek"); - report_failure(150); - } - iret = yaffs_write(fd, good_buf + offset, size); - if (iret != size) { - if (iret == -1) - prterr("dowrite: write"); - else - prt("short write: 0x%x bytes instead of 0x%x\n", - iret, size); - report_failure(151); - } -} - - - -void -dotruncate(unsigned size) -{ - int oldsize = file_size; - - size -= size % truncbdy; - if (size > biggest) { - biggest = size; - if (!quiet && testcalls > simulatedopcount) - prt("truncating to largest ever: 0x%x\n", size); - } - - log4(OP_TRUNCATE, size, (unsigned)file_size, 0); - - if (size > file_size) - memset(good_buf + file_size, '\0', size - file_size); - file_size = size; - - if (testcalls <= simulatedopcount) - return; - - if ((progressinterval && testcalls % progressinterval == 0) || - (debug && (monitorstart == -1 || monitorend == -1 || - size <= monitorend))) - prt("%lu trunc\tfrom 0x%x to 0x%x\n", testcalls, oldsize, size); - if (yaffs_truncate(fd, (off_t)size) == -1) { - prt("ftruncate1: %x\n", size); - prterr("dotruncate: ftruncate"); - report_failure(160); - } -} - - -void -writefileimage() -{ - ssize_t iret; - - if (yaffs_lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { - prterr("writefileimage: lseek"); - report_failure(171); - } - iret = yaffs_write(fd, good_buf, file_size); - if ((off_t)iret != file_size) { - if (iret == -1) - prterr("writefileimage: write"); - else - prt("short write: 0x%x bytes instead of 0x%llx\n", - iret, (unsigned long long)file_size); - report_failure(172); - } - if (lite ? 0 : yaffs_truncate(fd, file_size) == -1) { - prt("ftruncate2: %llx\n", (unsigned long long)file_size); - prterr("writefileimage: ftruncate"); - report_failure(173); - } -} - - -void -docloseopen(void) -{ - if (testcalls <= simulatedopcount) - return; - - if (debug) - prt("%lu close/open\n", testcalls); - if (yaffs_close(fd)) { - prterr("docloseopen: close"); - report_failure(180); - } - fd = yaffs_open(fname, O_RDWR, 0); - if (fd < 0) { - prterr("docloseopen: open"); - report_failure(181); - } -} - - -void -test(void) -{ - unsigned long offset; - unsigned long size = maxoplen; - unsigned long rv = random(); - unsigned long op = rv % (3 + !lite + mapped_writes); - - /* turn off the map read if necessary */ - - if (op == 2 && !mapped_reads) - op = 0; - - if (simulatedopcount > 0 && testcalls == simulatedopcount) - writefileimage(); - - testcalls++; - - if (closeprob) - closeopen = (rv >> 3) < (1 << 28) / closeprob; - - if (debugstart > 0 && testcalls >= debugstart) - debug = 1; - - if (!quiet && testcalls < simulatedopcount && testcalls % 100000 == 0) - prt("%lu...\n", testcalls); - - /* - * READ: op = 0 - * WRITE: op = 1 - * MAPREAD: op = 2 - * TRUNCATE: op = 3 - * MAPWRITE: op = 3 or 4 - */ - if (lite ? 0 : op == 3 && (style & 1) == 0) /* vanilla truncate? */ - dotruncate(random() % maxfilelen); - else { - if (randomoplen) - size = random() % (maxoplen+1); - if (lite ? 0 : op == 3) - dotruncate(size); - else { - offset = random(); - if (op == 1 || op == (lite ? 3 : 4)) { - offset %= maxfilelen; - if (offset + size > maxfilelen) - size = maxfilelen - offset; - dowrite(offset, size); - } else { - if (file_size) - offset %= file_size; - else - offset = 0; - if (offset + size > file_size) - size = file_size - offset; - doread(offset, size); - } - } - } - if (sizechecks && testcalls > simulatedopcount) - check_size(); - if (closeopen) - docloseopen(); -} - - -void -cleanup(sig) - int sig; -{ - if (sig) - prt("signal %d\n", sig); - prt("testcalls = %lu\n", testcalls); - exit(sig); -} - - -void -usage(void) -{ - fprintf(stdout, "usage: %s", - "fsx [-dnqLOW] [-b opnum] [-c Prob] [-l flen] [-m start:end] [-o oplen] [-p progressinterval] [-r readbdy] [-s style] [-t truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath] [-S seed] fname\n\ - -b opnum: beginning operation number (default 1)\n\ - -c P: 1 in P chance of file close+open at each op (default infinity)\n\ - -d: debug output for all operations\n\ - -l flen: the upper bound on file size (default 262144)\n\ - -m startop:endop: monitor (print debug output) specified byte range (default 0:infinity)\n\ - -n: no verifications of file size\n\ - -o oplen: the upper bound on operation size (default 65536)\n\ - -p progressinterval: debug output at specified operation interval\n\ - -q: quieter operation\n\ - -r readbdy: 4096 would make reads page aligned (default 1)\n\ - -s style: 1 gives smaller truncates (default 0)\n\ - -t truncbdy: 4096 would make truncates page aligned (default 1)\n\ - -w writebdy: 4096 would make writes page aligned (default 1)\n\ - -D startingop: debug output starting at specified operation\n\ - -L: fsxLite - no file creations & no file size changes\n\ - -N numops: total # operations to do (default infinity)\n\ - -O: use oplen (see -o flag) for every op (default random)\n\ - -P dirpath: save .fsxlog and .fsxgood files in dirpath (default ./)\n\ - -S seed: for random # generator (default 1) 0 gets timestamp\n\ - fname: this filename is REQUIRED (no default)\n"); - exit(90); -} - - -int -getnum(char *s, char **e) -{ - int ret = -1; - - *e = (char *) 0; - ret = strtol(s, e, 0); - if (*e) - switch (**e) { - case 'b': - case 'B': - ret *= 512; - *e = *e + 1; - break; - case 'k': - case 'K': - ret *= 1024; - *e = *e + 1; - break; - case 'm': - case 'M': - ret *= 1024*1024; - *e = *e + 1; - break; - case 'w': - case 'W': - ret *= 4; - *e = *e + 1; - break; - } - return (ret); -} - - -int -main(int argc, char **argv) -{ - int i, style, ch; - char *endp; - char goodfile[1024]; - char logfile[1024]; - - goodfile[0] = 0; - logfile[0] = 0; - - page_size = getpagesize(); - page_mask = page_size - 1; - - setvbuf(stdout, (char *)0, _IOLBF, 0); /* line buffered stdout */ - - while ((ch = getopt(argc, argv, "b:c:dl:m:no:p:qr:s:t:w:D:LN:OP:RS:W")) - != EOF) - switch (ch) { - case 'b': - simulatedopcount = getnum(optarg, &endp); - if (!quiet) - fprintf(stdout, "Will begin at operation %ld\n", - simulatedopcount); - if (simulatedopcount == 0) - usage(); - simulatedopcount -= 1; - break; - case 'c': - closeprob = getnum(optarg, &endp); - if (!quiet) - fprintf(stdout, - "Chance of close/open is 1 in %d\n", - closeprob); - if (closeprob <= 0) - usage(); - break; - case 'd': - debug = 1; - break; - case 'l': - maxfilelen = getnum(optarg, &endp); - if (maxfilelen <= 0) - usage(); - break; - case 'm': - monitorstart = getnum(optarg, &endp); - if (monitorstart < 0) - usage(); - if (!endp || *endp++ != ':') - usage(); - monitorend = getnum(endp, &endp); - if (monitorend < 0) - usage(); - if (monitorend == 0) - monitorend = -1; /* aka infinity */ - debug = 1; - case 'n': - sizechecks = 0; - break; - case 'o': - maxoplen = getnum(optarg, &endp); - if (maxoplen <= 0) - usage(); - break; - case 'p': - progressinterval = getnum(optarg, &endp); - if (progressinterval < 0) - usage(); - break; - case 'q': - quiet = 1; - break; - case 'r': - readbdy = getnum(optarg, &endp); - if (readbdy <= 0) - usage(); - break; - case 's': - style = getnum(optarg, &endp); - if (style < 0 || style > 1) - usage(); - break; - case 't': - truncbdy = getnum(optarg, &endp); - if (truncbdy <= 0) - usage(); - break; - case 'w': - writebdy = getnum(optarg, &endp); - if (writebdy <= 0) - usage(); - break; - case 'D': - debugstart = getnum(optarg, &endp); - if (debugstart < 1) - usage(); - break; - case 'L': - lite = 1; - break; - case 'N': - numops = getnum(optarg, &endp); - if (numops < 0) - usage(); - break; - case 'O': - randomoplen = 0; - break; - case 'P': - strncpy(goodfile, optarg, sizeof(goodfile)); - strcat(goodfile, "/"); - strncpy(logfile, optarg, sizeof(logfile)); - strcat(logfile, "/"); - break; - case 'R': - mapped_reads = 0; - break; - case 'S': - seed = getnum(optarg, &endp); - if (seed == 0) - seed = time(0) % 10000; - if (!quiet) - fprintf(stdout, "Seed set to %d\n", seed); - if (seed < 0) - usage(); - break; - case 'W': - mapped_writes = 0; - if (!quiet) - fprintf(stdout, "mapped writes DISABLED\n"); - break; - - default: - usage(); - /* NOTREACHED */ - } - argc -= optind; - argv += optind; - - yaffs_StartUp(); - yaffs_mount("/flash/flash"); - - fname = "/flash/flash/fsxdata"; - - signal(SIGHUP, cleanup); - signal(SIGINT, cleanup); - signal(SIGPIPE, cleanup); - signal(SIGALRM, cleanup); - signal(SIGTERM, cleanup); - signal(SIGXCPU, cleanup); - signal(SIGXFSZ, cleanup); - signal(SIGVTALRM, cleanup); - signal(SIGUSR1, cleanup); - signal(SIGUSR2, cleanup); - - initstate(seed, state, 256); - setstate(state); - fd = yaffs_open(fname, O_RDWR|(lite ? 0 : O_CREAT|O_TRUNC), 0666); - if (fd < 0) { - prterr(fname); - exit(91); - } - strncat(goodfile, fname, 256); - strcat (goodfile, ".fsxgood"); - fsxgoodfd = yaffs_open(goodfile, O_RDWR|O_CREAT|O_TRUNC, 0666); - if (fsxgoodfd < 0) { - prterr(goodfile); - exit(92); - } - strncat(logfile, "fsx", 256); - strcat (logfile, ".fsxlog"); - fsxlogf = fopen(logfile, "w"); - if (fsxlogf == NULL) { - prterr(logfile); - exit(93); - } - if (lite) { - off_t ret; - file_size = maxfilelen = yaffs_lseek(fd, (off_t)0, SEEK_END); - if (file_size == (off_t)-1) { - prterr(fname); - warn("main: lseek eof"); - exit(94); - } - ret = yaffs_lseek(fd, (off_t)0, SEEK_SET); - if (ret == (off_t)-1) { - prterr(fname); - warn("main: lseek 0"); - exit(95); - } - } - original_buf = (char *) malloc(maxfilelen); - for (i = 0; i < maxfilelen; i++) - original_buf[i] = random() % 256; - good_buf = (char *) malloc(maxfilelen); - memset(good_buf, '\0', maxfilelen); - temp_buf = (char *) malloc(maxoplen); - memset(temp_buf, '\0', maxoplen); - if (lite) { /* zero entire existing file */ - ssize_t written; - - written = yaffs_write(fd, good_buf, (size_t)maxfilelen); - if (written != maxfilelen) { - if (written == -1) { - prterr(fname); - warn("main: error on write"); - } else - warn("main: short write, 0x%x bytes instead of 0x%x\n", - (unsigned)written, maxfilelen); - exit(98); - } - } else - check_trunc_hack(); - - while (numops == -1 || numops--) - test(); - - if (yaffs_close(fd)) { - prterr("close"); - report_failure(99); - } - - yaffs_close(fsxgoodfd); - - yaffs_unmount("flash/flash"); - prt("All operations completed A-OK!\n"); - - exit(0); - return 0; -} - diff --git a/fs/yaffs2/direct/yaffs_fileem.c b/fs/yaffs2/direct/yaffs_fileem.c deleted file mode 100644 index 5779d7e..0000000 --- a/fs/yaffs2/direct/yaffs_fileem.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * 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. - */ - -/* - * This provides a YAFFS nand emulation on a file. - * This is only intended as test code to test persistence etc. - */ - -/* XXX U-BOOT XXX */ -#include <common.h> - -const char *yaffs_flashif_c_version = "$Id: yaffs_fileem.c,v 1.3 2007/02/14 01:09:06 wookey Exp $"; - - -#include "yportenv.h" - -#include "yaffs_flashif.h" -#include "yaffs_guts.h" - -#include "devextras.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> - - - -#define SIZE_IN_MB 16 - -#define BLOCK_SIZE (32 * 528) -#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512)) - - - -typedef struct -{ - __u8 data[528]; // Data + spare -} yflash_Page; - -typedef struct -{ - yflash_Page page[32]; // The pages in the block - -} yflash_Block; - - - -typedef struct -{ - int handle; - int nBlocks; -} yflash_Device; - -static yflash_Device filedisk; - -static int CheckInit(yaffs_Device *dev) -{ - static int initialised = 0; - - int i; - - - int fSize; - int written; - - yflash_Page p; - - if(initialised) - { - return YAFFS_OK; - } - - initialised = 1; - - - filedisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024); - - filedisk.handle = open("yaffsemfile", O_RDWR | O_CREAT, S_IREAD | S_IWRITE); - - if(filedisk.handle < 0) - { - perror("Failed to open yaffs emulation file"); - return YAFFS_FAIL; - } - - - fSize = lseek(filedisk.handle,0,SEEK_END); - - if(fSize < SIZE_IN_MB * 1024 * 1024) - { - printf("Creating yaffs emulation file\n"); - - lseek(filedisk.handle,0,SEEK_SET); - - memset(&p,0xff,sizeof(yflash_Page)); - - for(i = 0; i < SIZE_IN_MB * 1024 * 1024; i+= 512) - { - written = write(filedisk.handle,&p,sizeof(yflash_Page)); - - if(written != sizeof(yflash_Page)) - { - printf("Write failed\n"); - return YAFFS_FAIL; - } - } - } - - return 1; -} - -int yflash_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare) -{ - int written; - - CheckInit(dev); - - - - if(data) - { - lseek(filedisk.handle,chunkInNAND * 528,SEEK_SET); - written = write(filedisk.handle,data,512); - - if(written != 512) return YAFFS_FAIL; - } - - if(spare) - { - lseek(filedisk.handle,chunkInNAND * 528 + 512,SEEK_SET); - written = write(filedisk.handle,spare,16); - - if(written != 16) return YAFFS_FAIL; - } - - - return YAFFS_OK; - -} - - -int yflash_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare) -{ - int nread; - - CheckInit(dev); - - - - if(data) - { - lseek(filedisk.handle,chunkInNAND * 528,SEEK_SET); - nread = read(filedisk.handle,data,512); - - if(nread != 512) return YAFFS_FAIL; - } - - if(spare) - { - lseek(filedisk.handle,chunkInNAND * 528 + 512,SEEK_SET); - nread= read(filedisk.handle,spare,16); - - if(nread != 16) return YAFFS_FAIL; - } - - - return YAFFS_OK; - -} - - -int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) -{ - - int i; - - CheckInit(dev); - - if(blockNumber < 0 || blockNumber >= filedisk.nBlocks) - { - T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); - return YAFFS_FAIL; - } - else - { - - yflash_Page pg; - - memset(&pg,0xff,sizeof(yflash_Page)); - - lseek(filedisk.handle, blockNumber * 32 * 528, SEEK_SET); - - for(i = 0; i < 32; i++) - { - write(filedisk.handle,&pg,528); - } - return YAFFS_OK; - } - -} - -int yflash_InitialiseNAND(yaffs_Device *dev) -{ - dev->useNANDECC = 1; // force on useNANDECC which gets faked. - // This saves us doing ECC checks. - - return YAFFS_OK; -} diff --git a/fs/yaffs2/direct/yaffs_fileem2k.c b/fs/yaffs2/direct/yaffs_fileem2k.c deleted file mode 100644 index 34a4e87..0000000 --- a/fs/yaffs2/direct/yaffs_fileem2k.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * 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. - */ - -/* - * This provides a YAFFS nand emulation on a file for emulating 2kB pages. - * This is only intended as test code to test persistence etc. - */ - -/* XXX U-BOOT XXX */ -#include <common.h> - -const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.12 2007/02/14 01:09:06 wookey Exp $"; - - -#include "yportenv.h" - -#include "yaffs_flashif.h" -#include "yaffs_guts.h" -#include "devextras.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> - -#include "yaffs_fileem2k.h" -#include "yaffs_packedtags2.h" - -//#define SIMULATE_FAILURES - -typedef struct -{ - __u8 data[PAGE_SIZE]; // Data + spare -} yflash_Page; - -typedef struct -{ - yflash_Page page[PAGES_PER_BLOCK]; // The pages in the block - -} yflash_Block; - - - -#define MAX_HANDLES 20 -#define BLOCKS_PER_HANDLE 8000 - -typedef struct -{ - int handle[MAX_HANDLES]; - int nBlocks; -} yflash_Device; - -static yflash_Device filedisk; - -int yaffs_testPartialWrite = 0; - - - - -static __u8 localBuffer[PAGE_SIZE]; - -static char *NToName(char *buf,int n) -{ - sprintf(buf,"emfile%d",n); - return buf; -} - -static char dummyBuffer[BLOCK_SIZE]; - -static int GetBlockFileHandle(int n) -{ - int h; - int requiredSize; - - char name[40]; - NToName(name,n); - int fSize; - int i; - - h = open(name, O_RDWR | O_CREAT, S_IREAD | S_IWRITE); - if(h >= 0){ - fSize = lseek(h,0,SEEK_END); - requiredSize = BLOCKS_PER_HANDLE * BLOCK_SIZE; - if(fSize < requiredSize){ - for(i = 0; i < BLOCKS_PER_HANDLE; i++) - if(write(h,dummyBuffer,BLOCK_SIZE) != BLOCK_SIZE) - return -1; - - } - } - - return h; - -} - -static int CheckInit(void) -{ - static int initialised = 0; - int h; - int i; - - - off_t fSize; - off_t requiredSize; - int written; - int blk; - - yflash_Page p; - - if(initialised) - { - return YAFFS_OK; - } - - initialised = 1; - - memset(dummyBuffer,0xff,sizeof(dummyBuffer)); - - - filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB; - - for(i = 0; i < MAX_HANDLES; i++) - filedisk.handle[i] = -1; - - for(i = 0,blk = 0; blk < filedisk.nBlocks; blk+=BLOCKS_PER_HANDLE,i++) - filedisk.handle[i] = GetBlockFileHandle(i); - - - return 1; -} - - -int yflash_GetNumberOfBlocks(void) -{ - CheckInit(); - - return filedisk.nBlocks; -} - -int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) -{ - int written; - int pos; - int h; - int i; - int nRead; - int error; - - T(YAFFS_TRACE_MTD,(TSTR("write chunk %d data %x tags %x" TENDSTR),chunkInNAND,(unsigned)data, (unsigned)tags)); - - CheckInit(); - - - - if(data) - { - pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; - h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - - lseek(h,pos,SEEK_SET); - nRead = read(h, localBuffer,dev->nDataBytesPerChunk); - for(i = error = 0; i < dev->nDataBytesPerChunk && !error; i++){ - if(localBuffer[i] != 0xFF){ - printf("nand simulation: chunk %d data byte %d was %0x2\n", - chunkInNAND,i,localBuffer[i]); - error = 1; - } - } - - for(i = 0; i < dev->nDataBytesPerChunk; i++) - localBuffer[i] &= data[i]; - - if(memcmp(localBuffer,data,dev->nDataBytesPerChunk)) - printf("nand simulator: data does not match\n"); - - lseek(h,pos,SEEK_SET); - written = write(h,localBuffer,dev->nDataBytesPerChunk); - - if(yaffs_testPartialWrite){ - close(h); - exit(1); - } - -#ifdef SIMULATE_FAILURES - if((chunkInNAND >> 6) == 100) - written = 0; - - if((chunkInNAND >> 6) == 110) - written = 0; -#endif - - - if(written != dev->nDataBytesPerChunk) return YAFFS_FAIL; - } - - if(tags) - { - pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ; - h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - - lseek(h,pos,SEEK_SET); - - if( 0 && dev->isYaffs2) - { - - written = write(h,tags,sizeof(yaffs_ExtendedTags)); - if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL; - } - else - { - yaffs_PackedTags2 pt; - yaffs_PackTags2(&pt,tags); - __u8 * ptab = (__u8 *)&pt; - - nRead = read(h,localBuffer,sizeof(pt)); - for(i = error = 0; i < sizeof(pt) && !error; i++){ - if(localBuffer[i] != 0xFF){ - printf("nand simulation: chunk %d oob byte %d was %0x2\n", - chunkInNAND,i,localBuffer[i]); - error = 1; - } - } - - for(i = 0; i < sizeof(pt); i++) - localBuffer[i] &= ptab[i]; - - if(memcmp(localBuffer,&pt,sizeof(pt))) - printf("nand sim: tags corruption\n"); - - lseek(h,pos,SEEK_SET); - - written = write(h,localBuffer,sizeof(pt)); - if(written != sizeof(pt)) return YAFFS_FAIL; - } - } - - - return YAFFS_OK; - -} - -int yaffs_CheckAllFF(const __u8 *ptr, int n) -{ - while(n) - { - n--; - if(*ptr!=0xFF) return 0; - ptr++; - } - return 1; -} - - -static int fail300 = 1; -static int fail320 = 1; - -static int failRead10 = 2; - -int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags) -{ - int nread; - int pos; - int h; - - T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %x tags %x" TENDSTR),chunkInNAND,(unsigned)data, (unsigned)tags)); - - CheckInit(); - - - - if(data) - { - - pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; - h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - lseek(h,pos,SEEK_SET); - nread = read(h,data,dev->nDataBytesPerChunk); - - - if(nread != dev->nDataBytesPerChunk) return YAFFS_FAIL; - } - - if(tags) - { - pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE; - h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - lseek(h,pos,SEEK_SET); - - if(0 && dev->isYaffs2) - { - nread= read(h,tags,sizeof(yaffs_ExtendedTags)); - if(nread != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL; - if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags))) - { - yaffs_InitialiseTags(tags); - } - else - { - tags->chunkUsed = 1; - } - } - else - { - yaffs_PackedTags2 pt; - nread= read(h,&pt,sizeof(pt)); - yaffs_UnpackTags2(tags,&pt); -#ifdef SIMULATE_FAILURES - if((chunkInNAND >> 6) == 100) { - if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){ - tags->eccResult = YAFFS_ECC_RESULT_FIXED; - fail300 = 0; - } - - } - if((chunkInNAND >> 6) == 110) { - if(fail320 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){ - tags->eccResult = YAFFS_ECC_RESULT_FIXED; - fail320 = 0; - } - } -#endif - if(failRead10>0 && chunkInNAND == 10){ - failRead10--; - nread = 0; - } - - if(nread != sizeof(pt)) return YAFFS_FAIL; - } - } - - - return YAFFS_OK; - -} - - -int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) -{ - int written; - int h; - - yaffs_PackedTags2 pt; - - CheckInit(); - - memset(&pt,0,sizeof(pt)); - h = filedisk.handle[(blockNo / ( BLOCKS_PER_HANDLE))]; - lseek(h,((blockNo % BLOCKS_PER_HANDLE) * dev->nChunksPerBlock) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET); - written = write(h,&pt,sizeof(pt)); - - if(written != sizeof(pt)) return YAFFS_FAIL; - - - return YAFFS_OK; - -} - -int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) -{ - - int i; - int h; - - CheckInit(); - - printf("erase block %d\n",blockNumber); - - if(blockNumber == 320) - fail320 = 1; - - if(blockNumber < 0 || blockNumber >= filedisk.nBlocks) - { - T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); - return YAFFS_FAIL; - } - else - { - - __u8 pg[PAGE_SIZE]; - int syz = PAGE_SIZE; - int pos; - - memset(pg,0xff,syz); - - - h = filedisk.handle[(blockNumber / ( BLOCKS_PER_HANDLE))]; - lseek(h,((blockNumber % BLOCKS_PER_HANDLE) * dev->nChunksPerBlock) * PAGE_SIZE,SEEK_SET); - for(i = 0; i < dev->nChunksPerBlock; i++) - { - write(h,pg,PAGE_SIZE); - } - pos = lseek(h, 0,SEEK_CUR); - - return YAFFS_OK; - } - -} - -int yflash_InitialiseNAND(yaffs_Device *dev) -{ - CheckInit(); - - return YAFFS_OK; -} - - - - -int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) -{ - yaffs_ExtendedTags tags; - int chunkNo; - - *sequenceNumber = 0; - - chunkNo = blockNo * dev->nChunksPerBlock; - - yflash_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags); - if(tags.blockBad) - { - *state = YAFFS_BLOCK_STATE_DEAD; - } - else if(!tags.chunkUsed) - { - *state = YAFFS_BLOCK_STATE_EMPTY; - } - else if(tags.chunkUsed) - { - *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; - *sequenceNumber = tags.sequenceNumber; - } - return YAFFS_OK; -} diff --git a/fs/yaffs2/direct/yaffs_fileem2k.h b/fs/yaffs2/direct/yaffs_fileem2k.h deleted file mode 100644 index e694c92..0000000 --- a/fs/yaffs2/direct/yaffs_fileem2k.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * YAFFS: Yet another Flash File System . A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 as - * published by the Free Software Foundation. - * - * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - */ - -#ifndef __FILEEM2K_H__ -#define __FILEEM2K_H__ - -#if 1 - -#define SIZE_IN_MB 128 -//#define SIZE_IN_MB 8000 -#define PAGE_DATA_SIZE (2048) -#define PAGE_SPARE_SIZE (64) -#define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE) -#define PAGES_PER_BLOCK (64) -#define BLOCK_DATA_SIZE (PAGE_DATA_SIZE * PAGES_PER_BLOCK) -#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE)) -#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE) -#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB) - -#else - -#define SIZE_IN_MB 128 -#define PAGE_DATA_SIZE (512) -#define SPARE_SIZE (16) -#define PAGE_SIZE (PAGE_DATA_SIZE + SPARE_SIZE) -#define PAGES_PER_BLOCK (32) -#define BLOCK_DATA_SIZE (PAGE_SIZE * PAGES_PER_BLOCK) -#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE)) -#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE) -#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB) - -#endif - - -int yflash_GetNumberOfBlocks(void); - -#endif - diff --git a/fs/yaffs2/direct/yaffs_flashif.c b/fs/yaffs2/direct/yaffs_flashif.c deleted file mode 100644 index 8d51dc6..0000000 --- a/fs/yaffs2/direct/yaffs_flashif.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * 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. - */ - -/* XXX U-BOOT XXX */ -#include <common.h> - -const char *yaffs_flashif_c_version = "$Id: yaffs_flashif.c,v 1.3 2007/02/14 01:09:06 wookey Exp $"; - - -#include "yportenv.h" - -#include "yaffs_flashif.h" -#include "yaffs_guts.h" -#include "devextras.h" - - -#define SIZE_IN_MB 16 - -#define BLOCK_SIZE (32 * 528) -#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512)) - - - -typedef struct -{ - __u8 data[528]; // Data + spare -} yflash_Page; - -typedef struct -{ - yflash_Page page[32]; // The pages in the block - -} yflash_Block; - - - -typedef struct -{ - yflash_Block **block; - int nBlocks; -} yflash_Device; - -static yflash_Device ramdisk; - -static int CheckInit(yaffs_Device *dev) -{ - static int initialised = 0; - - int i; - int fail = 0; - int nAllocated = 0; - - if(initialised) - { - return YAFFS_OK; - } - - initialised = 1; - - - ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024); - - ramdisk.block = YMALLOC(sizeof(yflash_Block *) * ramdisk.nBlocks); - - if(!ramdisk.block) return 0; - - for(i=0; i <ramdisk.nBlocks; i++) - { - ramdisk.block[i] = NULL; - } - - for(i=0; i <ramdisk.nBlocks && !fail; i++) - { - if((ramdisk.block[i] = YMALLOC(sizeof(yflash_Block))) == 0) - { - fail = 1; - } - else - { - yflash_EraseBlockInNAND(dev,i); - nAllocated++; - } - } - - if(fail) - { - for(i = 0; i < nAllocated; i++) - { - YFREE(ramdisk.block[i]); - } - YFREE(ramdisk.block); - - T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", - nAllocated/64,ramdisk.nBlocks * YAFFS_BYTES_PER_BLOCK)); - return 0; - } - - - - return 1; -} - -int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) -{ - int blk; - int pg; - - - CheckInit(dev); - - blk = chunkInNAND/32; - pg = chunkInNAND%32; - - - if(data) - { - memcpy(ramdisk.block[blk]->page[pg].data,data,512); - } - - - if(tags) - { - yaffs_PackedTags pt; - yaffs_PackTags(&pt,tags); - memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt)); - } - - return YAFFS_OK; - -} - - -int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Tags *tags) -{ - int blk; - int pg; - - - CheckInit(dev); - - blk = chunkInNAND/32; - pg = chunkInNAND%32; - - - if(data) - { - memcpy(data,ramdisk.block[blk]->page[pg].data,512); - } - - - if(tags) - { - yaffs_PackedTags pt; - memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(yaffs_PackedTags)); - yaffs_UnpackTags(tags,&pt); - } - - return YAFFS_OK; -} - - -int yflash_CheckChunkErased(yaffs_Device *dev,int chunkInNAND) -{ - int blk; - int pg; - int i; - - - CheckInit(dev); - - blk = chunkInNAND/32; - pg = chunkInNAND%32; - - - for(i = 0; i < 528; i++) - { - if(ramdisk.block[blk]->page[pg].data[i] != 0xFF) - { - return YAFFS_FAIL; - } - } - - return YAFFS_OK; - -} - -int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) -{ - - CheckInit(dev); - - if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks) - { - T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); - return YAFFS_FAIL; - } - else - { - memset(ramdisk.block[blockNumber],0xFF,sizeof(yflash_Block)); - return YAFFS_OK; - } - -} - -int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) -{ - return YAFFS_OK; - -} -int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) -{ - *state = YAFFS_BLOCK_STATE_EMPTY; - *sequenceNumber = 0; -} - - -int yflash_InitialiseNAND(yaffs_Device *dev) -{ - return YAFFS_OK; -} diff --git a/fs/yaffs2/direct/yaffs_ramdisk.c b/fs/yaffs2/direct/yaffs_ramdisk.c deleted file mode 100644 index 57f27ce..0000000 --- a/fs/yaffs2/direct/yaffs_ramdisk.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * 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. - */ - -/* - * yaffs_ramdisk.c: yaffs ram disk component - * This provides a ram disk under yaffs. - * NB this is not intended for NAND emulation. - * Use this with dev->useNANDECC enabled, then ECC overheads are not required. - */ - -/* XXX U-BOOT XXX */ -#include <common.h> - -const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.4 2007/02/14 01:09:06 wookey Exp $"; - - -#include "yportenv.h" - -#include "yaffs_ramdisk.h" -#include "yaffs_guts.h" -#include "devextras.h" -#include "yaffs_packedtags1.h" - - - -#define SIZE_IN_MB 2 - -#define BLOCK_SIZE (32 * 528) -#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512)) - - - - - -typedef struct -{ - __u8 data[528]; // Data + spare -} yramdisk_Page; - -typedef struct -{ - yramdisk_Page page[32]; // The pages in the block - -} yramdisk_Block; - - - -typedef struct -{ - yramdisk_Block **block; - int nBlocks; -} yramdisk_Device; - -static yramdisk_Device ramdisk; - -static int CheckInit(yaffs_Device *dev) -{ - static int initialised = 0; - - int i; - int fail = 0; - //int nBlocks; - int nAllocated = 0; - - if(initialised) - { - return YAFFS_OK; - } - - initialised = 1; - - - ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024); - - ramdisk.block = YMALLOC(sizeof(yramdisk_Block *) * ramdisk.nBlocks); - - if(!ramdisk.block) return 0; - - for(i=0; i <ramdisk.nBlocks; i++) - { - ramdisk.block[i] = NULL; - } - - for(i=0; i <ramdisk.nBlocks && !fail; i++) - { - if((ramdisk.block[i] = YMALLOC(sizeof(yramdisk_Block))) == 0) - { - fail = 1; - } - else - { - yramdisk_EraseBlockInNAND(dev,i); - nAllocated++; - } - } - - if(fail) - { - for(i = 0; i < nAllocated; i++) - { - YFREE(ramdisk.block[i]); - } - YFREE(ramdisk.block); - - T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", - nAllocated/64,ramdisk.nBlocks * 528)); - return 0; - } - - - return 1; -} - -int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) -{ - int blk; - int pg; - - - CheckInit(dev); - - blk = chunkInNAND/32; - pg = chunkInNAND%32; - - - if(data) - { - memcpy(ramdisk.block[blk]->page[pg].data,data,512); - } - - - if(tags) - { - yaffs_PackedTags1 pt; - - yaffs_PackTags1(&pt,tags); - memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt)); - } - - return YAFFS_OK; - -} - - -int yramdisk_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags) -{ - int blk; - int pg; - - - CheckInit(dev); - - blk = chunkInNAND/32; - pg = chunkInNAND%32; - - - if(data) - { - memcpy(data,ramdisk.block[blk]->page[pg].data,512); - } - - - if(tags) - { - yaffs_PackedTags1 pt; - - memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(pt)); - yaffs_UnpackTags1(tags,&pt); - - } - - return YAFFS_OK; -} - - -int yramdisk_CheckChunkErased(yaffs_Device *dev,int chunkInNAND) -{ - int blk; - int pg; - int i; - - - CheckInit(dev); - - blk = chunkInNAND/32; - pg = chunkInNAND%32; - - - for(i = 0; i < 528; i++) - { - if(ramdisk.block[blk]->page[pg].data[i] != 0xFF) - { - return YAFFS_FAIL; - } - } - - return YAFFS_OK; - -} - -int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) -{ - - CheckInit(dev); - - if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks) - { - T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); - return YAFFS_FAIL; - } - else - { - memset(ramdisk.block[blockNumber],0xFF,sizeof(yramdisk_Block)); - return YAFFS_OK; - } - -} - -int yramdisk_InitialiseNAND(yaffs_Device *dev) -{ - //dev->useNANDECC = 1; // force on useNANDECC which gets faked. - // This saves us doing ECC checks. - - return YAFFS_OK; -} diff --git a/fs/yaffs2/direct/yaffs_ramem2k.c b/fs/yaffs2/direct/yaffs_ramem2k.c deleted file mode 100644 index 8161789..0000000 --- a/fs/yaffs2/direct/yaffs_ramem2k.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * 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. - */ - -/* - * yaffs_ramem2k.c: RAM emulation in-kernel for 2K pages (YAFFS2) - */ - -/* XXX U-BOOT XXX */ -#include <common.h> - -const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.3 2007/02/14 01:09:06 wookey Exp $"; - -#ifndef __KERNEL__ -#define CONFIG_YAFFS_RAM_ENABLED -#else -#include <linux/config.h> -#endif - -#ifdef CONFIG_YAFFS_RAM_ENABLED - -#include "yportenv.h" - -#include "yaffs_nandemul2k.h" -#include "yaffs_guts.h" -#include "yaffsinterface.h" -#include "devextras.h" -#include "yaffs_packedtags2.h" - - - -#define EM_SIZE_IN_MEG (32) -#define PAGE_DATA_SIZE (2048) -#define PAGE_SPARE_SIZE (64) -#define PAGES_PER_BLOCK (64) - - - -#define EM_SIZE_IN_BYTES (EM_SIZE_IN_MEG * (1<<20)) - -#define PAGE_TOTAL_SIZE (PAGE_DATA_SIZE+PAGE_SPARE_SIZE) - -#define BLOCK_TOTAL_SIZE (PAGES_PER_BLOCK * PAGE_TOTAL_SIZE) - -#define BLOCKS_PER_MEG ((1<<20)/(PAGES_PER_BLOCK * PAGE_DATA_SIZE)) - - -typedef struct -{ - __u8 data[PAGE_TOTAL_SIZE]; // Data + spare - int empty; // is this empty? -} nandemul_Page; - - -typedef struct -{ - nandemul_Page *page[PAGES_PER_BLOCK]; - int damaged; -} nandemul_Block; - - - -typedef struct -{ - nandemul_Block**block; - int nBlocks; -} nandemul_Device; - -static nandemul_Device ned; - -static int sizeInMB = EM_SIZE_IN_MEG; - - -static void nandemul_yield(int n) -{ -#ifdef __KERNEL__ - if(n > 0) schedule_timeout(n); -#endif - -} - - -static void nandemul_ReallyEraseBlock(int blockNumber) -{ - int i; - - nandemul_Block *blk; - - if(blockNumber < 0 || blockNumber >= ned.nBlocks) - { - return; - } - - blk = ned.block[blockNumber]; - - for(i = 0; i < PAGES_PER_BLOCK; i++) - { - memset(blk->page[i],0xff,sizeof(nandemul_Page)); - blk->page[i]->empty = 1; - } - nandemul_yield(2); -} - - -static int nandemul2k_CalcNBlocks(void) -{ - return EM_SIZE_IN_MEG * BLOCKS_PER_MEG; -} - - - -static int CheckInit(void) -{ - static int initialised = 0; - - int i,j; - - int fail = 0; - int nBlocks; - - int nAllocated = 0; - - if(initialised) - { - return YAFFS_OK; - } - - - ned.nBlocks = nBlocks = nandemul2k_CalcNBlocks(); - - - ned.block = YMALLOC(sizeof(nandemul_Block*) * nBlocks ); - - if(!ned.block) return YAFFS_FAIL; - - - - - - for(i=fail=0; i <nBlocks; i++) - { - - nandemul_Block *blk; - - if(!(blk = ned.block[i] = YMALLOC(sizeof(nandemul_Block)))) - { - fail = 1; - } - else - { - for(j = 0; j < PAGES_PER_BLOCK; j++) - { - if((blk->page[j] = YMALLOC(sizeof(nandemul_Page))) == 0) - { - fail = 1; - } - } - nandemul_ReallyEraseBlock(i); - ned.block[i]->damaged = 0; - nAllocated++; - } - } - - if(fail) - { - //Todo thump pages - - for(i = 0; i < nAllocated; i++) - { - YFREE(ned.block[i]); - } - YFREE(ned.block); - - T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", - nAllocated/64,sizeInMB)); - return 0; - } - - ned.nBlocks = nBlocks; - - initialised = 1; - - return 1; -} - -int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) -{ - int blk; - int pg; - int i; - - __u8 *x; - - - blk = chunkInNAND/PAGES_PER_BLOCK; - pg = chunkInNAND%PAGES_PER_BLOCK; - - - if(data) - { - x = ned.block[blk]->page[pg]->data; - - for(i = 0; i < PAGE_DATA_SIZE; i++) - { - x[i] &=data[i]; - } - - ned.block[blk]->page[pg]->empty = 0; - } - - - if(tags) - { - x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE]; - - yaffs_PackTags2((yaffs_PackedTags2 *)x,tags); - - } - - if(tags || data) - { - nandemul_yield(1); - } - - return YAFFS_OK; -} - - -int nandemul2k_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags) -{ - int blk; - int pg; - - __u8 *x; - - - - blk = chunkInNAND/PAGES_PER_BLOCK; - pg = chunkInNAND%PAGES_PER_BLOCK; - - - if(data) - { - memcpy(data,ned.block[blk]->page[pg]->data,PAGE_DATA_SIZE); - } - - - if(tags) - { - x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE]; - - yaffs_UnpackTags2(tags,(yaffs_PackedTags2 *)x); - } - - return YAFFS_OK; -} - - -static int nandemul2k_CheckChunkErased(yaffs_Device *dev,int chunkInNAND) -{ - int blk; - int pg; - int i; - - - - blk = chunkInNAND/PAGES_PER_BLOCK; - pg = chunkInNAND%PAGES_PER_BLOCK; - - - for(i = 0; i < PAGE_TOTAL_SIZE; i++) - { - if(ned.block[blk]->page[pg]->data[i] != 0xFF) - { - return YAFFS_FAIL; - } - } - - return YAFFS_OK; - -} - -int nandemul2k_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) -{ - - - if(blockNumber < 0 || blockNumber >= ned.nBlocks) - { - T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); - } - else if(ned.block[blockNumber]->damaged) - { - T(YAFFS_TRACE_ALWAYS,("Attempt to erase damaged block %d\n",blockNumber)); - } - else - { - nandemul_ReallyEraseBlock(blockNumber); - } - - return YAFFS_OK; -} - -int nandemul2k_InitialiseNAND(yaffs_Device *dev) -{ - CheckInit(); - return YAFFS_OK; -} - -int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) -{ - - __u8 *x; - - x = &ned.block[blockNo]->page[0]->data[PAGE_DATA_SIZE]; - - memset(x,0,sizeof(yaffs_PackedTags2)); - - - return YAFFS_OK; - -} - -int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) -{ - yaffs_ExtendedTags tags; - int chunkNo; - - *sequenceNumber = 0; - - chunkNo = blockNo * dev->nChunksPerBlock; - - nandemul2k_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags); - if(tags.blockBad) - { - *state = YAFFS_BLOCK_STATE_DEAD; - } - else if(!tags.chunkUsed) - { - *state = YAFFS_BLOCK_STATE_EMPTY; - } - else if(tags.chunkUsed) - { - *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; - *sequenceNumber = tags.sequenceNumber; - } - return YAFFS_OK; -} - -int nandemul2k_GetBytesPerChunk(void) { return PAGE_DATA_SIZE;} - -int nandemul2k_GetChunksPerBlock(void) { return PAGES_PER_BLOCK; } -int nandemul2k_GetNumberOfBlocks(void) {return nandemul2k_CalcNBlocks();} - - -#endif //YAFFS_RAM_ENABLED diff --git a/fs/yaffs2/direct/yaffscfg2k.c b/fs/yaffs2/direct/yaffscfg2k.c deleted file mode 100644 index 1daede1..0000000 --- a/fs/yaffs2/direct/yaffscfg2k.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * 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. - */ - -/* - * yaffscfg2k.c The configuration for the "direct" use of yaffs. - * - * This file is intended to be modified to your requirements. - * There is no need to redistribute this file. - */ - -/* XXX U-BOOT XXX */ -#include <common.h> - -#include "yaffscfg.h" -#include "yaffsfs.h" -#include "yaffs_fileem2k.h" -#include "yaffs_nandemul2k.h" - -#include <errno.h> - -unsigned yaffs_traceMask = - - YAFFS_TRACE_SCAN | - YAFFS_TRACE_GC | YAFFS_TRACE_GC_DETAIL | - YAFFS_TRACE_ERASE | - YAFFS_TRACE_TRACING | - YAFFS_TRACE_ALLOCATE | - YAFFS_TRACE_CHECKPOINT | - YAFFS_TRACE_BAD_BLOCKS | - YAFFS_TRACE_VERIFY | - YAFFS_TRACE_VERIFY_NAND | - YAFFS_TRACE_VERIFY_FULL | -// (~0) | - - 0; - - - -void yaffsfs_SetError(int err) -{ - //Do whatever to set error - errno = err; -} - -void yaffsfs_Lock(void) -{ -} - -void yaffsfs_Unlock(void) -{ -} - -__u32 yaffsfs_CurrentTime(void) -{ - return 0; -} - - -static int yaffs_kill_alloc = 0; -static size_t total_malloced = 0; -static size_t malloc_limit = 0 & 6000000; - -void *yaffs_malloc(size_t size) -{ - size_t this; - if(yaffs_kill_alloc) - return NULL; - if(malloc_limit && malloc_limit <(total_malloced + size) ) - return NULL; - - this = malloc(size); - if(this) - total_malloced += size; - return this; -} - -void yaffs_free(void *ptr) -{ - free(ptr); -} - -void yaffsfs_LocalInitialisation(void) -{ - // Define locking semaphore. -} - -// Configuration for: -// /ram 2MB ramdisk -// /boot 2MB boot disk (flash) -// /flash 14MB flash disk (flash) -// NB Though /boot and /flash occupy the same physical device they -// are still disticnt "yaffs_Devices. You may think of these as "partitions" -// using non-overlapping areas in the same device. -// - -#include "yaffs_ramdisk.h" -#include "yaffs_flashif.h" -#include "yaffs_nandemul2k.h" - -static yaffs_Device ramDev; -static yaffs_Device bootDev; -static yaffs_Device flashDev; -static yaffs_Device ram2kDev; - -static yaffsfs_DeviceConfiguration yaffsfs_config[] = { -#if 0 - { "/ram", &ramDev}, - { "/boot", &bootDev}, - { "/flash/", &flashDev}, - { "/ram2k", &ram2kDev}, - {(void *)0,(void *)0} -#else - { "/", &ramDev}, - { "/flash/boot", &bootDev}, - { "/flash/flash", &flashDev}, - { "/ram2k", &ram2kDev}, - {(void *)0,(void *)0} /* Null entry to terminate list */ -#endif -}; - - -int yaffs_StartUp(void) -{ - // Stuff to configure YAFFS - // Stuff to initialise anything special (eg lock semaphore). - yaffsfs_LocalInitialisation(); - - // Set up devices - // /ram - memset(&ramDev,0,sizeof(ramDev)); - ramDev.nDataBytesPerChunk = 512; - ramDev.nChunksPerBlock = 32; - ramDev.nReservedBlocks = 2; // Set this smaller for RAM - ramDev.startBlock = 0; // Can use block 0 - ramDev.endBlock = 127; // Last block in 2MB. - //ramDev.useNANDECC = 1; - ramDev.nShortOpCaches = 0; // Disable caching on this device. - ramDev.genericDevice = (void *) 0; // Used to identify the device in fstat. - ramDev.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND; - ramDev.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND; - ramDev.eraseBlockInNAND = yramdisk_EraseBlockInNAND; - ramDev.initialiseNAND = yramdisk_InitialiseNAND; - - // /boot - memset(&bootDev,0,sizeof(bootDev)); - bootDev.nDataBytesPerChunk = 512; - bootDev.nChunksPerBlock = 32; - bootDev.nReservedBlocks = 5; - bootDev.startBlock = 0; // Can use block 0 - bootDev.endBlock = 63; // Last block - //bootDev.useNANDECC = 0; // use YAFFS's ECC - bootDev.nShortOpCaches = 10; // Use caches - bootDev.genericDevice = (void *) 1; // Used to identify the device in fstat. - bootDev.writeChunkWithTagsToNAND = yflash_WriteChunkWithTagsToNAND; - bootDev.readChunkWithTagsFromNAND = yflash_ReadChunkWithTagsFromNAND; - bootDev.eraseBlockInNAND = yflash_EraseBlockInNAND; - bootDev.initialiseNAND = yflash_InitialiseNAND; - bootDev.markNANDBlockBad = yflash_MarkNANDBlockBad; - bootDev.queryNANDBlock = yflash_QueryNANDBlock; - - - - // /flash - // Set this puppy up to use - // the file emulation space as - // 2kpage/64chunk per block/128MB device - memset(&flashDev,0,sizeof(flashDev)); - - flashDev.nDataBytesPerChunk = 2048; - flashDev.nChunksPerBlock = 64; - flashDev.nReservedBlocks = 5; - flashDev.nCheckpointReservedBlocks = 5; - //flashDev.checkpointStartBlock = 1; - //flashDev.checkpointEndBlock = 20; - flashDev.startBlock = 0; - flashDev.endBlock = 200; // Make it smaller - //flashDev.endBlock = yflash_GetNumberOfBlocks()-1; - flashDev.isYaffs2 = 1; - flashDev.wideTnodesDisabled=0; - flashDev.nShortOpCaches = 10; // Use caches - flashDev.genericDevice = (void *) 2; // Used to identify the device in fstat. - flashDev.writeChunkWithTagsToNAND = yflash_WriteChunkWithTagsToNAND; - flashDev.readChunkWithTagsFromNAND = yflash_ReadChunkWithTagsFromNAND; - flashDev.eraseBlockInNAND = yflash_EraseBlockInNAND; - flashDev.initialiseNAND = yflash_InitialiseNAND; - flashDev.markNANDBlockBad = yflash_MarkNANDBlockBad; - flashDev.queryNANDBlock = yflash_QueryNANDBlock; - - // /ram2k - // Set this puppy up to use - // the file emulation space as - // 2kpage/64chunk per block/128MB device - memset(&ram2kDev,0,sizeof(ram2kDev)); - - ram2kDev.nDataBytesPerChunk = nandemul2k_GetBytesPerChunk(); - ram2kDev.nChunksPerBlock = nandemul2k_GetChunksPerBlock(); - ram2kDev.nReservedBlocks = 5; - ram2kDev.startBlock = 0; // First block after /boot - //ram2kDev.endBlock = 127; // Last block in 16MB - ram2kDev.endBlock = nandemul2k_GetNumberOfBlocks() - 1; // Last block in 512MB - ram2kDev.isYaffs2 = 1; - ram2kDev.nShortOpCaches = 10; // Use caches - ram2kDev.genericDevice = (void *) 3; // Used to identify the device in fstat. - ram2kDev.writeChunkWithTagsToNAND = nandemul2k_WriteChunkWithTagsToNAND; - ram2kDev.readChunkWithTagsFromNAND = nandemul2k_ReadChunkWithTagsFromNAND; - ram2kDev.eraseBlockInNAND = nandemul2k_EraseBlockInNAND; - ram2kDev.initialiseNAND = nandemul2k_InitialiseNAND; - ram2kDev.markNANDBlockBad = nandemul2k_MarkNANDBlockBad; - ram2kDev.queryNANDBlock = nandemul2k_QueryNANDBlock; - - yaffs_initialise(yaffsfs_config); - - return 0; -} - - - -void SetCheckpointReservedBlocks(int n) -{ - flashDev.nCheckpointReservedBlocks = n; -} diff --git a/fs/yaffs2/moduleconfig.h b/fs/yaffs2/moduleconfig.h deleted file mode 100644 index faf135d..0000000 --- a/fs/yaffs2/moduleconfig.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * YAFFS: Yet another Flash File System . A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Martin Fouts <Martin.Fouts@palmsource.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 as - * published by the Free Software Foundation. - * - * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - */ - -#ifndef __YAFFS_CONFIG_H__ -#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 - -/* 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 - -/* Default: 10 */ -/* Meaning: set the count of blocks to reserve for checkpointing */ -#define CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS 10 - -/* -Older-style on-NAND data format has a "pageStatus" byte to record -chunk/page state. This byte is zeroed when the page is discarded. -Choose this option if you have existing on-NAND data in this format -that you need to continue to support. New data written also uses the -older-style format. -Note: Use of this option generally requires that MTD's oob layout be -adjusted to use the older-style format. See notes on tags formats and -MTD versions in yaffs_mtdif1.c. -*/ -/* Default: Not selected */ -/* Meaning: Use older-style on-NAND data format with pageStatus byte */ -//#define CONFIG_YAFFS_9BYTE_TAGS - -#endif /* YAFFS_OUT_OF_TREE */ - -#endif /* __YAFFS_CONFIG_H__ */ diff --git a/fs/yaffs2/mtdemul/Makefile b/fs/yaffs2/mtdemul/Makefile deleted file mode 100644 index fe03b47..0000000 --- a/fs/yaffs2/mtdemul/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -#Makefile for NANDemul MTD -# -# NB this is not yet suitable for putting into the kernel tree. -# YAFFS: Yet another Flash File System. A NAND-flash specific file system. -# -# Copyright (C) 2002 Aleph One Ltd. -# for Toby Churchill Ltd and Brightstar Engineering -# -# Created by Charles Manning <charles@aleph1.co.uk> -# -# 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 -## comment out USE_xxxx if you don't want these features. - -KERNELDIR = /usr/src/kernel-headers-2.4.27 - -CFLAGS = -D__KERNEL__ -DMODULE -I$(KERNELDIR)/include -O2 -Wall -g - - - -TARGET = nandemul2k.o - -default: $(TARGET) - -clean: - rm -f $(TARGET) - -$(TARGET): %.o: %.c - gcc -c $(CFLAGS) $< -o $@ - diff --git a/fs/yaffs2/mtdemul/nandemul2k.c b/fs/yaffs2/mtdemul/nandemul2k.c deleted file mode 100644 index bcbf16a..0000000 --- a/fs/yaffs2/mtdemul/nandemul2k.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * - * 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. - */ - -/* - * This version hacked for emulating 2kpage NAND for YAFFS2 testing. - */ - -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/version.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/fs.h> -#include <linux/proc_fs.h> -#include <linux/pagemap.h> -#include <linux/mtd/mtd.h> -#include <linux/interrupt.h> -#include <linux/string.h> -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include <linux/locks.h> -#endif - -#include <asm/uaccess.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/partitions.h> -#include <linux/mtd/nand.h> -#include "../yaffs_nandemul2k.h" - -#define ALLOCATE(x) kmalloc(x,GFP_KERNEL) -#define FREE(x) kfree(x) - - - - - -#define NAND_SHIFT (11) // Shifter for 2k -#define PAGE_DATA_SIZE (1 << NAND_SHIFT) -#define PAGE_SPARE_SIZE (64) -#define BLK_SHIFT 6 -#define PAGES_PER_BLOCK (1 << BLK_SHIFT) // = 64 - - -#define EM_SIZE_IN_MEG 4 -#define EM_SIZE_IN_BYTES (EM_SIZE_IN_MEG * (1<<20)) - -#define PAGE_TOTAL_SIZE (PAGE_DATA_SIZE+PAGE_SPARE_SIZE) - -#define BLOCK_TOTAL_SIZE (PAGES_PER_BLOCK * PAGE_TOTAL_SIZE) - -#define BLOCKS_PER_MEG ((1<<20)/(PAGES_PER_BLOCK * PAGE_DATA_SIZE)) - - -static struct mtd_info nandemul2k_mtd; - -typedef struct -{ - __u8 data[PAGE_TOTAL_SIZE]; // Data + spare - int empty; // is this empty? -} nandemul_Page; - - -typedef struct -{ - nandemul_Page *page[PAGES_PER_BLOCK]; - int damaged; -} nandemul_Block; - - - -typedef struct -{ - nandemul_Block**block; - int nBlocks; -} nandemul_Device; - -static nandemul_Device ned; - -static int sizeInMB = EM_SIZE_IN_MEG; - - -static void nandemul_yield(int n) -{ -#ifdef __KERNEL__ - if(n > 0) schedule_timeout(n); -#endif - -} - - -static void nandemul2k_Read(void *buffer, int page, int start, int nBytes) -{ - int pg = page%PAGES_PER_BLOCK; - int blk = page/PAGES_PER_BLOCK; - if(buffer && nBytes > 0) - { - memcpy(buffer,&ned.block[blk]->page[pg]->data[start],nBytes); - } - -} - -static void nandemul2k_Program(const void *buffer, int page, int start, int nBytes) -{ - int pg = page%PAGES_PER_BLOCK; - int blk = page/PAGES_PER_BLOCK; - __u8 *p; - __u8 *b = (__u8 *)buffer; - - p = &ned.block[blk]->page[pg]->data[start]; - - while(buffer && nBytes>0) - { - *p = *p & *b; - p++; - b++; - nBytes--; - } -} - -static void nandemul2k_DoErase(int blockNumber) -{ - int i; - - nandemul_Block *blk; - - if(blockNumber < 0 || blockNumber >= ned.nBlocks) - { - return; - } - - blk = ned.block[blockNumber]; - - for(i = 0; i < PAGES_PER_BLOCK; i++) - { - memset(blk->page[i],0xff,sizeof(nandemul_Page)); - blk->page[i]->empty = 1; - } - nandemul_yield(2); -} - - -static int nandemul2k_CalcNBlocks(void) -{ - return EM_SIZE_IN_MEG * BLOCKS_PER_MEG; -} - - - -static int CheckInit(void) -{ - static int initialised = 0; - - int i,j; - - int fail = 0; - int nBlocks; - - int nAllocated = 0; - - if(initialised) - { - return 0; - } - - - ned.nBlocks = nBlocks = nandemul2k_CalcNBlocks(); - - - ned.block = ALLOCATE(sizeof(nandemul_Block*) * nBlocks ); - - if(!ned.block) return ENOMEM; - - - - - - for(i=fail=0; i <nBlocks; i++) - { - - nandemul_Block *blk; - - if(!(blk = ned.block[i] = ALLOCATE(sizeof(nandemul_Block)))) - { - fail = 1; - } - else - { - for(j = 0; j < PAGES_PER_BLOCK; j++) - { - if((blk->page[j] = ALLOCATE(sizeof(nandemul_Page))) == 0) - { - fail = 1; - } - } - nandemul2k_DoErase(i); - ned.block[i]->damaged = 0; - nAllocated++; - } - } - - if(fail) - { - //Todo thump pages - - for(i = 0; i < nAllocated; i++) - { - FREE(ned.block[i]); - } - FREE(ned.block); - - return ENOMEM; - } - - ned.nBlocks = nBlocks; - - initialised = 1; - - return 1; -} - - - -static void nandemul2k_CleanUp(void) -{ - int i,j; - - for(i = 0; i < ned.nBlocks; i++) - { - for(j = 0; j < PAGES_PER_BLOCK; j++) - { - FREE(ned.block[i]->page[j]); - } - FREE(ned.block[i]); - - } - FREE(ned.block); - ned.block = 0; -} - -int nandemul2k_GetBytesPerChunk(void) { return PAGE_DATA_SIZE;} - -int nandemul2k_GetChunksPerBlock(void) { return PAGES_PER_BLOCK; } -int nandemul2k_GetNumberOfBlocks(void) {return nandemul2k_CalcNBlocks();} - - - -static int nandemul2k_ReadId(__u8 *vendorId, __u8 *deviceId) -{ - *vendorId = 'Y'; - *deviceId = '2'; - - return 1; -} - - -static int nandemul2k_ReadStatus(__u8 *status) -{ - *status = 0; - return 1; -} - - -#ifdef CONFIG_MTD_NAND_ECC -#include <linux/mtd/nand_ecc.h> -#endif - -/* - * NAND low-level MTD interface functions - */ -static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf); -static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf, u_char *oob_buf, struct nand_oobinfo *dummy); -static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf); -static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf); -static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, - u_char *oob_buf, struct nand_oobinfo *dummy); -static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7)) -static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen); -#else -static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs, - unsigned long count, loff_t to, size_t *retlen); -#endif -static int nand_erase (struct mtd_info *mtd, struct erase_info *instr); -static void nand_sync (struct mtd_info *mtd); - - - -/* - * NAND read - */ -static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - return nand_read_ecc (mtd, from, len, retlen, buf, NULL,NULL); -} - - -/* - * NAND read with ECC - */ -static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf, u_char *oob_buf,struct nand_oobinfo *oobsel) -{ - int start, page; - int n = len; - int nToCopy; - - - - /* Do not allow reads past end of device */ - if ((from + len) > mtd->size) { - *retlen = 0; - return -EINVAL; - } - - - /* Initialize return value */ - *retlen = 0; - - while(n > 0) - { - - /* First we calculate the starting page */ - page = from >> NAND_SHIFT; - - /* Get raw starting column */ - - start = from & (mtd->oobblock-1); - - // OK now check for the curveball where the start and end are in - // the same page - if((start + n) < mtd->oobblock) - { - nToCopy = n; - } - else - { - nToCopy = mtd->oobblock - start; - } - - nandemul2k_Read(buf, page, start, nToCopy); - nandemul2k_Read(oob_buf,page,PAGE_DATA_SIZE,PAGE_SPARE_SIZE); - - n -= nToCopy; - from += nToCopy; - buf += nToCopy; - if(oob_buf) oob_buf += PAGE_SPARE_SIZE; - *retlen += nToCopy; - - } - - - return 0; -} - -/* - * NAND read out-of-band - */ -static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - int col, page; - - T(0,("nand_read_oob: from = 0x%08x, buf = 0x%08x, len = %i\n", (unsigned int) from, (unsigned int) buf, - (int) len)); - - /* Shift to get page */ - page = ((int) from) >> NAND_SHIFT; - - /* Mask to get column */ - col = from & 0x0f; - - /* Initialize return length value */ - *retlen = 0; - - /* Do not allow reads past end of device */ - if ((from + len) > mtd->size) { - T(0, - ("nand_read_oob: Attempt read beyond end of device\n")); - *retlen = 0; - return -EINVAL; - } - - nandemul2k_Read(buf,page,PAGE_DATA_SIZE + col,len); - - /* Return happy */ - *retlen = len; - return 0; -} - -/* - * NAND write - */ -static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - return nand_write_ecc (mtd, to, len, retlen, buf, NULL,NULL); -} - -/* - * NAND write with ECC - */ -static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, - u_char *oob_buf, struct nand_oobinfo *dummy) -{ - - int start, page; - int n = len; - int nToCopy; - - - - /* Do not allow reads past end of device */ - if ((to + len) > mtd->size) { - *retlen = 0; - return -EINVAL; - } - - - /* Initialize return value */ - *retlen = 0; - - while(n > 0) - { - - /* First we calculate the starting page */ - page = to >> NAND_SHIFT; - - /* Get raw starting column */ - - start = to & (mtd->oobblock - 1); - - // OK now check for the curveball where the start and end are in - // the same page - if((start + n) < mtd->oobblock) - { - nToCopy = n; - } - else - { - nToCopy = mtd->oobblock - start; - } - - nandemul2k_Program(buf, page, start, nToCopy); - nandemul2k_Program(oob_buf, page, PAGE_DATA_SIZE, PAGE_SPARE_SIZE); - - n -= nToCopy; - to += nToCopy; - buf += nToCopy; - if(oob_buf) oob_buf += PAGE_SPARE_SIZE; - *retlen += nToCopy; - - } - - - return 0; -} - -/* - * NAND write out-of-band - */ -static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - int col, page; - - - T(0,( - "nand_read_oob: to = 0x%08x, len = %i\n", (unsigned int) to, - (int) len)); - - /* Shift to get page */ - page = ((int) to) >> NAND_SHIFT; - - /* Mask to get column */ - col = to & 0x0f; - - /* Initialize return length value */ - *retlen = 0; - - /* Do not allow reads past end of device */ - if ((to + len) > mtd->size) { - T(0,( - "nand_read_oob: Attempt read beyond end of device\n")); - *retlen = 0; - return -EINVAL; - } - - nandemul2k_Program(buf,page,512 + col,len); - - /* Return happy */ - *retlen = len; - return 0; - -} - -/* - * NAND write with iovec - */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7)) -static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, - unsigned long count, loff_t to, size_t *retlen) -#else -static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs, - unsigned long count, loff_t to, size_t *retlen) -#endif -{ - return -EINVAL; -} - -/* - * NAND erase a block - */ -static int nand_erase (struct mtd_info *mtd, struct erase_info *instr) -{ - int i, nBlocks,block; - - T(0,( - "nand_erase: start = 0x%08x, len = %i\n", - (unsigned int) instr->addr, (unsigned int) instr->len)); - - /* Start address must align on block boundary */ - if (instr->addr & (mtd->erasesize - 1)) { - T(0,( - "nand_erase: Unaligned address\n")); - return -EINVAL; - } - - /* Length must align on block boundary */ - if (instr->len & (mtd->erasesize - 1)) { - T(0,( - "nand_erase: Length not block aligned\n")); - return -EINVAL; - } - - /* Do not allow erase past end of device */ - if ((instr->len + instr->addr) > mtd->size) { - T(0,( - "nand_erase: Erase past end of device\n")); - return -EINVAL; - } - - nBlocks = instr->len >> (NAND_SHIFT + BLK_SHIFT); - block = instr->addr >> (NAND_SHIFT + BLK_SHIFT); - - for(i = 0; i < nBlocks; i++) - { - nandemul2k_DoErase(block); - block++; - } - - instr->state = MTD_ERASE_DONE; Â * change state to ERASE_DONE */ - - instr->callback(instr); Â * wake up */ - - return 0; - - -} - - -static int nand_block_isbad(struct mtd_info *mtd, loff_t ofs) -{ - return 0; -} - -static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) -{ - return 0; -} - - -/* - * NAND sync - */ -static void nand_sync (struct mtd_info *mtd) -{ - T(0,("nand_sync: called\n")); - -} - -/* - * Scan for the NAND device - */ -static int nandemul2k_scan (struct mtd_info *mtd,int nchips) -{ - mtd->oobblock = PAGE_DATA_SIZE; - mtd->oobsize = PAGE_SPARE_SIZE; - mtd->erasesize = PAGE_DATA_SIZE * PAGES_PER_BLOCK; - mtd->size = sizeInMB * 1024*1024; - - - - /* Fill in remaining MTD driver data */ - mtd->type = MTD_NANDFLASH; - mtd->flags = MTD_CAP_NANDFLASH; - mtd->owner = THIS_MODULE; - mtd->ecctype = MTD_ECC_NONE; - mtd->erase = nand_erase; - mtd->point = NULL; - mtd->unpoint = NULL; - mtd->read = nand_read; - mtd->write = nand_write; - mtd->read_ecc = nand_read_ecc; - mtd->write_ecc = nand_write_ecc; - mtd->read_oob = nand_read_oob; - mtd->write_oob = nand_write_oob; - mtd->block_isbad = nand_block_isbad; - mtd->block_markbad = nand_block_markbad; - mtd->readv = NULL; - mtd->writev = nand_writev; - mtd->sync = nand_sync; - mtd->lock = NULL; - mtd->unlock = NULL; - mtd->suspend = NULL; - mtd->resume = NULL; - - mtd->name = "NANDemul2k"; - - /* Return happy */ - return 0; -} - -#if 0 -#ifdef MODULE -MODULE_PARM(sizeInMB, "i"); - -__setup("sizeInMB=",sizeInMB); -#endif -#endif - -/* - * Define partitions for flash devices - */ - -static struct mtd_partition nandemul2k_partition[] = -{ - { .name = "NANDemul partition 1", - .offset = 0, - .size = 0 }, -}; - -static int nPartitions = sizeof(nandemul2k_partition)/sizeof(nandemul2k_partition[0]); - -/* - * Main initialization routine - */ -int __init nandemul2k_init (void) -{ - - // Do the nand init - - CheckInit(); - - nandemul2k_scan(&nandemul2k_mtd,1); - - // Build the partition table - - nandemul2k_partition[0].size = sizeInMB * 1024 * 1024; - - // Register the partition - add_mtd_partitions(&nandemul2k_mtd,nandemul2k_partition,nPartitions); - - return 0; - -} - -module_init(nandemul2k_init); - -/* - * Clean up routine - */ -#ifdef MODULE -static void __exit nandemul2k_cleanup (void) -{ - - nandemul2k_CleanUp(); - - /* Unregister partitions */ - del_mtd_partitions(&nandemul2k_mtd); - - /* Unregister the device */ - del_mtd_device (&nandemul2k_mtd); - -} -module_exit(nandemul2k_cleanup); -#endif - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Charles Manning <manningc@aleph1.co.uk>"); -MODULE_DESCRIPTION("2k Page/128k Block NAND emulated in RAM"); - - - - diff --git a/fs/yaffs2/patch-ker.sh b/fs/yaffs2/patch-ker.sh deleted file mode 100755 index 173d1ce..0000000 --- a/fs/yaffs2/patch-ker.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh -# -# YAFFS: Yet another FFS. A NAND-flash specific file system. -# -# Copyright (C) 2002-2006 Aleph One Ltd. -# -# Created by Charles Manning <charles@aleph1.co.uk> -# -# 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. -# -# Patch YAFFS into the kernel -# -# args: kpath : Full path to kernel sources to be patched -# -# Somewhat "inspired by" the mtd patchin script -# -# $Id: patch-ker.sh,v 1.3 2007/07/25 01:04:38 charles Exp $ - -VERSION=0 -PATCHLEVEL=0 -SUBLEVEL=0 -COPYORLINK=$1 -LINUXDIR=$2 - -# To be a Linux directory, it must have a Makefile - - -# Display usage of this script -usage () { - echo "usage: $0 c/l kernelpath" - echo " if c/l is c, then copy. If l then link" - exit 1 -} - - - -if [ -z $LINUXDIR ] -then - usage; -fi - -if [ $COPYORLINK = l ]; then - CPY="ln -s" -elif [ $COPYORLINK = c ]; then - CPY="cp" -else - echo "unknown copy or link type" - usage; -fi - - -# Check if kerneldir contains a Makefile -if [ ! -f $LINUXDIR/Makefile ] -then - echo "Directory $LINUXDIR does not exist or is not a kernel source directory"; - exit 1; -fi - -# Get kernel version -VERSION=`grep -s VERSION <$LINUXDIR/Makefile | head -n 1 | sed s/'VERSION = '//` -PATCHLEVEL=`grep -s PATCHLEVEL <$LINUXDIR/Makefile | head -n 1 | sed s/'PATCHLEVEL = '//` -SUBLEVEL=`grep -s SUBLEVEL <$LINUXDIR/Makefile | head -n 1 | sed s/'SUBLEVEL = '//` - -# Can we handle this version? -if [ $VERSION -ne 2 -o $PATCHLEVEL -lt 6 ] -then - echo "Cannot patch kernel version $VERSION.$PATCHLEVEL.$SUBLEVEL, must be 2.6.x or higher" - exit 1; -fi - - -KCONFIG=$LINUXDIR/fs/Kconfig -KCONFIGOLD=$LINUXDIR/fs/Kconfig.pre.yaffs -YAFFS_PATCHED_STRING=`grep -s yaffs <$KCONFIG | head -n 1` - -MAKEFILE=$LINUXDIR/fs/Makefile -MAKEFILEOLD=$LINUXDIR/fs/Makefile.pre.yaffs - -if [ ! -z "$YAFFS_PATCHED_STRING" ] -then - YAFFS_PATCHED=0 - echo "$KCONFIG already mentions YAFFS, so we will not change it" -else - # Change the fs/Kconfig file - # Save the old Kconfig - # Copy all stuff up to JFFS - # Insert some YAFFS stuff - # Copy all the rest of the stuff - - YAFFS_PATCHED=1 - echo "Updating $KCONFIG" - mv -f $KCONFIG $KCONFIGOLD - sed -n -e "/JFFS/,99999 ! p" $KCONFIGOLD >$KCONFIG - echo "">>$KCONFIG - echo "# Patched by YAFFS" >>$KCONFIG - echo "source \"fs/yaffs2/Kconfig\"">>$KCONFIG - echo "">>$KCONFIG - sed -n -e "/JFFS/,99999 p" $KCONFIGOLD >>$KCONFIG - - # now do fs/Makefile -- simply add the target at the end - echo "Updating $MAKEFILE" - cp -f $MAKEFILE $MAKEFILEOLD - echo "">>$MAKEFILE - echo "# Patched by YAFFS" >>$MAKEFILE - echo "obj-\$(CONFIG_YAFFS_FS) += yaffs2/" >>$MAKEFILE - -fi - -YAFFSDIR=$LINUXDIR/fs/yaffs2 - -if [ -e $YAFFSDIR ] -then - echo "$YAFFSDIR exists, not patching" -else - mkdir $LINUXDIR/fs/yaffs2 - $CPY $PWD/Makefile.kernel $LINUXDIR/fs/yaffs2/Makefile - $CPY $PWD/Kconfig $LINUXDIR/fs/yaffs2 - $CPY $PWD/*.c $PWD/*.h $LINUXDIR/fs/yaffs2 -fi diff --git a/fs/yaffs2/patches/README.txt b/fs/yaffs2/patches/README.txt deleted file mode 100644 index e3666d9..0000000 --- a/fs/yaffs2/patches/README.txt +++ /dev/null @@ -1,6 +0,0 @@ -This directory holds patches that are useful for Linux integration. - -Right now there is only one patched file, yaffs_mtdif2.c. This has been -patched with a tweaked version of "Sergey's patch" and typically makes a -stock mtd work properly. - diff --git a/fs/yaffs2/patches/yaffs_mtdif2.c b/fs/yaffs2/patches/yaffs_mtdif2.c deleted file mode 100644 index df5753b..0000000 --- a/fs/yaffs2/patches/yaffs_mtdif2.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * 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 <charles@aleph1.co.uk> - * - * 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. - */ - -/* mtd interface for YAFFS2 */ - -const char *yaffs_mtdif2_c_version = - "$Id: yaffs_mtdif2.c,v 1.2 2007/03/07 08:05:58 colin Exp $"; - -#include "yportenv.h" - - -#include "yaffs_mtdif2.h" - -#include "linux/mtd/mtd.h" -#include "linux/types.h" -#include "linux/time.h" - -#include "yaffs_packedtags2.h" - - -void nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw) -{ - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); - __u8 *ptab = (__u8 *)pt; /* packed tags as bytes */ - - int i, j = 0, k, n; - - /* Pack buffer with 0xff */ - for (i = 0; i < mtd->oobsize; i++) - dev->spareBuffer[i] = 0xff; - - if(!is_raw){ - memcpy(dev->spareBuffer,pt,sizeof(yaffs_PackedTags2)); - } else { - j = 0; - k = mtd->oobinfo.oobfree[j][0]; - n = mtd->oobinfo.oobfree[j][1]; - - if (n == 0) { - T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR))); - YBUG(); - } - - for (i = 0; i < sizeof(yaffs_PackedTags2); i++) { - if (n == 0) { - j++; - k = mtd->oobinfo.oobfree[j][0]; - n = mtd->oobinfo.oobfree[j][1]; - if (n == 0) { - T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR))); - YBUG(); - } - } - dev->spareBuffer[k] = ptab[i]; - k++; - n--; - } - } - -} - -void nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw) -{ - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); - int i, j = 0, k, n; - __u8 *ptab = (__u8 *)pt; /* packed tags as bytes */ - - - if (!is_raw) { - - memcpy(pt,dev->spareBuffer,sizeof(yaffs_PackedTags2)); - } else { - j = 0; - k = mtd->oobinfo.oobfree[j][0]; - n = mtd->oobinfo.oobfree[j][1]; - - if (n == 0) { - T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR))); - YBUG(); - } - - for (i = 0; i < sizeof(yaffs_PackedTags2); i++) { - if (n == 0) { - j++; - k = mtd->oobinfo.oobfree[j][0]; - n = mtd->oobinfo.oobfree[j][1]; - if (n == 0) { - T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR))); - YBUG(); - } - } - ptab[i] = dev->spareBuffer[k]; - k++; - n--; - } - } - -} - -int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, - const __u8 * data, - const yaffs_ExtendedTags * tags) -{ - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); - size_t dummy; - int retval = 0; - - loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; - - yaffs_PackedTags2 pt; - - T(YAFFS_TRACE_MTD, - (TSTR - ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" - TENDSTR), chunkInNAND, data, tags)); - - if (tags) { - yaffs_PackTags2(&pt, tags); - } - - if (data && tags) { - nandmtd2_pt2buf(dev, &pt, 0); - retval = - mtd->write_ecc(mtd, addr, dev->nBytesPerChunk, - &dummy, data, dev->spareBuffer, - NULL); - - } else { - - T(YAFFS_TRACE_ALWAYS, - (TSTR - ("Write chunk with null tags or data!" TENDSTR))); - YBUG(); - } - - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; -} - -int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, - __u8 * data, yaffs_ExtendedTags * tags) -{ - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); - size_t dummy; - int retval = 0; - - loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; - - yaffs_PackedTags2 pt; - - T(YAFFS_TRACE_MTD, - (TSTR - ("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p" - TENDSTR), chunkInNAND, data, tags)); - - if (0 && data && tags) { - retval = - mtd->read_ecc(mtd, addr, dev->nBytesPerChunk, - &dummy, data, dev->spareBuffer, - NULL); - nandmtd2_buf2pt(dev, &pt, 0); - } else { - if (data) - retval = - mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy, - data); - if (tags) { - retval = - mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, - dev->spareBuffer); - nandmtd2_buf2pt(dev, &pt, 1); - } - } - - if (tags) - yaffs_UnpackTags2(tags, &pt); - - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; -} - -int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) -{ - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); - int retval; - T(YAFFS_TRACE_MTD, - (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo)); - - retval = - mtd->block_markbad(mtd, - blockNo * dev->nChunksPerBlock * - dev->nBytesPerChunk); - - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; - -} - -int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, - yaffs_BlockState * state, int *sequenceNumber) -{ - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); - int retval; - - T(YAFFS_TRACE_MTD, - (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo)); - retval = - mtd->block_isbad(mtd, - blockNo * dev->nChunksPerBlock * - dev->nBytesPerChunk); - - if (retval) { - T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); - - *state = YAFFS_BLOCK_STATE_DEAD; - *sequenceNumber = 0; - } else { - yaffs_ExtendedTags t; - nandmtd2_ReadChunkWithTagsFromNAND(dev, - blockNo * - dev->nChunksPerBlock, NULL, - &t); - - if (t.chunkUsed) { - *sequenceNumber = t.sequenceNumber; - *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; - } else { - *sequenceNumber = 0; - *state = YAFFS_BLOCK_STATE_EMPTY; - } - - T(YAFFS_TRACE_MTD, - (TSTR("block is OK seq %d state %d" TENDSTR), *sequenceNumber, - *state)); - } - - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; -} - diff --git a/fs/yaffs2/utils/Makefile b/fs/yaffs2/utils/Makefile deleted file mode 100644 index 49bf03b..0000000 --- a/fs/yaffs2/utils/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -#Makefile for mkyaffs -# -# NB this is not yet suitable for putting into the kernel tree. -# YAFFS: Yet another Flash File System. A NAND-flash specific file system. -# -# Copyright (C) 2002 Aleph One Ltd. -# for Toby Churchill Ltd and Brightstar Engineering -# -# Created by Charles Manning <charles@aleph1.co.uk> -# -# 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 - -COMMONLINKS = yaffs_ecc.c -COMMONOBJS = $(COMMONLINKS:.c=.o) - -MKYAFFSSOURCES = mkyaffsimage.c -MKYAFFSIMAGEOBJS = $(MKYAFFSSOURCES:.c=.o) - -MKYAFFS2SOURCES = mkyaffs2image.c -MKYAFFS2LINKS = yaffs_packedtags2.c yaffs_tagsvalidity.c -MKYAFFS2IMAGEOBJS = $(MKYAFFS2SOURCES:.c=.o) $(MKYAFFS2LINKS:.c=.o) - -all: mkyaffsimage mkyaffs2image - -$(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS2LINKS): - ln -s ../$@ $@ - -$(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) : %.o: %.c - $(CC) -c $(CFLAGS) $< -o $@ - -mkyaffsimage: $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) - $(CC) -o $@ $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) - -mkyaffs2image: $(COMMONOBJS) $(MKYAFFS2IMAGEOBJS) - $(CC) -o $@ $(COMMONOBJS) $(MKYAFFS2IMAGEOBJS) - - -clean: - rm -f $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) $(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS2LINKS) mkyaffsimage mkyaffs2image core diff --git a/fs/yaffs2/utils/mkyaffs2image.c b/fs/yaffs2/utils/mkyaffs2image.c deleted file mode 100644 index 051666b..0000000 --- a/fs/yaffs2/utils/mkyaffs2image.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * Nick Bane modifications flagged NCB - * Endian handling patches by James Ng. - * mkyaffs2image hacks by NCB - * - * 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. - */ - -/* - * makeyaffs2image.c - * - * Makes a YAFFS2 file system image that can be used to load up a file system. - * Uses default Linux MTD layout - change if you need something different. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <string.h> -#include <unistd.h> -#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.4 2007/02/14 01:09:06 wookey 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); -} - diff --git a/fs/yaffs2/utils/mkyaffsimage.c b/fs/yaffs2/utils/mkyaffsimage.c deleted file mode 100644 index 2b8dc1e..0000000 --- a/fs/yaffs2/utils/mkyaffsimage.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * Nick Bane modifications flagged NCB - * Endian handling patches by James Ng - * - * 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. - */ - -/* - * makeyaffsimage.c - * - * Makes a YAFFS file system image that can be used to load up a file system. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <string.h> -#include <unistd.h> -#include "yaffs_ecc.h" -#include "yaffs_guts.h" - - -#define MAX_OBJECTS 10000 - -const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.7 2003/07/16 03:00:48 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; -} - -// NCB added 10/9/2002 -static __u16 yaffs_CalcNameSum(const char *name) -{ - __u16 sum = 0; - __u16 i = 1; - - __u8 *bname = (__u8 *)name; - - while (*bname) - { - sum += (*bname) * i; - i++; - bname++; - } - return sum; -} - - -static void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) -{ - yaffs_ECCCalculate(data , spare->ecc1); - yaffs_ECCCalculate(&data[256] , spare->ecc2); -} - -static void yaffs_CalcTagsECC(yaffs_Tags *tags) -{ - // Todo don't do anything yet. Need to calculate ecc - unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; - unsigned i,j; - unsigned ecc = 0; - unsigned bit = 0; - - // Clear ECC fields - if (!convert_endian) - { - tags->ecc = 0; - } - else - { - // Because we're in "munged tag" mode, we have to clear it manually - b[6] &= 0xC0; - b[7] &= 0x03; - } - - for(i = 0; i < 8; i++) - { -// NCB modified 20-9-02 for(j = 1; j &0x7f; j<<=1) - for(j = 1; j &0xff; j<<=1) - { - bit++; - if(b[i] & j) - { - ecc ^= bit; - } - } - } - - // Write out ECC - if (!convert_endian) - { - tags->ecc = ecc; - } - else - { - // We have to munge the ECC again. - b[6] |= ((ecc >> 6) & 0x3F); - b[7] |= ((ecc & 0x3F) << 2); - } -} -static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr) -{ - yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; - - //yaffs_CalcTagsECC(tagsPtr); - - sparePtr->tagByte0 = tu->asBytes[0]; - sparePtr->tagByte1 = tu->asBytes[1]; - sparePtr->tagByte2 = tu->asBytes[2]; - sparePtr->tagByte3 = tu->asBytes[3]; - sparePtr->tagByte4 = tu->asBytes[4]; - sparePtr->tagByte5 = tu->asBytes[5]; - sparePtr->tagByte6 = tu->asBytes[6]; - sparePtr->tagByte7 = tu->asBytes[7]; -} - -/* 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) -{ - 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]; -} - -static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) -{ - yaffs_Tags t; - yaffs_Spare s; - - error = write(outFile,data,512); - if(error < 0) return error; - - memset(&t,0xff,sizeof (yaffs_Tags)); - memset(&s,0xff,sizeof (yaffs_Spare)); - - t.chunkId = chunkId; - t.serialNumber = 0; - t.byteCount = nBytes; - t.objectId = objId; - - if (convert_endian) - { - little_to_big_endian(&t); - } - - yaffs_CalcTagsECC(&t); - yaffs_LoadTagsIntoSpare(&s,&t); - yaffs_CalcECC(data,&s); - - nPages++; - - return write(outFile,&s,sizeof(yaffs_Spare)); - -} - -#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[512]; - - - yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes; - - memset(bytes,0xff,512); - - 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[512]; - int nBytes; - int chunk = 0; - - h = open(full_name,O_RDONLY); - if(h >= 0) - { - memset(bytes,0xff,512); - while((nBytes = read(h,bytes,512)) > 0) - { - chunk++; - write_chunk(bytes,newObj,chunk,nBytes); - memset(bytes,0xff,512); - } - 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("mkyaffsimage: image building tool for YAFFS built "__DATE__"\n"); - - if(argc < 3) - { - printf("usage: mkyaffsimage 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); -} - diff --git a/fs/yaffs2/yaffs_fs.c b/fs/yaffs2/yaffs_fs.c deleted file mode 100644 index f7a8ebd..0000000 --- a/fs/yaffs2/yaffs_fs.c +++ /dev/null @@ -1,2299 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning <charles@aleph1.co.uk> - * Acknowledgements: - * Luc van OostenRyck for numerous patches. - * Nick Bane for numerous patches. - * Nick Bane for 2.5/2.6 integration. - * Andras Toth for mknod rdev issue. - * Michael Fischer for finding the problem with inode inconsistency. - * Some code bodily lifted from JFFS - * - * 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. - */ - -/* - * - * This is the file system front-end to YAFFS that hooks it up to - * the VFS. - * - * Special notes: - * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with - * this superblock - * >> 2.6: sb->s_fs_info points to the yaffs_Device associated with this - * superblock - * >> inode->u.generic_ip points to the associated yaffs_Object. - */ - -const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.63 2007/09/19 20:35:40 imcd Exp $"; -extern const char *yaffs_guts_c_version; - -#include <linux/version.h> -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -#include <linux/config.h> -#endif -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/fs.h> -#include <linux/proc_fs.h> -#include <linux/smp_lock.h> -#include <linux/pagemap.h> -#include <linux/mtd/mtd.h> -#include <linux/interrupt.h> -#include <linux/string.h> -#include <linux/ctype.h> - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - -#include <linux/statfs.h> /* Added NCB 15-8-2003 */ -#include <asm/statfs.h> -#define UnlockPage(p) unlock_page(p) -#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) - -/* FIXME: use sb->s_id instead ? */ -#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf) - -#else - -#include <linux/locks.h> -#define BDEVNAME_SIZE 0 -#define yaffs_devname(sb, buf) kdevname(sb->s_dev) - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */ -#define __user -#endif - -#endif - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -#define WRITE_SIZE_STR "writesize" -#define WRITE_SIZE(mtd) (mtd)->writesize -#else -#define WRITE_SIZE_STR "oobblock" -#define WRITE_SIZE(mtd) (mtd)->oobblock -#endif - -#include <asm/uaccess.h> - -#include "yportenv.h" -#include "yaffs_guts.h" - -#include <linux/mtd/mtd.h> -#include "yaffs_mtdif.h" -#include "yaffs_mtdif1.h" -#include "yaffs_mtdif2.h" - -unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS; -unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS; - -/* Module Parameters */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -module_param(yaffs_traceMask,uint,0644); -module_param(yaffs_wr_attempts,uint,0644); -#else -MODULE_PARM(yaffs_traceMask,"i"); -MODULE_PARM(yaffs_wr_attempts,"i"); -#endif - -/*#define T(x) printk x */ - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) -#define yaffs_InodeToObjectLV(iptr) (iptr)->i_private -#else -#define yaffs_InodeToObjectLV(iptr) (iptr)->u.generic_ip -#endif - -#define yaffs_InodeToObject(iptr) ((yaffs_Object *)(yaffs_InodeToObjectLV(iptr))) -#define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode) - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -#define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->s_fs_info) -#else -#define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp) -#endif - -static void yaffs_put_super(struct super_block *sb); - -static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, - loff_t * pos); - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static int yaffs_file_flush(struct file *file, fl_owner_t id); -#else -static int yaffs_file_flush(struct file *file); -#endif - -static int yaffs_sync_object(struct file *file, struct dentry *dentry, - int datasync); - -static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir); - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *n); -static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *n); -#else -static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode); -static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry); -#endif -static int yaffs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *dentry); -static int yaffs_unlink(struct inode *dir, struct dentry *dentry); -static int yaffs_symlink(struct inode *dir, struct dentry *dentry, - const char *symname); -static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode); - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, - dev_t dev); -#else -static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, - int dev); -#endif -static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry); -static int yaffs_setattr(struct dentry *dentry, struct iattr *attr); - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static int yaffs_sync_fs(struct super_block *sb, int wait); -static void yaffs_write_super(struct super_block *sb); -#else -static int yaffs_sync_fs(struct super_block *sb); -static int yaffs_write_super(struct super_block *sb); -#endif - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf); -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf); -#else -static int yaffs_statfs(struct super_block *sb, struct statfs *buf); -#endif -static void yaffs_read_inode(struct inode *inode); - -static void yaffs_put_inode(struct inode *inode); -static void yaffs_delete_inode(struct inode *); -static void yaffs_clear_inode(struct inode *); - -static int yaffs_readpage(struct file *file, struct page *page); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int yaffs_writepage(struct page *page, struct writeback_control *wbc); -#else -static int yaffs_writepage(struct page *page); -#endif -static int yaffs_prepare_write(struct file *f, struct page *pg, - unsigned offset, unsigned to); -static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, - unsigned to); - -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, - .writepage = yaffs_writepage, - .prepare_write = yaffs_prepare_write, - .commit_write = yaffs_commit_write, -}; - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) -static struct file_operations yaffs_file_operations = { - .read = do_sync_read, - .write = do_sync_write, - .aio_read = generic_file_aio_read, - .aio_write = generic_file_aio_write, - .mmap = generic_file_mmap, - .flush = yaffs_file_flush, - .fsync = yaffs_sync_object, - .splice_read = generic_file_splice_read, - .splice_write = generic_file_splice_write, -}; - -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) - -static struct file_operations yaffs_file_operations = { - .read = do_sync_read, - .write = do_sync_write, - .aio_read = generic_file_aio_read, - .aio_write = generic_file_aio_write, - .mmap = generic_file_mmap, - .flush = yaffs_file_flush, - .fsync = yaffs_sync_object, - .sendfile = generic_file_sendfile, -}; - -#else - -static struct file_operations yaffs_file_operations = { - .read = generic_file_read, - .write = generic_file_write, - .mmap = generic_file_mmap, - .flush = yaffs_file_flush, - .fsync = yaffs_sync_object, -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - .sendfile = generic_file_sendfile, -#endif -}; -#endif - -static struct inode_operations yaffs_file_inode_operations = { - .setattr = yaffs_setattr, -}; - -static struct inode_operations yaffs_symlink_inode_operations = { - .readlink = yaffs_readlink, - .follow_link = yaffs_follow_link, - .setattr = yaffs_setattr, -}; - -static struct inode_operations yaffs_dir_inode_operations = { - .create = yaffs_create, - .lookup = yaffs_lookup, - .link = yaffs_link, - .unlink = yaffs_unlink, - .symlink = yaffs_symlink, - .mkdir = yaffs_mkdir, - .rmdir = yaffs_unlink, - .mknod = yaffs_mknod, - .rename = yaffs_rename, - .setattr = yaffs_setattr, -}; - -static struct file_operations yaffs_dir_operations = { - .read = generic_read_dir, - .readdir = yaffs_readdir, - .fsync = yaffs_sync_object, -}; - -static struct super_operations yaffs_super_ops = { - .statfs = yaffs_statfs, - .read_inode = yaffs_read_inode, - .put_inode = yaffs_put_inode, - .put_super = yaffs_put_super, - .delete_inode = yaffs_delete_inode, - .clear_inode = yaffs_clear_inode, - .sync_fs = yaffs_sync_fs, - .write_super = yaffs_write_super, -}; - -static void yaffs_GrossLock(yaffs_Device * dev) -{ - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs locking\n")); - - down(&dev->grossLock); -} - -static void yaffs_GrossUnlock(yaffs_Device * dev) -{ - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs unlocking\n")); - up(&dev->grossLock); - -} - -static int yaffs_readlink(struct dentry *dentry, char __user * buffer, - int buflen) -{ - unsigned char *alias; - int ret; - - yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; - - yaffs_GrossLock(dev); - - alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry)); - - yaffs_GrossUnlock(dev); - - if (!alias) - return -ENOMEM; - - ret = vfs_readlink(dentry, buffer, buflen, alias); - kfree(alias); - 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; - yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; - - yaffs_GrossLock(dev); - - alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry)); - - yaffs_GrossUnlock(dev); - - if (!alias) - { - 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, - yaffs_Object * obj); - -/* - * Lookup is used to find objects in the fs - */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - -static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *n) -#else -static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) -#endif -{ - yaffs_Object *obj; - struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */ - - yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev; - - yaffs_GrossLock(dev); - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_lookup for %d:%s\n", - yaffs_InodeToObject(dir)->objectId, dentry->d_name.name)); - - obj = - yaffs_FindObjectByName(yaffs_InodeToObject(dir), - dentry->d_name.name); - - obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */ - - /* Can't hold gross lock when calling yaffs_get_inode() */ - yaffs_GrossUnlock(dev); - - if (obj) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_lookup found %d\n", obj->objectId)); - - inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); - - if (inode) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_loookup dentry \n")); -/* #if 0 asserted by NCB for 2.5/6 compatability - falls through to - * d_add even if NULL inode */ -#if 0 - /*dget(dentry); // try to solve directory bug */ - d_add(dentry, inode); - - /* return dentry; */ - return NULL; -#endif - } - - } else { - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n")); - - } - -/* added NCB for 2.5/6 compatability - forces add even if inode is - * NULL which creates dentry hash */ - d_add(dentry, inode); - - return NULL; - /* return (ERR_PTR(-EIO)); */ - -} - -/* For now put inode is just for debugging - * Put inode is called when the inode **structure** is put. - */ -static void yaffs_put_inode(struct inode *inode) -{ - T(YAFFS_TRACE_OS, - ("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino, - atomic_read(&inode->i_count))); - -} - -/* clear is called to tell the fs to release any per-inode data it holds */ -static void yaffs_clear_inode(struct inode *inode) -{ - yaffs_Object *obj; - yaffs_Device *dev; - - obj = yaffs_InodeToObject(inode); - - T(YAFFS_TRACE_OS, - ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino, - atomic_read(&inode->i_count), - obj ? "object exists" : "null object")); - - if (obj) { - dev = obj->myDev; - yaffs_GrossLock(dev); - - /* Clear the association between the inode and - * the yaffs_Object. - */ - obj->myInode = NULL; - yaffs_InodeToObjectLV(inode) = NULL; - - /* If the object freeing was deferred, then the real - * free happens now. - * This should fix the inode inconsistency problem. - */ - - yaffs_HandleDeferedFree(obj); - - yaffs_GrossUnlock(dev); - } - -} - -/* delete is called when the link count is zero and the inode - * is put (ie. nobody wants to know about it anymore, time to - * delete the file). - * NB Must call clear_inode() - */ -static void yaffs_delete_inode(struct inode *inode) -{ - yaffs_Object *obj = yaffs_InodeToObject(inode); - yaffs_Device *dev; - - T(YAFFS_TRACE_OS, - ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino, - atomic_read(&inode->i_count), - obj ? "object exists" : "null object")); - - if (obj) { - dev = obj->myDev; - yaffs_GrossLock(dev); - 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); -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static int yaffs_file_flush(struct file *file, fl_owner_t id) -#else -static int yaffs_file_flush(struct file *file) -#endif -{ - yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry); - - yaffs_Device *dev = obj->myDev; - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_file_flush object %d (%s)\n", obj->objectId, - obj->dirty ? "dirty" : "clean")); - - yaffs_GrossLock(dev); - - yaffs_FlushFile(obj, 1); - - yaffs_GrossUnlock(dev); - - return 0; -} - -static int yaffs_readpage_nolock(struct file *f, struct page *pg) -{ - /* Lifted from jffs2 */ - - yaffs_Object *obj; - unsigned char *pg_buf; - int ret; - - yaffs_Device *dev; - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage at %08x, size %08x\n", - (unsigned)(pg->index << PAGE_CACHE_SHIFT), - (unsigned)PAGE_CACHE_SIZE)); - - obj = yaffs_DentryToObject(f->f_dentry); - - dev = obj->myDev; - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - BUG_ON(!PageLocked(pg)); -#else - if (!PageLocked(pg)) - PAGE_BUG(pg); -#endif - - pg_buf = kmap(pg); - /* FIXME: Can kmap fail? */ - - yaffs_GrossLock(dev); - - ret = - yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, - PAGE_CACHE_SIZE); - - yaffs_GrossUnlock(dev); - - if (ret >= 0) - ret = 0; - - if (ret) { - ClearPageUptodate(pg); - SetPageError(pg); - } else { - SetPageUptodate(pg); - ClearPageError(pg); - } - - flush_dcache_page(pg); - kunmap(pg); - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage done\n")); - return ret; -} - -static int yaffs_readpage_unlock(struct file *f, struct page *pg) -{ - int ret = yaffs_readpage_nolock(f, pg); - UnlockPage(pg); - return ret; -} - -static int yaffs_readpage(struct file *f, struct page *pg) -{ - return yaffs_readpage_unlock(f, pg); -} - -/* writepage inspired by/stolen from smbfs */ - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int yaffs_writepage(struct page *page, struct writeback_control *wbc) -#else -static int yaffs_writepage(struct page *page) -#endif -{ - struct address_space *mapping = page->mapping; - loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT; - struct inode *inode; - unsigned long end_index; - char *buffer; - yaffs_Object *obj; - int nWritten = 0; - unsigned nBytes; - - if (!mapping) - BUG(); - inode = mapping->host; - if (!inode) - BUG(); - - if (offset > inode->i_size) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG - "yaffs_writepage at %08x, inode size = %08x!!!\n", - (unsigned)(page->index << PAGE_CACHE_SHIFT), - (unsigned)inode->i_size)); - T(YAFFS_TRACE_OS, - (KERN_DEBUG " -> don't care!!\n")); - unlock_page(page); - return 0; - } - - end_index = inode->i_size >> PAGE_CACHE_SHIFT; - - /* easy case */ - if (page->index < end_index) { - nBytes = PAGE_CACHE_SIZE; - } else { - nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1); - } - - get_page(page); - - buffer = kmap(page); - - obj = yaffs_InodeToObject(inode); - yaffs_GrossLock(obj->myDev); - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_writepage at %08x, size %08x\n", - (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes)); - T(YAFFS_TRACE_OS, - (KERN_DEBUG "writepag0: obj = %05x, ino = %05x\n", - (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); - - nWritten = - yaffs_WriteDataToFile(obj, buffer, page->index << PAGE_CACHE_SHIFT, - nBytes, 0); - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "writepag1: obj = %05x, ino = %05x\n", - (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); - - yaffs_GrossUnlock(obj->myDev); - - kunmap(page); - SetPageUptodate(page); - UnlockPage(page); - put_page(page); - - return (nWritten == nBytes) ? 0 : -ENOSPC; -} - -static int yaffs_prepare_write(struct file *f, struct page *pg, - unsigned offset, unsigned to) -{ - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n")); - if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) - return yaffs_readpage_nolock(f, pg); - - return 0; - -} - -static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, - unsigned to) -{ - - void *addr = page_address(pg) + offset; - loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset; - int nBytes = to - offset; - int nWritten; - - unsigned spos = pos; - unsigned saddr = (unsigned)addr; - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr, - spos, nBytes)); - - nWritten = yaffs_file_write(f, addr, nBytes, &pos); - - if (nWritten != nBytes) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG - "yaffs_commit_write not same size nWritten %d nBytes %d\n", - nWritten, nBytes)); - SetPageError(pg); - ClearPageUptodate(pg); - } else { - SetPageUptodate(pg); - } - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_commit_write returning %d\n", - nWritten == nBytes ? 0 : nWritten)); - - return nWritten == nBytes ? 0 : nWritten; - -} - -static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj) -{ - if (inode && obj) { - - - /* Check mode against the variant type and attempt to repair if broken. */ - __u32 mode = obj->yst_mode; - switch( obj->variantType ){ - case YAFFS_OBJECT_TYPE_FILE : - if( ! S_ISREG(mode) ){ - obj->yst_mode &= ~S_IFMT; - obj->yst_mode |= S_IFREG; - } - - break; - case YAFFS_OBJECT_TYPE_SYMLINK : - if( ! S_ISLNK(mode) ){ - obj->yst_mode &= ~S_IFMT; - obj->yst_mode |= S_IFLNK; - } - - break; - case YAFFS_OBJECT_TYPE_DIRECTORY : - if( ! S_ISDIR(mode) ){ - obj->yst_mode &= ~S_IFMT; - obj->yst_mode |= S_IFDIR; - } - - break; - case YAFFS_OBJECT_TYPE_UNKNOWN : - case YAFFS_OBJECT_TYPE_HARDLINK : - case YAFFS_OBJECT_TYPE_SPECIAL : - default: - /* TODO? */ - break; - } - - inode->i_ino = obj->objectId; - inode->i_mode = obj->yst_mode; - inode->i_uid = obj->yst_uid; - inode->i_gid = obj->yst_gid; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) - inode->i_blksize = inode->i_sb->s_blocksize; -#endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - - inode->i_rdev = old_decode_dev(obj->yst_rdev); - inode->i_atime.tv_sec = (time_t) (obj->yst_atime); - inode->i_atime.tv_nsec = 0; - inode->i_mtime.tv_sec = (time_t) obj->yst_mtime; - inode->i_mtime.tv_nsec = 0; - inode->i_ctime.tv_sec = (time_t) obj->yst_ctime; - inode->i_ctime.tv_nsec = 0; -#else - inode->i_rdev = obj->yst_rdev; - inode->i_atime = obj->yst_atime; - inode->i_mtime = obj->yst_mtime; - inode->i_ctime = obj->yst_ctime; -#endif - inode->i_size = yaffs_GetObjectFileLength(obj); - inode->i_blocks = (inode->i_size + 511) >> 9; - - inode->i_nlink = yaffs_GetObjectLinkCount(obj); - - T(YAFFS_TRACE_OS, - (KERN_DEBUG - "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", - inode->i_mode, inode->i_uid, inode->i_gid, - (int)inode->i_size, atomic_read(&inode->i_count))); - - switch (obj->yst_mode & S_IFMT) { - default: /* fifo, device or socket */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - init_special_inode(inode, obj->yst_mode, - old_decode_dev(obj->yst_rdev)); -#else - init_special_inode(inode, obj->yst_mode, - (dev_t) (obj->yst_rdev)); -#endif - break; - case S_IFREG: /* file */ - inode->i_op = &yaffs_file_inode_operations; - inode->i_fop = &yaffs_file_operations; - inode->i_mapping->a_ops = - &yaffs_file_address_operations; - break; - case S_IFDIR: /* directory */ - inode->i_op = &yaffs_dir_inode_operations; - inode->i_fop = &yaffs_dir_operations; - break; - case S_IFLNK: /* symlink */ - inode->i_op = &yaffs_symlink_inode_operations; - break; - } - - yaffs_InodeToObjectLV(inode) = obj; - - obj->myInode = inode; - - } else { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_FileInode invalid parameters\n")); - } - -} - -struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, - yaffs_Object * obj) -{ - struct inode *inode; - - if (!sb) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_get_inode for NULL super_block!!\n")); - return NULL; - - } - - if (!obj) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_get_inode for NULL object!!\n")); - return NULL; - - } - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId)); - - inode = iget(sb, obj->objectId); - - /* NB Side effect: iget calls back to yaffs_read_inode(). */ - /* iget also increments the inode's i_count */ - /* NB You can't be holding grossLock or deadlock will happen! */ - - return inode; -} - -static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, - loff_t * pos) -{ - yaffs_Object *obj; - int nWritten, ipos; - struct inode *inode; - yaffs_Device *dev; - - obj = yaffs_DentryToObject(f->f_dentry); - - dev = obj->myDev; - - yaffs_GrossLock(dev); - - inode = f->f_dentry->d_inode; - - if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) { - ipos = inode->i_size; - } else { - ipos = *pos; - } - - if (!obj) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_file_write: hey obj is null!\n")); - } else { - T(YAFFS_TRACE_OS, - (KERN_DEBUG - "yaffs_file_write about to write writing %d bytes" - "to object %d at %d\n", - n, obj->objectId, ipos)); - } - - nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0); - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_file_write writing %d bytes, %d written at %d\n", - n, nWritten, ipos)); - if (nWritten > 0) { - ipos += nWritten; - *pos = ipos; - if (ipos > inode->i_size) { - inode->i_size = ipos; - inode->i_blocks = (ipos + 511) >> 9; - - T(YAFFS_TRACE_OS, - (KERN_DEBUG - "yaffs_file_write size updated to %d bytes, " - "%d blocks\n", - ipos, (int)(inode->i_blocks))); - } - - } - yaffs_GrossUnlock(dev); - return nWritten == 0 ? -ENOSPC : nWritten; -} - -static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) -{ - yaffs_Object *obj; - yaffs_Device *dev; - struct inode *inode = f->f_dentry->d_inode; - unsigned long offset, curoffs; - struct list_head *i; - yaffs_Object *l; - - char name[YAFFS_MAX_NAME_LENGTH + 1]; - - obj = yaffs_DentryToObject(f->f_dentry); - dev = obj->myDev; - - yaffs_GrossLock(dev); - - offset = f->f_pos; - - T(YAFFS_TRACE_OS, ("yaffs_readdir: starting at %d\n", (int)offset)); - - if (offset == 0) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_readdir: entry . ino %d \n", - (int)inode->i_ino)); - if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) - < 0) { - goto out; - } - offset++; - f->f_pos++; - } - if (offset == 1) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_readdir: entry .. ino %d \n", - (int)f->f_dentry->d_parent->d_inode->i_ino)); - if (filldir - (dirent, "..", 2, offset, - f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { - goto out; - } - offset++; - f->f_pos++; - } - - curoffs = 1; - - /* If the directory has changed since the open or last call to - readdir, rewind to after the 2 canned entries. */ - - if (f->f_version != inode->i_version) { - offset = 2; - f->f_pos = offset; - f->f_version = inode->i_version; - } - - list_for_each(i, &obj->variant.directoryVariant.children) { - curoffs++; - if (curoffs >= offset) { - l = list_entry(i, yaffs_Object, siblings); - - yaffs_GetObjectName(l, name, - YAFFS_MAX_NAME_LENGTH + 1); - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_readdir: %s inode %d\n", name, - yaffs_GetObjectInode(l))); - - if (filldir(dirent, - name, - strlen(name), - offset, - yaffs_GetObjectInode(l), - yaffs_GetObjectType(l)) - < 0) { - goto up_and_out; - } - - offset++; - f->f_pos++; - } - } - - up_and_out: - out: - - yaffs_GrossUnlock(dev); - - return 0; -} - -/* - * File creation. Allocate an inode, and we're done.. - */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, - dev_t rdev) -#else -static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, - int rdev) -#endif -{ - struct inode *inode; - - yaffs_Object *obj = NULL; - yaffs_Device *dev; - - yaffs_Object *parent = yaffs_InodeToObject(dir); - - int error = -ENOSPC; - uid_t uid = current->fsuid; - gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; - - if((dir->i_mode & S_ISGID) && S_ISDIR(mode)) - mode |= S_ISGID; - - if (parent) { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_mknod: parent object %d type %d\n", - parent->objectId, parent->variantType)); - } else { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_mknod: could not get parent object\n")); - return -EPERM; - } - - T(YAFFS_TRACE_OS, ("yaffs_mknod: making oject for %s, " - "mode %x dev %x\n", - dentry->d_name.name, mode, rdev)); - - dev = parent->myDev; - - yaffs_GrossLock(dev); - - switch (mode & S_IFMT) { - default: - /* Special (socket, fifo, device...) */ - T(YAFFS_TRACE_OS, (KERN_DEBUG - "yaffs_mknod: making special\n")); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - obj = - yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, - gid, old_encode_dev(rdev)); -#else - obj = - yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, - gid, rdev); -#endif - break; - case S_IFREG: /* file */ - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); - obj = - yaffs_MknodFile(parent, dentry->d_name.name, mode, uid, - gid); - break; - case S_IFDIR: /* directory */ - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_mknod: making directory\n")); - obj = - yaffs_MknodDirectory(parent, dentry->d_name.name, mode, - uid, gid); - break; - case S_IFLNK: /* symlink */ - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); - obj = NULL; /* Do we ever get here? */ - break; - } - - /* Can not call yaffs_get_inode() with gross lock held */ - yaffs_GrossUnlock(dev); - - if (obj) { - inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj); - d_instantiate(dentry, inode); - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_mknod created object %d count = %d\n", - obj->objectId, atomic_read(&inode->i_count))); - error = 0; - } else { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_mknod failed making object\n")); - error = -ENOMEM; - } - - return error; -} - -static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode) -{ - int retVal; - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mkdir\n")); - retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0); -#if 0 - /* attempt to fix dir bug - didn't work */ - if (!retVal) { - dget(dentry); - } -#endif - return retVal; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *n) -#else -static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode) -#endif -{ - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_create\n")); - return yaffs_mknod(dir, dentry, mode | S_IFREG, 0); -} - -static int yaffs_unlink(struct inode *dir, struct dentry *dentry) -{ - int retVal; - - yaffs_Device *dev; - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_unlink %d:%s\n", (int)(dir->i_ino), - dentry->d_name.name)); - - dev = yaffs_InodeToObject(dir)->myDev; - - yaffs_GrossLock(dev); - - retVal = yaffs_Unlink(yaffs_InodeToObject(dir), dentry->d_name.name); - - if (retVal == YAFFS_OK) { - dentry->d_inode->i_nlink--; - dir->i_version++; - yaffs_GrossUnlock(dev); - mark_inode_dirty(dentry->d_inode); - return 0; - } - yaffs_GrossUnlock(dev); - return -ENOTEMPTY; -} - -/* - * Create a link... - */ -static int yaffs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *dentry) -{ - struct inode *inode = old_dentry->d_inode; - yaffs_Object *obj = NULL; - yaffs_Object *link = NULL; - yaffs_Device *dev; - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_link\n")); - - obj = yaffs_InodeToObject(inode); - dev = obj->myDev; - - yaffs_GrossLock(dev); - - if (!S_ISDIR(inode->i_mode)) /* Don't link directories */ - { - link = - yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name, - obj); - } - - if (link) { - old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj); - d_instantiate(dentry, old_dentry->d_inode); - atomic_inc(&old_dentry->d_inode->i_count); - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_link link count %d i_count %d\n", - old_dentry->d_inode->i_nlink, - atomic_read(&old_dentry->d_inode->i_count))); - - } - - yaffs_GrossUnlock(dev); - - if (link) { - - return 0; - } - - return -EPERM; -} - -static int yaffs_symlink(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - yaffs_Object *obj; - yaffs_Device *dev; - uid_t uid = current->fsuid; - gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_symlink\n")); - - dev = yaffs_InodeToObject(dir)->myDev; - yaffs_GrossLock(dev); - obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, - S_IFLNK | S_IRWXUGO, uid, gid, symname); - yaffs_GrossUnlock(dev); - - if (obj) { - - struct inode *inode; - - inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); - d_instantiate(dentry, inode); - T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink created OK\n")); - return 0; - } else { - T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink not created\n")); - - } - - return -ENOMEM; -} - -static int yaffs_sync_object(struct file *file, struct dentry *dentry, - int datasync) -{ - - yaffs_Object *obj; - yaffs_Device *dev; - - obj = yaffs_DentryToObject(dentry); - - dev = obj->myDev; - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_object\n")); - yaffs_GrossLock(dev); - yaffs_FlushFile(obj, 1); - yaffs_GrossUnlock(dev); - return 0; -} - -/* - * The VFS layer already does all the dentry stuff for rename. - * - * NB: POSIX says you can rename an object over an old object of the same name - */ -static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - yaffs_Device *dev; - int retVal = YAFFS_FAIL; - yaffs_Object *target; - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_rename\n")); - dev = yaffs_InodeToObject(old_dir)->myDev; - - yaffs_GrossLock(dev); - - /* Check if the target is an existing directory that is not empty. */ - target = - yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), - new_dentry->d_name.name); - - - - if (target && - target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && - !list_empty(&target->variant.directoryVariant.children)) { - - T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n")); - - retVal = YAFFS_FAIL; - } else { - - /* Now does unlinking internally using shadowing mechanism */ - T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n")); - - retVal = - yaffs_RenameObject(yaffs_InodeToObject(old_dir), - old_dentry->d_name.name, - yaffs_InodeToObject(new_dir), - new_dentry->d_name.name); - - } - yaffs_GrossUnlock(dev); - - if (retVal == YAFFS_OK) { - if(target) { - new_dentry->d_inode->i_nlink--; - mark_inode_dirty(new_dentry->d_inode); - } - - return 0; - } else { - return -ENOTEMPTY; - } - -} - -static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) -{ - struct inode *inode = dentry->d_inode; - int error; - yaffs_Device *dev; - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_setattr of object %d\n", - yaffs_InodeToObject(inode)->objectId)); - - if ((error = inode_change_ok(inode, attr)) == 0) { - - dev = yaffs_InodeToObject(inode)->myDev; - yaffs_GrossLock(dev); - if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) == - YAFFS_OK) { - error = 0; - } else { - error = -EPERM; - } - yaffs_GrossUnlock(dev); - if (!error) - error = inode_setattr(inode, attr); - } - return error; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; - struct super_block *sb = dentry->d_sb; -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf) -{ - yaffs_Device *dev = yaffs_SuperToDevice(sb); -#else -static int yaffs_statfs(struct super_block *sb, struct statfs *buf) -{ - yaffs_Device *dev = yaffs_SuperToDevice(sb); -#endif - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n")); - - yaffs_GrossLock(dev); - - buf->f_type = YAFFS_MAGIC; - buf->f_bsize = sb->s_blocksize; - buf->f_namelen = 255; - if (sb->s_blocksize > dev->nDataBytesPerChunk) { - - buf->f_blocks = - (dev->endBlock - dev->startBlock + - 1) * dev->nChunksPerBlock / (sb->s_blocksize / - dev->nDataBytesPerChunk); - buf->f_bfree = - yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize / - dev->nDataBytesPerChunk); - } else { - - buf->f_blocks = - (dev->endBlock - dev->startBlock + - 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk / - sb->s_blocksize); - buf->f_bfree = - yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk / - sb->s_blocksize); - } - buf->f_files = 0; - buf->f_ffree = 0; - buf->f_bavail = buf->f_bfree; - - yaffs_GrossUnlock(dev); - return 0; -} - - -/** -static int yaffs_do_sync_fs(struct super_block *sb) -{ - - yaffs_Device *dev = yaffs_SuperToDevice(sb); - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_do_sync_fs\n")); - - if(sb->s_dirt) { - yaffs_GrossLock(dev); - - if(dev) - yaffs_CheckpointSave(dev); - - yaffs_GrossUnlock(dev); - - sb->s_dirt = 0; - } - return 0; -} -**/ - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static void yaffs_write_super(struct super_block *sb) -#else -static int yaffs_write_super(struct super_block *sb) -#endif -{ - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n")); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) - return 0; /* yaffs_do_sync_fs(sb);*/ -#endif -} - - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static int yaffs_sync_fs(struct super_block *sb, int wait) -#else -static int yaffs_sync_fs(struct super_block *sb) -#endif -{ - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n")); - - return 0; /* yaffs_do_sync_fs(sb);*/ - -} - - -static void yaffs_read_inode(struct inode *inode) -{ - /* NB This is called as a side effect of other functions, but - * we had to release the lock to prevent deadlocks, so - * need to lock again. - */ - - yaffs_Object *obj; - yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb); - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); - - yaffs_GrossLock(dev); - - obj = yaffs_FindObjectByNumber(dev, inode->i_ino); - - yaffs_FillInodeFromObject(inode, obj); - - yaffs_GrossUnlock(dev); -} - -static LIST_HEAD(yaffs_dev_list); - -#if 0 // not used -static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) -{ - yaffs_Device *dev = yaffs_SuperToDevice(sb); - - if( *flags & MS_RDONLY ) { - struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; - - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_remount_fs: %s: RO\n", dev->name )); - - yaffs_GrossLock(dev); - - yaffs_FlushEntireDeviceCache(dev); - - yaffs_CheckpointSave(dev); - - if (mtd->sync) - mtd->sync(mtd); - - yaffs_GrossUnlock(dev); - } - else { - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_remount_fs: %s: RW\n", dev->name )); - } - - return 0; -} -#endif - -static void yaffs_put_super(struct super_block *sb) -{ - yaffs_Device *dev = yaffs_SuperToDevice(sb); - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_put_super\n")); - - yaffs_GrossLock(dev); - - yaffs_FlushEntireDeviceCache(dev); - - yaffs_CheckpointSave(dev); - - if (dev->putSuperFunc) { - dev->putSuperFunc(sb); - } - - yaffs_Deinitialise(dev); - - yaffs_GrossUnlock(dev); - - /* we assume this is protected by lock_kernel() in mount/umount */ - list_del(&dev->devList); - - if(dev->spareBuffer){ - YFREE(dev->spareBuffer); - dev->spareBuffer = NULL; - } - - kfree(dev); -} - - -static void yaffs_MTDPutSuper(struct super_block *sb) -{ - - struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; - - if (mtd->sync) { - mtd->sync(mtd); - } - - put_mtd_device(mtd); -} - - -static void yaffs_MarkSuperBlockDirty(void *vsb) -{ - struct super_block *sb = (struct super_block *)vsb; - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb)); -// if(sb) -// sb->s_dirt = 1; -} - -typedef struct { - int inband_tags; - int skip_checkpoint_read; - int skip_checkpoint_write; - int no_cache; -} yaffs_options; - -#define MAX_OPT_LEN 20 -static int yaffs_parse_options(yaffs_options *options, const char *options_str) -{ - char cur_opt[MAX_OPT_LEN+1]; - int p; - int error = 0; - - /* Parse through the options which is a comma seperated list */ - - while(options_str && *options_str && !error){ - memset(cur_opt,0,MAX_OPT_LEN+1); - p = 0; - - while(*options_str && *options_str != ','){ - if(p < MAX_OPT_LEN){ - cur_opt[p] = *options_str; - p++; - } - options_str++; - } - - if(!strcmp(cur_opt,"inband-tags")) - options->inband_tags = 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; - else if(!strcmp(cur_opt,"no-checkpoint-write")) - options->skip_checkpoint_write = 1; - else if(!strcmp(cur_opt,"no-checkpoint")){ - options->skip_checkpoint_read = 1; - options->skip_checkpoint_write = 1; - } else { - printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",cur_opt); - error = 1; - } - - } - - return error; -} - -static struct super_block *yaffs_internal_read_super(int yaffsVersion, - struct super_block *sb, - void *data, int silent) -{ - int nBlocks; - struct inode *inode = NULL; - struct dentry *root; - yaffs_Device *dev = 0; - char devname_buf[BDEVNAME_SIZE + 1]; - struct mtd_info *mtd; - int err; - char *data_str = (char *)data; - - yaffs_options options; - - sb->s_magic = YAFFS_MAGIC; - sb->s_op = &yaffs_super_ops; - - if (!sb) - printk(KERN_INFO "yaffs: sb is NULL\n"); - else if (!sb->s_dev) - printk(KERN_INFO "yaffs: sb->s_dev is NULL\n"); - else if (!yaffs_devname(sb, devname_buf)) - printk(KERN_INFO "yaffs: devname is NULL\n"); - else - printk(KERN_INFO "yaffs: dev is %d name is \"%s\"\n", - sb->s_dev, - yaffs_devname(sb, devname_buf)); - - if(!data_str) - data_str = ""; - - printk(KERN_INFO "yaffs: passed flags \"%s\"\n",data_str); - - memset(&options,0,sizeof(options)); - - if(yaffs_parse_options(&options,data_str)){ - /* Option parsing failed */ - return NULL; - } - - - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - T(YAFFS_TRACE_OS, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion)); - T(YAFFS_TRACE_OS, - ("yaffs_read_super: block size %d\n", (int)(sb->s_blocksize))); - -#ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY - T(YAFFS_TRACE_OS, - ("yaffs: Write verification disabled. All guarantees " - "null and void\n")); -#endif - - T(YAFFS_TRACE_ALWAYS, ("yaffs: Attempting MTD mount on %u.%u, " - "\"%s\"\n", - MAJOR(sb->s_dev), MINOR(sb->s_dev), - yaffs_devname(sb, devname_buf))); - - /* Check it's an mtd device..... */ - if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { - return NULL; /* This isn't an mtd device */ - } - /* Get the device */ - mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); - if (!mtd) { - T(YAFFS_TRACE_ALWAYS, - ("yaffs: MTD device #%u doesn't appear to exist\n", - MINOR(sb->s_dev))); - return NULL; - } - /* Check it's NAND */ - if (mtd->type != MTD_NANDFLASH) { - T(YAFFS_TRACE_ALWAYS, - ("yaffs: MTD device is not NAND it's type %d\n", mtd->type)); - return NULL; - } - - T(YAFFS_TRACE_OS, (" erase %p\n", mtd->erase)); - T(YAFFS_TRACE_OS, (" read %p\n", mtd->read)); - T(YAFFS_TRACE_OS, (" write %p\n", mtd->write)); - T(YAFFS_TRACE_OS, (" readoob %p\n", mtd->read_oob)); - T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob)); - T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad)); - T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad)); - T(YAFFS_TRACE_OS, (" %s %d\n", WRITE_SIZE_STR, WRITE_SIZE(mtd))); - T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); - T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); - T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); - -#ifdef CONFIG_YAFFS_AUTO_YAFFS2 - - if (yaffsVersion == 1 && -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - mtd->writesize >= 2048) { -#else - mtd->oobblock >= 2048) { -#endif - T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); - yaffsVersion = 2; - } - - /* Added NCB 26/5/2006 for completeness */ - if (yaffsVersion == 2 && -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - mtd->writesize == 512) { -#else - mtd->oobblock == 512) { -#endif - T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); - yaffsVersion = 1; - } - -#endif - - if (yaffsVersion == 2) { - /* Check for version 2 style functions */ - if (!mtd->erase || - !mtd->block_isbad || - !mtd->block_markbad || - !mtd->read || - !mtd->write || -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - !mtd->read_oob || !mtd->write_oob) { -#else - !mtd->write_ecc || - !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) { -#endif - T(YAFFS_TRACE_ALWAYS, - ("yaffs: MTD device does not support required " - "functions\n"));; - return NULL; - } - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE || -#else - if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE || -#endif - mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) { - T(YAFFS_TRACE_ALWAYS, - ("yaffs: MTD device does not have the " - "right page sizes\n")); - return NULL; - } - } else { - /* Check for V1 style functions */ - if (!mtd->erase || - !mtd->read || - !mtd->write || -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - !mtd->read_oob || !mtd->write_oob) { -#else - !mtd->write_ecc || - !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) { -#endif - T(YAFFS_TRACE_ALWAYS, - ("yaffs: MTD device does not support required " - "functions\n"));; - return NULL; - } - - if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK || - mtd->oobsize != YAFFS_BYTES_PER_SPARE) { - T(YAFFS_TRACE_ALWAYS, - ("yaffs: MTD device does not support have the " - "right page sizes\n")); - return NULL; - } - } - - /* OK, so if we got here, we have an MTD that's NAND and looks - * like it has the right capabilities - * Set the yaffs_Device up for mtd - */ - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); -#else - sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); -#endif - if (!dev) { - /* Deep shit could not allocate device structure */ - T(YAFFS_TRACE_ALWAYS, - ("yaffs_read_super: Failed trying to allocate " - "yaffs_Device. \n")); - return NULL; - } - - memset(dev, 0, sizeof(yaffs_Device)); - dev->genericDevice = mtd; - dev->name = mtd->name; - - /* Set up the memory size parameters.... */ - - nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); - dev->startBlock = 0; - dev->endBlock = nBlocks - 1; - dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; - dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK; - dev->nReservedBlocks = 5; - dev->nShortOpCaches = (options.no_cache) ? 0 : 10; - - /* ... and the functions. */ - if (yaffsVersion == 2) { - dev->writeChunkWithTagsToNAND = - nandmtd2_WriteChunkWithTagsToNAND; - dev->readChunkWithTagsFromNAND = - nandmtd2_ReadChunkWithTagsFromNAND; - dev->markNANDBlockBad = nandmtd2_MarkNANDBlockBad; - dev->queryNANDBlock = nandmtd2_QueryNANDBlock; - dev->spareBuffer = YMALLOC(mtd->oobsize); - dev->isYaffs2 = 1; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - dev->nDataBytesPerChunk = mtd->writesize; - dev->nChunksPerBlock = mtd->erasesize / mtd->writesize; -#else - dev->nDataBytesPerChunk = mtd->oobblock; - dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; -#endif - nBlocks = mtd->size / mtd->erasesize; - - dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS; - dev->startBlock = 0; - dev->endBlock = nBlocks - 1; - } else { -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - /* use the MTD interface in yaffs_mtdif1.c */ - dev->writeChunkWithTagsToNAND = - nandmtd1_WriteChunkWithTagsToNAND; - dev->readChunkWithTagsFromNAND = - nandmtd1_ReadChunkWithTagsFromNAND; - dev->markNANDBlockBad = nandmtd1_MarkNANDBlockBad; - dev->queryNANDBlock = nandmtd1_QueryNANDBlock; -#else - dev->writeChunkToNAND = nandmtd_WriteChunkToNAND; - dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND; -#endif - dev->isYaffs2 = 0; - } - /* ... and common functions */ - dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND; - dev->initialiseNAND = nandmtd_InitialiseNAND; - - dev->putSuperFunc = yaffs_MTDPutSuper; - - dev->superBlock = (void *)sb; - dev->markSuperBlockDirty = yaffs_MarkSuperBlockDirty; - - -#ifndef CONFIG_YAFFS_DOES_ECC - dev->useNANDECC = 1; -#endif - -#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES - dev->wideTnodesDisabled = 1; -#endif - - dev->skipCheckpointRead = options.skip_checkpoint_read; - dev->skipCheckpointWrite = options.skip_checkpoint_write; - - /* we assume this is protected by lock_kernel() in mount/umount */ - list_add_tail(&dev->devList, &yaffs_dev_list); - - init_MUTEX(&dev->grossLock); - - yaffs_GrossLock(dev); - - err = yaffs_GutsInitialise(dev); - - T(YAFFS_TRACE_OS, - ("yaffs_read_super: guts initialised %s\n", - (err == YAFFS_OK) ? "OK" : "FAILED")); - - /* Release lock before yaffs_get_inode() */ - yaffs_GrossUnlock(dev); - - /* Create root inode */ - if (err == YAFFS_OK) - inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, - yaffs_Root(dev)); - - if (!inode) - return NULL; - - inode->i_op = &yaffs_dir_inode_operations; - inode->i_fop = &yaffs_dir_operations; - - T(YAFFS_TRACE_OS, ("yaffs_read_super: got root inode\n")); - - root = d_alloc_root(inode); - - T(YAFFS_TRACE_OS, ("yaffs_read_super: d_alloc_root done\n")); - - if (!root) { - iput(inode); - return NULL; - } - sb->s_root = root; - - T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n")); - return sb; -} - - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -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 : -EINVAL; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static int yaffs_read_super(struct file_system_type *fs, - int flags, const char *dev_name, - void *data, struct vfsmount *mnt) -{ - - return get_sb_bdev(fs, flags, dev_name, data, - yaffs_internal_read_super_mtd, mnt); -} -#else -static struct super_block *yaffs_read_super(struct file_system_type *fs, - int flags, const char *dev_name, - void *data) -{ - - return get_sb_bdev(fs, flags, dev_name, data, - yaffs_internal_read_super_mtd); -} -#endif - -static struct file_system_type yaffs_fs_type = { - .owner = THIS_MODULE, - .name = "yaffs", - .get_sb = yaffs_read_super, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, -}; -#else -static struct super_block *yaffs_read_super(struct super_block *sb, void *data, - int silent) -{ - return yaffs_internal_read_super(1, sb, data, silent); -} - -static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, - FS_REQUIRES_DEV); -#endif - - -#ifdef CONFIG_YAFFS_YAFFS2 - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -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 : -EINVAL; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -static int yaffs2_read_super(struct file_system_type *fs, - int flags, const char *dev_name, void *data, - struct vfsmount *mnt) -{ - return get_sb_bdev(fs, flags, dev_name, data, - yaffs2_internal_read_super_mtd, mnt); -} -#else -static struct super_block *yaffs2_read_super(struct file_system_type *fs, - int flags, const char *dev_name, - void *data) -{ - - return get_sb_bdev(fs, flags, dev_name, data, - yaffs2_internal_read_super_mtd); -} -#endif - -static struct file_system_type yaffs2_fs_type = { - .owner = THIS_MODULE, - .name = "yaffs2", - .get_sb = yaffs2_read_super, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, -}; -#else -static struct super_block *yaffs2_read_super(struct super_block *sb, - void *data, int silent) -{ - return yaffs_internal_read_super(2, sb, data, silent); -} - -static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, - FS_REQUIRES_DEV); -#endif - -#endif /* CONFIG_YAFFS_YAFFS2 */ - -static struct proc_dir_entry *my_proc_entry; - -static char *yaffs_dump_dev(char *buf, yaffs_Device * dev) -{ - buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock); - buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); - buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk); - buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits); - buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize); - buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks); - buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks); - buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks); - buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint); - buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated); - buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes); - buf += sprintf(buf, "nObjectsCreated.... %d\n", dev->nObjectsCreated); - buf += sprintf(buf, "nFreeObjects....... %d\n", dev->nFreeObjects); - buf += sprintf(buf, "nFreeChunks........ %d\n", dev->nFreeChunks); - buf += sprintf(buf, "nPageWrites........ %d\n", dev->nPageWrites); - buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads); - buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures); - buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies); - buf += - sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections); - buf += - sprintf(buf, "passiveGCs......... %d\n", - dev->passiveGarbageCollections); - buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites); - buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches); - buf += sprintf(buf, "nRetireBlocks...... %d\n", dev->nRetiredBlocks); - buf += sprintf(buf, "eccFixed........... %d\n", dev->eccFixed); - buf += sprintf(buf, "eccUnfixed......... %d\n", dev->eccUnfixed); - buf += sprintf(buf, "tagsEccFixed....... %d\n", dev->tagsEccFixed); - buf += sprintf(buf, "tagsEccUnfixed..... %d\n", dev->tagsEccUnfixed); - buf += sprintf(buf, "cacheHits.......... %d\n", dev->cacheHits); - buf += sprintf(buf, "nDeletedFiles...... %d\n", dev->nDeletedFiles); - buf += sprintf(buf, "nUnlinkedFiles..... %d\n", dev->nUnlinkedFiles); - buf += - sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions); - buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC); - buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2); - - return buf; -} - -static int yaffs_proc_read(char *page, - char **start, - off_t offset, int count, int *eof, void *data) -{ - struct list_head *item; - char *buf = page; - int step = offset; - int n = 0; - - /* Get proc_file_read() to step 'offset' by one on each sucessive call. - * We use 'offset' (*ppos) to indicate where we are in devList. - * This also assumes the user has posted a read buffer large - * enough to hold the complete output; but that's life in /proc. - */ - - *(int *)start = 1; - - /* Print header first */ - if (step == 0) { - buf += sprintf(buf, "YAFFS built:" __DATE__ " " __TIME__ - "\n%s\n%s\n", yaffs_fs_c_version, - yaffs_guts_c_version); - } - - /* hold lock_kernel while traversing yaffs_dev_list */ - lock_kernel(); - - /* Locate and print the Nth entry. Order N-squared but N is small. */ - list_for_each(item, &yaffs_dev_list) { - yaffs_Device *dev = list_entry(item, yaffs_Device, devList); - if (n < step) { - n++; - continue; - } - buf += sprintf(buf, "\nDevice %d \"%s\"\n", n, dev->name); - buf = yaffs_dump_dev(buf, dev); - break; - } - unlock_kernel(); - - return buf - page < count ? buf - page : count; -} - -/** - * Set the verbosity of the warnings and error messages. - * - * Note that the names can only be a..z or _ with the current code. - */ - -static struct { - char *mask_name; - unsigned mask_bitfield; -} mask_flags[] = { - {"allocate", YAFFS_TRACE_ALLOCATE}, - {"always", YAFFS_TRACE_ALWAYS}, - {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, - {"buffers", YAFFS_TRACE_BUFFERS}, - {"bug", YAFFS_TRACE_BUG}, - {"checkpt", YAFFS_TRACE_CHECKPOINT}, - {"deletion", YAFFS_TRACE_DELETION}, - {"erase", YAFFS_TRACE_ERASE}, - {"error", YAFFS_TRACE_ERROR}, - {"gc_detail", YAFFS_TRACE_GC_DETAIL}, - {"gc", YAFFS_TRACE_GC}, - {"mtd", YAFFS_TRACE_MTD}, - {"nandaccess", YAFFS_TRACE_NANDACCESS}, - {"os", YAFFS_TRACE_OS}, - {"scan_debug", YAFFS_TRACE_SCAN_DEBUG}, - {"scan", YAFFS_TRACE_SCAN}, - {"tracing", YAFFS_TRACE_TRACING}, - - {"verify", YAFFS_TRACE_VERIFY}, - {"verify_nand", YAFFS_TRACE_VERIFY_NAND}, - {"verify_full", YAFFS_TRACE_VERIFY_FULL}, - {"verify_all", YAFFS_TRACE_VERIFY_ALL}, - - {"write", YAFFS_TRACE_WRITE}, - {"all", 0xffffffff}, - {"none", 0}, - {NULL, 0}, -}; - -#define MAX_MASK_NAME_LENGTH 40 -static int yaffs_proc_write(struct file *file, const char *buf, - unsigned long count, void *data) -{ - unsigned rg = 0, mask_bitfield; - char *end; - char *mask_name; - const char *x; - char substring[MAX_MASK_NAME_LENGTH+1]; - int i; - int done = 0; - int add, len = 0; - int pos = 0; - - rg = yaffs_traceMask; - - while (!done && (pos < count)) { - done = 1; - while ((pos < count) && isspace(buf[pos])) { - pos++; - } - - switch (buf[pos]) { - case '+': - case '-': - case '=': - add = buf[pos]; - pos++; - break; - - default: - add = ' '; - break; - } - mask_name = NULL; - - mask_bitfield = simple_strtoul(buf + pos, &end, 0); - if (end > buf + pos) { - mask_name = "numeral"; - len = end - (buf + pos); - pos += len; - done = 0; - } else { - for(x = buf + pos, i = 0; - (*x == '_' || (*x >='a' && *x <= 'z')) && - i <MAX_MASK_NAME_LENGTH; x++, i++, pos++) - substring[i] = *x; - substring[i] = '\0'; - - for (i = 0; mask_flags[i].mask_name != NULL; i++) { - if(strcmp(substring,mask_flags[i].mask_name) == 0){ - mask_name = mask_flags[i].mask_name; - mask_bitfield = mask_flags[i].mask_bitfield; - done = 0; - break; - } - } - } - - if (mask_name != NULL) { - done = 0; - switch(add) { - case '-': - rg &= ~mask_bitfield; - break; - case '+': - rg |= mask_bitfield; - break; - case '=': - rg = mask_bitfield; - break; - default: - rg |= mask_bitfield; - break; - } - } - } - - yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS; - - printk("new trace = 0x%08X\n",yaffs_traceMask); - - if (rg & YAFFS_TRACE_ALWAYS) { - for (i = 0; mask_flags[i].mask_name != NULL; i++) { - char flag; - flag = ((rg & mask_flags[i].mask_bitfield) == mask_flags[i].mask_bitfield) ? '+' : '-'; - printk("%c%s\n", flag, mask_flags[i].mask_name); - } - } - - return count; -} - -/* Stuff to handle installation of file systems */ -struct file_system_to_install { - struct file_system_type *fst; - int installed; -}; - -static struct file_system_to_install fs_to_install[] = { -//#ifdef CONFIG_YAFFS_YAFFS1 - {&yaffs_fs_type, 0}, -//#endif -//#ifdef CONFIG_YAFFS_YAFFS2 - {&yaffs2_fs_type, 0}, -//#endif - {NULL, 0} -}; - -static int __init init_yaffs_fs(void) -{ - int error = 0; - struct file_system_to_install *fsinst; - - T(YAFFS_TRACE_ALWAYS, - ("yaffs " __DATE__ " " __TIME__ " Installing. \n")); - - /* Install the proc_fs entry */ - my_proc_entry = create_proc_entry("yaffs", - S_IRUGO | S_IFREG, - &proc_root); - - if (my_proc_entry) { - my_proc_entry->write_proc = yaffs_proc_write; - my_proc_entry->read_proc = yaffs_proc_read; - my_proc_entry->data = NULL; - } else { - return -ENOMEM; - } - - /* Now add the file system entries */ - - fsinst = fs_to_install; - - while (fsinst->fst && !error) { - error = register_filesystem(fsinst->fst); - if (!error) { - fsinst->installed = 1; - } - fsinst++; - } - - /* Any errors? uninstall */ - if (error) { - fsinst = fs_to_install; - - while (fsinst->fst) { - if (fsinst->installed) { - unregister_filesystem(fsinst->fst); - fsinst->installed = 0; - } - fsinst++; - } - } - - return error; -} - -static void __exit exit_yaffs_fs(void) -{ - - struct file_system_to_install *fsinst; - - T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__ - " removing. \n")); - - remove_proc_entry("yaffs", &proc_root); - - fsinst = fs_to_install; - - while (fsinst->fst) { - if (fsinst->installed) { - unregister_filesystem(fsinst->fst); - fsinst->installed = 0; - } - fsinst++; - } - -} - -module_init(init_yaffs_fs) -module_exit(exit_yaffs_fs) - -MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system"); -MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2006"); -MODULE_LICENSE("GPL"); diff --git a/fs/yaffs2/yaffs_mtdif1.c b/fs/yaffs2/yaffs_mtdif1.c deleted file mode 100644 index 36185b6..0000000 --- a/fs/yaffs2/yaffs_mtdif1.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * YAFFS: Yet another FFS. A NAND-flash specific file system. - * yaffs_mtdif1.c NAND mtd interface functions for small-page NAND. - * - * Copyright (C) 2002 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * 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. - */ - -/* - * This module provides the interface between yaffs_nand.c and the - * MTD API. This version is used when the MTD interface supports the - * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17, - * and we have small-page NAND device. - * - * These functions are invoked via function pointers in yaffs_nand.c. - * This replaces functionality provided by functions in yaffs_mtdif.c - * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are - * called in yaffs_mtdif.c when the function pointers are NULL. - * We assume the MTD layer is performing ECC (useNANDECC is true). - */ - -#include "yportenv.h" -#include "yaffs_guts.h" -#include "yaffs_packedtags1.h" -#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC - -#include "linux/kernel.h" -#include "linux/version.h" -#include "linux/types.h" -#include "linux/mtd/mtd.h" - -/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - -const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.5 2007/10/29 14:59:57 imcd Exp $"; - -#ifndef CONFIG_YAFFS_9BYTE_TAGS -# define YTAG1_SIZE 8 -#else -# define YTAG1_SIZE 9 -#endif - -#if 0 -/* Use the following nand_ecclayout with MTD when using - * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout. - * If you have existing Yaffs images and the byte order differs from this, - * adjust 'oobfree' to match your existing Yaffs data. - * - * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the - * pageStatus byte (at NAND spare offset 4) scattered/gathered from/to - * the 9th byte. - * - * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5 - * We have/need PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P - * where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus - * byte and B is the small-page bad-block indicator byte. - */ -static struct nand_ecclayout nand_oob_16 = { - .eccbytes = 6, - .eccpos = { 8, 9, 10, 13, 14, 15 }, - .oobavail = 9, - .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } -}; -#endif - -/* Write a chunk (page) of data to NAND. - * - * Caller always provides ExtendedTags data which are converted to a more - * compact (packed) form for storage in NAND. A mini-ECC runs over the - * contents of the tags meta-data; used to valid the tags when read. - * - * - Pack ExtendedTags to PackedTags1 form - * - Compute mini-ECC for PackedTags1 - * - Write data and packed tags to NAND. - * - * Note: Due to the use of the PackedTags1 meta-data which does not include - * a full sequence number (as found in the larger PackedTags2 form) it is - * necessary for Yaffs to re-write a chunk/page (just once) to mark it as - * discarded and dirty. This is not ideal: newer NAND parts are supposed - * to be written just once. When Yaffs performs this operation, this - * function is called with a NULL data pointer -- calling MTD write_oob - * without data is valid usage (2.6.17). - * - * Any underlying MTD error results in YAFFS_FAIL. - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, - int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags) -{ - struct mtd_info * mtd = dev->genericDevice; - int chunkBytes = dev->nDataBytesPerChunk; - loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; - struct mtd_oob_ops ops; - yaffs_PackedTags1 pt1; - int retval; - - /* we assume that PackedTags1 and yaffs_Tags are compatible */ - compile_time_assertion(sizeof(yaffs_PackedTags1) == 12); - compile_time_assertion(sizeof(yaffs_Tags) == 8); - - dev->nPageWrites++; - - yaffs_PackTags1(&pt1, etags); - yaffs_CalcTagsECC((yaffs_Tags *)&pt1); - - /* When deleting a chunk, the upper layer provides only skeletal - * etags, one with chunkDeleted set. However, we need to update the - * tags, not erase them completely. So we use the NAND write property - * that only zeroed-bits stick and set tag bytes to all-ones and - * zero just the (not) deleted bit. - */ -#ifndef CONFIG_YAFFS_9BYTE_TAGS - if (etags->chunkDeleted) { - memset(&pt1, 0xff, 8); - /* clear delete status bit to indicate deleted */ - pt1.deleted = 0; - } -#else - ((__u8 *)&pt1)[8] = 0xff; - if (etags->chunkDeleted) { - memset(&pt1, 0xff, 8); - /* zero pageStatus byte to indicate deleted */ - ((__u8 *)&pt1)[8] = 0; - } -#endif - - memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OOB_AUTO; - ops.len = (data) ? chunkBytes : 0; - ops.ooblen = YTAG1_SIZE; - ops.datbuf = (__u8 *)data; - ops.oobbuf = (__u8 *)&pt1; - - retval = mtd->write_oob(mtd, addr, &ops); - if (retval) { - yaffs_trace(YAFFS_TRACE_MTD, - "write_oob failed, chunk %d, mtd error %d\n", - chunkInNAND, retval); - } - return retval ? YAFFS_FAIL : YAFFS_OK; -} - -/* Return with empty ExtendedTags but add eccResult. - */ -static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval) -{ - if (etags) { - memset(etags, 0, sizeof(*etags)); - etags->eccResult = eccResult; - } - return retval; -} - -/* Read a chunk (page) from NAND. - * - * Caller expects ExtendedTags data to be usable even on error; that is, - * all members except eccResult and blockBad are zeroed. - * - * - Check ECC results for data (if applicable) - * - Check for blank/erased block (return empty ExtendedTags if blank) - * - Check the PackedTags1 mini-ECC (correct if necessary/possible) - * - Convert PackedTags1 to ExtendedTags - * - Update eccResult and blockBad members to refect state. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, - int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags) -{ - struct mtd_info * mtd = dev->genericDevice; - int chunkBytes = dev->nDataBytesPerChunk; - loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; - int eccres = YAFFS_ECC_RESULT_NO_ERROR; - struct mtd_oob_ops ops; - yaffs_PackedTags1 pt1; - int retval; - int deleted; - - dev->nPageReads++; - - memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OOB_AUTO; - ops.len = (data) ? chunkBytes : 0; - ops.ooblen = YTAG1_SIZE; - ops.datbuf = data; - ops.oobbuf = (__u8 *)&pt1; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) - /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; - * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. - */ - ops.len = (ops.datbuf) ? ops.len : ops.ooblen; -#endif - /* Read page and oob using MTD. - * Check status and determine ECC result. - */ - retval = mtd->read_oob(mtd, addr, &ops); - if (retval) { - yaffs_trace(YAFFS_TRACE_MTD, - "read_oob failed, chunk %d, mtd error %d\n", - chunkInNAND, retval); - } - - switch (retval) { - case 0: - /* no error */ - break; - - case -EUCLEAN: - /* MTD's ECC fixed the data */ - eccres = YAFFS_ECC_RESULT_FIXED; - dev->eccFixed++; - break; - - case -EBADMSG: - /* MTD's ECC could not fix the data */ - dev->eccUnfixed++; - /* fall into... */ - default: - rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0); - etags->blockBad = (mtd->block_isbad)(mtd, addr); - return YAFFS_FAIL; - } - - /* Check for a blank/erased chunk. - */ - if (yaffs_CheckFF((__u8 *)&pt1, 8)) { - /* when blank, upper layers want eccResult to be <= NO_ERROR */ - return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); - } - -#ifndef CONFIG_YAFFS_9BYTE_TAGS - /* Read deleted status (bit) then return it to it's non-deleted - * state before performing tags mini-ECC check. pt1.deleted is - * inverted. - */ - deleted = !pt1.deleted; - pt1.deleted = 1; -#else - deleted = (yaffs_CountBits(((__u8 *)&pt1)[8]) < 7); -#endif - - /* Check the packed tags mini-ECC and correct if necessary/possible. - */ - retval = yaffs_CheckECCOnTags((yaffs_Tags *)&pt1); - switch (retval) { - case 0: - /* no tags error, use MTD result */ - break; - case 1: - /* recovered tags-ECC error */ - dev->tagsEccFixed++; - if (eccres == YAFFS_ECC_RESULT_NO_ERROR) - eccres = YAFFS_ECC_RESULT_FIXED; - break; - default: - /* unrecovered tags-ECC error */ - dev->tagsEccUnfixed++; - return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL); - } - - /* Unpack the tags to extended form and set ECC result. - * [set shouldBeFF just to keep yaffs_UnpackTags1 happy] - */ - pt1.shouldBeFF = 0xFFFFFFFF; - yaffs_UnpackTags1(etags, &pt1); - etags->eccResult = eccres; - - /* Set deleted state */ - etags->chunkDeleted = deleted; - return YAFFS_OK; -} - -/* Mark a block bad. - * - * This is a persistant state. - * Use of this function should be rare. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) -{ - struct mtd_info * mtd = dev->genericDevice; - int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk; - int retval; - - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo); - - retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo); - return (retval) ? YAFFS_FAIL : YAFFS_OK; -} - -/* Check any MTD prerequists. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -static int nandmtd1_TestPrerequists(struct mtd_info * mtd) -{ - /* 2.6.18 has mtd->ecclayout->oobavail */ - /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ - int oobavail = mtd->ecclayout->oobavail; - - if (oobavail < YTAG1_SIZE) { - yaffs_trace(YAFFS_TRACE_ERROR, - "mtd device has only %d bytes for tags, need %d\n", - oobavail, YTAG1_SIZE); - return YAFFS_FAIL; - } - return YAFFS_OK; -} - -/* Query for the current state of a specific block. - * - * Examine the tags of the first chunk of the block and return the state: - * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad - * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use - * - YAFFS_BLOCK_STATE_EMPTY, the block is clean - * - * Always returns YAFFS_OK. - */ -int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, - yaffs_BlockState * pState, int *pSequenceNumber) -{ - struct mtd_info * mtd = dev->genericDevice; - int chunkNo = blockNo * dev->nChunksPerBlock; - loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk; - yaffs_ExtendedTags etags; - int state = YAFFS_BLOCK_STATE_DEAD; - int seqnum = 0; - int retval; - - /* We don't yet have a good place to test for MTD config prerequists. - * Do it here as we are called during the initial scan. - */ - if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) { - return YAFFS_FAIL; - } - - retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags); - etags.blockBad = (mtd->block_isbad)(mtd, addr); - if (etags.blockBad) { - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, - "block %d is marked bad\n", blockNo); - state = YAFFS_BLOCK_STATE_DEAD; - } - else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) { - /* bad tags, need to look more closely */ - state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; - } - else if (etags.chunkUsed) { - state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; - seqnum = etags.sequenceNumber; - } - else { - state = YAFFS_BLOCK_STATE_EMPTY; - } - - *pState = state; - *pSequenceNumber = seqnum; - - /* query always succeeds */ - return YAFFS_OK; -} - -#endif /*KERNEL_VERSION*/ diff --git a/fs/yaffs2/yaffs_mtdif1.h b/fs/yaffs2/yaffs_mtdif1.h deleted file mode 100644 index c4f6197..0000000 --- a/fs/yaffs2/yaffs_mtdif1.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * YAFFS: Yet another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2007 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 as - * published by the Free Software Foundation. - * - * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - */ - -#ifndef __YAFFS_MTDIF1_H__ -#define __YAFFS_MTDIF1_H__ - -int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, - const __u8 * data, const yaffs_ExtendedTags * tags); - -int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, - __u8 * data, yaffs_ExtendedTags * tags); - -int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); - -int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, - yaffs_BlockState * state, int *sequenceNumber); - -#endif |