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);
// 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;
yaffs_Tags tags;
int found;
int chunkDeleted;
+ int allDone = 1;
if(tn)
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)
{
}
}
+ return 1;
+
}
}
+ return 1;
+
}
{
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;
}
}
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;
{
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;
}
if(directory == obj->myDev->unlinkedDir)
{
obj->unlinked = 1;
+ obj->myDev->nUnlinkedFiles++;
obj->renameAllowed = 0;
}
}
dev->doingBufferedBlockRewrite = 0;
dev->blockSelectedForGC = -1;
dev->nDeletedFiles = 0;
+ dev->nBackgroundDeletions=0;
+ dev->nUnlinkedFiles = 0;
yaffs_InitialiseBlocks(dev,nBlocks);