X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs%2F.git;a=blobdiff_plain;f=yaffs_guts.c;h=fcb217ae850f3b4d98fc85abccac0c7a43684b26;hp=cfe955f8ca306e7298b24a56f1534a42171557a3;hb=f0494eb05c40ce19d74bedc92a020a743fbec08e;hpb=1dea37b139c892671df123e8ad4204ab4dc20fa5 diff --git a/yaffs_guts.c b/yaffs_guts.c index cfe955f..fcb217a 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -14,22 +14,25 @@ */ //yaffs_guts.c -const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.20 2003-01-31 03:30:33 charles Exp $"; +const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.44 2005-11-07 07:03:02 charles Exp $"; #include "yportenv.h" #include "yaffsinterface.h" #include "yaffs_guts.h" - - - #define YAFFS_PASSIVE_GC_CHUNKS 2 +#if 0 +// Use Steven Hill's ECC struff instead // External functions for ECC on data void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); - +#define yaffs_ECCCalculate(data,ecc) nand_calculate_ecc(data,ecc) +#define yaffs_ECCCorrect(data,read_ecc,calc_ecc) nand_correct_ecc(data,read_ecc,calc_ecc) +#else +#include "yaffs_ecc.h" +#endif // countBits is a quick way of counting the number of bits in a byte. // ie. countBits[n] holds the number of 1 bits in a byte with the value n. @@ -117,12 +120,12 @@ static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId); static __inline __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk) { - if(blk < dev->startBlock || blk > dev->endBlock) + if(blk < dev->internalStartBlock || blk > dev->internalEndBlock) { T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),blk)); YBUG(); } - return dev->chunkBits + (dev->chunkBitmapStride * (blk - dev->startBlock)); + return dev->chunkBits + (dev->chunkBitmapStride * (blk - dev->internalStartBlock)); } static __inline__ void yaffs_ClearChunkBits(yaffs_Device *dev,int blk) @@ -167,12 +170,12 @@ static __inline__ int yaffs_StillSomeChunkBits(yaffs_Device *dev,int blk) // Function to manipulate block info static __inline__ yaffs_BlockInfo* yaffs_GetBlockInfo(yaffs_Device *dev, int blk) { - if(blk < dev->startBlock || blk > dev->endBlock) + 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->startBlock]; + return &dev->blockInfo[blk - dev->internalStartBlock]; } @@ -195,14 +198,14 @@ yaffs_Object *yaffs_LostNFound(yaffs_Device *dev) static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare) { - if(chunkInNAND < dev->startBlock * dev->nChunksPerBlock) + if(chunkInNAND < dev->internalStartBlock * dev->nChunksPerBlock) { T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs chunk %d is not valid" TENDSTR),chunkInNAND)); return YAFFS_FAIL; } dev->nPageWrites++; - return dev->writeChunkToNAND(dev,chunkInNAND,data,spare); + return dev->writeChunkToNAND(dev,chunkInNAND - dev->chunkOffset,data,spare); } @@ -216,10 +219,6 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, int retVal; yaffs_Spare localSpare; - __u8 calcEcc[3]; - int eccResult1,eccResult2; - struct yaffs_NANDSpare nspare; - dev->nPageReads++; @@ -235,35 +234,38 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, if(!dev->useNANDECC) { - retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,spare); + retVal = dev->readChunkFromNAND(dev,chunkInNAND - dev->chunkOffset,data,spare); if(data && doErrorCorrection) { // Do ECC correction //Todo handle any errors - nand_calculate_ecc(data,calcEcc); - eccResult1 = nand_correct_data (data,spare->ecc1, calcEcc); - nand_calculate_ecc(&data[256],calcEcc); - eccResult2 = nand_correct_data (&data[256],spare->ecc2, calcEcc); + int eccResult1,eccResult2; + __u8 calcEcc[3]; + + yaffs_ECCCalculate(data,calcEcc); + eccResult1 = yaffs_ECCCorrect (data,spare->ecc1, calcEcc); + yaffs_ECCCalculate(&data[256],calcEcc); + eccResult2 = yaffs_ECCCorrect(&data[256],spare->ecc2, calcEcc); if(eccResult1>0) { - T(YAFFS_TRACE_ERROR, (TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND)); + T(YAFFS_TRACE_ERROR, (TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND - dev->chunkOffset)); dev->eccFixed++; } else if(eccResult1<0) { - T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND)); + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND - dev->chunkOffset)); dev->eccUnfixed++; } if(eccResult2>0) { - T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND)); + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND - dev->chunkOffset)); dev->eccFixed++; } else if(eccResult2<0) { - T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND)); + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND - dev->chunkOffset)); dev->eccUnfixed++; } @@ -276,29 +278,31 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, } else { - retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare*)&nspare); + // Must allocate enough memory for spare+2*sizeof(int) for ecc results from device. + struct yaffs_NANDSpare nspare; + retVal = dev->readChunkFromNAND(dev,chunkInNAND - dev->chunkOffset,data,(yaffs_Spare*)&nspare); memcpy (spare, &nspare, sizeof(yaffs_Spare)); if(data && doErrorCorrection) { if(nspare.eccres1>0) { - T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND)); + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND - dev->chunkOffset)); } else if(nspare.eccres1<0) { - T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND)); + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND - dev->chunkOffset)); } if(nspare.eccres2>0) { - T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND)); + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND - dev->chunkOffset)); } else if(nspare.eccres2<0) { - T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND)); + T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND - dev->chunkOffset)); } - if(nspare.eccres2 || nspare.eccres2) + if(nspare.eccres1 || nspare.eccres2) { // Hoosterman, we had a data problem on this page yaffs_HandleReadDataError(dev,chunkInNAND); @@ -316,12 +320,10 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND static int init = 0; static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK]; static __u8 data[YAFFS_BYTES_PER_CHUNK]; - static __u8 spare[16]; - - - dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare *)spare); - - + // Might as well always allocate the larger size for dev->useNANDECC == true; + static __u8 spare[sizeof(struct yaffs_NANDSpare)]; + + dev->readChunkFromNAND(dev,chunkInNAND - dev->chunkOffset,data,(yaffs_Spare *)spare); if(!init) { @@ -342,7 +344,7 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND) { dev->nBlockErasures++; - return dev->eraseBlockInNAND(dev,blockInNAND); + return dev->eraseBlockInNAND(dev,blockInNAND - dev->blockOffset); } int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev) @@ -583,8 +585,8 @@ void yaffs_SetObjectName(yaffs_Object *obj, const char *name) void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) { - nand_calculate_ecc (data , spare->ecc1); - nand_calculate_ecc (&data[256] , spare->ecc2); + yaffs_ECCCalculate(data , spare->ecc1); + yaffs_ECCCalculate(&data[256] , spare->ecc2); } void yaffs_CalcTagsECC(yaffs_Tags *tags) @@ -780,11 +782,16 @@ static void yaffs_FreeTnode(yaffs_Device*dev, yaffs_Tnode *tn) static void yaffs_DeinitialiseTnodes(yaffs_Device*dev) { // Free the list of allocated tnodes - + yaffs_TnodeList *tmp; + while(dev->allocatedTnodeList) { + tmp = dev->allocatedTnodeList->next; + YFREE(dev->allocatedTnodeList->tnodes); - dev->allocatedTnodeList = dev->allocatedTnodeList->next; + YFREE(dev->allocatedTnodeList); + dev->allocatedTnodeList = tmp; + } dev->freeTnodes = NULL; @@ -1078,7 +1085,7 @@ static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, in if(limit) { *limit = *limit-1; - if(limit <= 0) + if(*limit <= 0) { hitLimit = 1; } @@ -1149,6 +1156,8 @@ static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level { if(tn->level0[i]) { + // Note this does not find the real chunk, only the chunk group. + // We make an assumption that a chunk group is niot larger than a block. theChunk = (tn->level0[i] << in->myDev->chunkGroupBits); T(YAFFS_TRACE_SCAN,(TSTR("soft delete tch %d cgb %d chunk %d" TENDSTR), tn->level0[i],in->myDev->chunkGroupBits,theChunk)); @@ -1402,7 +1411,7 @@ static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev,int number,__u3 obj->unlinkAllowed= 0; // ... or unlink it obj->deleted = 0; obj->unlinked = 0; - obj->st_mode = mode; + obj->yst_mode = mode; obj->myDev = dev; obj->chunkId = 0; // Not a valid chunk. } @@ -1435,6 +1444,16 @@ static void yaffs_FreeObject(yaffs_Object *tn) yaffs_Device *dev = tn->myDev; +#ifdef __KERNEL__ + if(tn->myInode) + { + // We're still hooked up to a cached inode. + // Don't delete now, but mark for later deletion + tn->deferedFree = 1; + return; + } +#endif + yaffs_UnhashObject(tn); // Link into the free list. @@ -1444,16 +1463,33 @@ static void yaffs_FreeObject(yaffs_Object *tn) } +#ifdef __KERNEL__ + +void yaffs_HandleDeferedFree(yaffs_Object *obj) +{ + if(obj->deferedFree) + { + yaffs_FreeObject(obj); + } +} + +#endif + static void yaffs_DeinitialiseObjects(yaffs_Device *dev) { // Free the list of allocated Objects + yaffs_ObjectList *tmp; + while( dev->allocatedObjectList) { + tmp = dev->allocatedObjectList->next; YFREE(dev->allocatedObjectList->objects); - dev->allocatedObjectList = dev->allocatedObjectList->next; + YFREE(dev->allocatedObjectList); + + dev->allocatedObjectList = tmp; } dev->freeObjects = NULL; @@ -1587,6 +1623,11 @@ yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number) in = list_entry(i, yaffs_Object,hashLink); if(in->objectId == number) { +#ifdef __KERNEL__ + // Don't tell the VFS about this if it has been marked for freeing + if(in->deferedFree) + return NULL; +#endif return in; } } @@ -1623,7 +1664,9 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectTyp theObject->win_ctime[1] = theObject->win_mtime[1] = theObject->win_atime[1]; #else - theObject->st_atime = theObject->st_mtime = theObject->st_ctime = CURRENT_TIME; + + theObject->yst_atime = theObject->yst_mtime = theObject->yst_ctime = Y_CURRENT_TIME; + #endif switch(type) { @@ -1719,18 +1762,19 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type, in->valid = 1; in->variantType = type; - in->st_mode = mode; + in->yst_mode = mode; #ifdef CONFIG_YAFFS_WINCE yfsd_WinFileTimeNow(in->win_atime); in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0]; - in->win_ctime[1] = in->win_mtime[1] = in->win_atime[0]; + in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1]; #else - in->st_atime = in->st_mtime = in->st_ctime = CURRENT_TIME; - in->st_rdev = rdev; - in->st_uid = uid; - in->st_gid = gid; + + in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME; + in->yst_rdev = rdev; + in->yst_uid = uid; + in->yst_gid = gid; #endif in->nDataChunks = 0; @@ -1784,7 +1828,7 @@ yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const char *name, __u32 yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid, __u32 rdev) { - return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY,parent,name,mode,uid,gid,NULL,NULL,rdev); + return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL,parent,name,mode,uid,gid,NULL,NULL,rdev); } yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid,const char *alias) @@ -1853,7 +1897,7 @@ int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object * yaffs_Object *obj; int force = 0; -#ifdef YAFFS_CASE_INSENSITIVE +#ifdef CONFIG_YAFFS_CASE_INSENSITIVE // Special case for WinCE. // While look-up is case insensitive, the name isn't. // THerefore we might want to change x.txt to X.txt @@ -2010,11 +2054,11 @@ static int yaffs_FindDirtiestBlock(yaffs_Device *dev,int aggressive) pagesInUse = (aggressive)? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1; if(aggressive) { - iterations = dev->endBlock - dev->startBlock + 1; + iterations = dev->internalEndBlock - dev->internalStartBlock + 1; } else { - iterations = dev->endBlock - dev->startBlock + 1; + iterations = dev->internalEndBlock - dev->internalStartBlock + 1; iterations = iterations / 16; if(iterations > 200) { @@ -2025,12 +2069,12 @@ static int yaffs_FindDirtiestBlock(yaffs_Device *dev,int aggressive) for(i = 0; i <= iterations && pagesInUse > 0 ; i++) { b++; - if ( b < dev->startBlock || b > dev->endBlock) + if ( b < dev->internalStartBlock || b > dev->internalEndBlock) { - b = dev->startBlock; + b = dev->internalStartBlock; } - if(b < dev->startBlock || b > dev->endBlock) + if(b < dev->internalStartBlock || b > dev->internalEndBlock) { T(YAFFS_TRACE_ERROR,(TSTR("**>> Block %d is not valid" TENDSTR),b)); YBUG(); @@ -2107,12 +2151,12 @@ static int yaffs_FindBlockForAllocation(yaffs_Device *dev) // Find an empty block. - for(i = dev->startBlock; i <= dev->endBlock; i++) + for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { dev->allocationBlockFinder++; - if(dev->allocationBlockFinder startBlock || dev->allocationBlockFinder> dev->endBlock) + if(dev->allocationBlockFinder internalStartBlock || dev->allocationBlockFinder> dev->internalEndBlock) { - dev->allocationBlockFinder = dev->startBlock; + dev->allocationBlockFinder = dev->internalStartBlock; } bi = yaffs_GetBlockInfo(dev,dev->allocationBlockFinder); @@ -2279,6 +2323,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block) { // It's a header object->chunkId = newChunk; + object->serial = tags.serialNumber; } else { @@ -2820,6 +2865,7 @@ int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffe } else { + memset(buffer,0,YAFFS_BYTES_PER_CHUNK); return 0; } @@ -2842,7 +2888,14 @@ static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND) if(markNAND) { yaffs_SpareInitialise(&spare); - + +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + + //read data before write, to ensure correct ecc + //if we're using MTD verification under Linux + yaffs_ReadChunkFromNAND(dev,chunkId,NULL,&spare,0); +#endif + spare.pageStatus = 0; // To mark it as deleted. @@ -2971,7 +3024,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force) // Header data oh->type = in->variantType; - oh->st_mode = in->st_mode; + oh->yst_mode = in->yst_mode; #ifdef CONFIG_YAFFS_WINCE oh->win_atime[0] = in->win_atime[0]; @@ -2981,12 +3034,12 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force) oh->win_ctime[1] = in->win_ctime[1]; oh->win_mtime[1] = in->win_mtime[1]; #else - oh->st_uid = in->st_uid; - oh->st_gid = in->st_gid; - oh->st_atime = in->st_atime; - oh->st_mtime = in->st_mtime; - oh->st_ctime = in->st_ctime; - oh->st_rdev = in->st_rdev; + oh->yst_uid = in->yst_uid; + oh->yst_gid = in->yst_gid; + oh->yst_atime = in->yst_atime; + oh->yst_mtime = in->yst_mtime; + oh->yst_ctime = in->yst_ctime; + oh->yst_rdev = in->yst_rdev; #endif if(in->parent) { @@ -3088,7 +3141,7 @@ static void yaffs_FlushFilesChunkCache(yaffs_Object *obj) int lowest; int i; yaffs_ChunkCache *cache; - int chunkWritten; + int chunkWritten = 0; int nBytes; int nCaches = obj->myDev->nShortOpCaches; @@ -3129,6 +3182,7 @@ static void yaffs_FlushFilesChunkCache(yaffs_Object *obj) cache->nBytes,1); cache->dirty = 0; + cache->object = NULL; } } while(cache && chunkWritten > 0); @@ -3161,10 +3215,14 @@ static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev) if(!dev->srCache[i].object) { //T(("Grabbing empty %d\n",i)); + + //printf("Grabbing empty %d\n",i); return &dev->srCache[i]; } } + + return NULL; theOne = -1; usage = 0; // just to stop the compiler grizzling @@ -3181,6 +3239,9 @@ static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev) } //T(("Grabbing non-empty %d\n",theOne)); + + //if(theOne >= 0) printf("Grabbed non-empty cache %d\n",theOne); + return theOne >= 0 ? &dev->srCache[theOne] : NULL; } else @@ -3197,6 +3258,7 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev) yaffs_Object *theObj; int usage; int i; + int pushout; if(dev->nShortOpCaches > 0) { @@ -3213,6 +3275,8 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev) theObj = dev->srCache[0].object; usage = dev->srCache[0].lastUse; + cache = &dev->srCache[0]; + pushout = 0; for(i = 1; i < dev->nShortOpCaches; i++) { @@ -3221,15 +3285,27 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev) { usage = dev->srCache[i].lastUse; theObj = dev->srCache[i].object; + cache = &dev->srCache[i]; + pushout = i; } } - yaffs_FlushFilesChunkCache(theObj); + if(!cache || cache->dirty) + { + + //printf("Dirty "); + yaffs_FlushFilesChunkCache(theObj); - // Try again - cache = yaffs_GrabChunkCacheWorker(dev); + // Try again + cache = yaffs_GrabChunkCacheWorker(dev); + } + else + { + //printf(" pushout %d\n",pushout); + } + } - + return cache; } else @@ -3347,6 +3423,7 @@ int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nB int nToCopy; int n = nBytes; int nDone = 0; + yaffs_ChunkCache *cache; yaffs_Device *dev; @@ -3368,14 +3445,18 @@ int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nB nToCopy = YAFFS_BYTES_PER_CHUNK - start; } - if(nToCopy != YAFFS_BYTES_PER_CHUNK) + 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) + // else bypass the cache. + if( cache || nToCopy != YAFFS_BYTES_PER_CHUNK) { - // An incomplete start or end chunk (or maybe both start and end chunk) if(dev->nShortOpCaches > 0) { - yaffs_ChunkCache *cache; + // If we can't find the data in the cache, then load it up. - cache = yaffs_FindChunkCache(in,chunk); + if(!cache) { cache = yaffs_GrabChunkCache(in->myDev); @@ -3593,7 +3674,8 @@ int yaffs_ResizeFile(yaffs_Object *in, int newSize) // using yaffs_DeleteChunk chunkId = yaffs_FindAndDeleteChunkInFile(in,i,NULL); - if(chunkId <= 0 || chunkId >= (dev->endBlock * 32)) + if(chunkId < (dev->internalStartBlock * dev->nChunksPerBlock) || + chunkId >= ((dev->internalEndBlock+1) * dev->nChunksPerBlock)) { //T(("Found daft chunkId %d for %d\n",chunkId,i)); } @@ -3610,8 +3692,10 @@ int yaffs_ResizeFile(yaffs_Object *in, int newSize) int lastChunk = 1+ newSize/YAFFS_BYTES_PER_CHUNK; // Got to read and rewrite the last chunk with its new size. + // NB Got to zero pad to nuke old data yaffs_ReadChunkDataFromObject(in,lastChunk,dev->localBuffer); - + memset(dev->localBuffer + sizeOfPartialChunk,0, YAFFS_BYTES_PER_CHUNK - sizeOfPartialChunk); + yaffs_WriteChunkDataToObject(in,lastChunk,dev->localBuffer,sizeOfPartialChunk,1); } @@ -3663,7 +3747,7 @@ int yaffs_FlushFile(yaffs_Object *in, int updateTime) #ifdef CONFIG_YAFFS_WINCE yfsd_WinFileTimeNow(in->win_mtime); #else - in->st_mtime = CURRENT_TIME; + in->yst_mtime = Y_CURRENT_TIME; #endif } @@ -3687,12 +3771,15 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object *in) yaffs_RemoveObjectFromDirectory(in); yaffs_DeleteChunk(in->myDev,in->chunkId,1); + in->chunkId = -1; +#if 0 #ifdef __KERNEL__ if(in->myInode) { in->myInode->u.generic_ip = NULL; - in->myInode = 0; + in->myInode = NULL; } +#endif #endif yaffs_FreeObject(in); return YAFFS_OK; @@ -3730,6 +3817,8 @@ static int yaffs_UnlinkFile(yaffs_Object *in) #ifdef __KERNEL__ if(!in->myInode) { + // Might be open at present, + // Caught by delete_inode in yaffs_fs.c immediateDeletion = 1; } @@ -3887,6 +3976,9 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj) case YAFFS_OBJECT_TYPE_SYMLINK: return yaffs_DeleteSymLink(obj); break; + case YAFFS_OBJECT_TYPE_SPECIAL: + return yaffs_DoGenericObjectDeletion(obj); + break; case YAFFS_OBJECT_TYPE_HARDLINK: case YAFFS_OBJECT_TYPE_UNKNOWN: default: @@ -3977,7 +4069,7 @@ static int yaffs_Scan(yaffs_Device *dev) // Scan all the blocks... - for(blk = dev->startBlock; blk <= dev->endBlock; blk++) + for(blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) { deleted = 0; bi = yaffs_GetBlockInfo(dev,blk); @@ -4101,7 +4193,7 @@ static int yaffs_Scan(yaffs_Device *dev) in->valid = 1; in->variantType = oh->type; - in->st_mode = oh->st_mode; + in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE in->win_atime[0] = oh->win_atime[0]; in->win_ctime[0] = oh->win_ctime[0]; @@ -4110,12 +4202,12 @@ static int yaffs_Scan(yaffs_Device *dev) in->win_ctime[1] = oh->win_ctime[1]; in->win_mtime[1] = oh->win_mtime[1]; #else - in->st_uid = oh->st_uid; - in->st_gid = oh->st_gid; - in->st_atime = oh->st_atime; - in->st_mtime = oh->st_mtime; - in->st_ctime = oh->st_ctime; - in->st_rdev = oh->st_rdev; + in->yst_uid = oh->yst_uid; + in->yst_gid = oh->yst_gid; + in->yst_atime = oh->yst_atime; + in->yst_mtime = oh->yst_mtime; + in->yst_ctime = oh->yst_ctime; + in->yst_rdev = oh->yst_rdev; #endif in->chunkId = chunk; @@ -4127,7 +4219,7 @@ static int yaffs_Scan(yaffs_Device *dev) in->valid = 1; in->variantType = oh->type; - in->st_mode = oh->st_mode; + in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE in->win_atime[0] = oh->win_atime[0]; in->win_ctime[0] = oh->win_ctime[0]; @@ -4136,12 +4228,12 @@ static int yaffs_Scan(yaffs_Device *dev) in->win_ctime[1] = oh->win_ctime[1]; in->win_mtime[1] = oh->win_mtime[1]; #else - in->st_uid = oh->st_uid; - in->st_gid = oh->st_gid; - in->st_atime = oh->st_atime; - in->st_mtime = oh->st_mtime; - in->st_ctime = oh->st_ctime; - in->st_rdev = oh->st_rdev; + in->yst_uid = oh->yst_uid; + in->yst_gid = oh->yst_gid; + in->yst_atime = oh->yst_atime; + in->yst_mtime = oh->yst_mtime; + in->yst_ctime = oh->yst_ctime; + in->yst_rdev = oh->yst_rdev; #endif in->chunkId = chunk; @@ -4162,8 +4254,9 @@ static int yaffs_Scan(yaffs_Device *dev) { // Hoosterman, another problem.... // We're trying to use a non-directory as a directory - // Todo ... handle - T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: attempting to use non-directory as a directory in scan" TENDSTR))); + + T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR))); + parent = dev->lostNFoundDir; } @@ -4485,10 +4578,10 @@ unsigned yaffs_GetObjectType(yaffs_Object *obj) case YAFFS_OBJECT_TYPE_SYMLINK: return DT_LNK; break; case YAFFS_OBJECT_TYPE_HARDLINK: return DT_REG; break; case YAFFS_OBJECT_TYPE_SPECIAL: - if(S_ISFIFO(obj->st_mode)) return DT_FIFO; - if(S_ISCHR(obj->st_mode)) return DT_CHR; - if(S_ISBLK(obj->st_mode)) return DT_BLK; - if(S_ISSOCK(obj->st_mode)) return DT_SOCK; + if(S_ISFIFO(obj->yst_mode)) return DT_FIFO; + if(S_ISCHR(obj->yst_mode)) return DT_CHR; + if(S_ISBLK(obj->yst_mode)) return DT_BLK; + if(S_ISSOCK(obj->yst_mode)) return DT_SOCK; default: return DT_REG; break; } } @@ -4512,13 +4605,14 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr) { unsigned int valid = attr->ia_valid; - if(valid & ATTR_MODE) obj->st_mode = attr->ia_mode; - if(valid & ATTR_UID) obj->st_uid = attr->ia_uid; - if(valid & ATTR_GID) obj->st_gid = attr->ia_gid; + if(valid & ATTR_MODE) obj->yst_mode = attr->ia_mode; + if(valid & ATTR_UID) obj->yst_uid = attr->ia_uid; + if(valid & ATTR_GID) obj->yst_gid = attr->ia_gid; - if(valid & ATTR_ATIME) obj->st_atime = attr->ia_atime; - if(valid & ATTR_CTIME) obj->st_ctime = attr->ia_ctime; - if(valid & ATTR_MTIME) obj->st_mtime = attr->ia_mtime; + if(valid & ATTR_ATIME) obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime); + if(valid & ATTR_CTIME) obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime); + if(valid & ATTR_MTIME) obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime); + if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size); @@ -4527,18 +4621,20 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr) return YAFFS_OK; } + int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr) { unsigned int valid = 0; - attr->ia_mode = obj->st_mode; valid |= ATTR_MODE; - attr->ia_uid = obj->st_uid; valid |= ATTR_UID; - attr->ia_gid = obj->st_gid; valid |= ATTR_GID; + attr->ia_mode = obj->yst_mode; valid |= ATTR_MODE; + attr->ia_uid = obj->yst_uid; valid |= ATTR_UID; + attr->ia_gid = obj->yst_gid; valid |= ATTR_GID; - attr->ia_atime = obj->st_atime; valid |= ATTR_ATIME; - attr->ia_ctime = obj->st_ctime; valid |= ATTR_CTIME; - attr->ia_mtime = obj->st_mtime; valid |= ATTR_MTIME; + Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime; valid |= ATTR_ATIME; + Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime; valid |= ATTR_CTIME; + Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime; valid |= ATTR_MTIME; + attr->ia_size = yaffs_GetFileSize(obj); valid |= ATTR_SIZE; attr->ia_valid = valid; @@ -4602,17 +4698,16 @@ int yaffs_GutsInitialise(yaffs_Device *dev) int extraBits; int nBlocks; - if( dev->nBytesPerChunk != YAFFS_BYTES_PER_CHUNK || - + if( dev->nBytesPerChunk != YAFFS_BYTES_PER_CHUNK || dev->nChunksPerBlock < 2 || dev->nReservedBlocks < 2 || - dev->startBlock <= 0 || + dev->startBlock < 0 || dev->endBlock <= 0 || dev->endBlock <= (dev->startBlock + dev->nReservedBlocks) ) { //these parameters must be set before stating yaffs - // Other parameters startBlock, + // Other parameters internalStartBlock, return YAFFS_FAIL; } @@ -4631,8 +4726,8 @@ int yaffs_GutsInitialise(yaffs_Device *dev) } dev->isMounted = 1; - - if(dev->startBlock <= 0 || + + if(dev->startBlock < 0 || (dev->endBlock - dev->startBlock) < 10) { T(YAFFS_TRACE_ALWAYS,(TSTR("startBlock %d or endBlock %d invalid\n" TENDSTR), @@ -4640,15 +4735,32 @@ int yaffs_GutsInitialise(yaffs_Device *dev) return YAFFS_FAIL; } - nBlocks = dev->endBlock - dev->startBlock + 1; + + // Do we need to add an offset to use block 0? + + dev->internalStartBlock = dev->startBlock; + dev->internalEndBlock = dev->endBlock; + dev->blockOffset = 0; + dev->chunkOffset = 0; + + if(dev->startBlock == 0) + { + dev->internalStartBlock++; + dev->internalEndBlock++; + dev->blockOffset++; + dev->chunkOffset = dev->nChunksPerBlock; + } + + + nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; // OK now calculate a few things for the device // Calculate chunkGroupBits. - // We need to find the next power of 2 > than endBlock + // We need to find the next power of 2 > than internalEndBlock - x = dev->nChunksPerBlock * (dev->endBlock+1); + x = dev->nChunksPerBlock * (dev->internalEndBlock+1); for(bits = extraBits = 0; x > 1; bits++) { @@ -4670,7 +4782,18 @@ int yaffs_GutsInitialise(yaffs_Device *dev) { dev->chunkGroupBits = bits - 16; } + dev->chunkGroupSize = 1 << dev->chunkGroupBits; + + if(dev->nChunksPerBlock < dev->chunkGroupSize) + { + // We have a problem because the soft delete won't work if + // the chunk group size > chunks per block. + // This can be remedied by using larger "virtual blocks". + + return YAFFS_FAIL; + } + @@ -4687,6 +4810,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev) dev->eccUnfixed=0; dev->tagsEccFixed=0; dev->tagsEccUnfixed=0; + dev->nErasedBlocks=0; dev->localBuffer = YMALLOC(dev->nBytesPerChunk); @@ -4756,7 +4880,10 @@ void yaffs_Deinitialise(yaffs_Device *dev) yaffs_DeinitialiseBlocks(dev); yaffs_DeinitialiseTnodes(dev); yaffs_DeinitialiseObjects(dev); + if(dev->nShortOpCaches > 0) + YFREE(dev->srCache); YFREE(dev->localBuffer); + dev->isMounted = 0; } } @@ -4783,7 +4910,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) } - printf("___________ nFreeChunks is %d nFree is %d\n",dev->nFreeChunks,nFree); + // printf("___________ nFreeChunks is %d nFree is %d\n",dev->nFreeChunks,nFree); if(nFree < 0) nFree = 0; @@ -4798,13 +4925,14 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) int nFree; int pending; int b; + int nDirtyCacheChunks=0; yaffs_BlockInfo *blk; struct list_head *i; yaffs_Object *l; - for(nFree = 0, b = dev->startBlock; b <= dev->endBlock; b++) + for(nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock; b++) { blk = yaffs_GetBlockInfo(dev,b); @@ -4845,6 +4973,20 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) nFree += pending; + // Now count the number of dirty chunks in the cache and subtract those + + { + int i; + for(i = 0; i < dev->nShortOpCaches; i++) + { + if(dev->srCache[i].dirty) nDirtyCacheChunks++; + } + } + + nFree -= nDirtyCacheChunks; + + nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock); + if(nFree < 0) nFree = 0; return nFree; @@ -4894,3 +5036,7 @@ void yaffs_GutsTest(yaffs_Device *dev) + + + +