From: charles Date: Fri, 7 Nov 2008 00:32:20 +0000 (+0000) Subject: Some fixes and add NOR integrity code X-Git-Tag: pre-name-change~263 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=49942b13d7cfbdba72c18de0f37d16d81b4372a8;hp=9f0dab8f26ae946761792c1b2de425b3232ee6e1 Some fixes and add NOR integrity code --- diff --git a/direct/Makefile b/direct/Makefile index e816df1..9f4b606 100644 --- a/direct/Makefile +++ b/direct/Makefile @@ -14,31 +14,35 @@ # # NB Warning this Makefile does not include header dependencies. # -# $Id: Makefile,v 1.18 2008-07-21 01:03:19 charles Exp $ +# $Id: Makefile,v 1.19 2008-11-07 00:32:21 charles Exp $ #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC 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 += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing -fno-strict-aliasing +CFLAGS += -O0 +#CFLAGS += -DVALGRIND_TEST #CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations #CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline -DIRECTTESTOBJS = dtest.o yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \ +COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \ yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ - yaffs_checkptrw.o yaffs_qsort.o + yaffs_checkptrw.o yaffs_qsort.o\ + yaffs_norif1.o ynorsim.o nor_stress.o # yaffs_checkptrwtest.o\ - + +DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o +YAFFSTESTOBJS = $(COMMONTESTOBJS) yaffs_test.o BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o #ALLOBJS = dtest.o nand_ecc.o yaffscfg.o yaffs_fileem.o yaffsfs.o yaffs_ramdisk.o bootldtst.o yboot.o yaffs_ramem2k.o -ALLOBJS = $(DIRECTTESTOBJS) $(BOOTTESTOBJS) +ALLOBJS = $(sort $(DIRECTTESTOBJS) $(YAFFSTESTOBJS)) 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 \ @@ -48,7 +52,7 @@ SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsin #all: directtest2k boottest -all: directtest2k +all: directtest2k yaffs_test $(ALLOBJS): %.o: %.c gcc -c $(CFLAGS) -o $@ $< @@ -59,6 +63,9 @@ $(SYMLINKS): directtest2k: $(SYMLINKS) $(DIRECTTESTOBJS) gcc -o $@ $(DIRECTTESTOBJS) +yaffs_test: $(SYMLINKS) $(YAFFSTESTOBJS) + gcc -o $@ $(YAFFSTESTOBJS) + boottest: $(SYMLINKS) $(BOOTTESTOBJS) gcc -o $@ $(BOOTTESTOBJS) diff --git a/direct/dtest.c b/direct/dtest.c index 8476743..fd4f966 100644 --- a/direct/dtest.c +++ b/direct/dtest.c @@ -22,6 +22,8 @@ #include "yaffsfs.h" +#include "nor_stress.h" + void dumpDir(const char *dname); char xx[600]; @@ -2284,6 +2286,7 @@ void random_small_file_test(const char *mountpt,int iterations) int main(int argc, char *argv[]) { + //return long_test(argc,argv); //return cache_read_test(); diff --git a/direct/fsx_test/Makefile b/direct/fsx_test/Makefile index 3d4b4fd..93d2bac 100644 --- a/direct/fsx_test/Makefile +++ b/direct/fsx_test/Makefile @@ -14,7 +14,7 @@ # # NB Warning this Makefile does not include header dependencies. # -# $Id: Makefile,v 1.3 2008-08-07 22:45:44 charles Exp $ +# $Id: Makefile,v 1.4 2008-11-07 00:32:22 charles Exp $ #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC @@ -31,6 +31,7 @@ FSXTESTOBJS = yaffs_fsx.o yaffscfg2k.o yaffs_ecc.o yaffs_fileem2k.o yaffs_fileem yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ yaffs_checkptrw.o yaffs_qsort.o \ + yaffs_norif1.o ynorsim.o # yaffs_checkptrwtest.o\ @@ -48,7 +49,8 @@ YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h ya YAFFSDIRECTSYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \ - yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c + yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c\ + yaffs_norif1.c yaffs_norif1.h ynorsim.c ynorsim.h diff --git a/direct/fsx_test/yaffs_fsx.c b/direct/fsx_test/yaffs_fsx.c index 64588c8..31b0751 100644 --- a/direct/fsx_test/yaffs_fsx.c +++ b/direct/fsx_test/yaffs_fsx.c @@ -130,11 +130,7 @@ int writebdy = 1; /* -w flag */ long monitorstart = -1; /* -m flag */ long monitorend = -1; /* -m flag */ int lite = 0; /* -L flag */ -<<<<<<< yaffs_fsx.c -long numops = 5000; /* -N flag */ -======= -long numops = /*-1 */ 100000; /* -N flag */ ->>>>>>> 1.3 +long numops = /*-1 */ 10000000; /* -N flag */ int randomoplen = 1; /* -O flag disables it */ int seed = 1; /* -S flag */ @@ -778,7 +774,7 @@ getnum(char *s, char **e) } -#define BASE_NAME "/flash/yaffs2" +#define BASE_NAME "/flash/yaffs1" int main(int argc, char **argv) diff --git a/direct/nor_stress.c b/direct/nor_stress.c new file mode 100644 index 0000000..0eaaf1b --- /dev/null +++ b/direct/nor_stress.c @@ -0,0 +1,353 @@ +#include "nor_stress.h" + + +#include "yaffsfs.h" + +#include + + + +static unsigned powerUps; +static unsigned cycleStarts; +static unsigned cycleEnds; + + +char fullPathName[100]; +char fullPowerUpName[100]; +char fullStartName[100]; +char fullEndName[100]; +char fullMainName[100]; +char fullTempMainName[100]; +char fullTempCounterName[100]; + + +void MakeName(char *fullName,const char *prefix, const char *name) +{ + strcpy(fullName,prefix); + strcat(fullName,"/"); + strcat(fullName,name); +} + + +void MakeFullNames(const char *prefix) +{ + MakeName(fullPathName,prefix,""); + MakeName(fullPowerUpName,prefix,"powerUps"); + MakeName(fullStartName,prefix,"starts"); + MakeName(fullEndName,prefix,"ends"); + MakeName(fullMainName,prefix,"main"); + MakeName(fullTempCounterName,prefix,"tmp-counter"); + MakeName(fullTempMainName,prefix,"tmp-main"); +} + +static void FatalError(void) +{ + printf("Integrity error\n"); + while(1){} +} + +static void UpdateCounter(const char *name, unsigned *val, int initialise) +{ + int inh; + int outh; + unsigned x[2]; + int nread = 0; + int nwritten = 0; + + x[0] = x[1] = 0; + + if(initialise){ + x[0] = 0; + x[1] = 1; + } else { + inh = yaffs_open(name,O_RDONLY, S_IREAD | S_IWRITE); + if(inh >= 0){ + nread = yaffs_read(inh,x,sizeof(x)); + yaffs_close(inh); + } + + if(nread != sizeof(x) || + x[0] + 1 != x[1]){ + printf("Error reading counter %s handle %d, x[0] %u x[1] %u last error %d\n", + name, inh, x[0], x[1],yaffsfs_GetLastError()); + FatalError(); + + } + x[0]++; + x[1]++; + } + + outh = yaffs_open(fullTempCounterName, O_RDWR | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE); + if(outh >= 0){ + nwritten = yaffs_write(outh,x,sizeof(x)); + yaffs_close(outh); + yaffs_rename(fullTempCounterName,name); + } + + if(nwritten != sizeof(x)){ + printf("Error writing counter %s handle %d, x[0] %u x[1] %u\n", + name, inh, x[0], x[1]); + FatalError(); + } + + *val = x[0]; + + printf("##\n" + "## Set counter %s to %u\n" + "##\n", name,x[0]); +} + + +static void dump_directory_tree_worker(const char *dname,int recursive) +{ + yaffs_DIR *d; + yaffs_dirent *de; + struct yaffs_stat s; + char str[1000]; + + d = yaffs_opendir(dname); + + if(!d) + { + printf("opendir failed\n"); + } + else + { + while((de = yaffs_readdir(d)) != NULL) + { + strcpy(str,dname); + strcat(str,"/"); + strcat(str,de->d_name); + + yaffs_lstat(str,&s); + + printf("%s inode %d obj %x length %d mode %X ",str,s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode); + switch(s.st_mode & S_IFMT) + { + case S_IFREG: printf("data file"); break; + case S_IFDIR: printf("directory"); break; + case S_IFLNK: printf("symlink -->"); + if(yaffs_readlink(str,str,100) < 0) + printf("no alias"); + else + printf("\"%s\"",str); + break; + default: printf("unknown"); break; + } + + printf("\n"); + + if((s.st_mode & S_IFMT) == S_IFDIR && recursive) + dump_directory_tree_worker(str,1); + + } + + yaffs_closedir(d); + } + +} + +static void dump_directory_tree(const char *dname) +{ + dump_directory_tree_worker(dname,1); + printf("\n"); + printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname)); +} + + + + +#define XX_SIZE 500 + +static unsigned xx[XX_SIZE]; + +static int yWriteFile(const char *fname, unsigned sz32) +{ + int h; + int r; + int i; + unsigned checksum = 0; + + printf("Writing file %s\n",fname); + + h = yaffs_open(fname,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); + + if(h < 0){ + printf("could not open file %s\n",fname); + return h; + } + + xx[0] = sz32; + checksum ^= xx[0]; + + if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){ + goto WRITE_ERROR; + } + + while(sz32> 0){ + for(i = 0; i < XX_SIZE; i++){ + xx[i] = sz32 + i; + checksum ^= xx[i]; + } + + if((r = yaffs_write(h,xx,sizeof(xx))) != sizeof(xx)){ + goto WRITE_ERROR; + } + sz32--; + } + + xx[0] = checksum; + + if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){ + goto WRITE_ERROR; + } + + + yaffs_close(h); + return 0; + +WRITE_ERROR: + printf("ywrite error at position %d\n",(int)yaffs_lseek(h,0,SEEK_END)); + yaffs_close(h); + return -1; + +} + +static int yVerifyFile(const char *fName) +{ + unsigned checksum = 0; + unsigned totalSize; + unsigned sz32; + unsigned recordedSize = 0; + int r; + int h; + int i; + int retval = 0; + + + printf("Verifying file %s\n",fName); + + h = yaffs_open(fName, O_RDONLY,S_IREAD | S_IWRITE); + + if(h < 0){ + printf("could not open file %s\n",fName); + return -1; + } + + totalSize = yaffs_lseek(h,0,SEEK_END); + yaffs_lseek(h,0,SEEK_SET); + + r = yaffs_read(h,&sz32,sizeof(sz32)); + + if(r != sizeof(sz32)){ + printf("reading size failed ... returned %d\n",r); + yaffs_close(h); + return -1; + } + + recordedSize = sz32 * sizeof(xx) + 8; + + printf("verify %s: file size is %d, recorded size is %d\n", fName, totalSize, recordedSize); + if(totalSize != recordedSize){ + printf("!!!!!!!!!!!!!!!!!!!!!!!!file size is wrong, should be %d, is %d\n", recordedSize,totalSize); + yaffs_close(h); + return -1; + } + + checksum ^= sz32; + + + while(sz32 > 0){ + r = yaffs_read(h,xx,sizeof(xx)); + if(r != sizeof(xx)){ + printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r); + yaffs_close(h); + return -1; + } + for(i = 0; i < XX_SIZE; i++) + checksum ^= xx[i]; + sz32--; + } + r = yaffs_read(h,xx,sizeof(xx[0])); + if(r != sizeof(xx[0])){ + printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r); + yaffs_close(h); + return -1; + } + + checksum ^= xx[0]; + + if(checksum != 0){ + printf("!!!!!!!!!!!!!!!!!!!!! checksum failed\n"); + retval = -1; + } else + printf("verified ok\n"); + yaffs_close(h); + + return retval; +} + +static unsigned long next = 1; +int myrand(void) { + next = next * 1103515245 + 12345; + return((unsigned)(next/65536) % 32768); +} + +static void DoUpdateMainFile(void) +{ + int result; + int sz32; + sz32 = (myrand() % 1000) + 20; + + result = yWriteFile(fullTempMainName,sz32); + if(result) + FatalError(); + yaffs_rename(fullTempMainName,fullMainName); +} + +static void DoVerifyMainFile(void) +{ + int result; + result = yVerifyFile(fullMainName); + if(result) + FatalError(); + +} + + +void NorStressTestInitialise(const char *prefix) +{ + MakeFullNames(prefix); + + yaffs_StartUp(); + yaffs_mount(fullPathName); + UpdateCounter(fullPowerUpName,&powerUps,1); + UpdateCounter(fullStartName,&cycleStarts,1); + UpdateCounter(fullEndName,&cycleEnds,1); + UpdateCounter(fullPowerUpName,&powerUps,1); + DoUpdateMainFile(); + DoVerifyMainFile(); + yaffs_unmount(fullPathName); +} + + +void NorStressTestRun(const char *prefix) +{ + MakeFullNames(prefix); + + yaffs_StartUp(); + yaffs_mount(fullPathName); + + dump_directory_tree(fullPathName); + + UpdateCounter(fullPowerUpName,&powerUps,0); + + while(1){ + UpdateCounter(fullStartName, &cycleStarts,0); + DoVerifyMainFile(); + DoUpdateMainFile(); + dump_directory_tree(fullPathName); + + UpdateCounter(fullEndName,&cycleEnds,0); + } +} diff --git a/direct/nor_stress.h b/direct/nor_stress.h new file mode 100644 index 0000000..e17db29 --- /dev/null +++ b/direct/nor_stress.h @@ -0,0 +1,8 @@ +#ifndef __NOR_STRESS_H__ +#define __NOR_STRESS_H__ + +void NorStressTestInitialise(const char *path); +void NorStressTestRun(const char *path); + +#endif + diff --git a/direct/yaffs_norif1.c b/direct/yaffs_norif1.c new file mode 100644 index 0000000..c9534ac --- /dev/null +++ b/direct/yaffs_norif1.c @@ -0,0 +1,306 @@ +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2007 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * This is an interface module for handling NOR in yaffs1 mode. + */ + +/* First set up for M18 with 1k chunks and 16-byte spares. + * + * NB We're using the oddball M18 modes of operation here + * The chip is 64MB based at 0x0000, but YAFFS only going to use the top half + * ie. YAFFS will be from 32MB to 64MB. + * + * The M18 has two ways of writing data. Every Programming Region (1kbytes) + * can be programmed in two modes: + * * Object Mode 1024 bytes of write once data. + * * Control Mode: 512bytes of bit-writeable data. + * This is arranged as 32 * (16 bytes of bit-writable followed by 16 bytes of "dont touch") + * + * The block size is 256kB, making 128 blocks in the 32MB YAFFS area. + * Each block comprises: + * Offset 0k: 248 x 1k data pages + * Offset 248k: 248 x 32-byte spare areas implemented as 16 bytes of spare followed by 16 bytes untouched) + * Offset 248k + (248 * 32): Format marker + * + */ + +const char *yaffs_norif1_c_version = "$Id: yaffs_norif1.c,v 1.1 2008-11-07 00:34:47 charles Exp $"; + +#include "yaffs_norif1.h" + +#include "yportenv.h" + +#include "yaffs_flashif.h" +#include "yaffs_guts.h" + +#include "devextras.h" + +#define SPARE_BYTES_PER_CHUNK 16 +#define M18_SKIP 16 +#define PROG_REGION_SIZE 1024 +#define BLOCK_SIZE_IN_BYTES (256*1024) +#define CHUNKS_PER_BLOCK 248 +#define SPARE_AREA_OFFSET (CHUNKS_PER_BLOCK * PROG_REGION_SIZE) + +#define FORMAT_OFFSET (SPARE_AREA_OFFSET + CHUNKS_PER_BLOCK * (SPARE_BYTES_PER_CHUNK + M18_SKIP)) + +#define FORMAT_VALUE 0x1234 + +#define DATA_BYTES_PER_CHUNK 1024 +#define BLOCKS_IN_DEVICE (32*1024/256) + + +#define YNOR_PREMARKER (0xF6) +#define YNOR_POSTMARKER (0xF0) + + +#if 1 + +/* Compile this for a simulation */ +#include "ynorsim.h" +#define ynorif1_FlashInit() ynorsim_Initialise() +#define ynorif1_FlashDeinit() ynorsim_Shutdown() +#define ynorif1_FlashWrite32(addr,buf,nwords) ynorsim_Write32(addr,buf,nwords) +#define ynorif1_FlashRead32(addr,buf,nwords) ynorsim_Read32(addr,buf,nwords) +#define ynorif1_FlashEraseBlock(addr) ynorsim_EraseBlock(addr) +#define DEVICE_BASE ynorsim_GetBase() +#else + +/* Compile this for running on blob, hacked for yaffs access */ +#include "../blob/yflashrw.h" +#define ynorif1_FlashInit() do{} while(0) +#define ynorif1_FlashDeinit() do {} while(0) +#define ynorif1_FlashWrite32(addr,buf,nwords) Y_FlashWrite(addr,buf,nwords) +#define ynorif1_FlashRead32(addr,buf,nwords) Y_FlashRead(addr,buf,nwords) +#define ynorif1_FlashEraseBlock(addr) Y_FlashErase(addr,BLOCK_SIZE_IN_BYTES) +#define DEVICE_BASE (32 * 1024 * 1024) +#endif + +__u32 *Block2Addr(yaffs_Device *dev, int blockNumber) +{ + __u32 addr; + + addr = (__u32) DEVICE_BASE; + addr += blockNumber * BLOCK_SIZE_IN_BYTES; + + return (__u32 *) addr; +} + +__u32 *Block2FormatAddr(yaffs_Device *dev,int blockNumber) +{ + __u32 addr; + + addr = (__u32) Block2Addr(dev,blockNumber); + addr += FORMAT_OFFSET; + + return (__u32 *)addr; +} +__u32 *Chunk2DataAddr(yaffs_Device *dev,int chunkId) +{ + unsigned block; + unsigned chunkInBlock; + __u32 addr; + + block = chunkId/dev->nChunksPerBlock; + chunkInBlock = chunkId % dev->nChunksPerBlock; + + addr = (__u32) Block2Addr(dev,block); + addr += chunkInBlock * DATA_BYTES_PER_CHUNK; + + return (__u32 *)addr; +} + +__u32 *Chunk2SpareAddr(yaffs_Device *dev,int chunkId) +{ + unsigned block; + unsigned chunkInBlock; + __u32 addr; + + block = chunkId/dev->nChunksPerBlock; + chunkInBlock = chunkId % dev->nChunksPerBlock; + + addr = (__u32) Block2Addr(dev,block); + addr += SPARE_AREA_OFFSET; + addr += chunkInBlock * (SPARE_BYTES_PER_CHUNK + M18_SKIP); + return (__u32 *)addr; +} + + +void ynorif1_AndBytes(__u8*target, const __u8 *src, int nbytes) +{ + while(nbytes > 0){ + *target &= *src; + target++; + src++; + nbytes--; + } +} + +int ynorif1_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare) +{ + __u32 *dataAddr = Chunk2DataAddr(dev,chunkInNAND); + __u32 *spareAddr = Chunk2SpareAddr(dev,chunkInNAND); + + yaffs_Spare tmpSpare; + + /* We should only be getting called for one of 3 reasons: + * Writing a chunk: data and spare will not be NULL + * Writing a deletion marker: data will be NULL, spare not NULL + * Writing a bad block marker: data will be NULL, spare not NULL + */ + + if(sizeof(yaffs_Spare) != 16) + YBUG(); + + if(data && spare) + { + if(spare->pageStatus != 0xff) + YBUG(); + /* Write a pre-marker */ + memset(&tmpSpare,0xff,sizeof(tmpSpare)); + tmpSpare.pageStatus = YNOR_PREMARKER; + ynorif1_FlashWrite32(spareAddr,(__u32 *)&tmpSpare,sizeof(yaffs_Spare)/4); + + /* Write the data */ + ynorif1_FlashWrite32(dataAddr,(__u32 *)data,dev->totalBytesPerChunk / 4); + + + memcpy(&tmpSpare,spare,sizeof(yaffs_Spare)); + + /* Write the real tags, but override the premarker*/ + tmpSpare.pageStatus = YNOR_PREMARKER; + ynorif1_FlashWrite32(spareAddr,(__u32 *)&tmpSpare,sizeof(yaffs_Spare)/4); + + /* Write a post-marker */ + tmpSpare.pageStatus = YNOR_POSTMARKER; + ynorif1_FlashWrite32(spareAddr,(__u32 *)&tmpSpare,sizeof(tmpSpare)/4); + + } else if(spare){ + /* This has to be a read-modify-write operation to handle NOR-ness */ + + ynorif1_FlashRead32(spareAddr,(__u32 *)&tmpSpare,16/ 4); + + ynorif1_AndBytes((__u8 *)&tmpSpare,(__u8 *)spare,sizeof(yaffs_Spare)); + + ynorif1_FlashWrite32(spareAddr,(__u32 *)&tmpSpare,16/ 4); + } + else { + YBUG(); + } + + + return YAFFS_OK; + +} + +int ynorif1_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare) +{ + + __u32 *dataAddr = Chunk2DataAddr(dev,chunkInNAND); + __u32 *spareAddr = Chunk2SpareAddr(dev,chunkInNAND); + + if(data) + { + ynorif1_FlashRead32(dataAddr,(__u32 *)data,dev->totalBytesPerChunk / 4); + } + + if(spare) + { + ynorif1_FlashRead32(spareAddr,(__u32 *)spare,16/ 4); + + /* If the page status is 0xF then it was written properly + * so change that to 0xFF so that the rest of yaffs is happy. + */ + if(spare->pageStatus == YNOR_POSTMARKER) + spare->pageStatus = 0xFF; + } + + + return YAFFS_OK; + +} + +static int ynorif1_FormatBlock(yaffs_Device *dev, int blockNumber) +{ + __u32 *blockAddr = Block2Addr(dev,blockNumber); + __u32 *formatAddr = Block2FormatAddr(dev,blockNumber); + __u32 formatValue = FORMAT_VALUE; + + ynorif1_FlashEraseBlock(blockAddr); + ynorif1_FlashWrite32(formatAddr,&formatValue,1); + + return YAFFS_OK; +} + +static int ynorif1_UnformatBlock(yaffs_Device *dev, int blockNumber) +{ + __u32 *formatAddr = Block2FormatAddr(dev,blockNumber); + __u32 formatValue = 0; + + ynorif1_FlashWrite32(formatAddr,&formatValue,1); + + return YAFFS_OK; +} + +static int ynorif1_IsBlockFormatted(yaffs_Device *dev, int blockNumber) +{ + __u32 *formatAddr = Block2FormatAddr(dev,blockNumber); + __u32 formatValue; + + + ynorif1_FlashRead32(formatAddr,&formatValue,1); + + return (formatValue == FORMAT_VALUE); +} + +int ynorif1_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) +{ + + if(blockNumber < 0 || blockNumber >= BLOCKS_IN_DEVICE) + { + T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); + return YAFFS_FAIL; + } + else + { + ynorif1_UnformatBlock(dev,blockNumber); + ynorif1_FormatBlock(dev,blockNumber); + return YAFFS_OK; + } + +} + +int ynorif1_InitialiseNAND(yaffs_Device *dev) +{ + int i; + + ynorif1_FlashInit(); + /* Go through the blocks formatting them if they are not formatted */ + for(i = dev->startBlock; i <= dev->endBlock; i++){ + if(!ynorif1_IsBlockFormatted(dev,i)){ + ynorif1_FormatBlock(dev,i); + } + } + return YAFFS_OK; +} + +int ynorif1_DeinitialiseNAND(yaffs_Device *dev) +{ + + ynorif1_FlashDeinit(); + + return YAFFS_OK; +} + + diff --git a/direct/yaffs_norif1.h b/direct/yaffs_norif1.h new file mode 100644 index 0000000..bee10e9 --- /dev/null +++ b/direct/yaffs_norif1.h @@ -0,0 +1,30 @@ +/* + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. + * + * Copyright (C) 2002-2007 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. + */ + + +#ifndef __YAFFS_NOR_IF1_H__ +#define __YAFFS_NOR_IF1_H__ + +#include "yaffs_guts.h" + +int ynorif1_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare); +int ynorif1_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare); +int ynorif1_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); +int ynorif1_InitialiseNAND(yaffs_Device *dev); +int ynorif1_DeinitialiseNAND(yaffs_Device *dev); + +#endif + + diff --git a/direct/yaffs_test.c b/direct/yaffs_test.c new file mode 100644 index 0000000..381df44 --- /dev/null +++ b/direct/yaffs_test.c @@ -0,0 +1,51 @@ +/* + * YAFFS: Yet another FFS. A NAND-flash specific file system. + * + * Copyright (C) 2002 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + + + + +#include +#include +#include +#include + +#include "yaffsfs.h" + +#include "nor_stress.h" + + + +void BadUsage(void) +{ + printf("usage root_dir test_id\n"); + printf(" test_id: fw_update fw_update_init\n"); + exit(2); +} +int main(int argc, const char *argv[]) +{ + yaffs_StartUp(); + if(argc == 3) { + if(!strcmp(argv[2],"fw_update_init")){ + NorStressTestInitialise(argv[1]); + } + else if(!strcmp(argv[2],"fw_update")){ + NorStressTestRun(argv[1]); + } + else + BadUsage(); + } + else + BadUsage(); + return 0; +} diff --git a/direct/yaffscfg2k.c b/direct/yaffscfg2k.c index 0a91e3f..0a59d95 100644 --- a/direct/yaffscfg2k.c +++ b/direct/yaffscfg2k.c @@ -22,18 +22,22 @@ #include "yaffsfs.h" #include "yaffs_fileem2k.h" #include "yaffs_nandemul2k.h" +#include "yaffs_norif1.h" #include unsigned yaffs_traceMask = YAFFS_TRACE_SCAN | - YAFFS_TRACE_GC | YAFFS_TRACE_GC_DETAIL | + YAFFS_TRACE_GC | YAFFS_TRACE_ERASE | + YAFFS_TRACE_ERROR | YAFFS_TRACE_TRACING | YAFFS_TRACE_ALLOCATE | YAFFS_TRACE_CHECKPOINT | YAFFS_TRACE_BAD_BLOCKS | + +/* YAFFS_TRACE_VERIFY | */ 0; @@ -108,26 +112,20 @@ void yaffsfs_LocalInitialisation(void) #include "yaffs_flashif2.h" #include "yaffs_nandemul2k.h" -static yaffs_Device ramDev; -static yaffs_Device bootDev; +static yaffs_Device ram1Dev; +static yaffs_Device nand2; static yaffs_Device flashDev; static yaffs_Device ram2kDev; +static yaffs_Device m18_1Dev; static yaffsfs_DeviceConfiguration yaffsfs_config[] = { -#if 0 - { "/ram", &ramDev}, - { "/boot", &bootDev}, - { "/flash/", &flashDev}, - { "/ram2k", &ram2kDev}, - {(void *)0,(void *)0} -#else - //{ "/", &ramDev}, - { "/flash/yaffs1", &bootDev}, - { "/flash/yaffs2", &flashDev}, + + { "/ram1", &ram1Dev}, + { "/M18-1", &m18_1Dev}, + { "/yaffs2", &flashDev}, { "/ram2k", &ram2kDev}, { "/flash/bigblock", &flashDev}, {(void *)0,(void *)0} /* Null entry to terminate list */ -#endif }; @@ -138,36 +136,36 @@ int yaffs_StartUp(void) yaffsfs_LocalInitialisation(); // Set up devices - // /ram - memset(&ramDev,0,sizeof(ramDev)); - ramDev.totalBytesPerChunk = 512; - ramDev.nChunksPerBlock = 32; - ramDev.nReservedBlocks = 2; // Set this smaller for RAM - ramDev.startBlock = 0; // Can use block 0 - ramDev.endBlock = 127; // Last block in 2MB. - //ramDev.useNANDECC = 1; - ramDev.nShortOpCaches = 0; // Disable caching on this device. - ramDev.genericDevice = (void *) 0; // Used to identify the device in fstat. - ramDev.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND; - ramDev.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND; - ramDev.eraseBlockInNAND = yramdisk_EraseBlockInNAND; - ramDev.initialiseNAND = yramdisk_InitialiseNAND; - - // /boot (yaffs1) - memset(&bootDev,0,sizeof(bootDev)); - bootDev.totalBytesPerChunk = 512; - bootDev.nChunksPerBlock = 32; - bootDev.nReservedBlocks = 5; - bootDev.startBlock = 0; // Can use block 0 - bootDev.endBlock = 63; // Last block - //bootDev.useNANDECC = 0; // use YAFFS's ECC - bootDev.nShortOpCaches = 10; // Use caches - bootDev.genericDevice = (void *) 1; // Used to identify the device in fstat. - bootDev.writeChunkToNAND = yflash_WriteChunkToNAND; - bootDev.readChunkFromNAND = yflash_ReadChunkFromNAND; - bootDev.eraseBlockInNAND = yflash_EraseBlockInNAND; - bootDev.initialiseNAND = yflash_InitialiseNAND; - + // /ram1 ram, yaffs1 + memset(&ram1Dev,0,sizeof(ram1Dev)); + ram1Dev.totalBytesPerChunk = 512; + ram1Dev.nChunksPerBlock = 32; + ram1Dev.nReservedBlocks = 2; // Set this smaller for RAM + ram1Dev.startBlock = 0; // Can use block 0 + ram1Dev.endBlock = 127; // Last block in 2MB. + //ram1Dev.useNANDECC = 1; + ram1Dev.nShortOpCaches = 0; // Disable caching on this device. + ram1Dev.genericDevice = (void *) 0; // Used to identify the device in fstat. + ram1Dev.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND; + ram1Dev.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND; + ram1Dev.eraseBlockInNAND = yramdisk_EraseBlockInNAND; + ram1Dev.initialiseNAND = yramdisk_InitialiseNAND; + + // /M18-1 yaffs1 on M18 nor sim + memset(&m18_1Dev,0,sizeof(m18_1Dev)); + m18_1Dev.totalBytesPerChunk = 1024; + m18_1Dev.nChunksPerBlock =248; + m18_1Dev.nReservedBlocks = 2; + m18_1Dev.startBlock = 0; // Can use block 0 + m18_1Dev.endBlock = 127; // Last block + m18_1Dev.useNANDECC = 0; // use YAFFS's ECC + m18_1Dev.nShortOpCaches = 10; // Use caches + m18_1Dev.genericDevice = (void *) 1; // Used to identify the device in fstat. + m18_1Dev.writeChunkToNAND = ynorif1_WriteChunkToNAND; + m18_1Dev.readChunkFromNAND = ynorif1_ReadChunkFromNAND; + m18_1Dev.eraseBlockInNAND = ynorif1_EraseBlockInNAND; + m18_1Dev.initialiseNAND = ynorif1_InitialiseNAND; + m18_1Dev.deinitialiseNAND = ynorif1_DeinitialiseNAND; // /flash (yaffs2) diff --git a/direct/ynorsim.c b/direct/ynorsim.c new file mode 100644 index 0000000..569e0de --- /dev/null +++ b/direct/ynorsim.c @@ -0,0 +1,156 @@ + + +#include "ynorsim.h" + + + +#include +#include +#include +#include +#include + +#define YNORSIM_FNAME "ynorsimdata" + +/* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to + *simulate bit flipping as the programming happens. + * A low value results in faster simulation with less chance of encountering a partially programmed + * word. + */ + +//#define YNORSIM_BIT_CHANGES 15 +#define YNORSIM_BIT_CHANGES 1 + +/* Simulate 32MB of flash in 256k byte blocks. + * This stuff is x32. + */ + +#define YNORSIM_BLOCK_SIZE_U32 (256*1024/4) +#define YNORSIM_DEV_SIZE_U32 (32*1024 * 1024/4) + +static __u32 word[YNORSIM_DEV_SIZE_U32]; + + +static void NorError(void) +{ + printf("Nor error\n"); + while(1){} +} + +static void ynorsim_SaveImage(void) +{ + int h = open(YNORSIM_FNAME, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); + write(h,word,sizeof(word)); + close(h); +} + +static void ynorsim_RestoreImage(void) +{ + int h = open(YNORSIM_FNAME, O_RDONLY, S_IREAD | S_IWRITE); + memset(word,0xFF,sizeof(word)); + read(h,word,sizeof(word)); + close(h); +} + + +static void ynorsim_PowerFail(void) +{ + ynorsim_SaveImage(); + exit(1); +} + +static int initialised = 0; +static int remaining_ops; +static int nops_so_far; + +static void ynorsim_MaybePowerFail(void) +{ + + nops_so_far++; + + + remaining_ops--; + if(remaining_ops < 1){ + printf("Simulated power failure after %d operations\n",nops_so_far); + ynorsim_PowerFail(); + } +} + +static void ynorsim_Ready(void) +{ + if(initialised) + return; + srand(time(NULL)); + remaining_ops = 1000000000; + remaining_ops = (rand() % 10000) * 10000; + ynorsim_RestoreImage(); +} + +void ynorsim_Read32(__u32 *addr,__u32 *buf, int nwords) +{ + while(nwords > 0){ + *buf = *addr; + buf++; + addr++; + nwords--; + } +} + +void ynorsim_WriteOneWord32(__u32 *addr,__u32 val) +{ + __u32 tmp; + __u32 m; + int i; + + tmp = *addr; + if(val & ~tmp){ + // Fail due to trying to change a zero into a 1 + printf("attempt to set a zero to one (%x)->(%x)\n",tmp,val); + NorError(); + } + + for(i = 0; i < YNORSIM_BIT_CHANGES; i++){ + m = 1 << (rand() & 31); + if(!(m & val)){ + tmp &= ~m; + *addr = tmp; + ynorsim_MaybePowerFail(); + } + + } + + *addr = tmp & val; + ynorsim_MaybePowerFail(); +} + +void ynorsim_Write32(__u32 *addr, __u32 *buf, int nwords) +{ + while(nwords >0){ + ynorsim_WriteOneWord32(addr,*buf); + addr++; + buf++; + nwords--; + } +} + +void ynorsim_EraseBlock(__u32 *addr) +{ + /* Todo... bit flipping */ + memset(addr,0xFF,YNORSIM_BLOCK_SIZE_U32 * 4); +} + +void ynorsim_Initialise(void) +{ + ynorsim_Ready(); +} + +void ynorsim_Shutdown(void) +{ + ynorsim_SaveImage(); + initialised=0; +} + +__u32 *ynorsim_GetBase(void) +{ + return word; +} diff --git a/direct/ynorsim.h b/direct/ynorsim.h new file mode 100644 index 0000000..2c70ad9 --- /dev/null +++ b/direct/ynorsim.h @@ -0,0 +1,14 @@ + +#ifndef __Y_NORSIM_H__ +#define __Y_NORSIM_H__ + +#include "yaffs_guts.h" + +void ynorsim_Read32(__u32 *addr, __u32 *data, int nwords); +void ynorsim_Write32(__u32 *addr, __u32 *data, int nwords); +void ynorsim_EraseBlock(__u32 *addr); +void ynorsim_Shutdown(void); +void ynorsim_Initialise(void); +__u32 * ynorsim_GetBase(void); + +#endif diff --git a/yaffs_guts.c b/yaffs_guts.c index eb34115..a16ec55 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -12,7 +12,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.61 2008-10-30 18:25:21 charles Exp $"; + "$Id: yaffs_guts.c,v 1.62 2008-11-07 00:32:20 charles Exp $"; #include "yportenv.h" @@ -97,6 +97,7 @@ static void yaffs_VerifyFreeChunks(yaffs_Device * dev); static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in); +static void yaffs_VerifyDirectory(yaffs_Object *directory); #ifdef YAFFS_PARANOID static int yaffs_CheckFileSanity(yaffs_Object * in); #else @@ -721,12 +722,6 @@ static void yaffs_VerifyFile(yaffs_Object *obj) } -static void yaffs_VerifyDirectory(yaffs_Object *obj) -{ - if(obj && yaffs_SkipVerification(obj->myDev)) - return; - -} static void yaffs_VerifyHardLink(yaffs_Object *obj) { @@ -1108,7 +1103,7 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name) __u16 sum = 0; __u16 i = 1; - YUCHAR *bname = (YUCHAR *) name; + const YUCHAR *bname = (const YUCHAR *) name; if (bname) { while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) { @@ -1121,12 +1116,14 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name) bname++; } } + return sum; } static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name) { #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM + memset(obj->shortName,0,sizeof (YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) { yaffs_strcpy(obj->shortName, name); } else { @@ -1911,6 +1908,9 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) { yaffs_Object *tn = NULL; +#ifdef VALGRIND_TEST + tn = YMALLOC(sizeof(yaffs_Object)); +#else /* If there are none left make more */ if (!dev->freeObjects) { yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS); @@ -1921,7 +1921,9 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) dev->freeObjects = (yaffs_Object *) (dev->freeObjects->siblings.next); dev->nFreeObjects--; - + } +#endif + if(tn){ /* Now sweeten it up... */ memset(tn, 0, sizeof(yaffs_Object)); @@ -1931,6 +1933,13 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) YINIT_LIST_HEAD(&(tn->hardLinks)); YINIT_LIST_HEAD(&(tn->hashLink)); YINIT_LIST_HEAD(&tn->siblings); + + + /* Now make the directory sane */ + if(dev->rootDir){ + tn->parent = dev->rootDir; + ylist_add(&(tn->siblings),&dev->rootDir->variant.directoryVariant.children); + } /* Add it to the lost and found directory. * NB Can't put root or lostNFound in lostNFound so @@ -1987,6 +1996,13 @@ static void yaffs_FreeObject(yaffs_Object * tn) yaffs_Device *dev = tn->myDev; + + if(tn->parent) + YBUG(); + if(!ylist_empty(&tn->siblings)) + YBUG(); + + #ifdef __KERNEL__ if (tn->myInode) { /* We're still hooked up to a cached inode. @@ -1999,11 +2015,14 @@ static void yaffs_FreeObject(yaffs_Object * tn) yaffs_UnhashObject(tn); +#ifdef VALGRIND_TEST + YFREE(tn); +#else /* Link into the free list. */ tn->siblings.next = (struct ylist_head *)(dev->freeObjects); dev->freeObjects = tn; dev->nFreeObjects++; - +#endif dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ } @@ -2201,6 +2220,12 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, theObject->yst_atime = theObject->yst_mtime = theObject->yst_ctime = Y_CURRENT_TIME; #endif + +#if 0 + theObject->sum_prev = 12345; + theObject->sum_trailer = 6789; +#endif + switch (type) { case YAFFS_OBJECT_TYPE_FILE: theObject->variant.fileVariant.fileSize = 0; @@ -2467,9 +2492,15 @@ static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir, int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, yaffs_Object * newDir, const YCHAR * newName) { - yaffs_Object *obj; - yaffs_Object *existingTarget; + yaffs_Object *obj=NULL; + yaffs_Object *existingTarget=NULL; int force = 0; + + + if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); + if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); #ifdef CONFIG_YAFFS_CASE_INSENSITIVE /* Special case for case insemsitive systems (eg. WinCE). @@ -2481,17 +2512,12 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, } #endif - obj = yaffs_FindObjectByName(oldDir, oldName); - /* Check new name to long. */ - if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK && - yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH) - /* ENAMETOOLONG */ - return YAFFS_FAIL; - else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK && - yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) + else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) /* ENAMETOOLONG */ return YAFFS_FAIL; + obj = yaffs_FindObjectByName(oldDir, oldName); + if (obj && obj->renameAllowed) { /* Now do the handling for an existing target, if there is one */ @@ -2846,7 +2872,8 @@ static int yaffs_FindBlockForAllocation(yaffs_Device * dev) static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev) { - if(!dev->nCheckpointBlocksRequired){ + if(!dev->nCheckpointBlocksRequired && + dev->isYaffs2){ /* Not a valid value so recalculate */ int nBytes = 0; int nBlocks; @@ -2885,9 +2912,14 @@ static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev) int reservedBlocks = dev->nReservedBlocks; int checkpointBlocks; - checkpointBlocks = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint; - if(checkpointBlocks < 0) - checkpointBlocks = 0; + if(dev->isYaffs2){ + checkpointBlocks = yaffs_CalcCheckpointBlocksRequired(dev) - + dev->blocksInCheckpoint; + if(checkpointBlocks < 0) + checkpointBlocks = 0; + } else { + checkpointBlocks =0; + } reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock); @@ -3063,9 +3095,11 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) tags.objectId, tags.chunkId, tags.byteCount)); } - if (object && object->deleted - && tags.chunkId != 0) { - /* Data chunk in a deleted file, throw it away + if (object && + object->deleted && + object->softDeleted && + tags.chunkId != 0) { + /* Data chunk in a soft deleted file, throw it away * It's a soft deleted data chunk, * No need to copy this, just forget about it and * fix up the object. @@ -3640,6 +3674,14 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode, newTags.serialNumber = (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1; newTags.byteCount = nBytes; + + if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){ + T(YAFFS_TRACE_ERROR, + (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes)); + while(1){} + } + + newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, @@ -4796,6 +4838,12 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, //chunk = offset / dev->nDataBytesPerChunk + 1; //start = offset % dev->nDataBytesPerChunk; yaffs_AddrToChunk(dev,offset,&chunk,&start); + + if(chunk * dev->nDataBytesPerChunk + start != offset || + start >= dev->nDataBytesPerChunk){ + T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR), + (int)offset, chunk,start)); + } chunk++; /* OK now check for the curveball where the start and end are in @@ -5149,62 +5197,66 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in) * and the inode associated with the file. * It does not delete the links associated with the file. */ + static int yaffs_UnlinkFile(yaffs_Object * in) { int retVal; int immediateDeletion = 0; - if (1) { #ifdef __KERNEL__ - if (!in->myInode) { - immediateDeletion = 1; - - } + if (!in->myInode) { + immediateDeletion = 1; + } #else - if (in->inUse <= 0) { - immediateDeletion = 1; - - } + if (in->inUse <= 0) { + immediateDeletion = 1; + } #endif - if (immediateDeletion) { - retVal = - yaffs_ChangeObjectName(in, in->myDev->deletedDir, - _Y("deleted"), 0, 0); - T(YAFFS_TRACE_TRACING, - (TSTR("yaffs: immediate deletion of file %d" TENDSTR), - in->objectId)); - in->deleted = 1; - in->myDev->nDeletedFiles++; - if (0 && in->myDev->isYaffs2) { - yaffs_ResizeFile(in, 0); - } - yaffs_SoftDeleteFile(in); - } else { - retVal = - yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, - _Y("unlinked"), 0, 0); - } + if (immediateDeletion) { + retVal = + yaffs_ChangeObjectName(in, in->myDev->deletedDir, + _Y("deleted"), 0, 0); + T(YAFFS_TRACE_TRACING, + (TSTR("yaffs: immediate deletion of file %d" TENDSTR), + in->objectId)); + in->deleted = 1; + in->myDev->nDeletedFiles++; + if (1 || in->myDev->isYaffs2) { + yaffs_ResizeFile(in, 0); + } + yaffs_SoftDeleteFile(in); + } else { + retVal = + yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, + _Y("unlinked"), 0, 0); } + + return retVal; } int yaffs_DeleteFile(yaffs_Object * in) { int retVal = YAFFS_OK; + int deleted = in->deleted; + + yaffs_ResizeFile(in,0); if (in->nDataChunks > 0) { - /* Use soft deletion if there is data in the file */ + /* Use soft deletion if there is data in the file. + * That won't be the case if it has been resized to zero. + */ if (!in->unlinked) { retVal = yaffs_UnlinkFile(in); } if (retVal == YAFFS_OK && in->unlinked && !in->deleted) { - in->deleted = 1; + in->deleted = deleted = 1; in->myDev->nDeletedFiles++; yaffs_SoftDeleteFile(in); } - return in->deleted ? YAFFS_OK : YAFFS_FAIL; + return deleted ? YAFFS_OK : YAFFS_FAIL; } else { /* The file has no data chunks so we toss it immediately */ yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top); @@ -5238,7 +5290,7 @@ static int yaffs_DeleteHardLink(yaffs_Object * in) /* remove this hardlink from the list assocaited with the equivalent * object */ - ylist_del(&in->hardLinks); + ylist_del_init(&in->hardLinks); return yaffs_DoGenericObjectDeletion(in); } @@ -5799,10 +5851,12 @@ static int yaffs_Scan(yaffs_Device * dev) break; } - if (parent == dev->deletedDir) { +/* + if (parent == dev->deletedDir) { yaffs_DestroyObject(in); bi->hasShrinkHeader = 1; } +*/ } } } @@ -6627,15 +6681,91 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) /*------------------------------ Directory Functions ----------------------------- */ +static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) +{ + struct ylist_head *lh; + yaffs_Object *listObj; + + int count = 0; + + if(!obj) + YBUG(); + + if(yaffs_SkipVerification(obj->myDev)) + return; + + if(!obj->parent) + YBUG(); + + if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); + + /* Iterate through the objects in each hash entry */ + + ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) { + if (lh) { + listObj = ylist_entry(lh, yaffs_Object, siblings); + yaffs_VerifyObject(listObj); + if(obj == listObj) + count ++; + } + } + + if(count != 1) + YBUG(); + + +} + +static void yaffs_VerifyDirectory(yaffs_Object *directory) +{ + + struct ylist_head *lh; + yaffs_Object *listObj; + + if(!directory) + YBUG(); + + if(yaffs_SkipVerification(directory->myDev)) + return; + + + if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); + + /* Iterate through the objects in each hash entry */ + + ylist_for_each(lh, &directory->variant.directoryVariant.children) { + if (lh) { + listObj = ylist_entry(lh, yaffs_Object, siblings); + if(listObj->parent != directory) + YBUG(); + yaffs_VerifyObjectInDirectory(listObj); + } + } + +} + + static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) { yaffs_Device *dev = obj->myDev; + yaffs_Object *parent; + yaffs_VerifyObjectInDirectory(obj); + parent = obj->parent; + + yaffs_VerifyDirectory(parent); + if(dev && dev->removeObjectCallback) dev->removeObjectCallback(obj); + ylist_del_init(&obj->siblings); obj->parent = NULL; + + yaffs_VerifyDirectory(parent); + } @@ -6660,12 +6790,18 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory, if (obj->siblings.prev == NULL) { /* Not initialised */ - YINIT_LIST_HEAD(&obj->siblings); + YBUG(); - } else if (!ylist_empty(&obj->siblings)) { - /* If it is holed up somewhere else, un hook it */ - yaffs_RemoveObjectFromDirectory(obj); - } + } else if (ylist_empty(&obj->siblings)) { + YBUG(); + } + + + yaffs_VerifyDirectory(directory); + + yaffs_RemoveObjectFromDirectory(obj); + + /* Now add it */ ylist_add(&obj->siblings, &directory->variant.directoryVariant.children); obj->parent = directory; @@ -6676,6 +6812,11 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory, obj->myDev->nUnlinkedFiles++; obj->renameAllowed = 0; } + + yaffs_VerifyDirectory(directory); + yaffs_VerifyObjectInDirectory(obj); + + } yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, @@ -6712,6 +6853,9 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, if (i) { l = ylist_entry(i, yaffs_Object, siblings); + if(l->parent != directory) + YBUG(); + yaffs_CheckObjectDetailsLoaded(l); /* Special case for lost-n-found */ @@ -7078,7 +7222,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) /* Check geometry parameters. */ if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || - (!dev->isYaffs2 && dev->totalBytesPerChunk != 512) || + (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) || (dev->inbandTags && !dev->isYaffs2 ) || dev->nChunksPerBlock < 2 || dev->nReservedBlocks < 2 || @@ -7372,6 +7516,9 @@ void yaffs_Deinitialise(yaffs_Device * dev) dev->isMounted = 0; + + if(dev->deinitialiseNAND) + dev->deinitialiseNAND(dev); } } diff --git a/yaffs_guts.h b/yaffs_guts.h index a193625..3c73583 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -132,12 +132,12 @@ typedef struct { #ifndef CONFIG_YAFFS_NO_YAFFS1 typedef struct { - unsigned chunkId:20; - unsigned serialNumber:2; - unsigned byteCount:10; - unsigned objectId:18; - unsigned ecc:12; - unsigned unusedStuff:2; + unsigned chunkId:20; + unsigned serialNumber:2; + unsigned byteCountLSB:10; + unsigned objectId:18; + unsigned ecc:12; + unsigned byteCountMSB:2; } yaffs_Tags; @@ -420,10 +420,12 @@ struct yaffs_ObjectStruct { __u8 deferedFree:1; /* For Linux kernel. Object is removed from NAND, but is * still in the inode cache. Free of object is defered. * until the inode is released. - */ + */ - __u8 serial; /* serial number of chunk in NAND. Cached here */ - __u16 sum; /* sum of the name to speed searching */ + __u8 serial; /* serial number of chunk in NAND. Cached here */ +/* __u16 sum_prev; */ + __u16 sum; /* sum of the name to speed searching */ +/* __u16 sum_trailer; */ struct yaffs_DeviceStruct *myDev; /* The device I'm on */ @@ -443,10 +445,10 @@ struct yaffs_ObjectStruct { __u32 objectId; /* the object id value */ - __u32 yst_mode; + __u32 yst_mode; #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM - YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1]; + YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1]; #endif #ifndef __KERNEL__ @@ -572,12 +574,13 @@ struct yaffs_DeviceStruct { int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev, int chunkInNAND, __u8 * data, yaffs_Spare * spare); - int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev, - int blockInNAND); - int (*initialiseNAND) (struct yaffs_DeviceStruct * dev); + int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev, + int blockInNAND); + int (*initialiseNAND) (struct yaffs_DeviceStruct * dev); + int (*deinitialiseNAND) (struct yaffs_DeviceStruct * dev); #ifdef CONFIG_YAFFS_YAFFS2 - int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev, + int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev, int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * tags); int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev, diff --git a/yaffs_tagscompat.c b/yaffs_tagscompat.c index 3e5e8a4..f6c4053 100644 --- a/yaffs_tagscompat.c +++ b/yaffs_tagscompat.c @@ -418,7 +418,16 @@ int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev, } else { tags.objectId = eTags->objectId; tags.chunkId = eTags->chunkId; - tags.byteCount = eTags->byteCount; + + tags.byteCountLSB = eTags->byteCount & 0x3ff; + + if(dev->nDataBytesPerChunk >= 1024){ + tags.byteCountMSB = (eTags->byteCount >> 10) & 3; + } else { + tags.byteCountMSB = 3; + } + + tags.serialNumber = eTags->serialNumber; if (!dev->useNANDECC && data) { @@ -470,7 +479,11 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, eTags->objectId = tags.objectId; eTags->chunkId = tags.chunkId; - eTags->byteCount = tags.byteCount; + eTags->byteCount = tags.byteCountLSB; + + if(dev->nDataBytesPerChunk >= 1024) + eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10); + eTags->serialNumber = tags.serialNumber; } }