X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=yaffs_guts.c;h=91fb73c598fda9e44ed5052abc06a0ff8de1b38d;hb=087046078841616093c6e6babe66eba1bd0ce0d6;hp=d82da3fc9bec225fc1975c573552d1d8e73ec4e3;hpb=fd03f2753af313fc90e59a4ef944106fac3afc0c;p=yaffs%2F.git diff --git a/yaffs_guts.c b/yaffs_guts.c index d82da3f..91fb73c 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.24 2003-04-03 17:58:56 charles Exp $"; +const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.36 2004-10-10 17:54:59 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. @@ -239,10 +242,10 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, int eccResult1,eccResult2; __u8 calcEcc[3]; - 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); + 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) { @@ -582,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) @@ -779,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; @@ -1077,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; } @@ -1148,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)); @@ -1449,10 +1459,15 @@ 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; @@ -1622,7 +1637,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->st_atime = theObject->st_mtime = theObject->st_ctime = Y_CURRENT_TIME; + #endif switch(type) { @@ -1723,10 +1740,11 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type, #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_atime = in->st_mtime = in->st_ctime = Y_CURRENT_TIME; in->st_rdev = rdev; in->st_uid = uid; in->st_gid = gid; @@ -2278,6 +2296,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block) { // It's a header object->chunkId = newChunk; + object->serial = tags.serialNumber; } else { @@ -2819,6 +2838,7 @@ int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffe } else { + memset(buffer,0,YAFFS_BYTES_PER_CHUNK); return 0; } @@ -2841,7 +2861,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. @@ -3620,7 +3647,7 @@ 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->startBlock * 32) || chunkId >= ((dev->endBlock+1) * 32)) { //T(("Found daft chunkId %d for %d\n",chunkId,i)); } @@ -3637,8 +3664,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); } @@ -3690,7 +3719,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->st_mtime = Y_CURRENT_TIME; #endif } @@ -4189,8 +4218,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; } @@ -4543,9 +4573,10 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr) if(valid & ATTR_UID) obj->st_uid = attr->ia_uid; if(valid & ATTR_GID) obj->st_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->st_atime = Y_TIME_CONVERT(attr->ia_atime); + if(valid & ATTR_CTIME) obj->st_ctime = Y_TIME_CONVERT(attr->ia_ctime); + if(valid & ATTR_MTIME) obj->st_mtime = Y_TIME_CONVERT(attr->ia_mtime); + if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size); @@ -4554,6 +4585,7 @@ 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; @@ -4562,10 +4594,11 @@ int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr) attr->ia_uid = obj->st_uid; valid |= ATTR_UID; attr->ia_gid = obj->st_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->st_atime; valid |= ATTR_ATIME; + Y_TIME_CONVERT(attr->ia_ctime) = obj->st_ctime; valid |= ATTR_CTIME; + Y_TIME_CONVERT(attr->ia_mtime) = obj->st_mtime; valid |= ATTR_MTIME; + attr->ia_size = yaffs_GetFileSize(obj); valid |= ATTR_SIZE; attr->ia_valid = valid; @@ -4629,8 +4662,7 @@ 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 || @@ -4697,7 +4729,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; + } + @@ -4783,6 +4826,8 @@ 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); } @@ -4825,6 +4870,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) int nFree; int pending; int b; + int nDirtyCacheChunks=0; yaffs_BlockInfo *blk; @@ -4872,6 +4918,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; @@ -4921,3 +4981,6 @@ void yaffs_GutsTest(yaffs_Device *dev) + + +