X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;f=yaffs_guts.c;h=eaa18fda50db7701b6235d0621ff51cb7141d41f;hb=f40b8435a109889e57bc37743ac7eb6badf1dd95;hp=b042a9a7c61dbaf9a0f659e503d34c60525a0583;hpb=a1d28cf77fe06fe98cea4c4e80cc1cab94ea6736;p=yaffs%2F.git diff --git a/yaffs_guts.c b/yaffs_guts.c index b042a9a..eaa18fd 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -72,7 +72,7 @@ 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); -static void yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit); +static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit); static int yaffs_DoGenericObjectDeletion(yaffs_Object *in); static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device *dev,int blockNo); @@ -833,8 +833,9 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, yaffs_FileStru // DeleteWorker scans backwards through the tnode tree and deletes all the // chunks and tnodes in the file +// Returns 1 if the tree was deleted. Returns 0 if it stopped early due to hitting the limit and the delete is incomplete. -static void yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit) +static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit) { int i; int chunkInInode; @@ -842,6 +843,7 @@ static void yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, i yaffs_Tags tags; int found; int chunkDeleted; + int allDone = 1; if(tn) @@ -849,17 +851,28 @@ static void yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, i if(level > 0) { - for(i = YAFFS_NTNODES_INTERNAL -1; i >= 0 && (!limit || *limit > 0); i--) + for(i = YAFFS_NTNODES_INTERNAL -1; allDone && i >= 0; i--) { if(tn->internal[i]) { - yaffs_DeleteWorker(in,tn->internal[i],level - 1, + if(limit && (*limit) < 0) + { + allDone = 0; + } + else + { + allDone = yaffs_DeleteWorker(in,tn->internal[i],level - 1, (chunkOffset << YAFFS_TNODES_INTERNAL_BITS ) + i ,limit); - yaffs_FreeTnode(in->myDev,tn->internal[i]); - tn->internal[i] = NULL; + } + if(allDone) + { + yaffs_FreeTnode(in->myDev,tn->internal[i]); + tn->internal[i] = NULL; + } } } + return (allDone) ? 1 : 0; } else if(level == 0) { @@ -904,11 +917,15 @@ static void yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, i } } + return 1; + } } + return 1; + } @@ -1929,14 +1946,19 @@ static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev) { yaffs_Object *obj = dev->unlinkedDeletion; int limit; + int delresult; limit = 50; // Max number of chunks to delete in a file. NB this can be exceeded, but not by much. - yaffs_DeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0,&limit); + delresult = yaffs_DeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0,&limit); + if(obj->nDataChunks == 0) { // Done all the deleting of data chunks. // Now dump the header and clean up - yaffs_DoGenericObjectDeletion(dev->unlinkedDeletion); + yaffs_FreeTnode(dev,obj->variant.fileVariant.top); + yaffs_DoGenericObjectDeletion(obj); dev->nDeletedFiles--; + dev->nUnlinkedFiles--; + dev->nBackgroundDeletions++; dev->unlinkedDeletion = NULL; } } @@ -3071,11 +3093,35 @@ static int yaffs_UnlinkFile(yaffs_Object *in) return yaffs_DoGenericObjectDeletion(in); #else int retVal; + int immediateDeletion=0; retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,NULL); if(retVal == YAFFS_OK) { - in->unlinked = 1; - in->renameAllowed = 0; + //in->unlinked = 1; + //in->myDev->nUnlinkedFiles++; + //in->renameAllowed = 0; +#ifdef __KERNEL__ + if(in->myInode) + { + immediateDeletion = 1; + + } +#endif +#if WIN32 + if(in->inUse <= 0) + { + immediateDeletion = 1; + + } +#endif + + if(immediateDeletion) + { + T((TSTR("yaffs: immediate deletion of file %d" TENDSTR),in->objectId)); + in->deleted=1; + in->myDev->nDeletedFiles++; + } + } return retVal; @@ -3090,9 +3136,12 @@ int yaffs_DeleteFile(yaffs_Object *in) { retVal = yaffs_UnlinkFile(in); } - if(retVal == YAFFS_OK && in->unlinked) + if(retVal == YAFFS_OK && + in->unlinked && + !in->deleted) { in->deleted = 1; + in->myDev->nDeletedFiles++; } return in->deleted ? YAFFS_OK : YAFFS_FAIL; } @@ -3639,6 +3688,7 @@ static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *ob if(directory == obj->myDev->unlinkedDir) { obj->unlinked = 1; + obj->myDev->nUnlinkedFiles++; obj->renameAllowed = 0; } } @@ -3986,6 +4036,8 @@ int yaffs_GutsInitialise(yaffs_Device *dev) dev->doingBufferedBlockRewrite = 0; dev->blockSelectedForGC = -1; dev->nDeletedFiles = 0; + dev->nBackgroundDeletions=0; + dev->nUnlinkedFiles = 0; yaffs_InitialiseBlocks(dev,nBlocks);