X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=yaffs_guts.c;h=fa1c9d59d1645a4c7953827ea7105750da19a155;hb=daffb0c61b90abbfc5fd8c335c5b79b0feeff2ab;hp=caf9289d0e6f99671d965211e1b87700965be058;hpb=aa39fbf7616e8b26833a09cb64c6a40859494599;p=yaffs%2F.git diff --git a/yaffs_guts.c b/yaffs_guts.c index caf9289..fa1c9d5 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -29,7 +29,7 @@ int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); // 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. -static const char yaffs_countBits[256] = +static const char yaffs_countBitsTable[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, @@ -49,6 +49,13 @@ static const char yaffs_countBits[256] = 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; +static int yaffs_CountBits(__u8 x) +{ + int retVal; + retVal = yaffs_countBitsTable[x]; + return retVal; +} + // Device info @@ -66,11 +73,27 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkIn static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type); static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj); -static int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name); +static int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force); static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId); static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj); static int yaffs_CheckStructures(void); +// Robustification +static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND); +static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND); +static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND); +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare); +static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_Spare *spare); + +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND); + +static int yaffs_UnlinkWorker(yaffs_Object *obj); + + +static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1); + + + loff_t yaffs_GetFileSize(yaffs_Object *obj); static int yaffs_ReadChunkTagsFromNAND(yaffs_Device *dev,int chunkInNAND, yaffs_Tags *tags, int *chunkDeleted); @@ -108,7 +131,8 @@ static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND return dev->writeChunkToNAND(dev,chunkInNAND,data,spare); } -int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare) + +int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare,int doErrorCorrection) { int retVal; __u8 calcEcc[3]; @@ -125,7 +149,7 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 } retVal = dev->readChunkFromNAND(dev,chunkInNAND,data,spare); - if(data) + if(data && doErrorCorrection) { // Do ECC correction //Todo handle any errors @@ -151,22 +175,25 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 { T((TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND)); } + + if(eccResult1 || eccResult2) + { + // Hoosterman, we had a data problem on this page + yaffs_HandleReadDataError(dev,chunkInNAND); + } } return retVal; } -#ifdef YAFFS_PARANOID 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]; - int retVal; - - retVal = YAFFS_OK; dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare *)spare); @@ -178,14 +205,14 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND init = 1; } - if(memcmp(cmpbuf,data,YAFFS_BYTES_PER_CHUNK)) retVal = YAFFS_FAIL; - if(memcmp(cmpbuf,spare,16)) retVal = YAFFS_FAIL; + if(memcmp(cmpbuf,data,YAFFS_BYTES_PER_CHUNK)) return YAFFS_FAIL; + if(memcmp(cmpbuf,spare,16)) return YAFFS_FAIL; + - return retVal; + return YAFFS_OK; } -#endif int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND) @@ -203,7 +230,7 @@ static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8 { int chunk; - int writeOk = 0; + int writeOk = 1; int attempts = 0; unsigned char rbData[YAFFS_BYTES_PER_CHUNK]; @@ -214,7 +241,19 @@ static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8 if(chunk >= 0) { - writeOk = yaffs_WriteChunkToNAND(dev,chunk,data,spare); + + // First check this chunk is erased... +#ifndef CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK + writeOk = yaffs_CheckChunkErased(dev,chunk); +#endif + if(!writeOk) + { + T((TSTR("**>> yaffs chunk %d was not erased" TENDSTR),chunk)); + } + else + { + writeOk = yaffs_WriteChunkToNAND(dev,chunk,data,spare); + } attempts++; if(writeOk) { @@ -222,33 +261,33 @@ static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8 // If verify fails, then delete this chunk and try again // To verify we compare everything except the block and // page status bytes. - yaffs_ReadChunkFromNAND(dev,chunk,rbData,&rbSpare); + // NB We check a raw read without ECC correction applied + yaffs_ReadChunkFromNAND(dev,chunk,rbData,&rbSpare,0); - if(memcmp(data,rbData,YAFFS_BYTES_PER_CHUNK) != 0 || - spare->tagByte0 != rbSpare.tagByte0 || - spare->tagByte1 != rbSpare.tagByte1 || - spare->tagByte2 != rbSpare.tagByte2 || - spare->tagByte3 != rbSpare.tagByte3 || - spare->tagByte4 != rbSpare.tagByte4 || - spare->tagByte5 != rbSpare.tagByte5 || - spare->tagByte6 != rbSpare.tagByte6 || - spare->tagByte7 != rbSpare.tagByte7 || - spare->ecc1[0] != rbSpare.ecc1[0] || - spare->ecc1[1] != rbSpare.ecc1[1] || - spare->ecc1[2] != rbSpare.ecc1[2] || - spare->ecc2[0] != rbSpare.ecc2[0] || - spare->ecc2[1] != rbSpare.ecc2[1] || - spare->ecc2[2] != rbSpare.ecc2[2] ) - { +#ifndef CONFIG_YAFFS_DISABLE_WRITE_VERIFY + if(!yaffs_VerifyCompare(data,rbData,spare,&rbSpare)) + { // Didn't verify - yaffs_DeleteChunk(dev,chunk); - T((TSTR("**>> yaffs write failed on chunk %d" TENDSTR), chunk)); + T((TSTR("**>> yaffs write verify failed on chunk %d" TENDSTR), chunk)); writeOk = 0; - } + } +#endif } + if(writeOk) + { + // Copy the data into the write buffer. + // NB We do this at the end to prevent duplicates in the case of a write error. + //Todo + yaffs_HandleWriteChunkOk(dev,chunk,data,spare); + } + else + { + yaffs_HandleWriteChunkError(dev,chunk); + } } + } while(chunk >= 0 && ! writeOk); if(attempts > 1) @@ -260,7 +299,107 @@ static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8 return chunk; } +/// +// Functions for robustisizing +// +// + +static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND) +{ + // Ding the blockStatus in the first two pages of the block. + + yaffs_Spare spare; + memset(&spare, 0xff,sizeof(yaffs_Spare)); + + spare.blockStatus = 0; + + yaffs_WriteChunkToNAND(dev, blockInNAND * YAFFS_CHUNKS_PER_BLOCK, NULL , &spare); + yaffs_WriteChunkToNAND(dev, blockInNAND * YAFFS_CHUNKS_PER_BLOCK + 1, NULL , &spare); + + dev->blockInfo[blockInNAND].blockState = YAFFS_BLOCK_STATE_DEAD; + dev->nRetiredBlocks++; +} + + + +static int yaffs_RewriteBufferedBlock(yaffs_Device *dev) +{ + dev->doingBufferedBlockRewrite = 1; + // + // Remove erased chunks + // Rewrite existing chunks to a new block + // Set current write block to the new block + + dev->doingBufferedBlockRewrite = 0; + + return 1; +} + + +static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND) +{ + int blockInNAND = chunkInNAND/YAFFS_CHUNKS_PER_BLOCK; + + // Mark the block for retirement + dev->blockInfo[blockInNAND].needsRetiring = 1; + + //TODO + // Just do a garbage collection on the affected block then retire the block + // NB recursion +} + + +static void yaffs_CheckWrittenBlock(yaffs_Device *dev,int chunkInNAND) +{ +} + +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare) +{ +} + +static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_Spare *spare) +{ +} + +static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND) +{ + int blockInNAND = chunkInNAND/YAFFS_CHUNKS_PER_BLOCK; + + // Mark the block for retirement + dev->blockInfo[blockInNAND].needsRetiring = 1; + // Delete the chunk + yaffs_DeleteChunk(dev,chunkInNAND); +} + + + + +static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1) +{ + + + if( memcmp(d0,d1,YAFFS_BYTES_PER_CHUNK) != 0 || + s0->tagByte0 != s1->tagByte0 || + s0->tagByte1 != s1->tagByte1 || + s0->tagByte2 != s1->tagByte2 || + s0->tagByte3 != s1->tagByte3 || + s0->tagByte4 != s1->tagByte4 || + s0->tagByte5 != s1->tagByte5 || + s0->tagByte6 != s1->tagByte6 || + s0->tagByte7 != s1->tagByte7 || + s0->ecc1[0] != s1->ecc1[0] || + s0->ecc1[1] != s1->ecc1[1] || + s0->ecc1[2] != s1->ecc1[2] || + s0->ecc2[0] != s1->ecc2[0] || + s0->ecc2[1] != s1->ecc2[1] || + s0->ecc2[2] != s1->ecc2[2] ) + { + return 0; + } + + return 1; +} ///////////////////////// Object management ////////////////// @@ -1291,7 +1430,12 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type, break; } - yaffs_UpdateObjectHeader(in,name); + if(yaffs_UpdateObjectHeader(in,name,0) < 0) + { + // Could not create the object header, fail the creation + yaffs_UnlinkWorker(in); + in = NULL; + } } @@ -1354,7 +1498,7 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const obj->dirty = 1; yaffs_AddObjectToDirectory(newDir,obj); - if(yaffs_UpdateObjectHeader(obj,newName) >= 0) + if(yaffs_UpdateObjectHeader(obj,newName,0) >= 0) { return YAFFS_OK; } @@ -1468,6 +1612,7 @@ void yaffs_ObjectTest(yaffs_Device *dev) static void yaffs_InitialiseBlocks(yaffs_Device *dev) { + //Todo we're assuming the malloc will pass. dev->blockInfo = YMALLOC(dev->nBlocks * sizeof(yaffs_BlockInfo)); memset(dev->blockInfo,0,dev->nBlocks * sizeof(yaffs_BlockInfo)); dev->allocationBlock = -1; // force it to get a new one @@ -1512,21 +1657,52 @@ static int yaffs_FindDirtiestBlock(yaffs_Device *dev) } -static int yaffs_FindBlockForAllocation(yaffs_Device *dev,int useReserve) +static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo) +{ + yaffs_BlockInfo *bi = &dev->blockInfo[blockNo]; + + int erasedOk = 0; + + // If the block is still healthy erase it and mark as clean. + // If the block has had a data failure, then retire it. + bi->blockState = YAFFS_BLOCK_STATE_DIRTY; + + if(!bi->needsRetiring) + { + erasedOk = yaffs_EraseBlockInNAND(dev,blockNo); + if(!erasedOk) + { + T((TSTR("**>> Erasure failed %d" TENDSTR),blockNo)); + } + } + + if( erasedOk ) + { + bi->blockState = YAFFS_BLOCK_STATE_EMPTY; + dev->nErasedBlocks++; + bi->pagesInUse = 0; + bi->pageBits = 0; + + T((TSTR("Erased block %d" TENDSTR),blockNo)); + } + else + { + yaffs_RetireBlock(dev,blockNo); + T((TSTR("**>> Block %d retired" TENDSTR),blockNo)); + } +} + + +static int yaffs_FindBlockForAllocation(yaffs_Device *dev) { int i; - if(useReserve && dev->nErasedBlocks < 1) + if(dev->nErasedBlocks < 1) { // Hoosterman we've got a problem. // Can't get space to gc return -1; } - else if(!useReserve && dev->nErasedBlocks <= YAFFS_RESERVED_BLOCKS) - { - // We are not in GC, so we hold some in reserve so we can get - // a gc done. - } // Find an empty block. @@ -1550,21 +1726,6 @@ static int yaffs_FindBlockForAllocation(yaffs_Device *dev,int useReserve) } -static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo) -{ - yaffs_BlockInfo *bi = &dev->blockInfo[blockNo]; - - // Mark as dirty, erase it and mark as clean. - bi->blockState = YAFFS_BLOCK_STATE_DIRTY; - yaffs_EraseBlockInNAND(dev,blockNo); - bi->blockState = YAFFS_BLOCK_STATE_EMPTY; - dev->nErasedBlocks++; - bi->pagesInUse = 0; - bi->pageBits = 0; - - T((TSTR("Erased block %d" TENDSTR),blockNo)); -} - static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve) { @@ -1573,10 +1734,16 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve) if(dev->allocationBlock < 0) { // Get next block to allocate off - dev->allocationBlock = yaffs_FindBlockForAllocation(dev,useReserve); + dev->allocationBlock = yaffs_FindBlockForAllocation(dev); dev->allocationPage = 0; } + if(!useReserve && dev->nErasedBlocks <= YAFFS_RESERVED_BLOCKS) + { + // Not enough space to allocate unless we're allowed to use the reserve. + return -1; + } + // Next page please.... if(dev->allocationBlock >= 0) { @@ -1597,12 +1764,7 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve) dev->allocationBlock = -1; } -#ifdef YAFFS_PARANOID - if(yaffs_CheckChunkErased(dev,retVal) == YAFFS_FAIL) - { - T((TSTR("..................Trying to allocate non-erased page %d" TENDSTR),retVal)); - } -#endif + return retVal; } @@ -1642,7 +1804,7 @@ int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block) //T(("copying page %x from %d to %d\n",mask,oldChunk,newChunk)); - yaffs_ReadChunkFromNAND(dev,oldChunk,buffer, &spare); + yaffs_ReadChunkFromNAND(dev,oldChunk,buffer, &spare,1); yaffs_GetTagsFromSpare(&spare,&tags); tags.serialNumber++; @@ -1696,7 +1858,15 @@ int yaffs_CheckGarbageCollection(yaffs_Device *dev) if(dev->garbageCollectionRequired) { dev->garbageCollectionRequired = 0; - block = yaffs_FindDirtiestBlock(dev); + if(dev->blockSelectedForGC >= 0) + { + block = dev->blockSelectedForGC; + } + else + { + block = yaffs_FindDirtiestBlock(dev); + } + if(block >= 0) { return yaffs_GarbageCollectBlock(dev,block); @@ -1755,9 +1925,9 @@ static int yaffs_ReadChunkTagsFromNAND(yaffs_Device *dev,int chunkInNAND, yaffs_ if(tags) { yaffs_Spare spare; - if(yaffs_ReadChunkFromNAND(dev,chunkInNAND,NULL,&spare) == YAFFS_OK) + if(yaffs_ReadChunkFromNAND(dev,chunkInNAND,NULL,&spare,1) == YAFFS_OK) { - *chunkDeleted = (yaffs_countBits[spare.pageStatus] < 7) ? 1 : 0; + *chunkDeleted = (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0; yaffs_GetTagsFromSpare(&spare,tags); return YAFFS_OK; } @@ -2089,7 +2259,7 @@ int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffe if(chunkInNAND >= 0) { - return yaffs_ReadChunkFromNAND(in->myDev,chunkInNAND,buffer,NULL); + return yaffs_ReadChunkFromNAND(in->myDev,chunkInNAND,buffer,NULL,1); } else { @@ -2101,16 +2271,21 @@ int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffe static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId) { - int block = chunkId / YAFFS_CHUNKS_PER_BLOCK; - int page = chunkId % YAFFS_CHUNKS_PER_BLOCK; + int block; + int page; yaffs_Spare spare; + + if(chunkId <= 0) return; + block = chunkId / YAFFS_CHUNKS_PER_BLOCK; + page = chunkId % YAFFS_CHUNKS_PER_BLOCK; yaffs_SpareInitialise(&spare); spare.pageStatus = 0; // To mark it as deleted. yaffs_WriteChunkToNAND(dev,chunkId,NULL,&spare); + yaffs_HandleUpdateChunk(dev,chunkId,&spare); // Pull out of the management area. @@ -2224,7 +2399,7 @@ int yaffs_WriteChunkDataToObject(yaffs_Object *in,int chunkInInode, const __u8 * // UpdateObjectHeader updates the header on NAND for an object. // If name is not NULL, then that new name is used. // -int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name) +int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force) { yaffs_Device *dev = in->myDev; @@ -2239,7 +2414,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name) yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bufferNew; yaffs_ObjectHeader *ohOld = (yaffs_ObjectHeader *)bufferOld; - if(!in->fake) + if(!in->fake || force) { yaffs_CheckGarbageCollection(dev); @@ -2250,7 +2425,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name) if(prevChunkId >= 0) { - yaffs_ReadChunkFromNAND(dev,prevChunkId,bufferOld,NULL); + yaffs_ReadChunkFromNAND(dev,prevChunkId,bufferOld,NULL,1); } // Header data @@ -2264,17 +2439,29 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name) oh->st_ctime = in->st_ctime; oh->st_rdev = in->st_rdev; - oh->parentObjectId = in->parent->objectId; + if(in->parent) + { + oh->parentObjectId = in->parent->objectId; + } + else + { + oh->parentObjectId = 0; + } + oh->sum = in->sum; if(name && *name) { memset(oh->name,0,YAFFS_MAX_NAME_LENGTH + 1); strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH); } - else + else if(prevChunkId) { memcpy(oh->name, ohOld->name,YAFFS_MAX_NAME_LENGTH + 1); } + else + { + memset(oh->name,0,YAFFS_MAX_NAME_LENGTH + 1); + } switch(in->variantType) { @@ -2597,7 +2784,7 @@ int yaffs_FlushFile(yaffs_Object *in) in->st_mtime = CURRENT_TIME; - retVal = yaffs_UpdateObjectHeader(in,NULL); + retVal = yaffs_UpdateObjectHeader(in,NULL,0); } else { @@ -2747,7 +2934,7 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj) yaffs_HashObject(hl); // Update the hardlink which has become an object - yaffs_UpdateObjectHeader(hl,NULL); + yaffs_UpdateObjectHeader(hl,NULL,0); // Finally throw away the deleted object yaffs_DeleteChunk(obj->myDev,obj->chunkId); @@ -2842,16 +3029,31 @@ static int yaffs_IsBlockBad(yaffs_Device *dev, int blk) { yaffs_Spare spare; - yaffs_ReadChunkFromNAND(dev,blk * YAFFS_CHUNKS_PER_BLOCK,NULL,&spare); + yaffs_ReadChunkFromNAND(dev,blk * YAFFS_CHUNKS_PER_BLOCK,NULL,&spare,1); +#if 1 + if(yaffs_CountBits(spare.blockStatus) < 7) + { + return 1; + } +#else if(spare.blockStatus != 0xFF) { return 1; } - yaffs_ReadChunkFromNAND(dev,blk * YAFFS_CHUNKS_PER_BLOCK + 1,NULL,&spare); +#endif + yaffs_ReadChunkFromNAND(dev,blk * YAFFS_CHUNKS_PER_BLOCK + 1,NULL,&spare,1); + +#if 1 + if(yaffs_CountBits(spare.blockStatus) < 7) + { + return 1; + } +#else if(spare.blockStatus != 0xFF) { return 1; } +#endif return 0; @@ -2902,13 +3104,13 @@ static int yaffs_Scan(yaffs_Device *dev) // Read the spare area and decide what to do chunk = blk * YAFFS_CHUNKS_PER_BLOCK + c; - yaffs_ReadChunkFromNAND(dev,chunk,NULL,&spare); + yaffs_ReadChunkFromNAND(dev,chunk,NULL,&spare,1); // This block looks ok, now what's in this chunk? yaffs_GetTagsFromSpare(&spare,&tags); - if(yaffs_countBits[spare.pageStatus] < 6) + if(yaffs_CountBits(spare.pageStatus) < 6) { // A deleted chunk deleted++; @@ -2953,6 +3155,11 @@ static int yaffs_Scan(yaffs_Device *dev) if(in->variant.fileVariant.scannedFileSize variant.fileVariant.scannedFileSize = endpos; +#ifndef CONFIG_YAFFS_USE_HEADER_FILE_SIZE + in->variant.fileVariant.fileSize = + in->variant.fileVariant.scannedFileSize; +#endif + } //T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); } @@ -2963,7 +3170,7 @@ static int yaffs_Scan(yaffs_Device *dev) dev->blockInfo[blk].pageBits |= (1 << c); dev->blockInfo[blk].pagesInUse++; - yaffs_ReadChunkFromNAND(dev,chunk,chunkData,NULL); + yaffs_ReadChunkFromNAND(dev,chunk,chunkData,NULL,1); oh = (yaffs_ObjectHeader *)chunkData; @@ -2989,7 +3196,25 @@ static int yaffs_Scan(yaffs_Device *dev) } } - if(!in->valid) + if(!in->valid && + (tags.objectId == YAFFS_OBJECTID_ROOT || + tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) + { + // We only load some info, don't fiddle with directory structure + in->valid = 1; + in->variantType = oh->type; + + in->st_mode = oh->st_mode; + 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->chunkId = chunk; + + } + else if(!in->valid) { // we need to load this info @@ -3038,7 +3263,9 @@ static int yaffs_Scan(yaffs_Device *dev) case YAFFS_OBJECT_TYPE_UNKNOWN: // Todo got a problem break; case YAFFS_OBJECT_TYPE_FILE: +#ifdef CONFIG_YAFFS_USE_HEADER_FILE_SIZE in->variant.fileVariant.fileSize = oh->fileSize; +#endif break; case YAFFS_OBJECT_TYPE_HARDLINK: in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId; @@ -3235,7 +3462,7 @@ int yaffs_GetObjectName(yaffs_Object *obj,char *name,int buffSize) if(obj->chunkId >= 0) { - yaffs_ReadChunkFromNAND(obj->myDev,obj->chunkId,buffer,NULL); + yaffs_ReadChunkFromNAND(obj->myDev,obj->chunkId,buffer,NULL,1); } strncpy(name,oh->name,buffSize - 1); } @@ -3332,7 +3559,7 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr) if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size); - yaffs_UpdateObjectHeader(obj,NULL); + yaffs_UpdateObjectHeader(obj,NULL,1); return YAFFS_OK; @@ -3411,7 +3638,6 @@ int yaffs_GutsInitialise(yaffs_Device *dev) int bits; - dev = dev; if(!yaffs_CheckStructures()) { @@ -3447,12 +3673,15 @@ int yaffs_GutsInitialise(yaffs_Device *dev) else { dev->chunkGroupBits = bits - 16; - dev->chunkGroupSize = nChunks/0x10000; + dev->chunkGroupSize = nChunks>> 16; } // More device initialisation dev->garbageCollectionRequired = 0; dev->currentDirtyChecker = 0; + dev->bufferedBlock = -1; + dev->doingBufferedBlockRewrite = 0; + dev->blockSelectedForGC = -1; yaffs_InitialiseBlocks(dev); @@ -3476,6 +3705,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev) dev->nBlockErasures = 0; dev->nGCCopies = 0; dev->nRetriedWrites = 0; + dev->nRetiredBlocks = 0; return YAFFS_OK;