X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=f9819f0428b578cb532d3a7a48ebdf9c44d44273;hp=fda5f8b311e47b50efafecf619e5d35ac0ff916b;hb=d62fba5f7dc6974473dab1612dca6504afa4c702;hpb=47f0aa3a5008048dd068bbc7fef87650d5df12fb diff --git a/yaffs_guts.c b/yaffs_guts.c index fda5f8b..f9819f0 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -12,7 +12,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.93 2009-11-07 02:06:58 charles Exp $"; + "$Id: yaffs_guts.c,v 1.105 2010-01-06 04:02:12 charles Exp $"; #include "yportenv.h" @@ -113,6 +113,12 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, yaffs_FileStructure *fStruct, __u32 chunkId); +static void yaffs_SkipRestOfBlock(yaffs_Device *dev); +static int yaffs_VerifyChunkWritten(yaffs_Device *dev, + int chunkInNAND, + const __u8 *data, + yaffs_ExtendedTags *tags); + /* Function to calculate chunk and offset */ static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, @@ -548,8 +554,8 @@ static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, if (!(tags && obj && oh)) { T(YAFFS_TRACE_VERIFY, - (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR), - (__u32)tags, (__u32)obj, (__u32)oh)); + (TSTR("Verifying object header tags %p obj %p oh %p"TENDSTR), + tags, obj, oh)); return; } @@ -918,6 +924,29 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, } + +static int yaffs_VerifyChunkWritten(yaffs_Device *dev, + int chunkInNAND, + const __u8 *data, + yaffs_ExtendedTags *tags) +{ + int retval = YAFFS_OK; + yaffs_ExtendedTags tempTags; + __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__); + int result; + + result = yaffs_ReadChunkWithTagsFromNAND(dev,chunkInNAND,buffer,&tempTags); + if(memcmp(buffer,data,dev->nDataBytesPerChunk) || + tempTags.objectId != tags->objectId || + tempTags.chunkId != tags->chunkId || + tempTags.byteCount != tags->byteCount) + retval = YAFFS_FAIL; + + yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); + + return retval; +} + static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, const __u8 *data, yaffs_ExtendedTags *tags, @@ -957,12 +986,11 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, * chunk due to power loss. This checking policy should * catch that case with very few checks and thus save a * lot of checks that are most likely not needed. + * + * Mods to the above + * If an erase check fails or the write fails we skip the + * rest of the block. */ - if (bi->gcPrioritise) { - yaffs_DeleteChunk(dev, chunk, 1, __LINE__); - /* try another chunk */ - continue; - } /* let's give it a try */ attempts++; @@ -977,20 +1005,30 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, (TSTR("**>> yaffs chunk %d was not erased" TENDSTR), chunk)); - /* try another chunk */ + /* If not erased, delete this one, + * skip rest of block and + * try another chunk */ + yaffs_DeleteChunk(dev,chunk,1,__LINE__); + yaffs_SkipRestOfBlock(dev); continue; } - bi->skipErasedCheck = 1; } writeOk = yaffs_WriteChunkWithTagsToNAND(dev, chunk, data, tags); + + if(!bi->skipErasedCheck) + writeOk = yaffs_VerifyChunkWritten(dev, chunk, data, tags); + if (writeOk != YAFFS_OK) { + /* Clean up aborted write, skip to next block and + * try another chunk */ yaffs_HandleWriteChunkError(dev, chunk, erasedOk); - /* try another chunk */ continue; } + bi->skipErasedCheck = 1; + /* Copy the data into the robustification buffer */ yaffs_HandleWriteChunkOk(dev, chunk, data, tags); @@ -1100,6 +1138,7 @@ static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND, /* Delete the chunk */ yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__); + yaffs_SkipRestOfBlock(dev); } @@ -1130,7 +1169,7 @@ static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name) { #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM memset(obj->shortName, 0, sizeof(YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); - if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) + if (name && yaffs_strnlen(name,YAFFS_SHORT_NAME_LENGTH+1) <= YAFFS_SHORT_NAME_LENGTH) yaffs_strcpy(obj->shortName, name); else obj->shortName[0] = _Y('\0'); @@ -1312,6 +1351,7 @@ static void yaffs_DeinitialiseTnodes(yaffs_Device *dev) dev->freeTnodes = NULL; dev->nFreeTnodes = 0; + dev->nTnodesCreated = 0; } static void yaffs_InitialiseTnodes(yaffs_Device *dev) @@ -1323,7 +1363,7 @@ static void yaffs_InitialiseTnodes(yaffs_Device *dev) } -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; @@ -1481,13 +1521,13 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, 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 */ @@ -1506,6 +1546,8 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, 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 */ @@ -1518,6 +1560,8 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, } else if (!tn->internal[x]) { /* Don't have one, none passed in */ tn->internal[x] = yaffs_GetTnode(dev); + if(!tn->internal[x]) + return NULL; } } @@ -1641,7 +1685,7 @@ static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, } - yaffs_PutLevel0Tnode(dev, tn, i, 0); + yaffs_LoadLevel0Tnode(dev, tn, i, 0); } } @@ -1718,7 +1762,7 @@ static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, * a block. */ yaffs_SoftDeleteChunk(dev, theChunk); - yaffs_PutLevel0Tnode(dev, tn, i, 0); + yaffs_LoadLevel0Tnode(dev, tn, i, 0); } } @@ -1764,6 +1808,10 @@ static void yaffs_SoftDeleteFile(yaffs_Object *obj) * level 0 tnode entries must be zeroed out. * Could also use this for file deletion, but that's probably better handled * by a special case. + * + * This function is recursive. For levels > 0 the function is called again on + * any sub-tree. For level == 0 we just check if the sub-tree has data. + * If there is no data in a subtree then it is pruned. */ static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn, @@ -1775,17 +1823,32 @@ static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn, if (tn) { hasData = 0; - for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) { - if (tn->internal[i] && level > 0) { - tn->internal[i] = - yaffs_PruneWorker(dev, tn->internal[i], - level - 1, - (i == 0) ? del0 : 1); + if(level > 0){ + for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) { + if (tn->internal[i]) { + tn->internal[i] = + yaffs_PruneWorker(dev, tn->internal[i], + level - 1, + (i == 0) ? del0 : 1); + } + + if (tn->internal[i]) + hasData++; } + } else { + int tnodeSize; + __u32 *map = (__u32 *)tn; + tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; - if (tn->internal[i]) - hasData++; - } + if (tnodeSize < sizeof(yaffs_Tnode)) + tnodeSize = sizeof(yaffs_Tnode); + tnodeSize /= sizeof(__u32); + + for(i = 0; !hasData && i < tnodeSize; i++){ + if(map[i]) + hasData++; + } + } if (hasData == 0 && del0) { /* Free and return NULL */ @@ -1860,10 +1923,14 @@ static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects) list = YMALLOC(sizeof(yaffs_ObjectList)); if (!newObjects || !list) { - if (newObjects) + if (newObjects){ YFREE(newObjects); - if (list) + newObjects = NULL; + } + if (list){ YFREE(list); + list = NULL; + } T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Could not allocate more objects" TENDSTR))); return YAFFS_FAIL; @@ -1983,9 +2050,7 @@ static void yaffs_FreeObject(yaffs_Object *tn) { yaffs_Device *dev = tn->myDev; -#ifdef __KERNEL__ T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), tn, tn->myInode)); -#endif if (tn->parent) YBUG(); @@ -1993,7 +2058,6 @@ static void yaffs_FreeObject(yaffs_Object *tn) YBUG(); -#ifdef __KERNEL__ if (tn->myInode) { /* We're still hooked up to a cached inode. * Don't delete now, but mark for later deletion @@ -2001,12 +2065,12 @@ static void yaffs_FreeObject(yaffs_Object *tn) tn->deferedFree = 1; return; } -#endif yaffs_UnhashObject(tn); #ifdef VALGRIND_TEST YFREE(tn); + tn = NULL; #else /* Link into the free list. */ tn->siblings.next = (struct ylist_head *)(dev->freeObjects); @@ -2042,6 +2106,7 @@ static void yaffs_DeinitialiseObjects(yaffs_Device *dev) dev->freeObjects = NULL; dev->nFreeObjects = 0; + dev->nObjectsCreated = 0; } static void yaffs_InitialiseObjects(yaffs_Device *dev) @@ -2169,18 +2234,20 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number, 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_FreeObject(theObject); + if (!tn) return NULL; - } } + theObject = yaffs_AllocateEmptyObject(dev); + if (!theObject){ + if(tn) + yaffs_FreeTnode(dev,tn); + return NULL; + } + + if (theObject) { theObject->fake = 0; theObject->renameAllowed = 1; @@ -2246,13 +2313,17 @@ static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, static YCHAR *yaffs_CloneString(const YCHAR *str) { YCHAR *newStr = NULL; + int len; - if (str && *str) { - newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR)); - if (newStr) - yaffs_strcpy(newStr, str); - } + if (!str) + str = _Y(""); + len = yaffs_strnlen(str,YAFFS_MAX_ALIAS_LENGTH); + newStr = YMALLOC((len + 1) * sizeof(YCHAR)); + if (newStr){ + yaffs_strncpy(newStr, str,len); + newStr[len] = 0; + } return newStr; } @@ -2260,7 +2331,7 @@ static YCHAR *yaffs_CloneString(const YCHAR *str) /* * Mknod (create) a new object. * equivalentObject only has meaning for a hard link; - * aliasString only has meaning for a sumlink. + * aliasString only has meaning for a symlink. * rdev only has meaning for devices (a subset of special objects) */ @@ -2282,21 +2353,23 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, 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_FreeObject(in); + if (!str) return NULL; - } + } + + in = yaffs_CreateNewObject(dev, -1, type); + + if (!in){ + if(str) + YFREE(str); + return NULL; } + if (in) { in->hdrChunk = 0; in->valid = 1; @@ -2485,7 +2558,7 @@ int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, force = 1; #endif - if(yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) + if(yaffs_strnlen(newName,YAFFS_MAX_NAME_LENGTH+1) > YAFFS_MAX_NAME_LENGTH) /* ENAMETOOLONG */ return YAFFS_FAIL; @@ -2962,6 +3035,22 @@ static int yaffs_GetErasedChunks(yaffs_Device *dev) } +/* + * yaffs_SkipRestOfBlock() skips over the rest of the allocation block + * if we don't want to write to it. + */ +static void yaffs_SkipRestOfBlock(yaffs_Device *dev) +{ + if(dev->allocationBlock > 0){ + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->allocationBlock); + if(bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING){ + bi->blockState = YAFFS_BLOCK_STATE_FULL; + dev->allocationBlock = -1; + } + } +} + + static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, int wholeBlock) { @@ -3121,6 +3210,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, if (tags.chunkId == 0) { /* It is an object Id, * We need to nuke the shrinkheader flags first + * Also need to clean up shadowing. * We no longer want the shrinkHeader flag since its work is done * and if it is left in place it will mess up scanning. */ @@ -3129,6 +3219,9 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, oh = (yaffs_ObjectHeader *)buffer; oh->isShrink = 0; tags.extraIsShrinkHeader = 0; + oh->shadowsObject = 0; + oh->inbandShadowsObject = 0; + tags.extraShadows = 0; yaffs_VerifyObjectHeader(object, oh, &tags, 1); } @@ -3353,7 +3446,7 @@ static int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in, int chunkInInode, /* 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; @@ -3423,6 +3516,8 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, /* 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; @@ -3454,6 +3549,11 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, NULL); if (!tn) return YAFFS_FAIL; + + if(!chunkInNAND) + /* Dummy insert, bail now */ + return YAFFS_OK; + existingChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode); @@ -3535,7 +3635,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, if (existingChunk == 0) in->nDataChunks++; - yaffs_PutLevel0Tnode(dev, tn, chunkInInode, chunkInNAND); + yaffs_LoadLevel0Tnode(dev, tn, chunkInInode, chunkInNAND); return YAFFS_OK; } @@ -3657,12 +3757,20 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object *in, int chunkInInode, (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes)); 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) @@ -3692,6 +3800,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, int newChunkId; yaffs_ExtendedTags newTags; yaffs_ExtendedTags oldTags; + YCHAR *alias = NULL; __u8 *buffer = NULL; YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1]; @@ -3780,8 +3889,11 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, /* Do nothing */ break; case YAFFS_OBJECT_TYPE_SYMLINK: + alias = in->variant.symLinkVariant.alias; + if(!alias) + alias = _Y("no alias"); yaffs_strncpy(oh->alias, - in->variant.symLinkVariant.alias, + alias, YAFFS_MAX_ALIAS_LENGTH); oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0; break; @@ -4424,8 +4536,8 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) cp.structType = sizeof(cp); T(YAFFS_TRACE_CHECKPOINT, ( - TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR), - cp.objectId, cp.parentId, cp.variantType, cp.hdrChunk, (unsigned) obj)); + TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %p" TENDSTR), + cp.objectId, cp.parentId, cp.variantType, cp.hdrChunk, obj)); ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); @@ -4458,7 +4570,7 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); if (cp.structType != sizeof(cp)) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("struct size %d instead of %d ok %d"TENDSTR), - cp.structType, sizeof(cp), ok)); + cp.structType, (int)sizeof(cp), ok)); ok = 0; } @@ -5060,13 +5172,17 @@ int yaffs_ResizeFile(yaffs_Object *in, loff_t newSize) loff_t yaffs_GetFileSize(yaffs_Object *obj) { + YCHAR *alias = NULL; obj = yaffs_GetEquivalentObject(obj); switch (obj->variantType) { case YAFFS_OBJECT_TYPE_FILE: return obj->variant.fileVariant.fileSize; case YAFFS_OBJECT_TYPE_SYMLINK: - return yaffs_strlen(obj->variant.symLinkVariant.alias); + alias = obj->variant.symLinkVariant.alias; + if(!alias) + return 0; + return yaffs_strnlen(alias,YAFFS_MAX_ALIAS_LENGTH); default: return 0; } @@ -5134,13 +5250,8 @@ static int yaffs_UnlinkFileIfNeeded(yaffs_Object *in) int retVal; int immediateDeletion = 0; -#ifdef __KERNEL__ if (!in->myInode) immediateDeletion = 1; -#else - if (in->inUse <= 0) - immediateDeletion = 1; -#endif if (immediateDeletion) { retVal = @@ -5212,7 +5323,9 @@ static int yaffs_DeleteDirectory(yaffs_Object *obj) static int yaffs_DeleteSymLink(yaffs_Object *in) { - YFREE(in->variant.symLinkVariant.alias); + if(in->variant.symLinkVariant.alias) + YFREE(in->variant.symLinkVariant.alias); + in->variant.symLinkVariant.alias=NULL; return yaffs_DoGenericObjectDeletion(in); } @@ -5258,13 +5371,8 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj) int immediateDeletion = 0; -#ifdef __KERNEL__ if (!obj->myInode) immediateDeletion = 1; -#else - if (obj->inUse <= 0) - immediateDeletion = 1; -#endif if(obj) yaffs_UpdateParent(obj->parent); @@ -5281,23 +5389,26 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj) * Instead, we do the following: * - Select a hardlink. * - Unhook it from the hard links - * - Unhook it from its parent directory (so that the rename can work) + * - Move it from its parent directory (so that the rename can work) * - Rename the object to the hardlink's name. * - Delete the hardlink */ yaffs_Object *hl; + yaffs_Object *parent; int retVal; YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks); + yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1); + parent = hl->parent; + ylist_del_init(&hl->hardLinks); - ylist_del_init(&hl->siblings); - yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1); + yaffs_AddObjectToDirectory(obj->myDev->unlinkedDir, hl); - retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0); + retVal = yaffs_ChangeObjectName(obj,parent, name, 0, 0); if (retVal == YAFFS_OK) retVal = yaffs_DoGenericObjectDeletion(hl); @@ -5712,7 +5823,7 @@ static int yaffs_Scan(yaffs_Device *dev) dev->allocationBlock = blk; dev->allocationPage = c; dev->allocationBlockFinder = blk; - /* Set it to here to encourage the allocator to go forth from here. */ + /* Set block finder here to encourage the allocator to go forth from here. */ } @@ -5958,12 +6069,6 @@ static int yaffs_Scan(yaffs_Device *dev) break; } -/* - if (parent == dev->deletedDir) { - yaffs_DestroyObject(in); - bi->hasShrinkHeader = 1; - } -*/ } } } @@ -5973,6 +6078,12 @@ static int yaffs_Scan(yaffs_Device *dev) state = YAFFS_BLOCK_STATE_FULL; } + if (state == YAFFS_BLOCK_STATE_ALLOCATING) { + /* If the block was partially allocated then treat it as fully allocated.*/ + state = YAFFS_BLOCK_STATE_FULL; + dev->allocationBlock = -1; + } + bi->blockState = state; /* Now let's see if it was dirty */ @@ -6315,13 +6426,9 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) dev->allocationBlockFinder = blk; } else { /* This is a partially written block that is not - * the current allocation block. This block must have - * had a write failure, so set up for retirement. + * the current allocation block. */ - /* bi->needsRetiring = 1; ??? TODO */ - bi->gcPrioritise = 1; - T(YAFFS_TRACE_ALWAYS, (TSTR("Partially written block %d detected" TENDSTR), blk)); @@ -6583,6 +6690,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) oh-> shadowsObject, 1); + yaffs_SetObjectName(in, oh->name); @@ -6714,6 +6822,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) state = YAFFS_BLOCK_STATE_FULL; } + bi->blockState = state; /* Now let's see if it was dirty */ @@ -6724,6 +6833,8 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) } } + + yaffs_SkipRestOfBlock(dev); if (altBlockIndex) YFREE_ALT(blockIndex); @@ -7048,7 +7159,7 @@ int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize) } #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM else if (obj->shortName[0]) - yaffs_strcpy(name, obj->shortName); + yaffs_strncpy(name, obj->shortName,YAFFS_SHORT_NAME_LENGTH+1); #endif else { int result; @@ -7064,11 +7175,12 @@ int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize) NULL); } yaffs_strncpy(name, oh->name, buffSize - 1); + name[buffSize-1]=0; yaffs_ReleaseTempBuffer(obj->myDev, buffer, __LINE__); } - return yaffs_strlen(name); + return yaffs_strnlen(name,buffSize-1); } int yaffs_GetObjectFileLength(yaffs_Object *obj) @@ -7078,9 +7190,11 @@ int yaffs_GetObjectFileLength(yaffs_Object *obj) if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) return obj->variant.fileVariant.fileSize; - if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) - return yaffs_strlen(obj->variant.symLinkVariant.alias); - else { + if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK){ + if(!obj->variant.symLinkVariant.alias) + return 0; + return yaffs_strnlen(obj->variant.symLinkVariant.alias,YAFFS_MAX_ALIAS_LENGTH); + } else { /* Only a directory should drop through to here */ return obj->myDev->nDataBytesPerChunk; } @@ -7717,7 +7831,7 @@ static void yaffs_VerifyFreeChunks(yaffs_Device *dev) do { \ if (sizeof(structure) != syze) { \ T(YAFFS_TRACE_ALWAYS, (TSTR("%s should be %d but is %d\n" TENDSTR),\ - name, syze, sizeof(structure))); \ + name, syze, (int) sizeof(structure))); \ return YAFFS_FAIL; \ } \ } while (0) @@ -7728,7 +7842,7 @@ static int yaffs_CheckStructures(void) /* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */ /* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */ #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG - yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode"); +/* yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode"); */ #endif #ifndef CONFIG_YAFFS_WINCE yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");