X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=ca1dd6a4c88f751e32ccef3e8490fc4bca107958;hp=d72cd49d3150d23c58eaff423d835ff000e68cd6;hb=da27a11ac14cc0db3e7a8dbce75ec0ff18fb4334;hpb=102ee9ef7f61177ab100570809d9dbde888e3904 diff --git a/yaffs_guts.c b/yaffs_guts.c index d72cd49..ca1dd6a 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -13,7 +13,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.18 2005-08-16 02:28:04 charles Exp $"; + "$Id: yaffs_guts.c,v 1.30 2006-03-01 08:14:32 charles Exp $"; #include "yportenv.h" @@ -57,6 +57,8 @@ static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, const yaffs_ExtendedTags * tags); /* Other local prototypes */ +static int yaffs_UnlinkObject( yaffs_Object *obj); + static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device * dev, const __u8 * buffer, yaffs_ExtendedTags * tags, @@ -333,6 +335,7 @@ static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk) static Y_INLINE int yaffs_HashFunction(int n) { + n = abs(n); return (n % YAFFS_NOBJECT_BUCKETS); } @@ -536,15 +539,24 @@ static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name) static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes) { int i; + int tnodeSize; yaffs_Tnode *newTnodes; + __u8 *mem; + yaffs_Tnode *curr; + yaffs_Tnode *next; yaffs_TnodeList *tnl; if (nTnodes < 1) return YAFFS_OK; + + /* Calculate the tnode size in bytes for variable width tnode support. + * Must be a multiple of 32-bits */ + tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; /* make these things */ - newTnodes = YMALLOC(nTnodes * sizeof(yaffs_Tnode)); + newTnodes = YMALLOC(nTnodes * tnodeSize); + mem = (__u8 *)newTnodes; if (!newTnodes) { T(YAFFS_TRACE_ERROR, @@ -553,6 +565,7 @@ static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes) } /* Hook them into the free list */ +#if 0 for (i = 0; i < nTnodes - 1; i++) { newTnodes[i].internal[0] = &newTnodes[i + 1]; #ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG @@ -565,6 +578,21 @@ static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes) newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1; #endif dev->freeTnodes = newTnodes; +#else + /* New hookup for wide tnodes */ + for(i = 0; i < nTnodes -1; i++) { + curr = (yaffs_Tnode *) &mem[i * tnodeSize]; + next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize]; + curr->internal[0] = next; + } + + curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize]; + curr->internal[0] = dev->freeTnodes; + dev->freeTnodes = (yaffs_Tnode *)mem; + +#endif + + dev->nFreeTnodes += nTnodes; dev->nTnodesCreated += nTnodes; @@ -613,7 +641,7 @@ static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev) dev->freeTnodes = dev->freeTnodes->internal[0]; dev->nFreeTnodes--; /* zero out */ - memset(tn, 0, sizeof(yaffs_Tnode)); + memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); } return tn; @@ -664,6 +692,64 @@ static void yaffs_InitialiseTnodes(yaffs_Device * dev) } + +void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val) +{ + __u32 *map = (__u32 *)tn; + __u32 bitInMap; + __u32 bitInWord; + __u32 wordInMap; + __u32 mask; + + pos &= YAFFS_TNODES_LEVEL0_MASK; + val >>= dev->chunkGroupBits; + + bitInMap = pos * dev->tnodeWidth; + wordInMap = bitInMap /32; + bitInWord = bitInMap & (32 -1); + + mask = dev->tnodeMask << bitInWord; + + map[wordInMap] &= ~mask; + map[wordInMap] |= (mask & (val << bitInWord)); + + if(dev->tnodeWidth > (32-bitInWord)) { + bitInWord = (32 - bitInWord); + wordInMap++;; + mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord); + map[wordInMap] &= ~mask; + map[wordInMap] |= (mask & (val >> bitInWord)); + } +} + +__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) +{ + __u32 *map = (__u32 *)tn; + __u32 bitInMap; + __u32 bitInWord; + __u32 wordInMap; + __u32 val; + + pos &= YAFFS_TNODES_LEVEL0_MASK; + + bitInMap = pos * dev->tnodeWidth; + wordInMap = bitInMap /32; + bitInWord = bitInMap & (32 -1); + + val = map[wordInMap] >> bitInWord; + + if(dev->tnodeWidth > (32-bitInWord)) { + bitInWord = (32 - bitInWord); + wordInMap++;; + val |= (map[wordInMap] << bitInWord); + } + + val &= dev->tnodeMask; + val <<= dev->chunkGroupBits; + + return val; +} + /* ------------------- End of individual tnode manipulation -----------------*/ /* ---------Functions to manipulate the look-up tree (made up of tnodes) ------ @@ -881,16 +967,13 @@ static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level, for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit; i--) { - if (tn->level0[i]) { + theChunk = yaffs_GetChunkGroupBase(dev,tn,i); + if (theChunk) { chunkInInode = (chunkOffset << YAFFS_TNODES_LEVEL0_BITS) + i; - theChunk = - tn->level0[i] << dev-> - chunkGroupBits; - foundChunk = yaffs_FindChunkInGroup(dev, theChunk, @@ -912,7 +995,7 @@ static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level, } - tn->level0[i] = 0; + yaffs_PutLevel0Tnode(dev,tn,i,0); } } @@ -983,17 +1066,14 @@ static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, } else if (level == 0) { for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) { - if (tn->level0[i]) { + theChunk = yaffs_GetChunkGroupBase(dev,tn,i); + if (theChunk) { /* Note this does not find the real chunk, only the chunk group. * We make an assumption that a chunk group is not larger than * a block. */ - theChunk = - (tn->level0[i] << dev-> - chunkGroupBits); - yaffs_SoftDeleteChunk(dev, theChunk); - tn->level0[i] = 0; + yaffs_PutLevel0Tnode(dev,tn,i,0); } } @@ -1729,10 +1809,10 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, */ yaffs_ChangeObjectName(obj, newDir, newName, force, existingTarget->objectId); - yaffs_Unlink(newDir, newName); + yaffs_UnlinkObject(existingTarget); } - return yaffs_ChangeObjectName(obj, newDir, newName, force, 0); + return yaffs_ChangeObjectName(obj, newDir, newName, 1, 0); } return YAFFS_FAIL; } @@ -1745,10 +1825,23 @@ static int yaffs_InitialiseBlocks(yaffs_Device * dev, int nBlocks) /* Todo we're assuming the malloc will pass. */ dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); + if(!dev->blockInfo){ + dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo)); + dev->blockInfoAlt = 1; + } + else + dev->blockInfoAlt = 0; /* Set up dynamic blockinfo stuff. */ dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); + if(!dev->chunkBits){ + dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); + dev->chunkBitsAlt = 1; + } + else + dev->chunkBitsAlt = 0; + if (dev->blockInfo && dev->chunkBits) { memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo)); memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks); @@ -1761,9 +1854,19 @@ static int yaffs_InitialiseBlocks(yaffs_Device * dev, int nBlocks) static void yaffs_DeinitialiseBlocks(yaffs_Device * dev) { - YFREE(dev->blockInfo); + if(dev->blockInfoAlt) + YFREE_ALT(dev->blockInfo); + else + YFREE(dev->blockInfo); + dev->blockInfoAlt = 0; + dev->blockInfo = NULL; - YFREE(dev->chunkBits); + + if(dev->chunkBitsAlt) + YFREE_ALT(dev->chunkBits); + else + YFREE(dev->chunkBits); + dev->chunkBitsAlt = 0; dev->chunkBits = NULL; } @@ -2244,6 +2347,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) ("yaffs: About to finally delete object %d" TENDSTR), object->objectId)); yaffs_DoGenericObjectDeletion(object); + object->myDev->nDeletedFiles--; } } @@ -2357,9 +2461,7 @@ static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode, tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode); if (tn) { - theChunk = - tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << - dev->chunkGroupBits; + theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); retVal = yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId, @@ -2388,9 +2490,7 @@ static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode, if (tn) { - theChunk = - tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << dev-> - chunkGroupBits; + theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); retVal = yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId, @@ -2398,7 +2498,7 @@ static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode, /* Delete the entry in the filestructure (if found) */ if (retVal != -1) { - tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = 0; + yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0); } } else { /*T(("No level 0 found for %d\n", chunkInInode)); */ @@ -2441,9 +2541,7 @@ static int yaffs_CheckFileSanity(yaffs_Object * in) if (tn) { - theChunk = - tn->level0[chunk & YAFFS_TNODES_LEVEL0_MASK] << in-> - myDev->chunkGroupBits; + theChunk = yaffs_GetChunkGroupBase(dev,tn,chunk); if (yaffs_CheckChunkBits (dev, theChunk / dev->nChunksPerBlock, @@ -2509,7 +2607,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, return YAFFS_FAIL; } - existingChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK]; + existingChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); if (inScan != 0) { /* If we're scanning then we need to test for duplicates @@ -2588,8 +2686,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, in->nDataChunks++; } - tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = - (chunkInNAND >> dev->chunkGroupBits); + yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND); return YAFFS_OK; } @@ -2635,14 +2732,6 @@ void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn) if (markNAND && bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->isYaffs2) { -#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 - yaffs_InitialiseTags(&tags); tags.chunkDeleted = 1; @@ -3771,11 +3860,9 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj) } } -int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name) -{ - yaffs_Object *obj; - obj = yaffs_FindObjectByName(dir, name); +static int yaffs_UnlinkObject( yaffs_Object *obj) +{ if (obj && obj->unlinkAllowed) { return yaffs_UnlinkWorker(obj); @@ -3784,6 +3871,13 @@ int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name) return YAFFS_FAIL; } +int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name) +{ + yaffs_Object *obj; + + obj = yaffs_FindObjectByName(dir, name); + return yaffs_UnlinkObject(obj); +} /*----------------------- Initialisation Scanning ---------------------- */ @@ -4324,6 +4418,46 @@ static int yaffs_Scan(yaffs_Device * dev) return YAFFS_OK; } +static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in) +{ + __u8 *chunkData; + yaffs_ObjectHeader *oh; + yaffs_Device *dev = in->myDev; + + if(in->lazyLoaded){ + in->lazyLoaded = 0; + chunkData = yaffs_GetTempBuffer(dev, __LINE__); + + yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,NULL); + oh = (yaffs_ObjectHeader *) chunkData; + + in->yst_mode = oh->yst_mode; +#ifdef CONFIG_YAFFS_WINCE + in->win_atime[0] = oh->win_atime[0]; + in->win_ctime[0] = oh->win_ctime[0]; + in->win_mtime[0] = oh->win_mtime[0]; + in->win_atime[1] = oh->win_atime[1]; + in->win_ctime[1] = oh->win_ctime[1]; + in->win_mtime[1] = oh->win_mtime[1]; +#else + in->yst_uid = oh->yst_uid; + in->yst_gid = oh->yst_gid; + in->yst_atime = oh->yst_atime; + in->yst_mtime = oh->yst_mtime; + in->yst_ctime = oh->yst_ctime; + in->yst_rdev = oh->yst_rdev; + +#endif + yaffs_SetObjectName(in, oh->name); + + if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) + in->variant.symLinkVariant.alias = + yaffs_CloneString(oh->alias); + + yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__); + } +} + static int yaffs_ScanBackwards(yaffs_Device * dev) { yaffs_ExtendedTags tags; @@ -4345,8 +4479,13 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) yaffs_Object *in; yaffs_Object *parent; int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; - + int itsUnlinked; __u8 *chunkData; + + int fileSize; + int isShrink; + int equivalentObjectId; + yaffs_BlockIndex *blockIndex = NULL; @@ -4571,7 +4710,15 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) tags.extraObjectType); } - if (!in || !in->valid) { + if (!in || +#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD + !in->valid || +#endif + tags.extraShadows || + (!in->valid && + (tags.objectId == YAFFS_OBJECTID_ROOT || + tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) + ) { /* If we don't have valid info then we need to read the chunk * TODO In future we can probably defer reading the chunk and @@ -4606,21 +4753,11 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) * we first have to suck out resize info if it is a file. */ - if ((in->variantType == - YAFFS_OBJECT_TYPE_FILE) && ((oh - && - oh-> - type - == - YAFFS_OBJECT_TYPE_FILE) - || - (tags. - extraHeaderInfoAvailable - && - tags. - extraObjectType - == - YAFFS_OBJECT_TYPE_FILE)) + if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) && + ((oh && + oh-> type == YAFFS_OBJECT_TYPE_FILE)|| + (tags.extraHeaderInfoAvailable && + tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE)) ) { __u32 thisSize = (oh) ? oh->fileSize : tags. @@ -4668,68 +4805,96 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) YAFFS_OBJECTID_LOSTNFOUND)) { /* We only load some info, don't fiddle with directory structure */ in->valid = 1; - in->variantType = oh->type; + + if(oh) { + in->variantType = oh->type; - in->yst_mode = oh->yst_mode; + in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE - in->win_atime[0] = oh->win_atime[0]; - in->win_ctime[0] = oh->win_ctime[0]; - in->win_mtime[0] = oh->win_mtime[0]; - in->win_atime[1] = oh->win_atime[1]; - in->win_ctime[1] = oh->win_ctime[1]; - in->win_mtime[1] = oh->win_mtime[1]; + in->win_atime[0] = oh->win_atime[0]; + in->win_ctime[0] = oh->win_ctime[0]; + in->win_mtime[0] = oh->win_mtime[0]; + in->win_atime[1] = oh->win_atime[1]; + in->win_ctime[1] = oh->win_ctime[1]; + in->win_mtime[1] = oh->win_mtime[1]; #else - in->yst_uid = oh->yst_uid; - in->yst_gid = oh->yst_gid; - in->yst_atime = oh->yst_atime; - in->yst_mtime = oh->yst_mtime; - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; + in->yst_uid = oh->yst_uid; + in->yst_gid = oh->yst_gid; + in->yst_atime = oh->yst_atime; + in->yst_mtime = oh->yst_mtime; + in->yst_ctime = oh->yst_ctime; + in->yst_rdev = oh->yst_rdev; + #endif + } else { + in->variantType = tags.extraObjectType; + in->lazyLoaded = 1; + } + in->chunkId = chunk; } else if (!in->valid) { /* we need to load this info */ in->valid = 1; - in->variantType = oh->type; + in->chunkId = chunk; + + if(oh) { + in->variantType = oh->type; - in->yst_mode = oh->yst_mode; + in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE - in->win_atime[0] = oh->win_atime[0]; - in->win_ctime[0] = oh->win_ctime[0]; - in->win_mtime[0] = oh->win_mtime[0]; - in->win_atime[1] = oh->win_atime[1]; - in->win_ctime[1] = oh->win_ctime[1]; - in->win_mtime[1] = oh->win_mtime[1]; + in->win_atime[0] = oh->win_atime[0]; + in->win_ctime[0] = oh->win_ctime[0]; + in->win_mtime[0] = oh->win_mtime[0]; + in->win_atime[1] = oh->win_atime[1]; + in->win_ctime[1] = oh->win_ctime[1]; + in->win_mtime[1] = oh->win_mtime[1]; #else - in->yst_uid = oh->yst_uid; - in->yst_gid = oh->yst_gid; - in->yst_atime = oh->yst_atime; - in->yst_mtime = oh->yst_mtime; - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; + in->yst_uid = oh->yst_uid; + in->yst_gid = oh->yst_gid; + in->yst_atime = oh->yst_atime; + in->yst_mtime = oh->yst_mtime; + in->yst_ctime = oh->yst_ctime; + in->yst_rdev = oh->yst_rdev; #endif - in->chunkId = chunk; - if (oh->shadowsObject > 0) { - yaffs_HandleShadowedObject(dev, + if (oh->shadowsObject > 0) + yaffs_HandleShadowedObject(dev, oh-> shadowsObject, 1); + + + yaffs_SetObjectName(in, oh->name); + parent = + yaffs_FindOrCreateObjectByNumber + (dev, oh->parentObjectId, + YAFFS_OBJECT_TYPE_DIRECTORY); + + fileSize = oh->fileSize; + isShrink = oh->isShrink; + equivalentObjectId = oh->equivalentObjectId; + } + else { + in->variantType = tags.extraObjectType; + parent = + yaffs_FindOrCreateObjectByNumber + (dev, tags.extraParentObjectId, + YAFFS_OBJECT_TYPE_DIRECTORY); + fileSize = tags.extraFileLength; + isShrink = tags.extraIsShrinkHeader; + equivalentObjectId = tags.extraEquivalentObjectId; + in->lazyLoaded = 1; - yaffs_SetObjectName(in, oh->name); + } in->dirty = 0; /* directory stuff... * hook up to parent */ - parent = - yaffs_FindOrCreateObjectByNumber - (dev, oh->parentObjectId, - YAFFS_OBJECT_TYPE_DIRECTORY); if (parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN) { /* Set up as a directory */ @@ -4755,13 +4920,10 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) 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; - } + itsUnlinked = (parent == dev->deletedDir) || + (parent == dev->unlinkedDir); - if (oh->isShrink) { + if (isShrink) { /* Mark the block as having a shrinkHeader */ bi->hasShrinkHeader = 1; } @@ -4780,33 +4942,31 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) case YAFFS_OBJECT_TYPE_FILE: if (in->variant.fileVariant. - scannedFileSize < - oh->fileSize) { + scannedFileSize < fileSize) { /* This covers the case where the file size is greater * than where the data is * This will happen if the file is resized to be larger * than its current data extents. */ - in->variant.fileVariant.fileSize = - oh->fileSize; + in->variant.fileVariant.fileSize = fileSize; in->variant.fileVariant.scannedFileSize = in->variant.fileVariant.fileSize; } - if (oh->isShrink && - in->variant.fileVariant.shrinkSize > - oh->fileSize) { - in->variant.fileVariant.shrinkSize = - oh->fileSize; + if (isShrink && + in->variant.fileVariant.shrinkSize > fileSize) { + in->variant.fileVariant.shrinkSize = fileSize; } break; case YAFFS_OBJECT_TYPE_HARDLINK: - in->variant.hardLinkVariant.equivalentObjectId = - oh->equivalentObjectId; - in->hardLinks.next = + if(!itsUnlinked) { + in->variant.hardLinkVariant.equivalentObjectId = + equivalentObjectId; + in->hardLinks.next = (struct list_head *) hardList; - hardList = in; + hardList = in; + } break; case YAFFS_OBJECT_TYPE_DIRECTORY: /* Do nothing */ @@ -4815,8 +4975,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) /* Do nothing */ break; case YAFFS_OBJECT_TYPE_SYMLINK: - in->variant.symLinkVariant. - alias = + if(oh) + in->variant.symLinkVariant.alias = yaffs_CloneString(oh-> alias); break; @@ -4910,6 +5070,18 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) /*------------------------------ Directory Functions ----------------------------- */ +static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) +{ + yaffs_Device *dev = obj->myDev; + + if(dev && dev->removeObjectCallback) + dev->removeObjectCallback(obj); + + list_del_init(&obj->siblings); + obj->parent = NULL; +} + + static void yaffs_AddObjectToDirectory(yaffs_Object * directory, yaffs_Object * obj) { @@ -4935,7 +5107,7 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory, } else if (!list_empty(&obj->siblings)) { /* If it is holed up somewhere else, un hook it */ - list_del_init(&obj->siblings); + yaffs_RemoveObjectFromDirectory(obj); } /* Now add it */ list_add(&obj->siblings, &directory->variant.directoryVariant.children); @@ -4949,12 +5121,6 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory, } } -static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) -{ - list_del_init(&obj->siblings); - obj->parent = NULL; -} - yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, const YCHAR * name) { @@ -4988,6 +5154,8 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, list_for_each(i, &directory->variant.directoryVariant.children) { if (i) { l = list_entry(i, yaffs_Object, siblings); + + yaffs_CheckObjectDetailsLoaded(l); /* Special case for lost-n-found */ if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) { @@ -5065,6 +5233,8 @@ yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj) int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) { memset(name, 0, buffSize * sizeof(YCHAR)); + + yaffs_CheckObjectDetailsLoaded(obj); if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) { yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1); @@ -5297,7 +5467,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) int extraBits; int nBlocks; - T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR))); + T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR))); /* Check stuff that must be set */ @@ -5380,16 +5550,33 @@ int yaffs_GutsInitialise(yaffs_Device * dev) if (extraBits > 0) bits++; - - /* Level0 Tnodes are 16 bits, so if the bitwidth of the + + /* Set up tnode width if wide tnodes are enabled. */ + if(!dev->wideTnodesDisabled){ + /* bits must be even so that we end up with 32-bit words */ + if(bits & 1) + bits++; + if(bits < 16) + dev->tnodeWidth = 16; + else + dev->tnodeWidth = bits; + } + else + dev->tnodeWidth = 16; + + dev->tnodeMask = (1<tnodeWidth)-1; + + /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled), + * so if the bitwidth of the * chunk range we're using is greater than 16 we need * to figure out chunk shift and chunkGroupSize */ - if (bits <= 16) { + + if (bits <= dev->tnodeWidth) dev->chunkGroupBits = 0; - } else { - dev->chunkGroupBits = bits - 16; - } + else + dev->chunkGroupBits = bits - dev->tnodeWidth; + dev->chunkGroupSize = 1 << dev->chunkGroupBits; @@ -5500,7 +5687,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) yaffs_VerifyFreeChunks(dev); - T(YAFFS_TRACE_ALWAYS, + T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); return YAFFS_OK; @@ -5576,6 +5763,8 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev) nFree = yaffs_CountFreeChunks(dev); #endif + nFree += dev->nDeletedFiles; + /* Now count the number of dirty chunks in the cache and subtract those */ {