On Tue, 2005-10-04 at 13:14, Charles Manning wrote: > On Wednesday 05 October 2005 04:51, Blair Barnett wrote: > > > The system has four partitions on the NAND (kernel image, root, > > application, spare). After booting up and mounting root, application and > > the spare partition, I create a file in the spare partition. Size > > doesn't matter in this case. :-) A df command reveals that indeed some > > blocks have been allocated to this file and all is well. Now if I remove > > the file, a df command shows that indeed the blocks have been returned > > to the free list (I know this is not exactly the case as the blocks have > > all been "soft deleted" and waiting for GC). Now if I create another > > file, the aforementioned blocks get GC'ed and df again shows that all is > > right with the file system. If, however, I remove a file, then unmount > > the file system, then mount it, df shows that the blocks the were "soft > > deleted" are now marked as used (never to be returned to the free list, > > as far as my tests show). > > Someone reported something similar recently, but did not seem to have come > back with the requested debug info. > > I will do some investigation anyway. > > After you have deleted a file (even if it is only soft deleted), this is free > space from a user perspective and should show up as being available under df. > mount/unmount should not change df status. > > ie > You should observe something like: > > * df. Shows 5MB free > * dd to create a 1MB file > *df. Shows 4MB free > * rm file. > * df shows 5MB free. This works as stated above. Add the step of unmounting and mounting the partition and you'll see that df shows 4 MB free (you lose the 1 MB of soft deleted files *forever*, or at least until you do a flash_eraseall). > > The only valid reason for df showing something else is if blocks got lost due > to being retired because they had ECC errors. > > > > > My question is shouldn't the unmount or mount code path cause GC to run > > and return these "soft deleted" blocks back to the free list? > > Mounting/unmounting does not cause GC to run. GC only runs as a side effect of > when you do any writing operations. > > Running gc at mount would only slow down mount time and would break the > benefits of deferred GC. Good point. This design decision is a very good one. > > > > > > Am I missing something? This unmount/mount block lost is filling our > > application file system nightly. > > Do you get any warnings from mtd? None at all. > > -- Charles > Hi Charles, Here's a possible fix to the yaffs2 "losing blocks between mounts/unmounts". This may not be the optimum way to fix it, but it works for me. I just made yaffs_ScanBackwards() handle soft deleted files just like yaffs_Scan(). Now my kernel works the same for both 512 and 2K page devices AND df works. In looking through yaffs_Scan() and yaffs_ScanBackward(), it appears to me as if you (or someone else) tried to get one scanning method to work, which I think is admirable and "the right way to go"(TM). Since we call yaffs_Scan() based on whether we're on a yaffs2 device or not, we can probably safely remove all the "isYaffs2" tests in the yaffs_Scan() code. thanks again, Blair ========================snip======================== diff -Naur yaffs2/yaffs_guts.c yaffs2_fixed/yaffs_guts.c --- yaffs2/yaffs_guts.c 2005-09-19 22:08:50.000000000 -0700 +++ yaffs2_fixed/yaffs_guts.c 2005-10-04 15:56:56.000000000 -0700 @@ -1657,13 +1657,8 @@ YBUG(); } - /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */ - if (obj->myDev->isYaffs2) { - unlinkOp = (newDir == obj->myDev->unlinkedDir); - } else { - unlinkOp = (newDir == obj->myDev->unlinkedDir + unlinkOp = (newDir == obj->myDev->unlinkedDir && obj->variantType == YAFFS_OBJECT_TYPE_FILE); - } deleteOp = (newDir == obj->myDev->deletedDir); @@ -4194,16 +4189,12 @@ yaffs_AddObjectToDirectory(parent, in); - if (0 && (parent == dev->deletedDir || - parent == dev->unlinkedDir)) {- in->deleted = 1; /* If it is unlinked at start up then it wants deleting */ - dev->nDeletedFiles++; - } /* Note re hardlinks. - * Since we might scan a hardlink before its equivalent object is scanned - * we put them all in a list. - * After scanning is complete, we should have all the objects, so we run through this - * list and fix up all the chains. + * Since we might scan a hardlink before its equivalent + * object is scanned we put them all in a list. + * After scanning is complete, we should have all + * the objects, so we run through this list and fix up + * all the chains. */ switch (in->variantType) { @@ -4762,22 +4753,17 @@ yaffs_AddObjectToDirectory(parent, in); - if ((parent == dev->deletedDir || - parent == dev->unlinkedDir)) { - /* If it is unlinked at start up then it wants deleting */ - in->deleted = 1; - } - if (oh->isShrink) { /* Mark the block as having a shrinkHeader */ bi->hasShrinkHeader = 1; } /* Note re hardlinks. - * Since we might scan a hardlink before its equivalent object is scanned - * we put them all in a list. - * After scanning is complete, we should have all the objects, so we run - * through this list and fix up all the chains. + * Since we might scan a hardlink before its equivalent + * object is scanned we put them all in a list. + * After scanning is complete, we should have all + * the objects, so we run through this list and + * fix up all the chains. */ switch (in->variantType) {