Mercurial > yaffs-ecoscentric
changeset 353:fa7270d25c51
Merge from upstream
| author | Ross Younger <wry@ecoscentric.com> |
|---|---|
| date | Tue, 17 Nov 2009 10:49:51 +0000 |
| parents | 73b6efce8c58 (current diff) 88c898910859 (diff) |
| children | 68aafa1d2927 |
| files | linux-tests/initnandsim linux-tests/mkdirtree packages/fs/yaffs/current/ChangeLog packages/fs/yaffs/current/src/yaffs_checkptrw.c packages/fs/yaffs/current/src/yaffs_guts.c packages/fs/yaffs/current/src/yaffs_guts.h |
| diffstat | 4 files changed, 186 insertions(+), 33 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/fs/yaffs/current/ChangeLog +++ b/packages/fs/yaffs/current/ChangeLog @@ -1,6 +1,8 @@ 2009-11-13 Ross Younger <wry@ecoscentric.com> * tests: yaffs1-6 NA unless CYGPKG_KERNEL is present. + * Update upstream: (pulled up to 2009-11-11 02:11:13 +0000) + - mostly bugfixes 2009-11-09 Ross Younger <wry@ecoscentric.com>
--- a/packages/fs/yaffs/current/src/yaffs_checkptrw.c +++ b/packages/fs/yaffs/current/src/yaffs_checkptrw.c @@ -395,7 +395,8 @@ int yaffs_CheckpointInvalidateStream(yaf { /* Erase the checkpoint data */ - T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate"TENDSTR))); + T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate of %d blocks"TENDSTR), + dev->blocksInCheckpoint)); return yaffs_CheckpointErase(dev); }
--- a/packages/fs/yaffs/current/src/yaffs_guts.c +++ b/packages/fs/yaffs/current/src/yaffs_guts.c @@ -117,7 +117,6 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod yaffs_FileStructure *fStruct, __u32 chunkId); - /* Function to calculate chunk and offset */ static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, @@ -1328,7 +1327,7 @@ static void yaffs_InitialiseTnodes(yaffs } -void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, +void yaffs_LoadLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val) { __u32 *map = (__u32 *)tn; @@ -1486,13 +1485,13 @@ static yaffs_Tnode *yaffs_AddOrFindLevel if (tn) { tn->internal[0] = fStruct->top; fStruct->top = tn; + fStruct->topLevel++; } else { T(YAFFS_TRACE_ERROR, - (TSTR("yaffs: no more tnodes" TENDSTR))); + (TSTR("yaffs: no more tnodes" TENDSTR))); + return NULL; } } - - fStruct->topLevel = requiredTallness; } /* Traverse down to level 0, adding anything we need */ @@ -1511,6 +1510,8 @@ static yaffs_Tnode *yaffs_AddOrFindLevel if ((l > 1) && !tn->internal[x]) { /* Add missing non-level-zero tnode */ tn->internal[x] = yaffs_GetTnode(dev); + if(!tn->internal[x]) + return NULL; } else if (l == 1) { /* Looking from level 1 at level 0 */ @@ -1523,6 +1524,8 @@ static yaffs_Tnode *yaffs_AddOrFindLevel } else if (!tn->internal[x]) { /* Don't have one, none passed in */ tn->internal[x] = yaffs_GetTnode(dev); + if(!tn->internal[x]) + return NULL; } } @@ -1646,7 +1649,7 @@ static int yaffs_DeleteWorker(yaffs_Obje } - yaffs_PutLevel0Tnode(dev, tn, i, 0); + yaffs_LoadLevel0Tnode(dev, tn, i, 0); } } @@ -1723,7 +1726,7 @@ static int yaffs_SoftDeleteWorker(yaffs_ * a block. */ yaffs_SoftDeleteChunk(dev, theChunk); - yaffs_PutLevel0Tnode(dev, tn, i, 0); + yaffs_LoadLevel0Tnode(dev, tn, i, 0); } } @@ -2174,17 +2177,19 @@ yaffs_Object *yaffs_CreateNewObject(yaff if (number < 0) number = yaffs_CreateNewObjectNumber(dev); - theObject = yaffs_AllocateEmptyObject(dev); - if (!theObject) - return NULL; - if (type == YAFFS_OBJECT_TYPE_FILE) { tn = yaffs_GetTnode(dev); - if (!tn) { - yaffs_DoGenericObjectDeletion(theObject); + if (!tn) return NULL; - } - } + } + + theObject = yaffs_AllocateEmptyObject(dev); + if (!theObject){ + if(tn) + yaffs_FreeTnode(dev,tn); + return NULL; + } + if (theObject) { theObject->fake = 0; @@ -2287,18 +2292,20 @@ static yaffs_Object *yaffs_MknodObject(y if (yaffs_FindObjectByName(parent, name)) return NULL; - in = yaffs_CreateNewObject(dev, -1, type); - - if (!in) - return YAFFS_FAIL; - if (type == YAFFS_OBJECT_TYPE_SYMLINK) { str = yaffs_CloneString(aliasString); - if (!str) { - yaffs_DoGenericObjectDeletion(in); + if (!str) return NULL; - } - } + } + + in = yaffs_CreateNewObject(dev, -1, type); + + if (!in){ + if(str) + YFREE(str); + return NULL; + } + @@ -3361,7 +3368,7 @@ static int yaffs_FindAndDeleteChunkInFil /* Delete the entry in the filestructure (if found) */ if (retVal != -1) - yaffs_PutLevel0Tnode(dev, tn, chunkInInode, 0); + yaffs_LoadLevel0Tnode(dev, tn, chunkInInode, 0); } return retVal; @@ -3431,6 +3438,8 @@ static int yaffs_PutChunkIntoFile(yaffs_ /* NB inScan is zero unless scanning. * For forward scanning, inScan is > 0; * for backward scanning inScan is < 0 + * + * chunkInNAND = 0 is a dummy insert to make sure the tnodes are there. */ yaffs_Tnode *tn; @@ -3462,6 +3471,11 @@ static int yaffs_PutChunkIntoFile(yaffs_ NULL); if (!tn) return YAFFS_FAIL; + + if(!chunkInNAND) + /* Dummy insert, bail now */ + return YAFFS_OK; + existingChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode); @@ -3543,7 +3557,7 @@ static int yaffs_PutChunkIntoFile(yaffs_ if (existingChunk == 0) in->nDataChunks++; - yaffs_PutLevel0Tnode(dev, tn, chunkInInode, chunkInNAND); + yaffs_LoadLevel0Tnode(dev, tn, chunkInInode, chunkInNAND); return YAFFS_OK; } @@ -3666,11 +3680,19 @@ static int yaffs_WriteChunkDataToObject( YBUG(); } + /* + * If there isn't already a chunk there then do a dummy + * insert to make sue we have the desired tnode structure. + */ + if(prevChunkId < 1 && + yaffs_PutChunkIntoFile(in, chunkInInode, 0, 0) != YAFFS_OK) + return -1; + newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, useReserve); - if (newChunkId >= 0) { + if (newChunkId > 0) { yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0); if (prevChunkId > 0) @@ -5488,9 +5510,126 @@ static void yaffs_StripDeletedObjects(ya } } -#endif - -#ifndef CONFIG_YAFFS_NO_YAFFS1 + +/* + * This code iterates through all the objects making sure that they are rooted. + * Any unrooted objects are re-rooted in lost+found. + * An object needs to be in one of: + * - Directly under deleted, unlinked + * - Directly or indirectly under root. + * + * Note: + * This code assumes that we don't ever change the current relationships between + * directories: + * rootDir->parent == unlinkedDir->parent == deletedDir->parent == NULL + * lostNfound->parent == rootDir + * + * This fixes the problem where directories might have inadvertently been deleted + * leaving the object "hanging" without being rooted in the directory tree. + */ + +static int yaffs_HasNULLParent(yaffs_Device *dev, yaffs_Object *obj) +{ + return (obj == dev->deletedDir || + obj == dev->unlinkedDir|| + obj == dev->rootDir); +} + +static void yaffs_FixHangingObjects(yaffs_Device *dev) +{ + yaffs_Object *obj; + yaffs_Object *parent; + int i; + struct ylist_head *lh; + struct ylist_head *n; + int depthLimit; + int hanging; + + + /* Iterate through the objects in each hash entry, + * looking at each object. + * Make sure it is rooted. + */ + + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { + ylist_for_each_safe(lh, n, &dev->objectBucket[i].list) { + if (lh) { + obj = ylist_entry(lh, yaffs_Object, hashLink); + parent= obj->parent; + + if(yaffs_HasNULLParent(dev,obj)){ + /* These directories are not hanging */ + hanging = 0; + } + else if(!parent || parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + hanging = 1; + else if(yaffs_HasNULLParent(dev,parent)) + hanging = 0; + else { + /* + * Need to follow the parent chain to see if it is hanging. + */ + hanging = 0; + depthLimit=100; + + while(parent != dev->rootDir && + parent->parent && + parent->parent->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && + depthLimit > 0){ + parent = parent->parent; + depthLimit--; + } + if(parent != dev->rootDir) + hanging = 1; + } + if(hanging){ + T(YAFFS_TRACE_SCAN, + (TSTR("Hanging object %d moved to lost and found" TENDSTR), + obj->objectId)); + yaffs_AddObjectToDirectory(dev->lostNFoundDir,obj); + } + } + } + } +} + + +/* + * Delete directory contents for cleaning up lost and found. + */ +static void yaffs_DeleteDirectoryContents(yaffs_Object *dir) +{ + yaffs_Object *obj; + struct ylist_head *lh; + struct ylist_head *n; + + if(dir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); + + ylist_for_each_safe(lh, n, &dir->variant.directoryVariant.children) { + if (lh) { + obj = ylist_entry(lh, yaffs_Object, siblings); + if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) + yaffs_DeleteDirectoryContents(obj); + + T(YAFFS_TRACE_SCAN, + (TSTR("Deleting lost_found object %d" TENDSTR), + obj->objectId)); + + /* Need to use UnlinkObject since Delete would not handle + * hardlinked objects correctly. + */ + yaffs_UnlinkObject(obj); + } + } + +} + +static void yaffs_EmptyLostAndFound(yaffs_Device *dev) +{ + yaffs_DeleteDirectoryContents(dev->lostNFoundDir); +} + static int yaffs_Scan(yaffs_Device *dev) { yaffs_ExtendedTags tags; @@ -7465,8 +7604,10 @@ int yaffs_GutsInitialise(yaffs_Device *d init_failed = 1; yaffs_StripDeletedObjects(dev); + yaffs_FixHangingObjects(dev); + if(dev->emptyLostAndFound) + yaffs_EmptyLostAndFound(dev); #endif - } } if (init_failed) { @@ -7490,6 +7631,9 @@ int yaffs_GutsInitialise(yaffs_Device *d yaffs_VerifyFreeChunks(dev); yaffs_VerifyBlocks(dev); + /* Clean up any aborted checkpoint data */ + if(!dev->isCheckpointed && dev->blocksInCheckpoint > 0) + yaffs_InvalidateCheckpoint(dev); T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
--- a/packages/fs/yaffs/current/src/yaffs_guts.h +++ b/packages/fs/yaffs/current/src/yaffs_guts.h @@ -405,6 +405,8 @@ typedef union { yaffs_HardLinkStructure hardLinkVariant; } yaffs_ObjectVariant; + + struct yaffs_ObjectStruct { __u8 deleted:1; /* This should only apply to unlinked files. */ __u8 softDeleted:1; /* it has also been soft deleted */ @@ -532,6 +534,7 @@ typedef struct { /*----------------- Device ---------------------------------*/ + struct yaffs_DeviceStruct { struct ylist_head devList; const char *name; @@ -637,6 +640,7 @@ struct yaffs_DeviceStruct { struct semaphore sem; /* Semaphore for waiting on erasure.*/ struct semaphore grossLock; /* Gross locking semaphore */ + struct rw_semaphore dirLock; /* Lock the directory structure */ __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer * at compile time so we have to allocate it. */ @@ -768,7 +772,9 @@ struct yaffs_DeviceStruct { /* yaffs2 runtime stuff */ unsigned sequenceNumber; /* Sequence number of currently allocating block */ unsigned oldestDirtySequence; - + + /* Auto empty lost and found directory on mount */ + int emptyLostAndFound; }; typedef struct yaffs_DeviceStruct yaffs_Device;
