From b9d0902ef84af3e242f6a95fb7a1b79e1eb94aa8 Mon Sep 17 00:00:00 2001 From: charles Date: Sun, 21 May 2006 09:39:12 +0000 Subject: [PATCH] Fix some checkpoint stuff, add qsort --- direct/Makefile | 7 ++- direct/dtest.c | 57 ++++++++++++++++- direct/yaffscfg2k.c | 5 +- direct/ydirectenv.h | 7 ++- yaffs_checkptrw.c | 15 ++--- yaffs_fs.c | 4 +- yaffs_guts.c | 145 ++++++++++++++++++++++++++++++++++++-------- yportenv.h | 6 +- 8 files changed, 201 insertions(+), 45 deletions(-) diff --git a/direct/Makefile b/direct/Makefile index 5b6bf46..ff9ac16 100644 --- a/direct/Makefile +++ b/direct/Makefile @@ -10,7 +10,7 @@ # # NB Warning this Makefile does not include header dependencies. # -# $Id: Makefile,v 1.9 2006-05-08 10:13:34 charles Exp $ +# $Id: Makefile,v 1.10 2006-05-21 09:39:12 charles Exp $ EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC @@ -22,7 +22,7 @@ CFLAGS = -Wall -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONF DIRECTTESTOBJS = dtest.o yaffscfg2k.o yaffs_ecc.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \ yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ - yaffs_checkptrw.o \ + yaffs_checkptrw.o yaffs_qsort.o \ # yaffs_checkptrwtest.o\ @@ -35,7 +35,8 @@ 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_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c + yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ + yaffs_qsort.c yaffs_qsort.h #all: directtest2k boottest diff --git a/direct/dtest.c b/direct/dtest.c index 13e55c7..ed552e7 100644 --- a/direct/dtest.c +++ b/direct/dtest.c @@ -1723,7 +1723,7 @@ void multi_mount_test(const char *mountpt,int nmounts) write_200k_file(b,"",""); - printf("######## Iteration %d Start\n",i); + printf("######## Iteration %d End\n",i); dump_directory_tree(mountpt); yaffs_unmount(mountpt); @@ -1731,6 +1731,58 @@ void multi_mount_test(const char *mountpt,int nmounts) } +void yaffs_touch(const char *fn) +{ + yaffs_chmod(fn, S_IREAD | S_IWRITE); +} + +void checkpoint_fill_test(const char *mountpt,int nmounts) +{ + + char a[50]; + char b[50]; + char c[50]; + + int i; + int j; + int h; + + sprintf(a,"%s/a",mountpt); + + + + + yaffs_StartUp(); + + for(i = 0; i < nmounts; i++){ + printf("############### Iteration %d Start\n",i); + yaffs_mount(mountpt); + dump_directory_tree(mountpt); + yaffs_mkdir(a,0); + + sprintf(b,"%s/zz",a); + + h = yaffs_open(b,O_CREAT | O_RDWR,S_IREAD |S_IWRITE); + + + while(yaffs_write(h,c,50) == 50){} + + yaffs_close(h); + + for(j = 0; j < 100; j++){ + printf("touch %d\n",j); + yaffs_touch(b); + yaffs_unmount(mountpt); + yaffs_mount(mountpt); + } + + dump_directory_tree(mountpt); + yaffs_unmount(mountpt); + } +} + + + int main(int argc, char *argv[]) { //return long_test(argc,argv); @@ -1747,7 +1799,8 @@ int main(int argc, char *argv[]) //scan_pattern_test("/flash",10000,10); //short_scan_test("/flash/flash",40000,200); - multi_mount_test("/flash/flash",20); + //multi_mount_test("/flash/flash",20); + checkpoint_fill_test("/flash/flash",20); diff --git a/direct/yaffscfg2k.c b/direct/yaffscfg2k.c index 38384bb..77cbbdf 100644 --- a/direct/yaffscfg2k.c +++ b/direct/yaffscfg2k.c @@ -125,11 +125,12 @@ int yaffs_StartUp(void) flashDev.nBytesPerChunk = 2048; flashDev.nChunksPerBlock = 64; flashDev.nReservedBlocks = 5; + flashDev.nCheckpointReservedBlocks = 5; //flashDev.checkpointStartBlock = 1; //flashDev.checkpointEndBlock = 20; flashDev.startBlock = 20; - //flashDev.endBlock = 127; // Last block in 16MB - flashDev.endBlock = yflash_GetNumberOfBlocks()-1; + flashDev.endBlock = 127; // Make it smaller + //flashDev.endBlock = yflash_GetNumberOfBlocks()-1; flashDev.isYaffs2 = 1; flashDev.wideTnodesDisabled=0; flashDev.nShortOpCaches = 10; // Use caches diff --git a/direct/ydirectenv.h b/direct/ydirectenv.h index 561c8b5..d059126 100644 --- a/direct/ydirectenv.h +++ b/direct/ydirectenv.h @@ -14,7 +14,7 @@ * * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. * - * $Id: ydirectenv.h,v 1.2 2005-10-07 03:48:50 charles Exp $ + * $Id: ydirectenv.h,v 1.3 2006-05-21 09:39:12 charles Exp $ * */ @@ -46,6 +46,11 @@ #define YMALLOC_ALT(x) malloc(x) #define YFREE_ALT(x) free(x) +#define YMALLOC_DMA(x) malloc(x) + +#define YYIELD() do {} while(0) + + //#define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s)) //#define YALERT(s) YINFO(s) diff --git a/yaffs_checkptrw.c b/yaffs_checkptrw.c index 686a47b..f56b311 100644 --- a/yaffs_checkptrw.c +++ b/yaffs_checkptrw.c @@ -13,7 +13,7 @@ */ const char *yaffs_checkptrw_c_version = - "$Id: yaffs_checkptrw.c,v 1.2 2006-05-17 09:31:07 charles Exp $"; + "$Id: yaffs_checkptrw.c,v 1.3 2006-05-21 09:39:12 charles Exp $"; #include "yaffs_checkptrw.h" @@ -24,16 +24,12 @@ static int yaffs_CheckpointSpaceOk(yaffs_Device *dev) int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks; - if(blocksAvailable < 0) - blocksAvailable = 0; - - T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpt blocks available" TENDSTR))); + T(YAFFS_TRACE_CHECKPOINT, + (TSTR("checkpt blocks available = %d" TENDSTR), + blocksAvailable)); - if(blocksAvailable <= 0) - return 0; - - return 1; + return (blocksAvailable <= 0) ? 0 : 1; } @@ -167,6 +163,7 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting) dev->checkpointByteOffset = dev->nBytesPerChunk; /* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully) * going to be way more than we need */ + dev->blocksInCheckpoint = 0; dev->checkpointMaxBlocks = (dev->endBlock - dev->startBlock)/16 + 2; dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks); for(i = 0; i < dev->checkpointMaxBlocks; i++) diff --git a/yaffs_fs.c b/yaffs_fs.c index bcc148b..f28a6e8 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -31,7 +31,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.47 2006-05-17 09:36:06 charles Exp $"; + "$Id: yaffs_fs.c,v 1.48 2006-05-21 09:39:12 charles Exp $"; extern const char *yaffs_guts_c_version; #include @@ -1547,6 +1547,8 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, dev->nBytesPerChunk = mtd->oobblock; dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; nBlocks = mtd->size / mtd->erasesize; + + dev->nCheckpointReservedBlocks = 10; dev->startBlock = 0; dev->endBlock = nBlocks - 1; } else { diff --git a/yaffs_guts.c b/yaffs_guts.c index 8b7ccc3..74ddb9d 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -13,7 +13,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.33 2006-05-17 09:20:26 charles Exp $"; + "$Id: yaffs_guts.c,v 1.34 2006-05-21 09:39:12 charles Exp $"; #include "yportenv.h" @@ -22,6 +22,9 @@ const char *yaffs_guts_c_version = #include "yaffs_tagsvalidity.h" #include "yaffs_tagscompat.h" +#ifndef CONFIG_YAFFS_OWN_SORT +#include "yaffs_qsort.h" +#endif #include "yaffs_nand.h" #include "yaffs_checkptrw.h" @@ -165,6 +168,32 @@ static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, } +/* + * Determine if we have a managed buffer. + */ +int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer) +{ + int i; + for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { + if (dev->tempBuffer[i].buffer == buffer) + return 1; + + } + + for (i = 0; i < dev->nShortOpCaches; i++) { + if( dev->srCache[i].data == buffer ) + return 1; + + } + + if (buffer == dev->checkpointBuffer) + return 1; + + T(YAFFS_TRACE_ALWAYS, + (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR))); + return 0; +} + /* * Chunk bitmap manipulations */ @@ -1722,6 +1751,15 @@ 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) + /* ENAMETOOLONG */ + return YAFFS_FAIL; if (obj && obj->renameAllowed) { @@ -2336,6 +2374,8 @@ static int yaffs_CheckGarbageCollection(yaffs_Device * dev) int aggressive; int gcOk = YAFFS_OK; int maxTries = 0; + + int checkpointBlockAdjust; if (dev->isDoingGC) { /* Bail out so we don't get recursive gc */ @@ -2348,7 +2388,12 @@ static int yaffs_CheckGarbageCollection(yaffs_Device * dev) do { maxTries++; - if (dev->nErasedBlocks < dev->nReservedBlocks) { + + checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint); + if(checkpointBlockAdjust < 0) + checkpointBlockAdjust = 0; + + if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) { /* We need a block soon...*/ aggressive = 1; } else { @@ -3382,13 +3427,15 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn, { int i; yaffs_Device *dev = in->myDev; + int ok = 1; + int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; if (tn) { if (level > 0) { - for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++){ + for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){ if (tn->internal[i]) { - yaffs_CheckpointTnodeWorker(in, + ok = yaffs_CheckpointTnodeWorker(in, tn->internal[i], level - 1, (chunkOffset<tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); + ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset)); + if(ok) + ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes); } } - return 1; + return ok; } @@ -3519,13 +3567,13 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) if(ok && cp.objectId == ~0) done = 1; - else { + else if(ok){ /* printf("Read object %d type %d\n",cp.objectId,cp.variantType); */ obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType); if(obj) { yaffs_CheckpointObjectToObject(obj,&cp); if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) { - yaffs_ReadCheckpointTnodes(obj); + ok = yaffs_ReadCheckpointTnodes(obj); } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { obj->hardLinks.next = (struct list_head *) @@ -3559,12 +3607,13 @@ static int yaffs_WriteCheckpointData(yaffs_Device *dev) if(ok) ok = yaffs_WriteCheckpointValidityMarker(dev,0); - yaffs_CheckpointClose(dev); - -// if(dev->checkpointBytes) + if(!yaffs_CheckpointClose(dev)) + ok = 0; + + if(ok) dev->isCheckpointed = 1; -// else - //dev->isCheckpointed = 0; + else + dev->isCheckpointed = 0; return dev->isCheckpointed; } @@ -3586,12 +3635,13 @@ static int yaffs_ReadCheckpointData(yaffs_Device *dev) - yaffs_CheckpointClose(dev); + if(!yaffs_CheckpointClose(dev)) + ok = 0; -// if(ok) + if(ok) dev->isCheckpointed = 1; -// else -// dev->isCheckpointed = 0; + else + dev->isCheckpointed = 0; return ok ? 1 : 0; @@ -3599,7 +3649,8 @@ static int yaffs_ReadCheckpointData(yaffs_Device *dev) static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) { - if(dev->isCheckpointed){ + if(dev->isCheckpointed || + dev->blocksInCheckpoint > 0){ dev->isCheckpointed = 0; yaffs_CheckpointInvalidateStream(dev); if(dev->superBlock && dev->markSuperBlockDirty) @@ -3610,16 +3661,26 @@ static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) int yaffs_CheckpointSave(yaffs_Device *dev) { + T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); + if(!dev->isCheckpointed) yaffs_WriteCheckpointData(dev); + T(YAFFS_TRACE_CHECKPOINT,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); + return dev->isCheckpointed; } int yaffs_CheckpointRestore(yaffs_Device *dev) { + int retval; + T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); - return yaffs_ReadCheckpointData(dev); + retval = yaffs_ReadCheckpointData(dev); + + T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); + + return retval; } /*--------------------- File read/write ------------------------ @@ -4378,6 +4439,18 @@ static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList) +static int ybicmp(const void *a, const void *b){ + register int aseq = ((yaffs_BlockIndex *)a)->seq; + register int bseq = ((yaffs_BlockIndex *)b)->seq; + register int ablock = ((yaffs_BlockIndex *)a)->block; + register int bblock = ((yaffs_BlockIndex *)b)->block; + if( aseq == bseq ) + return ablock - bblock; + else + return aseq - bseq; + +} + static int yaffs_Scan(yaffs_Device * dev) { yaffs_ExtendedTags tags; @@ -5004,11 +5077,23 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) } } - /* - * Sort the blocks - * Dungy old bubble sort for now... - */ + T(YAFFS_TRACE_SCAN, + (TSTR("%d blocks to be sorted..." TENDSTR), nBlocksToScan)); + + + + YYIELD(); + + /* Sort the blocks */ +#ifndef CONFIG_YAFFS_USE_OWN_SORT { + /* Use qsort now. */ + qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp); + } +#else + { + /* Dungy old bubble sort... */ + yaffs_BlockIndex temp; int i; int j; @@ -5021,6 +5106,11 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) blockIndex[i] = temp; } } +#endif + + YYIELD(); + + T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR))); /* Now scan the blocks looking at the data. */ startIterator = 0; @@ -5031,6 +5121,9 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) /* For each block.... backwards */ for (blockIterator = endIterator; blockIterator >= startIterator; blockIterator--) { + /* Cooperative multitasking! This loop can run for so + long that watchdog timers expire. */ + YYIELD(); /* get the block to scan in the correct order */ blk = blockIndex[blockIterator].block; @@ -6074,7 +6167,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { dev->tempBuffer[i].line = 0; /* not in use */ dev->tempBuffer[i].buffer = - YMALLOC(dev->nBytesPerChunk); + YMALLOC_DMA(dev->nBytesPerChunk); } } @@ -6092,7 +6185,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 = YMALLOC(dev->nBytesPerChunk); + dev->srCache[i].data = YMALLOC_DMA(dev->nBytesPerChunk); } dev->srLastUse = 0; } diff --git a/yportenv.h b/yportenv.h index e072742..e8b9d09 100644 --- a/yportenv.h +++ b/yportenv.h @@ -15,7 +15,7 @@ * * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. * - * $Id: yportenv.h,v 1.10 2006-05-08 10:13:34 charles Exp $ + * $Id: yportenv.h,v 1.11 2006-05-21 09:39:12 charles Exp $ * */ @@ -58,6 +58,10 @@ #define YFREE(x) kfree(x) #define YMALLOC_ALT(x) vmalloc(x) #define YFREE_ALT(x) vfree(x) +#define YMALLOC_DMA(x) YMALLOC(x) + +// KR - added for use in scan so processes aren't blocked indefinitely. +#define YYIELD() schedule() #define YAFFS_ROOT_MODE 0666 #define YAFFS_LOSTNFOUND_MODE 0666 -- 2.30.2