From: charles Date: Mon, 5 May 2008 07:58:58 +0000 (+0000) Subject: Check in inband tags, some extra yaffs direct functions and some other changes X-Git-Tag: pre-name-change~283 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=e8cfe05cf0d057f6978c37943e51b17bb14664e3 Check in inband tags, some extra yaffs direct functions and some other changes --- diff --git a/devextras.h b/devextras.h index 2ba88a2..55c3121 100644 --- a/devextras.h +++ b/devextras.h @@ -23,31 +23,29 @@ #ifndef __EXTRAS_H__ #define __EXTRAS_H__ -#if defined WIN32 -#define __inline__ __inline -#define new newHack -#endif -#if !(defined __KERNEL__) || (defined WIN32) +#if !(defined __KERNEL__) /* Definition of types */ typedef unsigned char __u8; typedef unsigned short __u16; typedef unsigned __u32; +#endif + /* * This is a simple doubly linked list implementation that matches the * way the Linux kernel doubly linked list implementation works. */ -struct list_head { - struct list_head *next; /* next in chain */ - struct list_head *prev; /* previous in chain */ +struct ylist_head { + struct ylist_head *next; /* next in chain */ + struct ylist_head *prev; /* previous in chain */ }; /* Initialise a list head to an empty list */ -#define INIT_LIST_HEAD(p) \ +#define YINIT_LIST_HEAD(p) \ do { \ (p)->next = (p);\ (p)->prev = (p); \ @@ -55,10 +53,10 @@ do { \ /* Add an element to a list */ -static __inline__ void list_add(struct list_head *newEntry, - struct list_head *list) +static __inline__ void ylist_add(struct ylist_head *newEntry, + struct ylist_head *list) { - struct list_head *listNext = list->next; + struct ylist_head *listNext = list->next; list->next = newEntry; newEntry->prev = list; @@ -70,52 +68,63 @@ static __inline__ void list_add(struct list_head *newEntry, /* Take an element out of its current list, with or without * reinitialising the links.of the entry*/ -static __inline__ void list_del(struct list_head *entry) +static __inline__ void ylist_del(struct ylist_head *entry) { - struct list_head *listNext = entry->next; - struct list_head *listPrev = entry->prev; + struct ylist_head *listNext = entry->next; + struct ylist_head *listPrev = entry->prev; listNext->prev = listPrev; listPrev->next = listNext; } -static __inline__ void list_del_init(struct list_head *entry) +static __inline__ void ylist_del_init(struct ylist_head *entry) { - list_del(entry); + ylist_del(entry); entry->next = entry->prev = entry; } /* Test if the list is empty */ -static __inline__ int list_empty(struct list_head *entry) +static __inline__ int ylist_empty(struct ylist_head *entry) { return (entry->next == entry); } -/* list_entry takes a pointer to a list entry and offsets it to that +/* ylist_entry takes a pointer to a list entry and offsets it to that * we can find a pointer to the object it is embedded in. */ -#define list_entry(entry, type, member) \ +#define ylist_entry(entry, type, member) \ ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member))) -/* list_for_each and list_for_each_safe iterate over lists. - * list_for_each_safe uses temporary storage to make the list delete safe +/* ylist_for_each and list_for_each_safe iterate over lists. + * ylist_for_each_safe uses temporary storage to make the list delete safe */ -#define list_for_each(itervar, list) \ +#define ylist_for_each(itervar, list) \ for (itervar = (list)->next; itervar != (list); itervar = itervar->next ) -#define list_for_each_safe(itervar,saveVar, list) \ +#define ylist_for_each_safe(itervar,saveVar, list) \ for (itervar = (list)->next, saveVar = (list)->next->next; itervar != (list); \ itervar = saveVar, saveVar = saveVar->next) + +#if !(defined __KERNEL__) + + +#ifndef WIN32 +#include +#endif + + +#ifdef CONFIG_YAFFS_PROVIDE_DEFS /* File types */ + #define DT_UNKNOWN 0 #define DT_FIFO 1 #define DT_CHR 2 @@ -124,7 +133,7 @@ static __inline__ int list_empty(struct list_head *entry) #define DT_REG 8 #define DT_LNK 10 #define DT_SOCK 12 -#define DR_WHT 14 +#define DT_WHT 14 #ifndef WIN32 @@ -155,21 +164,18 @@ struct iattr { unsigned int ia_attr_flags; }; +#endif + + #define KERN_DEBUG #else -#ifndef WIN32 #include -#include #include #include -#endif #endif -#if defined WIN32 -#undef new -#endif #endif diff --git a/direct/Makefile b/direct/Makefile index dd6b61d..a65c0e6 100644 --- a/direct/Makefile +++ b/direct/Makefile @@ -14,12 +14,14 @@ # # NB Warning this Makefile does not include header dependencies. # -# $Id: Makefile,v 1.15 2007-07-18 19:40:38 charles Exp $ +# $Id: Makefile,v 1.16 2008-05-05 07:58:58 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 = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 +CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE +CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) +#CFLAGS+= -fstack-check -O0 #CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations #CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline @@ -40,7 +42,7 @@ ALLOBJS = $(DIRECTTESTOBJS) $(BOOTTESTOBJS) SYMLINKS = 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_nand.c yaffs_nand.h yaffs_getblockinfo.h \ yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ yaffs_qsort.c yaffs_qsort.h @@ -49,7 +51,7 @@ SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsin all: directtest2k $(ALLOBJS): %.o: %.c - gcc -c $(CFLAGS) $< -o $@ + gcc -c $(CFLAGS) -o $@ $< $(SYMLINKS): ln -s ../$@ $@ diff --git a/direct/dtest.c b/direct/dtest.c index be492b4..6f6da74 100644 --- a/direct/dtest.c +++ b/direct/dtest.c @@ -1,7 +1,7 @@ /* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * YAFFS: Yet another FFS. A NAND-flash specific file system. * - * Copyright (C) 2002-2007 Aleph One Ltd. + * Copyright (C) 2002 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning @@ -9,11 +9,10 @@ * 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. -*/ + #include @@ -125,9 +124,7 @@ int check_pattern_file(char *fn) int dump_file_data(char *fn) { int h; - int marker; int i = 0; - int size; int ok = 1; unsigned char b; @@ -178,6 +175,7 @@ void create_file_of_size(const char *fn,int syze) { int h; int n; + int result; char xx[200]; @@ -188,7 +186,10 @@ void create_file_of_size(const char *fn,int syze) while (iterations > 0) { sprintf(xx,"%s %8d",fn,iterations); - yaffs_write(h,xx,strlen(xx)); + n = strlen(xx); + result = yaffs_write(h,xx,n); + if(result != n) + printf("Wrote %d, should have been %d\n",result,n); iterations--; } yaffs_close (h); @@ -197,7 +198,7 @@ void create_file_of_size(const char *fn,int syze) void verify_file_of_size(const char *fn,int syze) { int h; - int n; + int result; char xx[200]; char yy[200]; @@ -212,11 +213,11 @@ void verify_file_of_size(const char *fn,int syze) sprintf(xx,"%s %8d",fn,iterations); l = strlen(xx); - yaffs_read(h,yy,l); + result = 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)); + printf("=====>>>>> verification of file %s failed near position %lld\n",fn,(long long)yaffs_lseek(h,0,SEEK_CUR)); } iterations--; } @@ -226,8 +227,6 @@ void verify_file_of_size(const char *fn,int syze) void create_resized_file_of_size(const char *fn,int syze1,int reSyze, int syze2) { int h; - int n; - int iterations; @@ -240,7 +239,7 @@ void create_resized_file_of_size(const char *fn,int syze1,int reSyze, int syze2) iterations--; } - yaffs_truncate(h,reSyze); + yaffs_ftruncate(h,reSyze); yaffs_lseek(h,0,SEEK_SET); iterations = (syze2 + strlen(fn) -1)/ strlen(fn); @@ -375,7 +374,7 @@ void scan_pattern_test(const char *path, int fsize, int niterations) } } -void fill_disk(char *path,int nfiles) +void fill_disk(const char *path,int nfiles) { int h; int n; @@ -401,7 +400,7 @@ void fill_disk(char *path,int nfiles) } } -void fill_disk_and_delete(char *path, int nfiles, int ncycles) +void fill_disk_and_delete(const char *path, int nfiles, int ncycles) { int i,j; char str[50]; @@ -883,18 +882,12 @@ int huge_directory_test_on_path(char *path) 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(); @@ -939,6 +932,7 @@ int huge_directory_test_on_path(char *path) int yaffs_scan_test(const char *path) { + return 0; } @@ -1012,7 +1006,7 @@ int resize_stress_test(const char *path) syz -= 500; if(syz < 0) syz = 0; - yaffs_truncate(a,syz); + yaffs_ftruncate(a,syz); } else @@ -1041,6 +1035,7 @@ int resize_stress_test_no_grow_complex(const char *path,int iters) char abuffer[1000]; char bbuffer[1000]; + yaffs_StartUp(); @@ -1079,7 +1074,7 @@ int resize_stress_test_no_grow_complex(const char *path,int iters) syz -= 2050; if(syz < 0) syz = 0; - yaffs_truncate(a,syz); + yaffs_ftruncate(a,syz); syz = yaffs_lseek(a,0,SEEK_END); printf("shrink to %d\n",syz); } @@ -1096,7 +1091,8 @@ int resize_stress_test_no_grow_complex(const char *path,int iters) } - printf("file size is %d\n",yaffs_lseek(a,0,SEEK_END)); + + printf("file size is %lld\n",(long long)yaffs_lseek(a,0,SEEK_END)); } @@ -1152,7 +1148,7 @@ int resize_stress_test_no_grow(const char *path,int iters) syz -= 2050; if(syz < 0) syz = 0; - yaffs_truncate(a,syz); + yaffs_ftruncate(a,syz); syz = yaffs_lseek(a,0,SEEK_END); printf("shrink to %d\n",syz); } @@ -1169,7 +1165,7 @@ int resize_stress_test_no_grow(const char *path,int iters) } - printf("file size is %d\n",yaffs_lseek(a,0,SEEK_END)); + printf("file size is %lld\n",(long long)yaffs_lseek(a,0,SEEK_END)); } @@ -1253,7 +1249,6 @@ int cache_bypass_bug_test(void) // This bug has been fixed. int a; - int i; char buffer1[1000]; char buffer2[1000]; @@ -1327,7 +1322,7 @@ int truncate_test(void) yaffs_write(a,"abcdefghijklmnopqrstuvwzyz",26); - yaffs_truncate(a,3); + yaffs_ftruncate(a,3); l= yaffs_lseek(a,0,SEEK_END); printf("truncated length is %d\n",l); @@ -1374,13 +1369,10 @@ 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(); @@ -1441,11 +1433,7 @@ void link_test(const char *mountpt) 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); @@ -1482,7 +1470,6 @@ void freespace_test(const char *mountpt) int i; int h; char a[100]; - char b[100]; int f0; int f1; @@ -1741,8 +1728,6 @@ void multi_mount_test(const char *mountpt,int nmounts) { char a[30]; - char b[30]; - char c[30]; int i; int j; @@ -1773,12 +1758,18 @@ void multi_mount_test(const char *mountpt,int nmounts) sprintf(xx,"%s/1",a); h1 = yaffs_open(xx, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); - + +#if 0 for(j = 0; j < 200; j++){ yaffs_write(h0,xx,1000); yaffs_write(h1,xx,1000); } - +#else + while(yaffs_write(h0,xx,1000) > 0){ + + yaffs_write(h1,xx,1000); + } +#endif len0 = yaffs_lseek(h0,0,SEEK_END); len1 = yaffs_lseek(h1,0,SEEK_END); @@ -1791,7 +1782,7 @@ void multi_mount_test(const char *mountpt,int nmounts) } - yaffs_truncate(h0,0); + // yaffs_truncate(h0,0); yaffs_close(h0); yaffs_close(h1); @@ -1808,8 +1799,6 @@ void small_mount_test(const char *mountpt,int nmounts) { char a[30]; - char b[30]; - char c[30]; int i; int j; @@ -1885,17 +1874,12 @@ 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); @@ -1921,7 +1905,7 @@ void small_overwrite_test(const char *mountpt,int nmounts) 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_ftruncate(h0,j); yaffs_lseek(h0,j,SEEK_SET); yaffs_write(h0,xx,7000); yaffs_write(h1,xx,7000); @@ -1941,6 +1925,44 @@ void small_overwrite_test(const char *mountpt,int nmounts) } +void seek_overwrite_test(const char *mountpt,int nmounts) +{ + + char a[30]; + + int i; + int j; + + int h0; + + + sprintf(a,"%s/f",mountpt); + + yaffs_StartUp(); + + yaffs_mount(mountpt); + + + for(i = 0; i < nmounts; i++){ + + h0 = yaffs_open(a, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); + + for(j = 0; j < 100000; j++){ + yaffs_lseek(h0,0,SEEK_SET); + yaffs_write(h0,xx,5000); + yaffs_lseek(h0,0x100000,SEEK_SET); + yaffs_write(h0,xx,5000); + + if(early_exit) + exit(0); + } + + yaffs_close(h0); + + } +} + + void yaffs_touch(const char *fn) { yaffs_chmod(fn, S_IREAD | S_IWRITE); @@ -2014,7 +2036,7 @@ int make_file2(const char *name1, const char *name2,int syz) } yaffs_close(h1); yaffs_close(h2); - + return 0; } @@ -2027,10 +2049,8 @@ void checkpoint_upgrade_test(const char *mountpt,int nmounts) char b[50]; char c[50]; char d[50]; - - int i; + int j; - int h; sprintf(a,"%s/a",mountpt); @@ -2087,8 +2107,7 @@ void huge_array_test(const char *mountpt,int n) int i; - int j; - int h; + int space; int fnum; @@ -2104,10 +2123,10 @@ void huge_array_test(const char *mountpt,int n) n--; fnum = 0; printf("\n\n START run\n\n"); - while(yaffs_freespace(mountpt) > 25000000){ + while((space = yaffs_freespace(mountpt)) > 25000000){ sprintf(a,"%s/file%d",mountpt,fnum); fnum++; - printf("create file %s\n",a); + printf("create file %s, free space %d\n",a,space); create_file_of_size(a,10000000); printf("verifying file %s\n",a); verify_file_of_size(a,10000000); @@ -2153,7 +2172,7 @@ void random_truncate(int h, char * name) flen = yaffs_lseek(h,0,SEEK_END); if(n > flen) n = flen / 2; - yaffs_truncate(name,n); + yaffs_ftruncate(h,n); yaffs_lseek(h,n,SEEK_SET); } @@ -2167,10 +2186,8 @@ void random_small_file_test(const char *mountpt,int iterations) int i; int n; - int j; int h[NSMALLFILES]; int r; - int fnum; yaffs_StartUp(); @@ -2189,7 +2206,7 @@ void random_small_file_test(const char *mountpt,int iterations) 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); + h[i] = yaffs_open(a[i],O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); } if(h[i] < -1) @@ -2248,6 +2265,10 @@ int main(int argc, char *argv[]) //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); + //seek_overwrite_test("/flash/flash",1000); + //checkpoint_fill_test("/flash/flash",20); + //checkpoint_upgrade_test("/flash/flash",20); //small_overwrite_test("/flash/flash",1000); //checkpoint_fill_test("/flash/flash",20); // random_small_file_test("/flash/flash",10000); diff --git a/direct/fsx_test/Makefile b/direct/fsx_test/Makefile index 30323ad..359a523 100644 --- a/direct/fsx_test/Makefile +++ b/direct/fsx_test/Makefile @@ -14,11 +14,13 @@ # # NB Warning this Makefile does not include header dependencies. # -# $Id: Makefile,v 1.1 2007-10-16 00:46:33 charles Exp $ +# $Id: Makefile,v 1.2 2008-05-05 07:58:58 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 = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -DNO_Y_INLINE +CFLAGS+= -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES +CFLAGS+= -Wall -g $(EXTRA_COMPILE_FLAGS) CFLAGS+= -fstack-check -O0 #CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations @@ -42,7 +44,7 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h ya 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 + yaffs_qsort.c yaffs_qsort.h yaffs_getblockinfo.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 \ diff --git a/direct/fsx_test/yaffs_fsx.c b/direct/fsx_test/yaffs_fsx.c index 1e110b9..26a8536 100644 --- a/direct/fsx_test/yaffs_fsx.c +++ b/direct/fsx_test/yaffs_fsx.c @@ -67,6 +67,7 @@ #include #include #include +#include #include "yaffsfs.h" @@ -421,14 +422,14 @@ check_trunc_hack(void) { struct yaffs_stat statbuf; - yaffs_truncate(fd, (off_t)0); - yaffs_truncate(fd, (off_t)100000); + yaffs_ftruncate(fd, (off_t)0); + yaffs_ftruncate(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); + yaffs_ftruncate(fd, (off_t)0); } @@ -579,7 +580,7 @@ dotruncate(unsigned size) (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) { + if (yaffs_ftruncate(fd, (off_t)size) == -1) { prt("ftruncate1: %x\n", size); prterr("dotruncate: ftruncate"); report_failure(160); @@ -605,7 +606,7 @@ writefileimage() iret, (unsigned long long)file_size); report_failure(172); } - if (lite ? 0 : yaffs_truncate(fd, file_size) == -1) { + if (lite ? 0 : yaffs_ftruncate(fd, file_size) == -1) { prt("ftruncate2: %llx\n", (unsigned long long)file_size); prterr("writefileimage: ftruncate"); report_failure(173); diff --git a/direct/yaffs_fileem2k.c b/direct/yaffs_fileem2k.c index 1e2cd6b..cb94486 100644 --- a/direct/yaffs_fileem2k.c +++ b/direct/yaffs_fileem2k.c @@ -16,7 +16,7 @@ * This is only intended as test code to test persistence etc. */ -const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.12 2007-02-14 01:09:06 wookey Exp $"; +const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.13 2008-05-05 07:58:58 charles Exp $"; #include "yportenv.h" @@ -103,16 +103,10 @@ static int GetBlockFileHandle(int n) 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) { @@ -144,7 +138,7 @@ int yflash_GetNumberOfBlocks(void) return filedisk.nBlocks; } -int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) +int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags) { int written; int pos; @@ -158,90 +152,114 @@ int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 CheckInit(); - - if(data) - { - pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; - h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; + if(dev->inbandTags){ - 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; - } - } + yaffs_PackedTags2TagsPart * pt2tp; + pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk]; + yaffs_PackTags2TagsPart(pt2tp,tags); - 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"); - + 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); - written = write(h,localBuffer,dev->nDataBytesPerChunk); + written = write(h,data,dev->totalBytesPerChunk); + 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->totalBytesPerChunk) return YAFFS_FAIL; - 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) + else { + + 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"); - written = write(h,tags,sizeof(yaffs_ExtendedTags)); - if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL; + 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; } - else + + if(tags) { - yaffs_PackedTags2 pt; - yaffs_PackTags2(&pt,tags); - __u8 * ptab = (__u8 *)&pt; + 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); - 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; - } + 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]; + for(i = 0; i < sizeof(pt); i++) + localBuffer[i] &= ptab[i]; - if(memcmp(localBuffer,&pt,sizeof(pt))) - printf("nand sim: tags corruption\n"); + if(memcmp(localBuffer,&pt,sizeof(pt))) + printf("nand sim: tags corruption\n"); - lseek(h,pos,SEEK_SET); + lseek(h,pos,SEEK_SET); - written = write(h,localBuffer,sizeof(pt)); - if(written != sizeof(pt)) return YAFFS_FAIL; + written = write(h,localBuffer,sizeof(pt)); + if(written != sizeof(pt)) return YAFFS_FAIL; + } } - } - + } return YAFFS_OK; } @@ -268,6 +286,9 @@ int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *da int nread; int pos; int h; + int localData = 0; + int retval = YAFFS_OK; + int nRead; T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %x tags %x" TENDSTR),chunkInNAND,(unsigned)data, (unsigned)tags)); @@ -275,68 +296,107 @@ int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *da - if(data) - { + + if(dev->inbandTags){ + /* Got to suck the tags out of the data area */ + if(!data) { + localData=1; + data = yaffs_GetTempBuffer(dev,__LINE__); + } + + yaffs_PackedTags2TagsPart * pt2tp; + pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk]; + + 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); + h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; + lseek(h,pos,SEEK_SET); + + nRead = read(h, data,dev->totalBytesPerChunk); + + yaffs_UnpackTags2TagsPart(tags,pt2tp); - if(nread != dev->nDataBytesPerChunk) return YAFFS_FAIL; + if(nread != dev->totalBytesPerChunk) + retval = YAFFS_FAIL; + + if(localData) + yaffs_ReleaseTempBuffer(dev,data,__LINE__); + + + } - 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); + else { + + if(data) + { - if(0 && dev->isYaffs2) + 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) + retval = YAFFS_FAIL; + } + + if(tags) { - nread= read(h,tags,sizeof(yaffs_ExtendedTags)); - if(nread != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL; - if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags))) + 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) { - yaffs_InitialiseTags(tags); + nread= read(h,tags,sizeof(yaffs_ExtendedTags)); + if(nread != sizeof(yaffs_ExtendedTags)) + retval = YAFFS_FAIL; + if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags))) + { + yaffs_InitialiseTags(tags); + } + else + { + tags->chunkUsed = 1; + } } else { - tags->chunkUsed = 1; - } - } - else - { - yaffs_PackedTags2 pt; - nread= read(h,&pt,sizeof(pt)); - yaffs_UnpackTags2(tags,&pt); + 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; - } - } + 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(failRead10>0 && chunkInNAND == 10){ + failRead10--; + nread = 0; + } - if(nread != sizeof(pt)) return YAFFS_FAIL; + if(nread != sizeof(pt)) + retval = YAFFS_FAIL; + } } } - return YAFFS_OK; + + return retval; } @@ -413,7 +473,7 @@ int yflash_InitialiseNAND(yaffs_Device *dev) -int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) +int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber) { yaffs_ExtendedTags tags; int chunkNo; diff --git a/direct/yaffs_flashif.h b/direct/yaffs_flashif.h index f7f4e42..a6bc65d 100644 --- a/direct/yaffs_flashif.h +++ b/direct/yaffs_flashif.h @@ -20,12 +20,12 @@ #include "yaffs_guts.h" int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); int yflash_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare); -int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags); +int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags); int yflash_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare); int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags); int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); int yflash_InitialiseNAND(yaffs_Device *dev); int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); -int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber); +int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber); #endif diff --git a/direct/yaffs_ramdisk.c b/direct/yaffs_ramdisk.c index 3cf054a..fa76b6c 100644 --- a/direct/yaffs_ramdisk.c +++ b/direct/yaffs_ramdisk.c @@ -18,7 +18,7 @@ * Use this with dev->useNANDECC enabled, then ECC overheads are not required. */ -const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.4 2007-02-14 01:09:06 wookey Exp $"; +const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.5 2008-05-05 07:58:58 charles Exp $"; #include "yportenv.h" @@ -118,7 +118,7 @@ static int CheckInit(yaffs_Device *dev) return 1; } -int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) +int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags) { int blk; int pg; diff --git a/direct/yaffs_ramdisk.h b/direct/yaffs_ramdisk.h index 045ab42..4565998 100644 --- a/direct/yaffs_ramdisk.h +++ b/direct/yaffs_ramdisk.h @@ -23,7 +23,7 @@ #include "yaffs_guts.h" int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); -int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags); +int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags); int yramdisk_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags); int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); int yramdisk_InitialiseNAND(yaffs_Device *dev); diff --git a/direct/yaffs_ramem2k.c b/direct/yaffs_ramem2k.c index c01bc97..b496cc6 100644 --- a/direct/yaffs_ramem2k.c +++ b/direct/yaffs_ramem2k.c @@ -16,7 +16,7 @@ */ -const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.3 2007-02-14 01:09:06 wookey Exp $"; +const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.4 2008-05-05 07:58:58 charles Exp $"; #ifndef __KERNEL__ #define CONFIG_YAFFS_RAM_ENABLED @@ -190,7 +190,7 @@ static int CheckInit(void) return 1; } -int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) +int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags) { int blk; int pg; @@ -327,7 +327,7 @@ int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) } -int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) +int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, __u32 *sequenceNumber) { yaffs_ExtendedTags tags; int chunkNo; diff --git a/direct/yaffscfg2k.c b/direct/yaffscfg2k.c index 2c95409..2f7442e 100644 --- a/direct/yaffscfg2k.c +++ b/direct/yaffscfg2k.c @@ -34,19 +34,22 @@ unsigned yaffs_traceMask = YAFFS_TRACE_ALLOCATE | YAFFS_TRACE_CHECKPOINT | YAFFS_TRACE_BAD_BLOCKS | - YAFFS_TRACE_VERIFY | - YAFFS_TRACE_VERIFY_NAND | - YAFFS_TRACE_VERIFY_FULL | -// (~0) | 0; +static int yaffsfs_lastError; void yaffsfs_SetError(int err) { //Do whatever to set error - errno = err; + yaffsfs_lastError = err; +} + + +int yaffsfs_GetLastError(void) +{ + return yaffsfs_lastError; } void yaffsfs_Lock(void) @@ -69,7 +72,7 @@ static size_t malloc_limit = 0 & 6000000; void *yaffs_malloc(size_t size) { - size_t this; + void * this; if(yaffs_kill_alloc) return NULL; if(malloc_limit && malloc_limit <(total_malloced + size) ) @@ -121,6 +124,7 @@ static yaffsfs_DeviceConfiguration yaffsfs_config[] = { { "/flash/boot", &bootDev}, { "/flash/flash", &flashDev}, { "/ram2k", &ram2kDev}, + { "/flash/bigblock", &flashDev}, {(void *)0,(void *)0} /* Null entry to terminate list */ #endif }; @@ -135,7 +139,7 @@ int yaffs_StartUp(void) // Set up devices // /ram memset(&ramDev,0,sizeof(ramDev)); - ramDev.nDataBytesPerChunk = 512; + ramDev.totalBytesPerChunk = 512; ramDev.nChunksPerBlock = 32; ramDev.nReservedBlocks = 2; // Set this smaller for RAM ramDev.startBlock = 0; // Can use block 0 @@ -150,7 +154,7 @@ int yaffs_StartUp(void) // /boot memset(&bootDev,0,sizeof(bootDev)); - bootDev.nDataBytesPerChunk = 512; + bootDev.totalBytesPerChunk = 512; bootDev.nChunksPerBlock = 32; bootDev.nReservedBlocks = 5; bootDev.startBlock = 0; // Can use block 0 @@ -173,9 +177,10 @@ int yaffs_StartUp(void) // 2kpage/64chunk per block/128MB device memset(&flashDev,0,sizeof(flashDev)); - flashDev.nDataBytesPerChunk = 2048; + flashDev.totalBytesPerChunk = 512; flashDev.nChunksPerBlock = 64; flashDev.nReservedBlocks = 5; + flashDev.inbandTags = 1; //flashDev.checkpointStartBlock = 1; //flashDev.checkpointEndBlock = 20; flashDev.startBlock = 0; @@ -198,7 +203,7 @@ int yaffs_StartUp(void) // 2kpage/64chunk per block/128MB device memset(&ram2kDev,0,sizeof(ram2kDev)); - ram2kDev.nDataBytesPerChunk = nandemul2k_GetBytesPerChunk(); + ram2kDev.totalBytesPerChunk = nandemul2k_GetBytesPerChunk(); ram2kDev.nChunksPerBlock = nandemul2k_GetChunksPerBlock(); ram2kDev.nReservedBlocks = 5; ram2kDev.startBlock = 0; // First block after /boot diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index dc6dab9..2b9d0bc 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -24,14 +24,14 @@ #endif -const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.18 2007-07-18 19:40:38 charles Exp $"; +const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.19 2008-05-05 07:58:58 charles Exp $"; // configurationList is the list of devices that are supported static yaffsfs_DeviceConfiguration *yaffsfs_configurationList; /* Some forward references */ -static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path, int symDepth); +static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path, int symDepth); static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj); @@ -137,22 +137,95 @@ static int yaffsfs_PutHandle(int handle) // Stuff to search for a directory from a path -int yaffsfs_Match(char a, char b) +int yaffsfs_Match(YCHAR a, YCHAR b) { // case sensitive return (a == b); } +int yaffsfs_IsPathDivider(YCHAR ch) +{ + YCHAR *str = YAFFS_PATH_DIVIDERS; + + while(*str){ + if(*str == ch) + return 1; + str++; + } + + return 0; +} + // yaffsfs_FindDevice // yaffsfs_FindRoot // Scan the configuration list to find the root. // Curveballs: Should match paths that end in '/' too // Curveball2 Might have "/x/ and "/x/y". Need to return the longest match -static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath) +static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath) +{ + yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList; + const YCHAR *leftOver; + const YCHAR *p; + yaffs_Device *retval = NULL; + int thisMatchLength; + int longestMatch = -1; + + // Check all configs, choose the one that: + // 1) Actually matches a prefix (ie /a amd /abc will not match + // 2) Matches the longest. + while(cfg && cfg->prefix && cfg->dev) + { + leftOver = path; + p = cfg->prefix; + thisMatchLength = 0; + + + // Strip off any leading /'s + + while(yaffsfs_IsPathDivider(*p)) + p++; + + while(yaffsfs_IsPathDivider(*leftOver)) + leftOver++; + + while(*p && *leftOver && + yaffsfs_Match(*p,*leftOver)) + { + p++; + leftOver++; + thisMatchLength++; + + // Skip over any multiple /'s to treat them as one or + // skip over a trailling / in the prefix, but not the matching string + while(yaffsfs_IsPathDivider(*p) && + (yaffsfs_IsPathDivider(*(p+1)) || !(*(p+1)))) + p++; + + // Only skip over multiple /'s + while(yaffsfs_IsPathDivider(*leftOver) && + yaffsfs_IsPathDivider(*(leftOver+1))) + leftOver++; + } + + if((!*p ) && + (!*leftOver || yaffsfs_IsPathDivider(*leftOver)) && // no more in this path name part + (thisMatchLength > longestMatch)) + { + // Matched prefix + *restOfPath = (YCHAR *)leftOver; + retval = cfg->dev; + longestMatch = thisMatchLength; + } + cfg++; + } + return retval; +} +#if 0 +static yaffs_Device *yaffsfs_FindDevice(const YCHAR *path, YCHAR **restOfPath) { yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList; - const char *leftOver; - const char *p; + const YCHAR *leftOver; + const YCHAR *p; yaffs_Device *retval = NULL; int thisMatchLength; int longestMatch = -1; @@ -167,7 +240,7 @@ static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath) thisMatchLength = 0; while(*p && //unmatched part of prefix - strcmp(p,"/") && // the rest of the prefix is not / (to catch / at end) + !(yaffsfs_IsPathDivider(*p) && (p[1] == 0)) && // the rest of the prefix is not / (to catch / at end) *leftOver && yaffsfs_Match(*p,*leftOver)) { @@ -175,12 +248,14 @@ static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath) leftOver++; thisMatchLength++; } - if((!*p || strcmp(p,"/") == 0) && // end of prefix - (!*leftOver || *leftOver == '/') && // no more in this path name part + + + if((!*p || (yaffsfs_IsPathDivider(*p) && (p[1] == 0))) && // end of prefix + (!*leftOver || yaffsfs_IsPathDivider(*leftOver)) && // no more in this path name part (thisMatchLength > longestMatch)) { // Matched prefix - *restOfPath = (char *)leftOver; + *restOfPath = (YCHAR *)leftOver; retval = cfg->dev; longestMatch = thisMatchLength; } @@ -188,8 +263,9 @@ static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath) } return retval; } +#endif -static yaffs_Object *yaffsfs_FindRoot(const char *path, char **restOfPath) +static yaffs_Object *yaffsfs_FindRoot(const YCHAR *path, YCHAR **restOfPath) { yaffs_Device *dev; @@ -207,9 +283,9 @@ static yaffs_Object *yaffsfs_FollowLink(yaffs_Object *obj,int symDepth) while(obj && obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { - char *alias = obj->variant.symLinkVariant.alias; + YCHAR *alias = obj->variant.symLinkVariant.alias; - if(*alias == '/') + if(yaffsfs_IsPathDivider(*alias)) { // Starts with a /, need to scan from root up obj = yaffsfs_FindObject(NULL,alias,symDepth++); @@ -228,11 +304,11 @@ static yaffs_Object *yaffsfs_FollowLink(yaffs_Object *obj,int symDepth) // Parse a path to determine the directory and the name within the directory. // // eg. "/data/xx/ff" --> puts name="ff" and returns the directory "/data/xx" -static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char *path,char **name,int symDepth) +static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const YCHAR *path,YCHAR **name,int symDepth) { yaffs_Object *dir; - char *restOfPath; - char str[YAFFS_MAX_NAME_LENGTH+1]; + YCHAR *restOfPath; + YCHAR str[YAFFS_MAX_NAME_LENGTH+1]; int i; if(symDepth > YAFFSFS_MAX_SYMLINK_DEREFERENCES) @@ -243,7 +319,7 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char * if(startDir) { dir = startDir; - restOfPath = (char *)path; + restOfPath = (YCHAR *)path; } else { @@ -255,7 +331,7 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char * // parse off /. // curve ball: also throw away surplus '/' // eg. "/ram/x////ff" gets treated the same as "/ram/x/ff" - while(*restOfPath == '/') + while(yaffsfs_IsPathDivider(*restOfPath)) { restOfPath++; // get rid of '/' } @@ -263,7 +339,7 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char * *name = restOfPath; i = 0; - while(*restOfPath && *restOfPath != '/') + while(*restOfPath && !yaffsfs_IsPathDivider(*restOfPath)) { if (i < YAFFS_MAX_NAME_LENGTH) { @@ -281,11 +357,11 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char * } else { - if(strcmp(str,".") == 0) + if(yaffs_strcmp(str,_Y(".")) == 0) { // Do nothing } - else if(strcmp(str,"..") == 0) + else if(yaffs_strcmp(str,_Y("..")) == 0) { dir = dir->parent; } @@ -311,17 +387,17 @@ static yaffs_Object *yaffsfs_DoFindDirectory(yaffs_Object *startDir,const char * return NULL; } -static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const char *path,char **name,int symDepth) +static yaffs_Object *yaffsfs_FindDirectory(yaffs_Object *relativeDirectory,const YCHAR *path,YCHAR **name,int symDepth) { return yaffsfs_DoFindDirectory(relativeDirectory,path,name,symDepth); } // yaffsfs_FindObject turns a path for an existing object into the object // -static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const char *path,int symDepth) +static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const YCHAR *path,int symDepth) { yaffs_Object *dir; - char *name; + YCHAR *name; dir = yaffsfs_FindDirectory(relativeDirectory,path,&name,symDepth); @@ -334,12 +410,39 @@ static yaffs_Object *yaffsfs_FindObject(yaffs_Object *relativeDirectory, const c } +int yaffs_dup(int fd) +{ + int newHandle = -1; + yaffsfs_Handle *oldPtr = NULL; + yaffsfs_Handle *newPtr = NULL; + + yaffsfs_Lock(); + + oldPtr = yaffsfs_GetHandlePointer(fd); + if(oldPtr && oldPtr->inUse) + newHandle = yaffsfs_GetHandle(); + if(newHandle >= 0) + newPtr = yaffsfs_GetHandlePointer(newHandle); + + if(newPtr){ + *newPtr = *oldPtr; + return newHandle; + } + + if(!oldPtr) + yaffsfs_SetError(-EBADF); + else + yaffsfs_SetError(-ENOMEM); + + return -1; + +} -int yaffs_open(const char *path, int oflag, int mode) +int yaffs_open(const YCHAR *path, int oflag, int mode) { yaffs_Object *obj = NULL; yaffs_Object *dir = NULL; - char *name; + YCHAR *name; int handle = -1; yaffsfs_Handle *h = NULL; int alreadyOpen = 0; @@ -373,6 +476,11 @@ int yaffs_open(const char *path, int oflag, int mode) obj = yaffsfs_FollowLink(obj,symDepth++); } + if(obj && obj->variantType != YAFFS_OBJECT_TYPE_FILE) + { + obj = NULL; + } + if(obj) { // Check if the object is already in use @@ -438,6 +546,7 @@ int yaffs_open(const char *path, int oflag, int mode) else { yaffsfs_SetError(-ENOTDIR); + errorReported = 1; } } @@ -463,17 +572,43 @@ int yaffs_open(const char *path, int oflag, int mode) yaffsfs_PutHandle(handle); if(!errorReported) { - yaffsfs_SetError(-EACCESS); + yaffsfs_SetError(-EACCES); errorReported = 1; } handle = -1; } - + } - + yaffsfs_Unlock(); + + return handle; +} + +int yaffs_flush(int fd) +{ + yaffsfs_Handle *h = NULL; + int retVal = 0; + + yaffsfs_Lock(); + + h = yaffsfs_GetHandlePointer(fd); + + if(h && h->inUse) + { + // flush the file + yaffs_FlushFile(h->obj,1); + } + else + { + // bad handle + yaffsfs_SetError(-EBADF); + retVal = -1; + } - return handle; + yaffsfs_Unlock(); + + return retVal; } int yaffs_close(int fd) @@ -515,7 +650,7 @@ int yaffs_read(int fd, void *buf, unsigned int nbyte) yaffs_Object *obj = NULL; int pos = 0; int nRead = -1; - int maxRead; + unsigned int maxRead; yaffsfs_Lock(); h = yaffsfs_GetHandlePointer(fd); @@ -570,6 +705,59 @@ int yaffs_read(int fd, void *buf, unsigned int nbyte) } +int yaffs_pread(int fd, void *buf, unsigned int nbyte, unsigned int offset) +{ + yaffsfs_Handle *h = NULL; + yaffs_Object *obj = NULL; + int pos = 0; + int nRead = -1; + unsigned int maxRead; + + yaffsfs_Lock(); + h = yaffsfs_GetHandlePointer(fd); + obj = yaffsfs_GetHandleObject(fd); + + if(!h || !obj) + { + // bad handle + yaffsfs_SetError(-EBADF); + } + else if( h && obj) + { + pos= offset; + if(yaffs_GetObjectFileLength(obj) > pos) + { + maxRead = yaffs_GetObjectFileLength(obj) - pos; + } + else + { + maxRead = 0; + } + + if(nbyte > maxRead) + { + nbyte = maxRead; + } + + + if(nbyte > 0) + { + nRead = yaffs_ReadDataFromFile(obj,buf,pos,nbyte); + } + else + { + nRead = 0; + } + + } + + yaffsfs_Unlock(); + + + return (nRead >= 0) ? nRead : -1; + +} + int yaffs_write(int fd, const void *buf, unsigned int nbyte) { yaffsfs_Handle *h = NULL; @@ -622,7 +810,77 @@ int yaffs_write(int fd, const void *buf, unsigned int nbyte) } -int yaffs_truncate(int fd, off_t newSize) +int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, unsigned int offset) +{ + yaffsfs_Handle *h = NULL; + yaffs_Object *obj = NULL; + int pos = 0; + int nWritten = -1; + int writeThrough = 0; + + yaffsfs_Lock(); + h = yaffsfs_GetHandlePointer(fd); + obj = yaffsfs_GetHandleObject(fd); + + if(!h || !obj) + { + // bad handle + yaffsfs_SetError(-EBADF); + } + else if( h && obj && h->readOnly) + { + // todo error + } + else if( h && obj) + { + pos = offset; + + nWritten = yaffs_WriteDataToFile(obj,buf,pos,nbyte,writeThrough); + + if(nWritten < nbyte) + yaffsfs_SetError(-ENOSPC); + + } + + yaffsfs_Unlock(); + + + return (nWritten >= 0) ? nWritten : -1; + +} + + +int yaffs_truncate(const YCHAR *path,off_t newSize) +{ + yaffs_Object *obj = NULL; + int result = YAFFS_FAIL; + + yaffsfs_Lock(); + + obj = yaffsfs_FindObject(NULL,path,0); + if(obj) + obj = yaffs_GetEquivalentObject(obj); + + if(!obj) + { + yaffsfs_SetError(-ENOENT); + } + else if(obj->variantType != YAFFS_OBJECT_TYPE_FILE) + { + yaffsfs_SetError(-EISDIR); + } + else + { + result = yaffs_ResizeFile(obj,newSize); + } + + yaffsfs_Unlock(); + + + return (result) ? 0 : -1; +} + +int yaffs_ftruncate(int fd, off_t newSize) { yaffsfs_Handle *h = NULL; yaffs_Object *obj = NULL; @@ -704,11 +962,11 @@ off_t yaffs_lseek(int fd, off_t offset, int whence) } -int yaffsfs_DoUnlink(const char *path,int isDirectory) +int yaffsfs_DoUnlink(const YCHAR *path,int isDirectory) { yaffs_Object *dir = NULL; yaffs_Object *obj = NULL; - char *name; + YCHAR *name; int result = YAFFS_FAIL; yaffsfs_Lock(); @@ -747,23 +1005,25 @@ int yaffsfs_DoUnlink(const char *path,int isDirectory) return (result == YAFFS_FAIL) ? -1 : 0; } -int yaffs_rmdir(const char *path) + + +int yaffs_rmdir(const YCHAR *path) { return yaffsfs_DoUnlink(path,1); } -int yaffs_unlink(const char *path) +int yaffs_unlink(const YCHAR *path) { return yaffsfs_DoUnlink(path,0); } -int yaffs_rename(const char *oldPath, const char *newPath) +int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath) { yaffs_Object *olddir = NULL; yaffs_Object *newdir = NULL; yaffs_Object *obj = NULL; - char *oldname; - char *newname; + YCHAR *oldname; + YCHAR *newname; int result= YAFFS_FAIL; int renameAllowed = 1; @@ -802,7 +1062,7 @@ int yaffs_rename(const char *oldPath, const char *newPath) } xx = xx->parent; } - if(!renameAllowed) yaffsfs_SetError(-EACCESS); + if(!renameAllowed) yaffsfs_SetError(-EACCES); } if(renameAllowed) @@ -851,15 +1111,24 @@ static int yaffsfs_DoStat(yaffs_Object *obj,struct yaffs_stat *buf) buf->st_size = yaffs_GetObjectFileLength(obj); buf->st_blksize = obj->myDev->nDataBytesPerChunk; buf->st_blocks = (buf->st_size + buf->st_blksize -1)/buf->st_blksize; - buf->yst_atime = obj->yst_atime; - buf->yst_ctime = obj->yst_ctime; - buf->yst_mtime = obj->yst_mtime; +#if CONFIG_YAFFS_WINCE + buf->yst_wince_atime[0] = obj->win_atime[0]; + buf->yst_wince_atime[1] = obj->win_atime[1]; + buf->yst_wince_ctime[0] = obj->win_ctime[0]; + buf->yst_wince_ctime[1] = obj->win_ctime[1]; + buf->yst_wince_mtime[0] = obj->win_mtime[0]; + buf->yst_wince_mtime[1] = obj->win_mtime[1]; +#else + buf->yst_atime = obj->yst_atime; + buf->yst_ctime = obj->yst_ctime; + buf->yst_mtime = obj->yst_mtime; +#endif retVal = 0; } return retVal; } -static int yaffsfs_DoStatOrLStat(const char *path, struct yaffs_stat *buf,int doLStat) +static int yaffsfs_DoStatOrLStat(const YCHAR *path, struct yaffs_stat *buf,int doLStat) { yaffs_Object *obj; @@ -889,12 +1158,12 @@ static int yaffsfs_DoStatOrLStat(const char *path, struct yaffs_stat *buf,int do } -int yaffs_stat(const char *path, struct yaffs_stat *buf) +int yaffs_stat(const YCHAR *path, struct yaffs_stat *buf) { return yaffsfs_DoStatOrLStat(path,buf,0); } -int yaffs_lstat(const char *path, struct yaffs_stat *buf) +int yaffs_lstat(const YCHAR *path, struct yaffs_stat *buf) { return yaffsfs_DoStatOrLStat(path,buf,1); } @@ -913,6 +1182,46 @@ int yaffs_fstat(int fd, struct yaffs_stat *buf) retVal = yaffsfs_DoStat(obj,buf); } else + { + // bad handle + yaffsfs_SetError(-EBADF); + } + + yaffsfs_Unlock(); + + return retVal; +} + +#ifdef CONFIG_YAFFS_WINCE +int yaffs_get_wince_times(int fd, unsigned *wctime, unsigned *watime, unsigned *wmtime) +{ + yaffs_Object *obj; + + int retVal = -1; + + yaffsfs_Lock(); + obj = yaffsfs_GetHandleObject(fd); + + if(obj) + { + + if(wctime){ + wctime[0] = obj->win_ctime[0]; + wctime[1] = obj->win_ctime[1]; + } + if(watime){ + watime[0] = obj->win_atime[0]; + watime[1] = obj->win_atime[1]; + } + if(wmtime){ + wmtime[0] = obj->win_mtime[0]; + wmtime[1] = obj->win_mtime[1]; + } + + + retVal = 0; + } + else { // bad handle yaffsfs_SetError(-EBADF); @@ -923,6 +1232,51 @@ int yaffs_fstat(int fd, struct yaffs_stat *buf) return retVal; } + +int yaffs_set_wince_times(int fd, + const unsigned *wctime, + const unsigned *watime, + const unsigned *wmtime) +{ + yaffs_Object *obj; + + int retVal = -1; + + yaffsfs_Lock(); + obj = yaffsfs_GetHandleObject(fd); + + if(obj) + { + + if(wctime){ + obj->win_ctime[0] = wctime[0]; + obj->win_ctime[1] = wctime[1]; + } + if(watime){ + obj->win_atime[0] = watime[0]; + obj->win_atime[1] = watime[1]; + } + if(wctime){ + obj->win_mtime[0] = wmtime[0]; + obj->win_mtime[1] = wmtime[1]; + } + + retVal = 0; + } + else + { + // bad handle + yaffsfs_SetError(-EBADF); + } + + yaffsfs_Unlock(); + + return retVal; +} + +#endif + + static int yaffsfs_DoChMod(yaffs_Object *obj,mode_t mode) { int result; @@ -943,7 +1297,46 @@ static int yaffsfs_DoChMod(yaffs_Object *obj,mode_t mode) } -int yaffs_chmod(const char *path, mode_t mode) +int yaffs_access(const YCHAR *path, int amode) +{ + yaffs_Object *obj; + + int retval = 0; + + yaffsfs_Lock(); + obj = yaffsfs_FindObject(NULL,path,0); + + if(obj) + { + int access_ok = 1; + + if((amode & R_OK) && !(obj->yst_mode & S_IREAD)) + access_ok = 0; + if((amode & W_OK) && !(obj->yst_mode & S_IWRITE)) + access_ok = 0; + if((amode & X_OK) && !(obj->yst_mode & S_IEXEC)) + access_ok = 0; + + if(!access_ok) { + yaffsfs_SetError(-EACCES); + retval = -1; + } + } + else + { + // todo error not found + yaffsfs_SetError(-ENOENT); + retval = -1; + } + + yaffsfs_Unlock(); + + return retval; + +} + + +int yaffs_chmod(const YCHAR *path, mode_t mode) { yaffs_Object *obj; @@ -994,11 +1387,11 @@ int yaffs_fchmod(int fd, mode_t mode) } -int yaffs_mkdir(const char *path, mode_t mode) +int yaffs_mkdir(const YCHAR *path, mode_t mode) { yaffs_Object *parent = NULL; yaffs_Object *dir = NULL; - char *name; + YCHAR *name; int retVal= -1; yaffsfs_Lock(); @@ -1011,7 +1404,14 @@ int yaffs_mkdir(const char *path, mode_t mode) } else { - yaffsfs_SetError(-ENOSPC); // just assume no space for now + if(!parent){ + yaffsfs_SetError(-ENOENT); // missing path + } + else if (yaffs_FindObjectByName(parent,name)){ + yaffsfs_SetError(-EEXIST); // the name already exists + } + else + yaffsfs_SetError(-ENOSPC); // just assume no space retVal = -1; } @@ -1020,14 +1420,14 @@ int yaffs_mkdir(const char *path, mode_t mode) return retVal; } -int yaffs_mount(const char *path) +int yaffs_mount(const YCHAR *path) { int retVal=-1; int result=YAFFS_FAIL; yaffs_Device *dev=NULL; - char *dummy; + YCHAR *dummy; - T(YAFFS_TRACE_ALWAYS,("yaffs: Mounting %s\n",path)); + T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Mounting %s" TENDSTR),path)); yaffsfs_Lock(); dev = yaffsfs_FindDevice(path,&dummy); @@ -1060,11 +1460,46 @@ int yaffs_mount(const char *path) } -int yaffs_unmount(const char *path) +int yaffs_sync(const YCHAR *path) { int retVal=-1; yaffs_Device *dev=NULL; - char *dummy; + YCHAR *dummy; + + yaffsfs_Lock(); + dev = yaffsfs_FindDevice(path,&dummy); + if(dev) + { + if(dev->isMounted) + { + + yaffs_FlushEntireDeviceCache(dev); + yaffs_CheckpointSave(dev); + + + } + else + { + //todo error - not mounted. + yaffsfs_SetError(-EINVAL); + + } + } + else + { + // todo error - no device + yaffsfs_SetError(-ENODEV); + } + yaffsfs_Unlock(); + return retVal; +} + + +int yaffs_unmount(const YCHAR *path) +{ + int retVal=-1; + yaffs_Device *dev=NULL; + YCHAR *dummy; yaffsfs_Lock(); dev = yaffsfs_FindDevice(path,&dummy); @@ -1116,11 +1551,11 @@ int yaffs_unmount(const char *path) } -loff_t yaffs_freespace(const char *path) +loff_t yaffs_freespace(const YCHAR *path) { loff_t retVal=-1; yaffs_Device *dev=NULL; - char *dummy; + YCHAR *dummy; yaffsfs_Lock(); dev = yaffsfs_FindDevice(path,&dummy); @@ -1128,7 +1563,31 @@ loff_t yaffs_freespace(const char *path) { retVal = yaffs_GetNumberOfFreeChunks(dev); retVal *= dev->nDataBytesPerChunk; - + + } + else + { + yaffsfs_SetError(-EINVAL); + } + + yaffsfs_Unlock(); + return retVal; +} + +loff_t yaffs_totalspace(const YCHAR *path) +{ + loff_t retVal=-1; + yaffs_Device *dev=NULL; + YCHAR *dummy; + + yaffsfs_Lock(); + dev = yaffsfs_FindDevice(path,&dummy); + if(dev && dev->isMounted) + { + retVal = (dev->endBlock - dev->startBlock + 1) - dev->nReservedBlocks; + retVal *= dev->nChunksPerBlock; + retVal *= dev->nDataBytesPerChunk; + } else { @@ -1176,16 +1635,16 @@ typedef struct { __u32 magic; yaffs_dirent de; /* directory entry being used by this dsc */ - char name[NAME_MAX+1]; /* name of directory being searched */ + YCHAR name[NAME_MAX+1]; /* name of directory being searched */ yaffs_Object *dirObj; /* ptr to directory being searched */ yaffs_Object *nextReturn; /* obj to be returned by next readddir */ int offset; - struct list_head others; + struct ylist_head others; } yaffsfs_DirectorySearchContext; -static struct list_head search_contexts; +static struct ylist_head search_contexts; static void yaffsfs_SetDirRewound(yaffsfs_DirectorySearchContext *dsc) @@ -1196,10 +1655,10 @@ static void yaffsfs_SetDirRewound(yaffsfs_DirectorySearchContext *dsc) dsc->offset = 0; - if( list_empty(&dsc->dirObj->variant.directoryVariant.children)){ + if( ylist_empty(&dsc->dirObj->variant.directoryVariant.children)){ dsc->nextReturn = NULL; } else { - dsc->nextReturn = list_entry(dsc->dirObj->variant.directoryVariant.children.next, + dsc->nextReturn = ylist_entry(dsc->dirObj->variant.directoryVariant.children.next, yaffs_Object,siblings); } } else { @@ -1214,15 +1673,15 @@ static void yaffsfs_DirAdvance(yaffsfs_DirectorySearchContext *dsc) dsc->dirObj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY){ if( dsc->nextReturn == NULL || - list_empty(&dsc->dirObj->variant.directoryVariant.children)){ + ylist_empty(&dsc->dirObj->variant.directoryVariant.children)){ dsc->nextReturn = NULL; } else { - struct list_head *next = dsc->nextReturn->siblings.next; + struct ylist_head *next = dsc->nextReturn->siblings.next; if( next == &dsc->dirObj->variant.directoryVariant.children) dsc->nextReturn = NULL; /* end of list */ else - dsc->nextReturn = list_entry(next,yaffs_Object,siblings); + dsc->nextReturn = ylist_entry(next,yaffs_Object,siblings); } } else { /* Hey someone isn't playing nice! */ @@ -1232,20 +1691,20 @@ static void yaffsfs_DirAdvance(yaffsfs_DirectorySearchContext *dsc) static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj) { - struct list_head *i; + struct ylist_head *i; yaffsfs_DirectorySearchContext *dsc; /* if search contexts not initilised then skip */ if(!search_contexts.next) return; - /* Iteratethrough the directory search contexts. + /* Iterate through the directory search contexts. * If any are the one being removed, then advance the dsc to * the next one to prevent a hanging ptr. */ - list_for_each(i, &search_contexts) { + ylist_for_each(i, &search_contexts) { if (i) { - dsc = list_entry(i, yaffsfs_DirectorySearchContext,others); + dsc = ylist_entry(i, yaffsfs_DirectorySearchContext,others); if(dsc->nextReturn == obj) yaffsfs_DirAdvance(dsc); } @@ -1253,7 +1712,7 @@ static void yaffsfs_RemoveObjectCallback(yaffs_Object *obj) } -yaffs_DIR *yaffs_opendir(const char *dirname) +yaffs_DIR *yaffs_opendir(const YCHAR *dirname) { yaffs_DIR *dir = NULL; yaffs_Object *obj = NULL; @@ -1273,13 +1732,13 @@ yaffs_DIR *yaffs_opendir(const char *dirname) memset(dsc,0,sizeof(yaffsfs_DirectorySearchContext)); dsc->magic = YAFFS_MAGIC; dsc->dirObj = obj; - strncpy(dsc->name,dirname,NAME_MAX); - INIT_LIST_HEAD(&dsc->others); + yaffs_strncpy(dsc->name,dirname,NAME_MAX); + YINIT_LIST_HEAD(&dsc->others); if(!search_contexts.next) - INIT_LIST_HEAD(&search_contexts); + YINIT_LIST_HEAD(&search_contexts); - list_add(&dsc->others,&search_contexts); + ylist_add(&dsc->others,&search_contexts); yaffsfs_SetDirRewound(dsc); } } @@ -1303,10 +1762,10 @@ struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp) dsc->de.d_dont_use = (unsigned)dsc->nextReturn; dsc->de.d_off = dsc->offset++; yaffs_GetObjectName(dsc->nextReturn,dsc->de.d_name,NAME_MAX); - if(strlen(dsc->de.d_name) == 0) + if(yaffs_strlen(dsc->de.d_name) == 0) { // this should not happen! - strcpy(dsc->de.d_name,"zz"); + yaffs_strcpy(dsc->de.d_name,_Y("zz")); } dsc->de.d_reclen = sizeof(struct yaffs_dirent); retVal = &dsc->de; @@ -1344,7 +1803,7 @@ int yaffs_closedir(yaffs_DIR *dirp) yaffsfs_Lock(); dsc->magic = 0; - list_del(&dsc->others); /* unhook from list */ + ylist_del(&dsc->others); /* unhook from list */ YFREE(dsc); yaffsfs_Unlock(); return 0; @@ -1353,11 +1812,11 @@ int yaffs_closedir(yaffs_DIR *dirp) // end of directory stuff -int yaffs_symlink(const char *oldpath, const char *newpath) +int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath) { yaffs_Object *parent = NULL; yaffs_Object *obj; - char *name; + YCHAR *name; int retVal= -1; int mode = 0; // ignore for now @@ -1380,7 +1839,7 @@ int yaffs_symlink(const char *oldpath, const char *newpath) } -int yaffs_readlink(const char *path, char *buf, int bufsiz) +int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz) { yaffs_Object *obj = NULL; int retVal; @@ -1402,16 +1861,16 @@ int yaffs_readlink(const char *path, char *buf, int bufsiz) } else { - char *alias = obj->variant.symLinkVariant.alias; + YCHAR *alias = obj->variant.symLinkVariant.alias; memset(buf,0,bufsiz); - strncpy(buf,alias,bufsiz - 1); + yaffs_strncpy(buf,alias,bufsiz - 1); retVal = 0; } yaffsfs_Unlock(); return retVal; } -int yaffs_link(const char *oldpath, const char *newpath) +int yaffs_link(const YCHAR *oldpath, const YCHAR *newpath) { // Creates a link called newpath to existing oldpath yaffs_Object *obj = NULL; @@ -1439,7 +1898,7 @@ int yaffs_link(const char *oldpath, const char *newpath) yaffs_Object *newdir = NULL; yaffs_Object *link = NULL; - char *newname; + YCHAR *newname; newdir = yaffsfs_FindDirectory(NULL,newpath,&newname,0); @@ -1453,7 +1912,7 @@ int yaffs_link(const char *oldpath, const char *newpath) yaffsfs_SetError(-EXDEV); retVal = -1; } - if(newdir && strlen(newname) > 0) + if(newdir && yaffs_strlen(newname) > 0) { link = yaffs_Link(newdir,newname,obj); if(link) @@ -1471,11 +1930,12 @@ int yaffs_link(const char *oldpath, const char *newpath) return retVal; } -int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev); +int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev); -int yaffs_DumpDevStruct(const char *path) +int yaffs_DumpDevStruct(const YCHAR *path) { - char *rest; +#if 0 + YCHAR *rest; yaffs_Object *obj = yaffsfs_FindRoot(path,&rest); @@ -1500,6 +1960,8 @@ int yaffs_DumpDevStruct(const char *path) ); } + +#endif return 0; } diff --git a/direct/yaffsfs.h b/direct/yaffsfs.h index 9afe60a..fe4eff5 100644 --- a/direct/yaffsfs.h +++ b/direct/yaffsfs.h @@ -35,6 +35,9 @@ #define NAME_MAX 256 #endif + +#ifdef CONFIG_YAFFSFS_PROVIDE_VALUES + #ifndef O_RDONLY #define O_RDONLY 00 #endif @@ -91,8 +94,8 @@ #define EBADF 9 #endif -#ifndef EACCESS -#define EACCESS 13 +#ifndef EACCES +#define EACCES 13 #endif #ifndef EXDEV @@ -154,14 +157,30 @@ #define S_IWRITE 0000200 #endif +#ifndef S_IEXEC +#define S_IEXEC 0000100 +#endif + +#ifndef R_OK +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#define F_OK 0 +#endif +#else +#include +#include +#include +#endif struct yaffs_dirent{ long d_ino; /* inode number */ off_t d_off; /* offset to this dirent */ unsigned short d_reclen; /* length of this d_name */ - char d_name [NAME_MAX+1]; /* file name (null-terminated) */ + YUCHAR d_type; /* type of this record */ + YCHAR d_name [NAME_MAX+1]; /* file name (null-terminated) */ unsigned d_dont_use; /* debug pointer, not for public consumption */ }; @@ -175,7 +194,7 @@ typedef struct __opaque yaffs_DIR; struct yaffs_stat{ int st_dev; /* device */ int st_ino; /* inode */ - mode_t st_mode; /* protection */ + unsigned st_mode; /* protection */ int st_nlink; /* number of hard links */ int st_uid; /* user ID of owner */ int st_gid; /* group ID of owner */ @@ -183,46 +202,68 @@ struct yaffs_stat{ off_t st_size; /* total size, in bytes */ unsigned long st_blksize; /* blocksize for filesystem I/O */ unsigned long st_blocks; /* number of blocks allocated */ - unsigned long yst_atime; /* time of last access */ +#ifdef CONFIG_YAFFS_WINCE + /* Special 64-bit times for WinCE */ + unsigned long yst_wince_atime[2]; + unsigned long yst_wince_mtime[2]; + unsigned long yst_wince_ctime[2]; +#else + unsigned long yst_atime; /* time of last access */ unsigned long yst_mtime; /* time of last modification */ unsigned long yst_ctime; /* time of last change */ +#endif }; -int yaffs_open(const char *path, int oflag, int mode) ; +int yaffs_open(const YCHAR *path, int oflag, int mode) ; +int yaffs_close(int fd) ; +int yaffs_flush(int fd) ; + +int yaffs_access(const YCHAR *path, int amode); + +int yaffs_dup(int fd); + int yaffs_read(int fd, void *buf, unsigned int nbyte) ; int yaffs_write(int fd, const void *buf, unsigned int nbyte) ; -int yaffs_close(int fd) ; + +int yaffs_pread(int fd, void *buf, unsigned int nbyte, unsigned int offset); +int yaffs_pwrite(int fd, const void *buf, unsigned int nbyte, unsigned int offset); + off_t yaffs_lseek(int fd, off_t offset, int whence) ; -int yaffs_truncate(int fd, off_t newSize); -int yaffs_unlink(const char *path) ; -int yaffs_rename(const char *oldPath, const char *newPath) ; +int yaffs_truncate(const YCHAR *path, off_t newSize); +int yaffs_ftruncate(int fd, off_t newSize); -int yaffs_stat(const char *path, struct yaffs_stat *buf) ; -int yaffs_lstat(const char *path, struct yaffs_stat *buf) ; +int yaffs_unlink(const YCHAR *path) ; +int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath) ; + +int yaffs_stat(const YCHAR *path, struct yaffs_stat *buf) ; +int yaffs_lstat(const YCHAR *path, struct yaffs_stat *buf) ; int yaffs_fstat(int fd, struct yaffs_stat *buf) ; -int yaffs_chmod(const char *path, mode_t mode); +int yaffs_chmod(const YCHAR *path, mode_t mode); int yaffs_fchmod(int fd, mode_t mode); -int yaffs_mkdir(const char *path, mode_t mode) ; -int yaffs_rmdir(const char *path) ; +int yaffs_mkdir(const YCHAR *path, mode_t mode) ; +int yaffs_rmdir(const YCHAR *path) ; -yaffs_DIR *yaffs_opendir(const char *dirname) ; +yaffs_DIR *yaffs_opendir(const YCHAR *dirname) ; struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp) ; void yaffs_rewinddir(yaffs_DIR *dirp) ; int yaffs_closedir(yaffs_DIR *dirp) ; -int yaffs_mount(const char *path) ; -int yaffs_unmount(const char *path) ; +int yaffs_mount(const YCHAR *path) ; +int yaffs_unmount(const YCHAR *path) ; + +int yaffs_sync(const YCHAR *path) ; -int yaffs_symlink(const char *oldpath, const char *newpath); -int yaffs_readlink(const char *path, char *buf, int bufsiz); +int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath); +int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz); -int yaffs_link(const char *oldpath, const char *newpath); -int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev); +int yaffs_link(const YCHAR *oldpath, const YCHAR *newpath); +int yaffs_mknod(const YCHAR *pathname, mode_t mode, dev_t dev); -loff_t yaffs_freespace(const char *path); +loff_t yaffs_freespace(const YCHAR *path); +loff_t yaffs_totalspace(const YCHAR *path); void yaffs_initialise(yaffsfs_DeviceConfiguration *configList); diff --git a/direct/ydirectenv.h b/direct/ydirectenv.h index 0c28205..6a2bb18 100644 --- a/direct/ydirectenv.h +++ b/direct/ydirectenv.h @@ -30,7 +30,8 @@ #include "yaffs_malloc.h" #include "assert.h" -#define YBUG() assert(1) +#define YBUG() assert(0) + #define YCHAR char #define YUCHAR unsigned char @@ -42,6 +43,8 @@ #define yaffs_sprintf sprintf #define yaffs_toupper(a) toupper(a) +#define YAFFS_PATH_DIVIDERS "/" + #ifdef NO_Y_INLINE #define Y_INLINE #else diff --git a/yaffs_checkptrw.c b/yaffs_checkptrw.c index d1ecdf5..68e6d0c 100644 --- a/yaffs_checkptrw.c +++ b/yaffs_checkptrw.c @@ -12,11 +12,11 @@ */ const char *yaffs_checkptrw_c_version = - "$Id: yaffs_checkptrw.c,v 1.15 2007-12-13 15:35:17 wookey Exp $"; + "$Id: yaffs_checkptrw.c,v 1.16 2008-05-05 07:58:58 charles Exp $"; #include "yaffs_checkptrw.h" - +#include "yaffs_getblockinfo.h" static int yaffs_CheckpointSpaceOk(yaffs_Device *dev) { @@ -142,7 +142,7 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting) return 0; if(!dev->checkpointBuffer) - dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk); + dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk); if(!dev->checkpointBuffer) return 0; diff --git a/yaffs_fs.c b/yaffs_fs.c index eceb34f..ab6a3a7 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -32,7 +32,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.65 2007-12-13 15:35:17 wookey Exp $"; + "$Id: yaffs_fs.c,v 1.66 2008-05-05 07:58:58 charles Exp $"; extern const char *yaffs_guts_c_version; #include @@ -53,6 +53,8 @@ extern const char *yaffs_guts_c_version; #include #include +#include "asm/div64.h" + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) #include /* Added NCB 15-8-2003 */ @@ -753,6 +755,8 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj) break; } + inode->i_flags |= S_NOATIME; + inode->i_ino = obj->objectId; inode->i_mode = obj->yst_mode; inode->i_uid = obj->yst_uid; @@ -1350,25 +1354,47 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf) buf->f_type = YAFFS_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_namelen = 255; - if (sb->s_blocksize > dev->nDataBytesPerChunk) { - + + if(dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)){ + /* Do this if chunk size is not a power of 2 */ + + uint64_t bytesInDev; + uint64_t bytesFree; + + bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock +1))) * + ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk)); + + do_div(bytesInDev,sb->s_blocksize); /* bytesInDev becomes the number of blocks */ + buf->f_blocks = bytesInDev; + + bytesFree = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) * + ((uint64_t)(dev->nDataBytesPerChunk)); + + do_div(bytesFree,sb->s_blocksize); + + buf->f_bfree = bytesFree; + + } else 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); + (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_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; @@ -1602,6 +1628,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, sb->s_magic = YAFFS_MAGIC; sb->s_op = &yaffs_super_ops; + sb->s_flags |= MS_NOATIME; if (!sb) printk(KERN_INFO "yaffs: sb is NULL\n"); @@ -1678,22 +1705,15 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, #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 + WRITE_SIZE(mtd) >= 2048) { 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 + if (yaffsVersion == 2 && + !options.inband_tags && + WRITE_SIZE(mtd) == 512){ T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); yaffsVersion = 1; } @@ -1719,12 +1739,9 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, 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) { + if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE || + mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) && + !options.inband_tags) { T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not have the " "right page sizes\n")); @@ -1784,9 +1801,10 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, dev->startBlock = 0; dev->endBlock = nBlocks - 1; dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; - dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK; + dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK; dev->nReservedBlocks = 5; dev->nShortOpCaches = (options.no_cache) ? 0 : 10; + dev->inbandTags = options.inband_tags; /* ... and the functions. */ if (yaffsVersion == 2) { @@ -1799,10 +1817,10 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, dev->spareBuffer = YMALLOC(mtd->oobsize); dev->isYaffs2 = 1; #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - dev->nDataBytesPerChunk = mtd->writesize; + dev->totalBytesPerChunk = mtd->writesize; dev->nChunksPerBlock = mtd->erasesize / mtd->writesize; #else - dev->nDataBytesPerChunk = mtd->oobblock; + dev->totalBytesPerChunk = mtd->oobblock; dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; #endif nBlocks = mtd->size / mtd->erasesize; @@ -1989,6 +2007,7 @@ 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, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk); buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk); buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits); buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize); @@ -2004,10 +2023,8 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev) 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", + 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); @@ -2023,6 +2040,7 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev) sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions); buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC); buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2); + buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags); return buf; } diff --git a/yaffs_guts.c b/yaffs_guts.c index 097b525..c1a5b0c 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -12,13 +12,14 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.54 2007-12-13 15:35:17 wookey Exp $"; + "$Id: yaffs_guts.c,v 1.55 2008-05-05 07:58:58 charles Exp $"; #include "yportenv.h" #include "yaffsinterface.h" #include "yaffs_guts.h" #include "yaffs_tagsvalidity.h" +#include "yaffs_getblockinfo.h" #include "yaffs_tagscompat.h" #ifndef CONFIG_YAFFS_USE_OWN_SORT @@ -78,9 +79,6 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in); static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo); -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo); -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, - int lineNo); static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, int chunkInNAND); @@ -121,23 +119,32 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev, /* Function to calculate chunk and offset */ -static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset) +static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, __u32 *offsetOut) { - if(dev->chunkShift){ - /* Easy-peasy power of 2 case */ - *chunk = (__u32)(addr >> dev->chunkShift); - *offset = (__u32)(addr & dev->chunkMask); - } - else if(dev->crumbsPerChunk) + int chunk; + __u32 offset; + + chunk = (__u32)(addr >> dev->chunkShift); + + if(dev->chunkDiv == 1) { - /* Case where we're using "crumbs" */ - *offset = (__u32)(addr & dev->crumbMask); - addr >>= dev->crumbShift; - *chunk = ((__u32)addr)/dev->crumbsPerChunk; - *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift); + /* easy power of 2 case */ + offset = (__u32)(addr & dev->chunkMask); } else - YBUG(); + { + /* Non power-of-2 case */ + + loff_t chunkBase; + + chunk /= dev->chunkDiv; + + chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk; + offset = (__u32)(addr - chunkBase); + } + + *chunkOut = chunk; + *offsetOut = offset; } /* Function to return the number of shifts for a power of 2 greater than or equal @@ -168,7 +175,7 @@ static __u32 ShiftsGE(__u32 x) /* Function to return the number of shifts to get a 1 in bit 0 */ -static __u32 ShiftDiv(__u32 x) +static __u32 Shifts(__u32 x) { int nShifts; @@ -200,16 +207,21 @@ static int yaffs_InitialiseTempBuffers(yaffs_Device *dev) for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) { dev->tempBuffer[i].line = 0; /* not in use */ dev->tempBuffer[i].buffer = buf = - YMALLOC_DMA(dev->nDataBytesPerChunk); + YMALLOC_DMA(dev->totalBytesPerChunk); } return buf ? YAFFS_OK : YAFFS_FAIL; } -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo) +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo) { int i, j; + + dev->tempInUse++; + if(dev->tempInUse > dev->maxTemp) + dev->maxTemp = dev->tempInUse; + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { if (dev->tempBuffer[i].line == 0) { dev->tempBuffer[i].line = lineNo; @@ -242,10 +254,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo) } -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo) { int i; + + dev->tempInUse--; + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { if (dev->tempBuffer[i].buffer == buffer) { dev->tempBuffer[i].line = 0; @@ -390,11 +405,14 @@ static int yaffs_SkipVerification(yaffs_Device *dev) return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL)); } +#if 0 static int yaffs_SkipFullVerification(yaffs_Device *dev) { return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL)); } +#endif + static int yaffs_SkipNANDVerification(yaffs_Device *dev) { return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND)); @@ -597,7 +615,6 @@ static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn, int i; yaffs_Device *dev = obj->myDev; int ok = 1; - int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; if (tn) { if (level > 0) { @@ -646,7 +663,6 @@ static void yaffs_VerifyFile(yaffs_Object *obj) __u32 lastChunk; __u32 x; __u32 i; - int ok; yaffs_Device *dev; yaffs_ExtendedTags tags; yaffs_Tnode *tn; @@ -829,7 +845,7 @@ static void yaffs_VerifyObjects(yaffs_Device *dev) { yaffs_Object *obj; int i; - struct list_head *lh; + struct ylist_head *lh; if(yaffs_SkipVerification(dev)) return; @@ -837,9 +853,9 @@ static void yaffs_VerifyObjects(yaffs_Device *dev) /* Iterate through the objects in each hash entry */ for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){ - list_for_each(lh, &dev->objectBucket[i].list) { + ylist_for_each(lh, &dev->objectBucket[i].list) { if (lh) { - obj = list_entry(lh, yaffs_Object, hashLink); + obj = ylist_entry(lh, yaffs_Object, hashLink); yaffs_VerifyObject(obj); } } @@ -1869,7 +1885,7 @@ static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects) /* Hook them into the free list */ for (i = 0; i < nObjects - 1; i++) { newObjects[i].siblings.next = - (struct list_head *)(&newObjects[i + 1]); + (struct ylist_head *)(&newObjects[i + 1]); } newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects; @@ -1909,9 +1925,9 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) tn->myDev = dev; tn->chunkId = -1; tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN; - INIT_LIST_HEAD(&(tn->hardLinks)); - INIT_LIST_HEAD(&(tn->hashLink)); - INIT_LIST_HEAD(&tn->siblings); + YINIT_LIST_HEAD(&(tn->hardLinks)); + YINIT_LIST_HEAD(&(tn->hashLink)); + YINIT_LIST_HEAD(&tn->siblings); /* Add it to the lost and found directory. * NB Can't put root or lostNFound in lostNFound so @@ -1954,8 +1970,8 @@ static void yaffs_UnhashObject(yaffs_Object * tn) yaffs_Device *dev = tn->myDev; /* If it is still linked into the bucket list, free from the list */ - if (!list_empty(&tn->hashLink)) { - list_del_init(&tn->hashLink); + if (!ylist_empty(&tn->hashLink)) { + ylist_del_init(&tn->hashLink); bucket = yaffs_HashFunction(tn->objectId); dev->objectBucket[bucket].count--; } @@ -1981,7 +1997,7 @@ static void yaffs_FreeObject(yaffs_Object * tn) yaffs_UnhashObject(tn); /* Link into the free list. */ - tn->siblings.next = (struct list_head *)(dev->freeObjects); + tn->siblings.next = (struct ylist_head *)(dev->freeObjects); dev->freeObjects = tn; dev->nFreeObjects++; @@ -2027,7 +2043,7 @@ static void yaffs_InitialiseObjects(yaffs_Device * dev) dev->nFreeObjects = 0; for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { - INIT_LIST_HEAD(&dev->objectBucket[i].list); + YINIT_LIST_HEAD(&dev->objectBucket[i].list); dev->objectBucket[i].count = 0; } @@ -2078,7 +2094,7 @@ static int yaffs_CreateNewObjectNumber(yaffs_Device * dev) */ int found = 0; - struct list_head *i; + struct ylist_head *i; __u32 n = (__u32) bucket; @@ -2088,10 +2104,10 @@ static int yaffs_CreateNewObjectNumber(yaffs_Device * dev) found = 1; n += YAFFS_NOBJECT_BUCKETS; if (1 || dev->objectBucket[bucket].count > 0) { - list_for_each(i, &dev->objectBucket[bucket].list) { + ylist_for_each(i, &dev->objectBucket[bucket].list) { /* If there is already one in the list */ if (i - && list_entry(i, yaffs_Object, + && ylist_entry(i, yaffs_Object, hashLink)->objectId == n) { found = 0; } @@ -2108,7 +2124,7 @@ static void yaffs_HashObject(yaffs_Object * in) int bucket = yaffs_HashFunction(in->objectId); yaffs_Device *dev = in->myDev; - list_add(&in->hashLink, &dev->objectBucket[bucket].list); + ylist_add(&in->hashLink, &dev->objectBucket[bucket].list); dev->objectBucket[bucket].count++; } @@ -2116,13 +2132,13 @@ static void yaffs_HashObject(yaffs_Object * in) yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number) { int bucket = yaffs_HashFunction(number); - struct list_head *i; + struct ylist_head *i; yaffs_Object *in; - list_for_each(i, &dev->objectBucket[bucket].list) { + ylist_for_each(i, &dev->objectBucket[bucket].list) { /* Look if it is in the list */ if (i) { - in = list_entry(i, yaffs_Object, hashLink); + in = ylist_entry(i, yaffs_Object, hashLink); if (in->objectId == number) { #ifdef __KERNEL__ /* Don't tell the VFS about this one if it is defered free */ @@ -2143,7 +2159,7 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, { yaffs_Object *theObject; - yaffs_Tnode *tn; + yaffs_Tnode *tn = NULL; if (number < 0) { number = yaffs_CreateNewObjectNumber(dev); @@ -2191,7 +2207,7 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, theObject->variant.fileVariant.top = tn; break; case YAFFS_OBJECT_TYPE_DIRECTORY: - INIT_LIST_HEAD(&theObject->variant.directoryVariant. + YINIT_LIST_HEAD(&theObject->variant.directoryVariant. children); break; case YAFFS_OBJECT_TYPE_SYMLINK: @@ -2258,7 +2274,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, const YCHAR * aliasString, __u32 rdev) { yaffs_Object *in; - YCHAR *str; + YCHAR *str = NULL; yaffs_Device *dev = parent->myDev; @@ -2316,7 +2332,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, equivalentObject; in->variant.hardLinkVariant.equivalentObjectId = equivalentObject->objectId; - list_add(&in->hardLinks, &equivalentObject->hardLinks); + ylist_add(&in->hardLinks, &equivalentObject->hardLinks); break; case YAFFS_OBJECT_TYPE_FILE: case YAFFS_OBJECT_TYPE_DIRECTORY: @@ -2477,7 +2493,7 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, existingTarget = yaffs_FindObjectByName(newDir, newName); if (existingTarget && existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && - !list_empty(&existingTarget->variant.directoryVariant.children)) { + !ylist_empty(&existingTarget->variant.directoryVariant.children)) { /* There is a target that is a non-empty directory, so we fail */ return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */ } else if (existingTarget && existingTarget != obj) { @@ -3091,7 +3107,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) yaffs_ObjectHeader *oh; oh = (yaffs_ObjectHeader *)buffer; oh->isShrink = 0; - oh->shadowsObject = -1; + oh->shadowsObject = oh->inbandShadowsObject = -1; tags.extraShadows = 0; tags.extraIsShrinkHeader = 0; @@ -3682,7 +3698,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, oh->type = in->variantType; oh->yst_mode = in->yst_mode; - oh->shadowsObject = shadows; + oh->shadowsObject = oh->inbandShadowsObject = shadows; #ifdef CONFIG_YAFFS_WINCE oh->win_atime[0] = in->win_atime[0]; @@ -4376,7 +4392,7 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) yaffs_CheckpointObject cp; int i; int ok = 1; - struct list_head *lh; + struct ylist_head *lh; /* Iterate through the objects in each hash entry, @@ -4384,9 +4400,9 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) */ for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){ - list_for_each(lh, &dev->objectBucket[i].list) { + ylist_for_each(lh, &dev->objectBucket[i].list) { if (lh) { - obj = list_entry(lh, yaffs_Object, hashLink); + obj = ylist_entry(lh, yaffs_Object, hashLink); if (!obj->deferedFree) { yaffs_ObjectToCheckpointObject(&cp,obj); cp.structType = sizeof(cp); @@ -4444,7 +4460,7 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) ok = yaffs_ReadCheckpointTnodes(obj); } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { obj->hardLinks.next = - (struct list_head *) + (struct ylist_head *) hardList; hardList = obj; } @@ -4650,7 +4666,7 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset, { int chunk; - int start; + __u32 start; int nToCopy; int n = nBytes; int nDone = 0; @@ -4678,10 +4694,10 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset, cache = yaffs_FindChunkCache(in, chunk); /* If the chunk is already in the cache or it is less than a whole chunk - * then use the cache (if there is caching) + * or we're using inband tags then use the cache (if there is caching) * else bypass the cache. */ - if (cache || nToCopy != dev->nDataBytesPerChunk) { + if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) { if (dev->nShortOpCaches > 0) { /* If we can't find the data in the cache, then load it up. */ @@ -4770,7 +4786,7 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, { int chunk; - int start; + __u32 start; int nToCopy; int n = nBytes; int nDone = 0; @@ -4818,8 +4834,10 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, nToWriteBack = dev->nDataBytesPerChunk; } - if (nToCopy != dev->nDataBytesPerChunk) { - /* An incomplete start or end chunk (or maybe both start and end chunk) */ + if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) { + /* An incomplete start or end chunk (or maybe both start and end chunk), + * or we're using inband tags, so we want to use the cache buffers. + */ if (dev->nShortOpCaches > 0) { yaffs_ChunkCache *cache; /* If we can't find the data in the cache, then load the cache */ @@ -4907,7 +4925,8 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, } } else { - + /* A full chunk. Write directly from the supplied buffer. */ + #ifdef CONFIG_YAFFS_WINCE /* Under WinCE can't do direct transfer. Need to use a local buffer. * This is because we otherwise screw up WinCE's memory mapper @@ -4926,7 +4945,7 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, 0); yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); #else - /* A full chunk. Write directly from the supplied buffer. */ + chunkWritten = yaffs_WriteChunkDataToObject(in, chunk, buffer, dev->nDataBytesPerChunk, @@ -5004,7 +5023,7 @@ int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize) { int oldFileSize = in->variant.fileVariant.fileSize; - int newSizeOfPartialChunk; + __u32 newSizeOfPartialChunk; int newFullChunks; yaffs_Device *dev = in->myDev; @@ -5017,11 +5036,11 @@ int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize) yaffs_CheckGarbageCollection(dev); if (in->variantType != YAFFS_OBJECT_TYPE_FILE) { - return yaffs_GetFileSize(in); + return YAFFS_FAIL; } if (newSize == oldFileSize) { - return oldFileSize; + return YAFFS_OK; } if (newSize < oldFileSize) { @@ -5119,7 +5138,7 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in) if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) { /* Move to the unlinked directory so we have a record that it was deleted. */ - yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0); + yaffs_ChangeObjectName(in, in->myDev->deletedDir,_Y("deleted"), 0, 0); } @@ -5157,7 +5176,7 @@ static int yaffs_UnlinkFile(yaffs_Object * in) if (immediateDeletion) { retVal = yaffs_ChangeObjectName(in, in->myDev->deletedDir, - "deleted", 0, 0); + _Y("deleted"), 0, 0); T(YAFFS_TRACE_TRACING, (TSTR("yaffs: immediate deletion of file %d" TENDSTR), in->objectId)); @@ -5170,7 +5189,7 @@ static int yaffs_UnlinkFile(yaffs_Object * in) } else { retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, - "unlinked", 0, 0); + _Y("unlinked"), 0, 0); } } @@ -5205,7 +5224,7 @@ int yaffs_DeleteFile(yaffs_Object * in) static int yaffs_DeleteDirectory(yaffs_Object * in) { /* First check that the directory is empty. */ - if (list_empty(&in->variant.directoryVariant.children)) { + if (ylist_empty(&in->variant.directoryVariant.children)) { return yaffs_DoGenericObjectDeletion(in); } @@ -5225,7 +5244,7 @@ static int yaffs_DeleteHardLink(yaffs_Object * in) /* remove this hardlink from the list assocaited with the equivalent * object */ - list_del(&in->hardLinks); + ylist_del(&in->hardLinks); return yaffs_DoGenericObjectDeletion(in); } @@ -5257,7 +5276,7 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj) if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { return yaffs_DeleteHardLink(obj); - } else if (!list_empty(&obj->hardLinks)) { + } else if (!ylist_empty(&obj->hardLinks)) { /* Curve ball: We're unlinking an object that has a hardlink. * * This problem arises because we are not strictly following @@ -5276,10 +5295,10 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj) int retVal; YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; - hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks); + hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks); - list_del_init(&hl->hardLinks); - list_del_init(&hl->siblings); + ylist_del_init(&hl->hardLinks); + ylist_del_init(&hl->siblings); yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1); @@ -5386,13 +5405,13 @@ static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList) if (in) { /* Add the hardlink pointers */ hl->variant.hardLinkVariant.equivalentObject = in; - list_add(&hl->hardLinks, &in->hardLinks); + ylist_add(&hl->hardLinks, &in->hardLinks); } else { /* Todo Need to report/handle this better. * Got a problem... hardlink to a non-existant object */ hl->variant.hardLinkVariant.equivalentObject = NULL; - INIT_LIST_HEAD(&hl->hardLinks); + YINIT_LIST_HEAD(&hl->hardLinks); } @@ -5432,7 +5451,7 @@ static int yaffs_Scan(yaffs_Device * dev) yaffs_BlockState state; yaffs_Object *hardList = NULL; yaffs_BlockInfo *bi; - int sequenceNumber; + __u32 sequenceNumber; yaffs_ObjectHeader *oh; yaffs_Object *in; yaffs_Object *parent; @@ -5609,8 +5628,7 @@ static int yaffs_Scan(yaffs_Device * dev) bi->sequenceNumber)) { T(YAFFS_TRACE_ALWAYS, (TSTR - ("yaffs: Allocation block %d was not highest sequence id:" - " block seq = %d, dev seq = %d" + ("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d" TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber)); } } @@ -5784,7 +5802,7 @@ static int yaffs_Scan(yaffs_Device * dev) /* Set up as a directory */ parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY; - INIT_LIST_HEAD(&parent->variant. + YINIT_LIST_HEAD(&parent->variant. directoryVariant. children); } else if (parent->variantType != @@ -5796,8 +5814,7 @@ static int yaffs_Scan(yaffs_Device * dev) T(YAFFS_TRACE_ERROR, (TSTR - ("yaffs tragedy: attempting to use non-directory as" - " a directory in scan. Put in lost+found." + ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR))); parent = dev->lostNFoundDir; } @@ -5842,7 +5859,7 @@ static int yaffs_Scan(yaffs_Device * dev) equivalentObjectId = oh->equivalentObjectId; in->hardLinks.next = - (struct list_head *) + (struct ylist_head *) hardList; hardList = in; break; @@ -5901,16 +5918,16 @@ static int yaffs_Scan(yaffs_Device * dev) * just delete them. */ { - struct list_head *i; - struct list_head *n; + struct ylist_head *i; + struct ylist_head *n; yaffs_Object *l; /* Soft delete all the unlinked files */ - list_for_each_safe(i, n, + ylist_for_each_safe(i, n, &dev->unlinkedDir->variant.directoryVariant. children) { if (i) { - l = list_entry(i, yaffs_Object, siblings); + l = ylist_entry(i, yaffs_Object, siblings); yaffs_DestroyObject(l); } } @@ -5999,7 +6016,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) yaffs_BlockState state; yaffs_Object *hardList = NULL; yaffs_BlockInfo *bi; - int sequenceNumber; + __u32 sequenceNumber; yaffs_ObjectHeader *oh; yaffs_Object *in; yaffs_Object *parent; @@ -6328,6 +6345,12 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) NULL); oh = (yaffs_ObjectHeader *) chunkData; + + if(dev->inbandTags){ + /* Fix up the header if they got corrupted by inband tags */ + oh->shadowsObject = oh->inbandShadowsObject; + oh->isShrink = oh->inbandIsShrink; + } if (!in) in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type); @@ -6338,8 +6361,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) /* TODO Hoosterman we have a problem! */ T(YAFFS_TRACE_ERROR, (TSTR - ("yaffs tragedy: Could not make object for object %d " - "at chunk %d during scan" + ("yaffs tragedy: Could not make object for object %d at chunk %d during scan" TENDSTR), tags.objectId, chunk)); } @@ -6497,7 +6519,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) /* Set up as a directory */ parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY; - INIT_LIST_HEAD(&parent->variant. + YINIT_LIST_HEAD(&parent->variant. directoryVariant. children); } else if (parent->variantType != @@ -6509,8 +6531,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) T(YAFFS_TRACE_ERROR, (TSTR - ("yaffs tragedy: attempting to use non-directory as" - " a directory in scan. Put in lost+found." + ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR))); parent = dev->lostNFoundDir; } @@ -6561,7 +6582,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) in->variant.hardLinkVariant.equivalentObjectId = equivalentObjectId; in->hardLinks.next = - (struct list_head *) hardList; + (struct ylist_head *) hardList; hardList = in; } break; @@ -6621,27 +6642,27 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) * Sort out state of unlinked and deleted objects. */ { - struct list_head *i; - struct list_head *n; + struct ylist_head *i; + struct ylist_head *n; yaffs_Object *l; /* Soft delete all the unlinked files */ - list_for_each_safe(i, n, + ylist_for_each_safe(i, n, &dev->unlinkedDir->variant.directoryVariant. children) { if (i) { - l = list_entry(i, yaffs_Object, siblings); + l = ylist_entry(i, yaffs_Object, siblings); yaffs_DestroyObject(l); } } /* Soft delete all the deletedDir files */ - list_for_each_safe(i, n, + ylist_for_each_safe(i, n, &dev->deletedDir->variant.directoryVariant. children) { if (i) { - l = list_entry(i, yaffs_Object, siblings); + l = ylist_entry(i, yaffs_Object, siblings); yaffs_DestroyObject(l); } @@ -6668,7 +6689,7 @@ static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) if(dev && dev->removeObjectCallback) dev->removeObjectCallback(obj); - list_del_init(&obj->siblings); + ylist_del_init(&obj->siblings); obj->parent = NULL; } @@ -6694,14 +6715,14 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory, if (obj->siblings.prev == NULL) { /* Not initialised */ - INIT_LIST_HEAD(&obj->siblings); + YINIT_LIST_HEAD(&obj->siblings); - } else if (!list_empty(&obj->siblings)) { + } else if (!ylist_empty(&obj->siblings)) { /* If it is holed up somewhere else, un hook it */ yaffs_RemoveObjectFromDirectory(obj); } /* Now add it */ - list_add(&obj->siblings, &directory->variant.directoryVariant.children); + ylist_add(&obj->siblings, &directory->variant.directoryVariant.children); obj->parent = directory; if (directory == obj->myDev->unlinkedDir @@ -6717,7 +6738,7 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, { int sum; - struct list_head *i; + struct ylist_head *i; YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1]; yaffs_Object *l; @@ -6742,9 +6763,9 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, sum = yaffs_CalcNameSum(name); - list_for_each(i, &directory->variant.directoryVariant.children) { + ylist_for_each(i, &directory->variant.directoryVariant.children) { if (i) { - l = list_entry(i, yaffs_Object, siblings); + l = ylist_entry(i, yaffs_Object, siblings); yaffs_CheckObjectDetailsLoaded(l); @@ -6776,7 +6797,7 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, int (*fn) (yaffs_Object *)) { - struct list_head *i; + struct ylist_head *i; yaffs_Object *l; if (!theDir) { @@ -6793,9 +6814,9 @@ int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, YBUG(); } - list_for_each(i, &theDir->variant.directoryVariant.children) { + ylist_for_each(i, &theDir->variant.directoryVariant.children) { if (i) { - l = list_entry(i, yaffs_Object, siblings); + l = ylist_entry(i, yaffs_Object, siblings); if (l && !fn(l)) { return YAFFS_FAIL; } @@ -6884,12 +6905,12 @@ int yaffs_GetObjectFileLength(yaffs_Object * obj) int yaffs_GetObjectLinkCount(yaffs_Object * obj) { int count = 0; - struct list_head *i; + struct ylist_head *i; if (!obj->unlinked) { count++; /* the object itself */ } - list_for_each(i, &obj->hardLinks) { + ylist_for_each(i, &obj->hardLinks) { count++; /* add the hard links; */ } return count; @@ -7112,8 +7133,9 @@ int yaffs_GutsInitialise(yaffs_Device * dev) /* Check geometry parameters. */ - if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) || - (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) || + if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || + (!dev->isYaffs2 && dev->totalBytesPerChunk != 512) || + (dev->inbandTags && !dev->isYaffs2 ) || dev->nChunksPerBlock < 2 || dev->nReservedBlocks < 2 || dev->internalStartBlock <= 0 || @@ -7122,8 +7144,8 @@ int yaffs_GutsInitialise(yaffs_Device * dev) ) { T(YAFFS_TRACE_ALWAYS, (TSTR - ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s " - TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : "")); + ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d " + TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags)); return YAFFS_FAIL; } @@ -7132,6 +7154,12 @@ int yaffs_GutsInitialise(yaffs_Device * dev) (TSTR("yaffs: InitialiseNAND failed" TENDSTR))); return YAFFS_FAIL; } + + /* Sort out space for inband tags, if required */ + if(dev->inbandTags) + dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart); + else + dev->nDataBytesPerChunk = dev->totalBytesPerChunk; /* Got the right mix of functions? */ if (!yaffs_CheckDevFunctions(dev)) { @@ -7167,22 +7195,14 @@ int yaffs_GutsInitialise(yaffs_Device * dev) /* * Calculate all the chunk size manipulation numbers: */ - /* Start off assuming it is a power of 2 */ - dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk); - dev->chunkMask = (1<chunkShift) - 1; - - if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){ - /* Yes it is a power of 2, disable crumbs */ - dev->crumbMask = 0; - dev->crumbShift = 0; - dev->crumbsPerChunk = 0; - } else { - /* Not a power of 2, use crumbs instead */ - dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart)); - dev->crumbMask = (1<crumbShift)-1; - dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift); - dev->chunkShift = 0; - dev->chunkMask = 0; + { + __u32 x = dev->nDataBytesPerChunk; + /* We always use dev->chunkShift and dev->chunkDiv */ + dev->chunkShift = Shifts(x); + x >>= dev->chunkShift; + dev->chunkDiv = x; + /* We only use chunk mask if chunkDiv is 1 */ + dev->chunkMask = (1<chunkShift) - 1; } @@ -7266,7 +7286,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) if (!init_failed && dev->nShortOpCaches > 0) { int i; - __u8 *buf; + void *buf; int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache); if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) { @@ -7282,7 +7302,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) dev->srCache[i].object = NULL; dev->srCache[i].lastUse = 0; dev->srCache[i].dirty = 0; - dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk); + dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk); } if(!buf) init_failed = 1; @@ -7408,6 +7428,7 @@ void yaffs_Deinitialise(yaffs_Device * dev) YFREE(dev->tempBuffer[i].buffer); } + dev->isMounted = 0; } @@ -7511,22 +7532,25 @@ static void yaffs_VerifyFreeChunks(yaffs_Device * dev) /*---------------------------------------- YAFFS test code ----------------------*/ #define yaffs_CheckStruct(structure,syze, name) \ + do { \ if(sizeof(structure) != syze) \ { \ T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\ name,syze,sizeof(structure))); \ return YAFFS_FAIL; \ - } + } \ + } while(0) static int yaffs_CheckStructures(void) { -/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */ -/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */ -/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */ +/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */ +/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */ +/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */ #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG - yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode") + yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode"); +#endif +#ifndef CONFIG_YAFFS_WINCE + yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader"); #endif - yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader") - return YAFFS_OK; } diff --git a/yaffs_guts.h b/yaffs_guts.h index cf89ef5..b9b2ea1 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -90,7 +90,7 @@ #define YAFFS_MAX_SHORT_OP_CACHES 20 -#define YAFFS_N_TEMP_BUFFERS 4 +#define YAFFS_N_TEMP_BUFFERS 6 /* We limit the number attempts at sucessfully saving a chunk of data. * Small-page devices have 32 pages per block; large-page devices have 64. @@ -331,11 +331,14 @@ typedef struct { __u32 win_ctime[2]; __u32 win_atime[2]; __u32 win_mtime[2]; - __u32 roomToGrow[4]; #else - __u32 roomToGrow[10]; + __u32 roomToGrow[6]; + #endif + __u32 inbandShadowsObject; + __u32 inbandIsShrink; + __u32 reservedSpace[2]; int shadowsObject; /* This object header shadows the specified object if > 0 */ /* isShrink applies to object headers written when we shrink the file (ie resize) */ @@ -381,7 +384,7 @@ typedef struct { } yaffs_FileStructure; typedef struct { - struct list_head children; /* list of child links */ + struct ylist_head children; /* list of child links */ } yaffs_DirectoryStructure; typedef struct { @@ -424,14 +427,14 @@ struct yaffs_ObjectStruct { struct yaffs_DeviceStruct *myDev; /* The device I'm on */ - struct list_head hashLink; /* list of objects in this hash bucket */ + struct ylist_head hashLink; /* list of objects in this hash bucket */ - struct list_head hardLinks; /* all the equivalent hard linked objects */ + struct ylist_head hardLinks; /* all the equivalent hard linked objects */ /* directory structure stuff */ /* also used for linking up the free list */ struct yaffs_ObjectStruct *parent; - struct list_head siblings; + struct ylist_head siblings; /* Where's my object header in NAND? */ int chunkId; @@ -485,7 +488,7 @@ struct yaffs_ObjectList_struct { typedef struct yaffs_ObjectList_struct yaffs_ObjectList; typedef struct { - struct list_head list; + struct ylist_head list; int count; } yaffs_ObjectBucket; @@ -528,7 +531,7 @@ typedef struct { /*----------------- Device ---------------------------------*/ struct yaffs_DeviceStruct { - struct list_head devList; + struct ylist_head devList; const char *name; /* Entry parameters set up way early. Yaffs sets up the rest.*/ @@ -583,7 +586,7 @@ struct yaffs_DeviceStruct { yaffs_ExtendedTags * tags); int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo); int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo, - yaffs_BlockState * state, int *sequenceNumber); + yaffs_BlockState * state, __u32 *sequenceNumber); #endif int isYaffs2; @@ -598,7 +601,8 @@ struct yaffs_DeviceStruct { void (*markSuperBlockDirty)(void * superblock); int wideTnodesDisabled; /* Set to disable wide tnodes */ - + + YCHAR *pathDividers; /* String of legal path dividers */ /* End of stuff that must be set before initialisation. */ @@ -615,16 +619,14 @@ struct yaffs_DeviceStruct { __u32 tnodeWidth; __u32 tnodeMask; - /* Stuff to support various file offses to chunk/offset translations */ - /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */ - __u32 crumbMask; - __u32 crumbShift; - __u32 crumbsPerChunk; - - /* Straight shifting for nDataBytesPerChunk being a power of 2 */ - __u32 chunkShift; - __u32 chunkMask; + /* Stuff for figuring out file offset to chunk conversions */ + __u32 chunkShift; /* Shift value */ + __u32 chunkDiv; /* Divisor after shifting: 1 for power-of-2 sizes */ + __u32 chunkMask; /* Mask to use for power-of-2 case */ + /* Stuff to handle inband tags */ + int inbandTags; + __u32 totalBytesPerChunk; #ifdef __KERNEL__ @@ -746,9 +748,11 @@ struct yaffs_DeviceStruct { int nUnlinkedFiles; /* Count of unlinked files. */ int nBackgroundDeletions; /* Count of background deletions. */ - + + /* Temporary buffer management */ yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS]; int maxTemp; + int tempInUse; int unmanagedTempAllocations; int unmanagedTempDeallocations; @@ -799,18 +803,6 @@ typedef struct { __u32 head; } yaffs_CheckpointValidity; -/* Function to manipulate block info */ -static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk) -{ - if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { - T(YAFFS_TRACE_ERROR, - (TSTR - ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR), - blk)); - YBUG(); - } - return &dev->blockInfo[blk - dev->internalStartBlock]; -} /*----------------------- YAFFS Functions -----------------------*/ @@ -901,4 +893,7 @@ void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn); int yaffs_CheckFF(__u8 * buffer, int nBytes); void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi); +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo); +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo); + #endif diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c index 125ed40..3768b9b 100644 --- a/yaffs_mtdif2.c +++ b/yaffs_mtdif2.c @@ -14,7 +14,7 @@ /* mtd interface for YAFFS2 */ const char *yaffs_mtdif2_c_version = - "$Id: yaffs_mtdif2.c,v 1.19 2007-12-13 15:35:18 wookey Exp $"; + "$Id: yaffs_mtdif2.c,v 1.20 2008-05-05 07:58:58 charles Exp $"; #include "yportenv.h" @@ -27,6 +27,10 @@ const char *yaffs_mtdif2_c_version = #include "yaffs_packedtags2.h" +/* NB For use with inband tags.... + * We assume that the data buffer is of size totalBytersPerChunk so that we can also + * use it to load the tags. + */ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * tags) @@ -39,7 +43,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, #endif int retval = 0; - loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; + loff_t addr; yaffs_PackedTags2 pt; @@ -47,47 +51,42 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, (TSTR ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" TENDSTR), chunkInNAND, data, tags)); - -#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17)) - if (tags) - yaffs_PackTags2(&pt, tags); + + + addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk; + + /* For yaffs2 writing there must be both data and tags. + * If we're using inband tags, then the tags are stuffed into + * the end of the data buffer. + */ + if(!data || !tags) + BUG(); + else if(dev->inbandTags){ + yaffs_PackedTags2TagsPart *pt2tp; + pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk); + yaffs_PackTags2TagsPart(pt2tp,tags); + } else - BUG(); /* both tags and data should always be present */ - - if (data) { - ops.mode = MTD_OOB_AUTO; - ops.ooblen = sizeof(pt); - ops.len = dev->nDataBytesPerChunk; - ops.ooboffs = 0; - ops.datbuf = (__u8 *)data; - ops.oobbuf = (void *)&pt; - retval = mtd->write_oob(mtd, addr, &ops); - } else - BUG(); /* both tags and data should always be present */ -#else - if (tags) { yaffs_PackTags2(&pt, tags); - } + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + ops.mode = MTD_OOB_AUTO; + ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt); + ops.len = dev->totalBytesPerChunk; + ops.ooboffs = 0; + ops.datbuf = (__u8 *)data; + ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt; + retval = mtd->write_oob(mtd, addr, &ops); - if (data && tags) { - if (dev->useNANDECC) - retval = - mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, - &dummy, data, (__u8 *) & pt, NULL); - else - retval = - mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, - &dummy, data, (__u8 *) & pt, NULL); +#else + if (!dev->inbandTags) { + retval = + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, + &dummy, data, (__u8 *) & pt, NULL); } else { - if (data) - retval = - mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, - data); - if (tags) - retval = - mtd->write_oob(mtd, addr, mtd->oobsize, &dummy, - (__u8 *) & pt); - + retval = + mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy, + data); } #endif @@ -106,6 +105,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, #endif size_t dummy; int retval = 0; + int localData = 0; loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; @@ -115,10 +115,21 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, (TSTR ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" TENDSTR), chunkInNAND, data, tags)); + + if(dev->inbandTags){ + + if(!data) { + localData = 1; + data = yaffs_GetTempBuffer(dev,__LINE__); + } + -#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17)) - if (data && !tags) - retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk, + } + + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + if (dev->inbandTags || (data && !tags)) + retval = mtd->read(mtd, addr, dev->totalBytesPerChunk, &dummy, data); else if (tags) { ops.mode = MTD_OOB_AUTO; @@ -130,38 +141,43 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, retval = mtd->read_oob(mtd, addr, &ops); } #else - if (data && tags) { - if (dev->useNANDECC) { - retval = - mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, - &dummy, data, dev->spareBuffer, - NULL); - } else { - retval = - mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, + if (!dev->inbandTags && data && tags) { + + retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, &dummy, data, dev->spareBuffer, NULL); - } } else { if (data) retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy, data); - if (tags) + if (!dev->inbandTags && tags) retval = mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, dev->spareBuffer); } #endif - memcpy(&pt, dev->spareBuffer, sizeof(pt)); - if (tags) - yaffs_UnpackTags2(tags, &pt); + if(dev->inbandTags){ + if(tags){ + yaffs_PackedTags2TagsPart * pt2tp; + pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk]; + yaffs_UnpackTags2TagsPart(tags,pt2tp); + } + } + else { + if (tags){ + memcpy(&pt, dev->spareBuffer, sizeof(pt)); + yaffs_UnpackTags2(tags, &pt); + } + } + if(localData) + yaffs_ReleaseTempBuffer(dev,data,__LINE__); + if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) - tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; - + tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; if (retval == 0) return YAFFS_OK; else diff --git a/yaffs_nand.c b/yaffs_nand.c index 3898985..af42157 100644 --- a/yaffs_nand.c +++ b/yaffs_nand.c @@ -12,12 +12,13 @@ */ const char *yaffs_nand_c_version = - "$Id: yaffs_nand.c,v 1.8 2007-12-13 15:35:18 wookey Exp $"; + "$Id: yaffs_nand.c,v 1.9 2008-05-05 07:58:58 charles Exp $"; #include "yaffs_nand.h" #include "yaffs_tagscompat.h" #include "yaffs_tagsvalidity.h" +#include "yaffs_getblockinfo.h" int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * buffer, @@ -98,7 +99,7 @@ int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo) int yaffs_QueryInitialBlockState(yaffs_Device * dev, int blockNo, yaffs_BlockState * state, - unsigned *sequenceNumber) + __u32 *sequenceNumber) { blockNo -= dev->blockOffset; diff --git a/yaffs_nandemul2k.h b/yaffs_nandemul2k.h index cd2e96f..c8576b3 100644 --- a/yaffs_nandemul2k.h +++ b/yaffs_nandemul2k.h @@ -22,13 +22,13 @@ int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, int chunkInNAND, const __u8 * data, - yaffs_ExtendedTags * tags); + const yaffs_ExtendedTags * tags); int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev, int chunkInNAND, __u8 * data, yaffs_ExtendedTags * tags); int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, - yaffs_BlockState * state, int *sequenceNumber); + yaffs_BlockState * state, __u32 *sequenceNumber); int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, int blockInNAND); int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev); diff --git a/yaffs_packedtags2.c b/yaffs_packedtags2.c index e420f95..957ed8b 100644 --- a/yaffs_packedtags2.c +++ b/yaffs_packedtags2.c @@ -37,60 +37,70 @@ #define EXTRA_OBJECT_TYPE_SHIFT (28) #define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT) -static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt) + +static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart * ptt) { T(YAFFS_TRACE_MTD, (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), - pt->t.objectId, pt->t.chunkId, pt->t.byteCount, - pt->t.sequenceNumber)); + ptt->objectId, ptt->chunkId, ptt->byteCount, + ptt->sequenceNumber)); +} +static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt) +{ + yaffs_DumpPackedTags2TagsPart(&pt->t); } static void yaffs_DumpTags2(const yaffs_ExtendedTags * t) { T(YAFFS_TRACE_MTD, (TSTR - ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte " - "%d del %d ser %d seq %d" + ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d" TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId, t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, t->sequenceNumber)); } -void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t) +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * ptt, const yaffs_ExtendedTags * t) { - pt->t.chunkId = t->chunkId; - pt->t.sequenceNumber = t->sequenceNumber; - pt->t.byteCount = t->byteCount; - pt->t.objectId = t->objectId; + ptt->chunkId = t->chunkId; + ptt->sequenceNumber = t->sequenceNumber; + ptt->byteCount = t->byteCount; + ptt->objectId = t->objectId; if (t->chunkId == 0 && t->extraHeaderInfoAvailable) { /* Store the extra header info instead */ /* We save the parent object in the chunkId */ - pt->t.chunkId = EXTRA_HEADER_INFO_FLAG + ptt->chunkId = EXTRA_HEADER_INFO_FLAG | t->extraParentObjectId; if (t->extraIsShrinkHeader) { - pt->t.chunkId |= EXTRA_SHRINK_FLAG; + ptt->chunkId |= EXTRA_SHRINK_FLAG; } if (t->extraShadows) { - pt->t.chunkId |= EXTRA_SHADOWS_FLAG; + ptt->chunkId |= EXTRA_SHADOWS_FLAG; } - pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK; - pt->t.objectId |= + ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK; + ptt->objectId |= (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT); if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { - pt->t.byteCount = t->extraEquivalentObjectId; + ptt->byteCount = t->extraEquivalentObjectId; } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) { - pt->t.byteCount = t->extraFileLength; + ptt->byteCount = t->extraFileLength; } else { - pt->t.byteCount = 0; + ptt->byteCount = 0; } } - yaffs_DumpPackedTags2(pt); + yaffs_DumpPackedTags2TagsPart(ptt); yaffs_DumpTags2(t); +} + + +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t) +{ + yaffs_PackTags2TagsPart(&pt->t,t); #ifndef YAFFS_IGNORE_TAGS_ECC { @@ -101,13 +111,60 @@ void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t) #endif } -void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) + +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * ptt) { memset(t, 0, sizeof(yaffs_ExtendedTags)); yaffs_InitialiseTags(t); + if (ptt->sequenceNumber != 0xFFFFFFFF) { + t->blockBad = 0; + t->chunkUsed = 1; + t->objectId = ptt->objectId; + t->chunkId = ptt->chunkId; + t->byteCount = ptt->byteCount; + t->chunkDeleted = 0; + t->serialNumber = 0; + t->sequenceNumber = ptt->sequenceNumber; + + /* Do extra header info stuff */ + + if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) { + t->chunkId = 0; + t->byteCount = 0; + + t->extraHeaderInfoAvailable = 1; + t->extraParentObjectId = + ptt->chunkId & (~(ALL_EXTRA_FLAGS)); + t->extraIsShrinkHeader = + (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; + t->extraShadows = + (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0; + t->extraObjectType = + ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT; + t->objectId &= ~EXTRA_OBJECT_TYPE_MASK; + + if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { + t->extraEquivalentObjectId = ptt->byteCount; + } else { + t->extraFileLength = ptt->byteCount; + } + } + } + + yaffs_DumpPackedTags2TagsPart(ptt); + yaffs_DumpTags2(t); + +} + + +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) +{ + + yaffs_UnpackTags2TagsPart(t,&pt->t); + if (pt->t.sequenceNumber != 0xFFFFFFFF) { /* Page is in use */ #ifdef YAFFS_IGNORE_TAGS_ECC @@ -142,41 +199,10 @@ void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) } } #endif - t->blockBad = 0; - t->chunkUsed = 1; - t->objectId = pt->t.objectId; - t->chunkId = pt->t.chunkId; - t->byteCount = pt->t.byteCount; - t->chunkDeleted = 0; - t->serialNumber = 0; - t->sequenceNumber = pt->t.sequenceNumber; - - /* Do extra header info stuff */ - - if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) { - t->chunkId = 0; - t->byteCount = 0; - - t->extraHeaderInfoAvailable = 1; - t->extraParentObjectId = - pt->t.chunkId & (~(ALL_EXTRA_FLAGS)); - t->extraIsShrinkHeader = - (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; - t->extraShadows = - (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0; - t->extraObjectType = - pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT; - t->objectId &= ~EXTRA_OBJECT_TYPE_MASK; - - if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { - t->extraEquivalentObjectId = pt->t.byteCount; - } else { - t->extraFileLength = pt->t.byteCount; - } - } } yaffs_DumpPackedTags2(pt); yaffs_DumpTags2(t); } + diff --git a/yaffs_packedtags2.h b/yaffs_packedtags2.h index c2242ff..75761d3 100644 --- a/yaffs_packedtags2.h +++ b/yaffs_packedtags2.h @@ -33,6 +33,11 @@ typedef struct { yaffs_ECCOther ecc; } yaffs_PackedTags2; +/* Full packed tags with ECC, used for oob tags */ void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t); void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt); + +/* Only the tags part (no ECC for use with inband tags */ +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * pt, const yaffs_ExtendedTags * t); +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * pt); #endif diff --git a/yaffs_tagscompat.c b/yaffs_tagscompat.c index 7622b1a..ab756d0 100644 --- a/yaffs_tagscompat.c +++ b/yaffs_tagscompat.c @@ -14,6 +14,7 @@ #include "yaffs_guts.h" #include "yaffs_tagscompat.h" #include "yaffs_ecc.h" +#include "yaffs_getblockinfo.h" static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND); #ifdef NOTYET @@ -438,7 +439,7 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, yaffs_ECCResult eccResult; static yaffs_Spare spareFF; - static int init; + static int init = 0; if (!init) { memset(&spareFF, 0xFF, sizeof(spareFF)); @@ -497,9 +498,9 @@ int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, } int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, - int blockNo, yaffs_BlockState * - state, - int *sequenceNumber) + int blockNo, + yaffs_BlockState *state, + __u32 *sequenceNumber) { yaffs_Spare spare0, spare1; diff --git a/yaffs_tagscompat.h b/yaffs_tagscompat.h index a61e3ba..6549398 100644 --- a/yaffs_tagscompat.h +++ b/yaffs_tagscompat.h @@ -30,8 +30,9 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, - int blockNo, yaffs_BlockState * - state, int *sequenceNumber); + int blockNo, + yaffs_BlockState *state, + __u32 *sequenceNumber); void yaffs_CalcTagsECC(yaffs_Tags * tags); int yaffs_CheckECCOnTags(yaffs_Tags * tags); diff --git a/yportenv.h b/yportenv.h index 6cd90da..097b2a6 100644 --- a/yportenv.h +++ b/yportenv.h @@ -193,8 +193,8 @@ extern unsigned int yaffs_wr_attempts; #define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0) -#ifndef CONFIG_YAFFS_WINCE -#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__)) +#ifndef YBUG +#define YBUG() do {T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__));} while(0) #endif #endif