X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=58e9442cc688c0663deff80eea0352f51c974850;hp=d55aa95b91e450758bf54474e047f7766100515f;hb=29e2dccbc8145ce3fd337a91a266d29e9b0f3f60;hpb=33549d2970236600573ab2609045400a898a7247 diff --git a/yaffs_guts.c b/yaffs_guts.c index d55aa95..58e9442 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -19,9 +19,8 @@ #include "yaffs_getblockinfo.h" #include "yaffs_tagscompat.h" -#ifndef CONFIG_YAFFS_USE_OWN_SORT #include "yaffs_qsort.h" -#endif + #include "yaffs_nand.h" #include "yaffs_checkptrw.h" @@ -29,6 +28,8 @@ #include "yaffs_nand.h" #include "yaffs_packedtags2.h" +#include "yaffs_nameval.h" +#include "yaffs_allocator.h" /* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */ #define YAFFS_GC_GOOD_ENOUGH 2 @@ -46,6 +47,15 @@ #include "yaffs_ecc.h" +/* Private structure for doing xattr modifications */ +typedef struct { + int set; /* If 0 then this is a deletion */ + const char *name; + const void *data; + int size; + int flags; + int result; +} yaffs_XAttrMod; /* Robustification (if it ever comes about...) */ static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND); @@ -76,7 +86,9 @@ static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number, static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj); static int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, - int force, int isShrink, int shadows); + int force, int isShrink, int shadows, yaffs_XAttrMod *xop); +static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod); + static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj); static int yaffs_CheckStructures(void); static int yaffs_DoGenericObjectDeletion(yaffs_Object *in); @@ -109,7 +121,7 @@ static int yaffs_CheckFileSanity(yaffs_Object *in); static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in); static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId); -static void yaffs_InvalidateCheckpoint(yaffs_Device *dev); +static void yaffs2_InvalidateCheckpoint(yaffs_Device *dev); static int yaffs_FindChunkInFile(yaffs_Object *in, int chunkInInode, yaffs_ExtendedTags *tags); @@ -120,7 +132,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, yaffs_FileStructure *fStruct, __u32 chunkId); -static int yaffs_HandleHole(yaffs_Object *obj, loff_t newSize); +static int yaffs2_HandleHole(yaffs_Object *obj, loff_t newSize); static void yaffs_SkipRestOfBlock(yaffs_Device *dev); static int yaffs_VerifyChunkWritten(yaffs_Device *dev, int chunkInNAND, @@ -440,6 +452,17 @@ static const char *blockStateName[] = { "Dead" }; +static void yaffs2_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n) +{ + if (!dev->param.isYaffs2) + return; + + if((bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) && + (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000)) + T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has suspect sequence number of %d"TENDSTR), + n, bi->sequenceNumber)); +} + static void yaffs_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n) { int actuallyUsed; @@ -480,13 +503,12 @@ static void yaffs_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n) /* Check that the sequence number is valid. * Ten million is legal, but is very unlikely */ - if (dev->param.isYaffs2 && - (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) && - (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000)) - T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has suspect sequence number of %d"TENDSTR), - n, bi->sequenceNumber)); + + yaffs2_VerifyBlock(dev,bi,n); } + + static void yaffs_VerifyCollectedBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n) { @@ -963,7 +985,7 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, int writeOk = 0; int chunk; - yaffs_InvalidateCheckpoint(dev); + yaffs2_InvalidateCheckpoint(dev); do { yaffs_BlockInfo *bi = 0; @@ -1061,11 +1083,11 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, * Oldest Dirty Sequence Number handling. */ -/* yaffs_CalcOldestDirtySequence() - * yaffs_FindOldestDirtySequence() +/* yaffs2_CalcOldestDirtySequence() + * yaffs2_FindOldestDirtySequence() * Calculate the oldest dirty sequence number if we don't know it. */ -static void yaffs_CalcOldestDirtySequence(yaffs_Device *dev) +static void yaffs2_CalcOldestDirtySequence(yaffs_Device *dev) { int i; unsigned seq; @@ -1096,10 +1118,13 @@ static void yaffs_CalcOldestDirtySequence(yaffs_Device *dev) } -static void yaffs_FindOldestDirtySequence(yaffs_Device *dev) +static void yaffs2_FindOldestDirtySequence(yaffs_Device *dev) { - if(dev->param.isYaffs2 && !dev->oldestDirtySequence) - yaffs_CalcOldestDirtySequence(dev); + if(!dev->param.isYaffs2) + return; + + if(!dev->oldestDirtySequence) + yaffs2_CalcOldestDirtySequence(dev); } /* @@ -1108,7 +1133,7 @@ static void yaffs_FindOldestDirtySequence(yaffs_Device *dev) * becomes invalid). If the value matches the oldest then we clear * dev->oldestDirtySequence to force its recomputation. */ -static void yaffs_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi) +static void yaffs2_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi) { if(!dev->param.isYaffs2) @@ -1121,13 +1146,16 @@ static void yaffs_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *b } /* - * yaffs_UpdateOldestDirtySequence() + * yaffs2_UpdateOldestDirtySequence() * Update the oldest dirty sequence number whenever we dirty a block. * Only do this if the oldestDirtySequence is actually being tracked. */ -static void yaffs_UpdateOldestDirtySequence(yaffs_Device *dev, unsigned blockNo, yaffs_BlockInfo *bi) +static void yaffs2_UpdateOldestDirtySequence(yaffs_Device *dev, unsigned blockNo, yaffs_BlockInfo *bi) { - if(dev->param.isYaffs2 && dev->oldestDirtySequence){ + if(!dev->param.isYaffs2) + return; + + if(dev->oldestDirtySequence){ if(dev->oldestDirtySequence > bi->sequenceNumber){ dev->oldestDirtySequence = bi->sequenceNumber; dev->oldestDirtyBlock = blockNo; @@ -1143,9 +1171,9 @@ static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND) { yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); - yaffs_InvalidateCheckpoint(dev); + yaffs2_InvalidateCheckpoint(dev); - yaffs_ClearOldestDirtySequence(dev,bi); + yaffs2_ClearOldestDirtySequence(dev,bi); if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) { if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) { @@ -1279,194 +1307,33 @@ static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name) * in the tnode. */ -/* yaffs_CreateTnodes creates a bunch more tnodes and - * adds them to the tnode free list. - * Don't use this function directly - */ -static Y_INLINE int yaffs_CalcTnodeSize(yaffs_Device *dev) -{ - int tnodeSize; - /* 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; - if (tnodeSize < sizeof(yaffs_Tnode)) - tnodeSize = sizeof(yaffs_Tnode); - return tnodeSize; -} - -static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes) +static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev) { - int i; - int tnodeSize = yaffs_CalcTnodeSize(dev); - yaffs_Tnode *newTnodes; - __u8 *mem; - yaffs_Tnode *curr; - yaffs_Tnode *next; - yaffs_TnodeList *tnl; - - if (nTnodes < 1) - return YAFFS_OK; - - - /* make these things */ - - newTnodes = YMALLOC(nTnodes * tnodeSize); - mem = (__u8 *)newTnodes; - - if (!newTnodes) { - T(YAFFS_TRACE_ERROR, - (TSTR("yaffs: Could not allocate Tnodes" TENDSTR))); - return YAFFS_FAIL; - } - - /* 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 - newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1; -#endif - } - - newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes; -#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG - 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; - - /* Now add this bunch of tnodes to a list for freeing up. - * NB If we can't add this to the management list it isn't fatal - * but it just means we can't free this bunch of tnodes later. - */ - - tnl = YMALLOC(sizeof(yaffs_TnodeList)); - if (!tnl) { - T(YAFFS_TRACE_ERROR, - (TSTR - ("yaffs: Could not add tnodes to management list" TENDSTR))); - return YAFFS_FAIL; - } else { - tnl->tnodes = newTnodes; - tnl->next = dev->allocatedTnodeList; - dev->allocatedTnodeList = tnl; + yaffs_Tnode *tn = yaffs_AllocateRawTnode(dev); + if (tn){ + memset(tn, 0, dev->tnodeSize); + dev->nTnodes++; } - T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR))); - - return YAFFS_OK; -} - -/* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */ - -static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device *dev) -{ - yaffs_Tnode *tn = NULL; - -#ifdef CONFIG_YAFFS_VALGRIND_TEST - tn = YMALLOC(yaffs_CalcTnodeSize(dev)); - if(tn) - dev->nTnodesCreated++; -#else - /* If there are none left make more */ - if (!dev->freeTnodes) - yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES); - - if (dev->freeTnodes) { - tn = dev->freeTnodes; -#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG - if (tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) { - /* Hoosterman, this thing looks like it isn't in the list */ - T(YAFFS_TRACE_ALWAYS, - (TSTR("yaffs: Tnode list bug 1" TENDSTR))); - } -#endif - dev->freeTnodes = dev->freeTnodes->internal[0]; - dev->nFreeTnodes--; - } -#endif dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ return tn; } -static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev) -{ - yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev); - int tnodeSize = yaffs_CalcTnodeSize(dev); - - if (tn) - memset(tn, 0, tnodeSize); - - return tn; -} - /* FreeTnode frees up a tnode and puts it back on the free list */ static void yaffs_FreeTnode(yaffs_Device *dev, yaffs_Tnode *tn) { - if (tn) { -#ifdef CONFIG_YAFFS_VALGRIND_TEST - YFREE(tn); - dev->nTnodesCreated--; -#else -#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG - if (tn->internal[YAFFS_NTNODES_INTERNAL] != 0) { - /* Hoosterman, this thing looks like it is already in the list */ - T(YAFFS_TRACE_ALWAYS, - (TSTR("yaffs: Tnode list bug 2" TENDSTR))); - } - tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1; -#endif - tn->internal[0] = dev->freeTnodes; - dev->freeTnodes = tn; - dev->nFreeTnodes++; -#endif - } + yaffs_FreeRawTnode(dev,tn); + dev->nTnodes--; dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ } -static void yaffs_DeinitialiseTnodes(yaffs_Device *dev) +static void yaffs_DeinitialiseTnodesAndObjects(yaffs_Device *dev) { - /* Free the list of allocated tnodes */ - yaffs_TnodeList *tmp; - - while (dev->allocatedTnodeList) { - tmp = dev->allocatedTnodeList->next; - - YFREE(dev->allocatedTnodeList->tnodes); - YFREE(dev->allocatedTnodeList); - dev->allocatedTnodeList = tmp; - - } - - dev->freeTnodes = NULL; - dev->nFreeTnodes = 0; - dev->nTnodesCreated = 0; -} - -static void yaffs_InitialiseTnodes(yaffs_Device *dev) -{ - dev->allocatedTnodeList = NULL; - dev->freeTnodes = NULL; - dev->nFreeTnodes = 0; - dev->nTnodesCreated = 0; + yaffs_DeinitialiseRawTnodesAndObjects(dev); + dev->nObjects = 0; + dev->nTnodes = 0; } @@ -1822,7 +1689,7 @@ static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk) if (theBlock) { theBlock->softDeletions++; dev->nFreeChunks++; - yaffs_UpdateOldestDirtySequence(dev, blockNo, theBlock); + yaffs2_UpdateOldestDirtySequence(dev, blockNo, theBlock); } } @@ -1950,7 +1817,7 @@ static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn, hasData++; } } else { - int tnodeSize_u32 = yaffs_CalcTnodeSize(dev)/sizeof(__u32); + int tnodeSize_u32 = dev->tnodeSize/sizeof(__u32); __u32 *map = (__u32 *)tn; for(i = 0; !hasData && i < tnodeSize_u32; i++){ @@ -2015,96 +1882,32 @@ static int yaffs_PruneFileStructure(yaffs_Device *dev, /*-------------------- End of File Structure functions.-------------------*/ -/* yaffs_CreateFreeObjects creates a bunch more objects and - * adds them to the object free list. - */ -static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects) -{ - int i; - yaffs_Object *newObjects; - yaffs_ObjectList *list; - - if (nObjects < 1) - return YAFFS_OK; - - /* make these things */ - newObjects = YMALLOC(nObjects * sizeof(yaffs_Object)); - list = YMALLOC(sizeof(yaffs_ObjectList)); - - if (!newObjects || !list) { - if (newObjects){ - YFREE(newObjects); - newObjects = NULL; - } - if (list){ - YFREE(list); - list = NULL; - } - T(YAFFS_TRACE_ALLOCATE, - (TSTR("yaffs: Could not allocate more objects" TENDSTR))); - return YAFFS_FAIL; - } - - /* Hook them into the free list */ - for (i = 0; i < nObjects - 1; i++) { - newObjects[i].siblings.next = - (struct ylist_head *)(&newObjects[i + 1]); - } - - newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects; - dev->freeObjects = newObjects; - dev->nFreeObjects += nObjects; - dev->nObjectsCreated += nObjects; - - /* Now add this bunch of Objects to a list for freeing up. */ - - list->objects = newObjects; - list->next = dev->allocatedObjectList; - dev->allocatedObjectList = list; - - return YAFFS_OK; -} - /* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev) { - yaffs_Object *tn = NULL; + yaffs_Object *obj = yaffs_AllocateRawObject(dev); -#ifdef CONFIG_YAFFS_VALGRIND_TEST - tn = YMALLOC(sizeof(yaffs_Object)); - if(tn) - dev->nObjectsCreated++; -#else - /* If there are none left make more */ - if (!dev->freeObjects) - yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS); + if (obj) { + dev->nObjects++; - if (dev->freeObjects) { - tn = dev->freeObjects; - dev->freeObjects = - (yaffs_Object *) (dev->freeObjects->siblings.next); - dev->nFreeObjects--; - } -#endif - if (tn) { /* Now sweeten it up... */ - memset(tn, 0, sizeof(yaffs_Object)); - tn->beingCreated = 1; + memset(obj, 0, sizeof(yaffs_Object)); + obj->beingCreated = 1; - tn->myDev = dev; - tn->hdrChunk = 0; - tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN; - YINIT_LIST_HEAD(&(tn->hardLinks)); - YINIT_LIST_HEAD(&(tn->hashLink)); - YINIT_LIST_HEAD(&tn->siblings); + obj->myDev = dev; + obj->hdrChunk = 0; + obj->variantType = YAFFS_OBJECT_TYPE_UNKNOWN; + YINIT_LIST_HEAD(&(obj->hardLinks)); + YINIT_LIST_HEAD(&(obj->hashLink)); + YINIT_LIST_HEAD(&obj->siblings); /* Now make the directory sane */ if (dev->rootDir) { - tn->parent = dev->rootDir; - ylist_add(&(tn->siblings), &dev->rootDir->variant.directoryVariant.children); + obj->parent = dev->rootDir; + ylist_add(&(obj->siblings), &dev->rootDir->variant.directoryVariant.children); } /* Add it to the lost and found directory. @@ -2112,14 +1915,14 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev) * check if lostNFound exists first */ if (dev->lostNFoundDir) - yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn); + yaffs_AddObjectToDirectory(dev->lostNFoundDir, obj); - tn->beingCreated = 0; + obj->beingCreated = 0; } dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ - return tn; + return obj; } static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev, int number, @@ -2143,54 +1946,46 @@ static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev, int number, } -static void yaffs_UnhashObject(yaffs_Object *tn) +static void yaffs_UnhashObject(yaffs_Object *obj) { int bucket; - yaffs_Device *dev = tn->myDev; + yaffs_Device *dev = obj->myDev; /* If it is still linked into the bucket list, free from the list */ - if (!ylist_empty(&tn->hashLink)) { - ylist_del_init(&tn->hashLink); - bucket = yaffs_HashFunction(tn->objectId); + if (!ylist_empty(&obj->hashLink)) { + ylist_del_init(&obj->hashLink); + bucket = yaffs_HashFunction(obj->objectId); dev->objectBucket[bucket].count--; } } /* FreeObject frees up a Object and puts it back on the free list */ -static void yaffs_FreeObject(yaffs_Object *tn) +static void yaffs_FreeObject(yaffs_Object *obj) { - yaffs_Device *dev = tn->myDev; + yaffs_Device *dev = obj->myDev; - T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), tn, tn->myInode)); + T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), obj, obj->myInode)); - if (!tn) + if (!obj) YBUG(); - if (tn->parent) + if (obj->parent) YBUG(); - if (!ylist_empty(&tn->siblings)) + if (!ylist_empty(&obj->siblings)) YBUG(); - if (tn->myInode) { + if (obj->myInode) { /* We're still hooked up to a cached inode. * Don't delete now, but mark for later deletion */ - tn->deferedFree = 1; + obj->deferedFree = 1; return; } - yaffs_UnhashObject(tn); + yaffs_UnhashObject(obj); -#ifdef CONFIG_YAFFS_VALGRIND_TEST - YFREE(tn); - dev->nObjectsCreated--; - tn = NULL; -#else - /* Link into the free list. */ - tn->siblings.next = (struct ylist_head *)(dev->freeObjects); - dev->freeObjects = tn; - dev->nFreeObjects++; -#endif + yaffs_FreeRawObject(dev,obj); + dev->nObjects--; dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ } @@ -2201,33 +1996,14 @@ void yaffs_HandleDeferedFree(yaffs_Object *obj) yaffs_FreeObject(obj); } - -static void yaffs_DeinitialiseObjects(yaffs_Device *dev) -{ - /* Free the list of allocated Objects */ - - yaffs_ObjectList *tmp; - - while (dev->allocatedObjectList) { - tmp = dev->allocatedObjectList->next; - YFREE(dev->allocatedObjectList->objects); - YFREE(dev->allocatedObjectList); - - dev->allocatedObjectList = tmp; - } - - dev->freeObjects = NULL; - dev->nFreeObjects = 0; - dev->nObjectsCreated = 0; -} - -static void yaffs_InitialiseObjects(yaffs_Device *dev) +static void yaffs_InitialiseTnodesAndObjects(yaffs_Device *dev) { int i; - dev->allocatedObjectList = NULL; - dev->freeObjects = NULL; - dev->nFreeObjects = 0; + dev->nObjects = 0; + dev->nTnodes = 0; + + yaffs_InitialiseRawTnodesAndObjects(dev); for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { YINIT_LIST_HEAD(&dev->objectBucket[i].list); @@ -2519,7 +2295,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, break; } - if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) { + if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0, NULL) < 0) { /* Could not create the object header, fail the creation */ yaffs_DeleteObject(in); in = NULL; @@ -2627,7 +2403,7 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, obj->unlinked = 1; /* If it is a deletion then we mark it as a shrink for gc purposes. */ - if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows) >= 0) + if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows, NULL) >= 0) return YAFFS_OK; } @@ -2760,7 +2536,7 @@ static void yaffs_DeinitialiseBlocks(yaffs_Device *dev) dev->chunkBits = NULL; } -static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, +static int yaffs2_BlockNotDisqualifiedFromGC(yaffs_Device *dev, yaffs_BlockInfo *bi) { @@ -2770,7 +2546,7 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, if (!bi->hasShrinkHeader) return 1; /* can gc */ - yaffs_FindOldestDirtySequence(dev); + yaffs2_FindOldestDirtySequence(dev); /* Can't do gc of this block if there are any blocks older than this one that have * discarded pages. @@ -2779,11 +2555,11 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, } /* - * yaffs_FindRefreshBlock() + * yaffs2_FindRefreshBlock() * periodically finds the oldest full block by sequence number for refreshing. * Only for yaffs2. */ -static __u32 yaffs_FindRefreshBlock(yaffs_Device *dev) +static __u32 yaffs2_FindRefreshBlock(yaffs_Device *dev) { __u32 b ; @@ -2792,11 +2568,13 @@ static __u32 yaffs_FindRefreshBlock(yaffs_Device *dev) yaffs_BlockInfo *bi; + if(!dev->param.isYaffs2) + return oldest; + /* * If refresh period < 10 then refreshing is disabled. */ - if(dev->param.refreshPeriod < 10 || - !dev->param.isYaffs2) + if(dev->param.refreshPeriod < 10) return oldest; /* @@ -2853,7 +2631,7 @@ static void yaffs_BlockBecameDirty(yaffs_Device *dev, int blockNo) (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR), blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : "")); - yaffs_ClearOldestDirtySequence(dev,bi); + yaffs2_ClearOldestDirtySequence(dev,bi); bi->blockState = YAFFS_BLOCK_STATE_DIRTY; @@ -2868,7 +2646,7 @@ static void yaffs_BlockBecameDirty(yaffs_Device *dev, int blockNo) } if (!bi->needsRetiring) { - yaffs_InvalidateCheckpoint(dev); + yaffs2_InvalidateCheckpoint(dev); erasedOk = yaffs_EraseBlockInNAND(dev, blockNo); if (!erasedOk) { dev->nErasureFailures++; @@ -2964,29 +2742,39 @@ static int yaffs_FindBlockForAllocation(yaffs_Device *dev) -static int yaffs_CheckpointRequired(yaffs_Device *dev) +static int yaffs2_CheckpointRequired(yaffs_Device *dev) { - int nblocks = dev->internalEndBlock - dev->internalStartBlock + 1 ; - return dev->param.isYaffs2 && - !dev->param.skipCheckpointWrite && + int nblocks; + + if(!dev->param.isYaffs2) + return 0; + + nblocks = dev->internalEndBlock - dev->internalStartBlock + 1 ; + + return !dev->param.skipCheckpointWrite && (nblocks >= YAFFS_CHECKPOINT_MIN_BLOCKS); } -static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev) + +static int yaffs2_CalcCheckpointBlocksRequired(yaffs_Device *dev) { + int retval; + + if(!dev->param.isYaffs2) + return 0; + if (!dev->nCheckpointBlocksRequired && - yaffs_CheckpointRequired(dev)){ + yaffs2_CheckpointRequired(dev)){ /* Not a valid value so recalculate */ int nBytes = 0; int nBlocks; int devBlocks = (dev->param.endBlock - dev->param.startBlock + 1); - int tnodeSize = yaffs_CalcTnodeSize(dev); nBytes += sizeof(yaffs_CheckpointValidity); nBytes += sizeof(yaffs_CheckpointDevice); nBytes += devBlocks * sizeof(yaffs_BlockInfo); nBytes += devBlocks * dev->chunkBitmapStride; - nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects); - nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes); + nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjects); + nBytes += (dev->tnodeSize + sizeof(__u32)) * (dev->nTnodes); nBytes += sizeof(yaffs_CheckpointValidity); nBytes += sizeof(__u32); /* checksum*/ @@ -2997,7 +2785,10 @@ static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev) dev->nCheckpointBlocksRequired = nBlocks; } - return dev->nCheckpointBlocksRequired; + retval = dev->nCheckpointBlocksRequired - dev->blocksInCheckpoint; + if(retval < 0) + retval = 0; + return retval; } /* @@ -3010,14 +2801,7 @@ static int yaffs_CheckSpaceForAllocation(yaffs_Device *dev, int nChunks) int reservedBlocks = dev->param.nReservedBlocks; int checkpointBlocks; - if (dev->param.isYaffs2) { - checkpointBlocks = yaffs_CalcCheckpointBlocksRequired(dev) - - dev->blocksInCheckpoint; - if (checkpointBlocks < 0) - checkpointBlocks = 0; - } else { - checkpointBlocks = 0; - } + checkpointBlocks = yaffs2_CalcCheckpointBlocksRequired(dev); reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->param.nChunksPerBlock); @@ -3404,7 +3188,7 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev, if (bi->gcPrioritise) { prioritisedExists = 1; if (bi->blockState == YAFFS_BLOCK_STATE_FULL && - yaffs_BlockNotDisqualifiedFromGC(dev, bi)) { + yaffs2_BlockNotDisqualifiedFromGC(dev, bi)) { selected = i; prioritised = 1; } @@ -3470,7 +3254,7 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev, if (bi->blockState == YAFFS_BLOCK_STATE_FULL && pagesUsed < dev->param.nChunksPerBlock && (dev->gcDirtiest < 1 || pagesUsed < dev->gcPagesInUse) && - yaffs_BlockNotDisqualifiedFromGC(dev, bi)) { + yaffs2_BlockNotDisqualifiedFromGC(dev, bi)) { dev->gcDirtiest = dev->gcBlockFinder; dev->gcPagesInUse = pagesUsed; } @@ -3487,7 +3271,7 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev, if(!selected && dev->param.isYaffs2 && dev->gcNotDone >= ( background ? 10 : 20)){ - yaffs_FindOldestDirtySequence(dev); + yaffs2_FindOldestDirtySequence(dev); if(dev->oldestDirtyBlock > 0) { selected = dev->oldestDirtyBlock; dev->gcDirtiest = selected; @@ -3562,9 +3346,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background) do { maxTries++; - checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint; - if (checkpointBlockAdjust < 0) - checkpointBlockAdjust = 0; + checkpointBlockAdjust = yaffs2_CalcCheckpointBlocksRequired(dev); minErased = dev->param.nReservedBlocks + checkpointBlockAdjust + 1; erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock; @@ -3590,7 +3372,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background) /* If we don't already have a block being gc'd then see if we should start another */ if (dev->gcBlock < 1 && !aggressive) { - dev->gcBlock = yaffs_FindRefreshBlock(dev); + dev->gcBlock = yaffs2_FindRefreshBlock(dev); dev->gcChunk = 0; } if (dev->gcBlock < 1) { @@ -3829,7 +3611,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, */ if (existingChunk > 0) { - /* NB Right now existing chunk will not be real chunkId if the device >= 32MB + /* NB Right now existing chunk will not be real chunkId if the chunk group size > 1 * thus we have to do a FindChunkInFile to get the real chunk id. * * We have a duplicate now we need to decide which one to use: @@ -3871,8 +3653,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, } if ((inScan > 0) && - (in->myDev->param.isYaffs2 || - existingChunk <= 0 || + (existingChunk <= 0 || ((existingSerial + 1) & 3) == newSerial)) { /* Forward scanning. * Use new @@ -3942,13 +3723,13 @@ void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn) bi = yaffs_GetBlockInfo(dev, block); - yaffs_UpdateOldestDirtySequence(dev, block, bi); + yaffs2_UpdateOldestDirtySequence(dev, block, bi); T(YAFFS_TRACE_DELETION, (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId)); - if (markNAND && - bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->param.isYaffs2) { + if (!dev->param.isYaffs2 && markNAND && + bi->blockState != YAFFS_BLOCK_STATE_COLLECTING) { yaffs_InitialiseTags(&tags); @@ -4048,7 +3829,7 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object *in, int chunkInInode, * If name is not NULL, then that new name is used. */ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, - int isShrink, int shadows) + int isShrink, int shadows, yaffs_XAttrMod *xmod) { yaffs_BlockInfo *bi; @@ -4074,7 +3855,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, if (!in->fake || in == dev->rootDir || /* The rootDir should also be saved */ - force) { + force || xmod) { yaffs_CheckGarbageCollection(dev,0); yaffs_CheckObjectDetailsLoaded(in); @@ -4091,9 +3872,9 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, yaffs_VerifyObjectHeader(in, oh, &oldTags, 0); memcpy(oldName, oh->name, sizeof(oh->name)); - } - - memset(buffer, 0xFF, dev->nDataBytesPerChunk); + memset(buffer, 0xFF, sizeof(yaffs_ObjectHeader)); + } else + memset(buffer, 0xFF, dev->nDataBytesPerChunk); oh->type = in->variantType; oh->yst_mode = in->yst_mode; @@ -4161,6 +3942,11 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, break; } + /* process any xattrib modifications */ + if(xmod) + yaffs_ApplyXMod(dev, (char *)buffer, xmod); + + /* Tags */ yaffs_InitialiseTags(&newTags); in->serial++; @@ -4475,7 +4261,7 @@ static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in) /*--------------------- Checkpointing --------------------*/ -static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev, int head) +static int yaffs2_WriteCheckpointValidityMarker(yaffs_Device *dev, int head) { yaffs_CheckpointValidity cp; @@ -4486,16 +4272,16 @@ static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev, int head) cp.version = YAFFS_CHECKPOINT_VERSION; cp.head = (head) ? 1 : 0; - return (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)) ? + return (yaffs2_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)) ? 1 : 0; } -static int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head) +static int yaffs2_ReadCheckpointValidityMarker(yaffs_Device *dev, int head) { yaffs_CheckpointValidity cp; int ok; - ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); + ok = (yaffs2_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); if (ok) ok = (cp.structType == sizeof(cp)) && @@ -4505,7 +4291,7 @@ static int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head) return ok ? 1 : 0; } -static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, +static void yaffs2_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, yaffs_Device *dev) { cp->nErasedBlocks = dev->nErasedBlocks; @@ -4520,7 +4306,7 @@ static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, } -static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev, +static void yaffs2_CheckpointDeviceToDevice(yaffs_Device *dev, yaffs_CheckpointDevice *cp) { dev->nErasedBlocks = cp->nErasedBlocks; @@ -4535,7 +4321,7 @@ static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev, } -static int yaffs_WriteCheckpointDevice(yaffs_Device *dev) +static int yaffs2_WriteCheckpointDevice(yaffs_Device *dev) { yaffs_CheckpointDevice cp; __u32 nBytes; @@ -4544,27 +4330,27 @@ static int yaffs_WriteCheckpointDevice(yaffs_Device *dev) int ok; /* Write device runtime values*/ - yaffs_DeviceToCheckpointDevice(&cp, dev); + yaffs2_DeviceToCheckpointDevice(&cp, dev); cp.structType = sizeof(cp); - ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); + ok = (yaffs2_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); /* Write block info */ if (ok) { nBytes = nBlocks * sizeof(yaffs_BlockInfo); - ok = (yaffs_CheckpointWrite(dev, dev->blockInfo, nBytes) == nBytes); + ok = (yaffs2_CheckpointWrite(dev, dev->blockInfo, nBytes) == nBytes); } /* Write chunk bits */ if (ok) { nBytes = nBlocks * dev->chunkBitmapStride; - ok = (yaffs_CheckpointWrite(dev, dev->chunkBits, nBytes) == nBytes); + ok = (yaffs2_CheckpointWrite(dev, dev->chunkBits, nBytes) == nBytes); } return ok ? 1 : 0; } -static int yaffs_ReadCheckpointDevice(yaffs_Device *dev) +static int yaffs2_ReadCheckpointDevice(yaffs_Device *dev) { yaffs_CheckpointDevice cp; __u32 nBytes; @@ -4572,7 +4358,7 @@ static int yaffs_ReadCheckpointDevice(yaffs_Device *dev) int ok; - ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); + ok = (yaffs2_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); if (!ok) return 0; @@ -4580,22 +4366,22 @@ static int yaffs_ReadCheckpointDevice(yaffs_Device *dev) return 0; - yaffs_CheckpointDeviceToDevice(dev, &cp); + yaffs2_CheckpointDeviceToDevice(dev, &cp); nBytes = nBlocks * sizeof(yaffs_BlockInfo); - ok = (yaffs_CheckpointRead(dev, dev->blockInfo, nBytes) == nBytes); + ok = (yaffs2_CheckpointRead(dev, dev->blockInfo, nBytes) == nBytes); if (!ok) return 0; nBytes = nBlocks * dev->chunkBitmapStride; - ok = (yaffs_CheckpointRead(dev, dev->chunkBits, nBytes) == nBytes); + ok = (yaffs2_CheckpointRead(dev, dev->chunkBits, nBytes) == nBytes); return ok ? 1 : 0; } -static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp, +static void yaffs2_ObjectToCheckpointObject(yaffs_CheckpointObject *cp, yaffs_Object *obj) { @@ -4618,7 +4404,7 @@ static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp, cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId; } -static int yaffs_CheckpointObjectToObject(yaffs_Object *obj, yaffs_CheckpointObject *cp) +static int yaffs2_CheckpointObjectToObject(yaffs_Object *obj, yaffs_CheckpointObject *cp) { yaffs_Object *parent; @@ -4682,7 +4468,6 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn, int i; yaffs_Device *dev = in->myDev; int ok = 1; - int tnodeSize = yaffs_CalcTnodeSize(dev); if (tn) { if (level > 0) { @@ -4697,9 +4482,9 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn, } } else if (level == 0) { __u32 baseOffset = chunkOffset << YAFFS_TNODES_LEVEL0_BITS; - ok = (yaffs_CheckpointWrite(dev, &baseOffset, sizeof(baseOffset)) == sizeof(baseOffset)); + ok = (yaffs2_CheckpointWrite(dev, &baseOffset, sizeof(baseOffset)) == sizeof(baseOffset)); if (ok) - ok = (yaffs_CheckpointWrite(dev, tn, tnodeSize) == tnodeSize); + ok = (yaffs2_CheckpointWrite(dev, tn, dev->tnodeSize) == dev->tnodeSize); } } @@ -4707,7 +4492,7 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn, } -static int yaffs_WriteCheckpointTnodes(yaffs_Object *obj) +static int yaffs2_WriteCheckpointTnodes(yaffs_Object *obj) { __u32 endMarker = ~0; int ok = 1; @@ -4718,14 +4503,14 @@ static int yaffs_WriteCheckpointTnodes(yaffs_Object *obj) obj->variant.fileVariant.topLevel, 0); if (ok) - ok = (yaffs_CheckpointWrite(obj->myDev, &endMarker, sizeof(endMarker)) == + ok = (yaffs2_CheckpointWrite(obj->myDev, &endMarker, sizeof(endMarker)) == sizeof(endMarker)); } return ok ? 1 : 0; } -static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj) +static int yaffs2_ReadCheckpointTnodes(yaffs_Object *obj) { __u32 baseChunk; int ok = 1; @@ -4733,19 +4518,18 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj) yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant; yaffs_Tnode *tn; int nread = 0; - int tnodeSize = yaffs_CalcTnodeSize(dev); - ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk)); + ok = (yaffs2_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk)); while (ok && (~baseChunk)) { nread++; /* Read level 0 tnode */ - tn = yaffs_GetTnodeRaw(dev); - if (tn) - ok = (yaffs_CheckpointRead(dev, tn, tnodeSize) == tnodeSize); - else + tn = yaffs_GetTnode(dev); + if (tn){ + ok = (yaffs2_CheckpointRead(dev, tn, dev->tnodeSize) == dev->tnodeSize); + } else ok = 0; if (tn && ok) @@ -4755,7 +4539,7 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj) tn) ? 1 : 0; if (ok) - ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk)); + ok = (yaffs2_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk)); } @@ -4767,7 +4551,7 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj) } -static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) +static int yaffs2_WriteCheckpointObjects(yaffs_Device *dev) { yaffs_Object *obj; yaffs_CheckpointObject cp; @@ -4785,17 +4569,17 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) if (lh) { obj = ylist_entry(lh, yaffs_Object, hashLink); if (!obj->deferedFree) { - yaffs_ObjectToCheckpointObject(&cp, obj); + yaffs2_ObjectToCheckpointObject(&cp, obj); cp.structType = sizeof(cp); T(YAFFS_TRACE_CHECKPOINT, ( 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)); + ok = (yaffs2_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); if (ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE) - ok = yaffs_WriteCheckpointTnodes(obj); + ok = yaffs2_WriteCheckpointTnodes(obj); } } } @@ -4806,12 +4590,12 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) cp.structType = sizeof(cp); if (ok) - ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); + ok = (yaffs2_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); return ok ? 1 : 0; } -static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) +static int yaffs2_ReadCheckpointObjects(yaffs_Device *dev) { yaffs_Object *obj; yaffs_CheckpointObject cp; @@ -4820,7 +4604,7 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) yaffs_Object *hardList = NULL; while (ok && !done) { - ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); + ok = (yaffs2_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, (int)sizeof(cp), ok)); @@ -4835,11 +4619,11 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) else if (ok) { obj = yaffs_FindOrCreateObjectByNumber(dev, cp.objectId, cp.variantType); if (obj) { - ok = yaffs_CheckpointObjectToObject(obj, &cp); + ok = yaffs2_CheckpointObjectToObject(obj, &cp); if (!ok) break; if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) { - ok = yaffs_ReadCheckpointTnodes(obj); + ok = yaffs2_ReadCheckpointTnodes(obj); } else if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { obj->hardLinks.next = (struct ylist_head *) hardList; @@ -4856,14 +4640,14 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) return ok ? 1 : 0; } -static int yaffs_WriteCheckpointSum(yaffs_Device *dev) +static int yaffs2_WriteCheckpointSum(yaffs_Device *dev) { __u32 checkpointSum; int ok; - yaffs_GetCheckpointSum(dev, &checkpointSum); + yaffs2_GetCheckpointSum(dev, &checkpointSum); - ok = (yaffs_CheckpointWrite(dev, &checkpointSum, sizeof(checkpointSum)) == sizeof(checkpointSum)); + ok = (yaffs2_CheckpointWrite(dev, &checkpointSum, sizeof(checkpointSum)) == sizeof(checkpointSum)); if (!ok) return 0; @@ -4871,15 +4655,15 @@ static int yaffs_WriteCheckpointSum(yaffs_Device *dev) return 1; } -static int yaffs_ReadCheckpointSum(yaffs_Device *dev) +static int yaffs2_ReadCheckpointSum(yaffs_Device *dev) { __u32 checkpointSum0; __u32 checkpointSum1; int ok; - yaffs_GetCheckpointSum(dev, &checkpointSum0); + yaffs2_GetCheckpointSum(dev, &checkpointSum0); - ok = (yaffs_CheckpointRead(dev, &checkpointSum1, sizeof(checkpointSum1)) == sizeof(checkpointSum1)); + ok = (yaffs2_CheckpointRead(dev, &checkpointSum1, sizeof(checkpointSum1)) == sizeof(checkpointSum1)); if (!ok) return 0; @@ -4891,39 +4675,39 @@ static int yaffs_ReadCheckpointSum(yaffs_Device *dev) } -static int yaffs_WriteCheckpointData(yaffs_Device *dev) +static int yaffs2_WriteCheckpointData(yaffs_Device *dev) { int ok = 1; - if (!yaffs_CheckpointRequired(dev)) { + if (!yaffs2_CheckpointRequired(dev)) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint write" TENDSTR))); ok = 0; } if (ok) - ok = yaffs_CheckpointOpen(dev, 1); + ok = yaffs2_CheckpointOpen(dev, 1); if (ok) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR))); - ok = yaffs_WriteCheckpointValidityMarker(dev, 1); + ok = yaffs2_WriteCheckpointValidityMarker(dev, 1); } if (ok) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint device" TENDSTR))); - ok = yaffs_WriteCheckpointDevice(dev); + ok = yaffs2_WriteCheckpointDevice(dev); } if (ok) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint objects" TENDSTR))); - ok = yaffs_WriteCheckpointObjects(dev); + ok = yaffs2_WriteCheckpointObjects(dev); } if (ok) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR))); - ok = yaffs_WriteCheckpointValidityMarker(dev, 0); + ok = yaffs2_WriteCheckpointValidityMarker(dev, 0); } if (ok) - ok = yaffs_WriteCheckpointSum(dev); + ok = yaffs2_WriteCheckpointSum(dev); - if (!yaffs_CheckpointClose(dev)) + if (!yaffs2_CheckpointClose(dev)) ok = 0; if (ok) @@ -4934,41 +4718,44 @@ static int yaffs_WriteCheckpointData(yaffs_Device *dev) return dev->isCheckpointed; } -static int yaffs_ReadCheckpointData(yaffs_Device *dev) +static int yaffs2_ReadCheckpointData(yaffs_Device *dev) { int ok = 1; + + if(!dev->param.isYaffs2) + ok = 0; - if (dev->param.skipCheckpointRead || !dev->param.isYaffs2) { + if (ok && dev->param.skipCheckpointRead) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint read" TENDSTR))); ok = 0; } if (ok) - ok = yaffs_CheckpointOpen(dev, 0); /* open for read */ + ok = yaffs2_CheckpointOpen(dev, 0); /* open for read */ if (ok) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR))); - ok = yaffs_ReadCheckpointValidityMarker(dev, 1); + ok = yaffs2_ReadCheckpointValidityMarker(dev, 1); } if (ok) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint device" TENDSTR))); - ok = yaffs_ReadCheckpointDevice(dev); + ok = yaffs2_ReadCheckpointDevice(dev); } if (ok) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint objects" TENDSTR))); - ok = yaffs_ReadCheckpointObjects(dev); + ok = yaffs2_ReadCheckpointObjects(dev); } if (ok) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR))); - ok = yaffs_ReadCheckpointValidityMarker(dev, 0); + ok = yaffs2_ReadCheckpointValidityMarker(dev, 0); } if (ok) { - ok = yaffs_ReadCheckpointSum(dev); + ok = yaffs2_ReadCheckpointSum(dev); T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint checksum %d" TENDSTR), ok)); } - if (!yaffs_CheckpointClose(dev)) + if (!yaffs2_CheckpointClose(dev)) ok = 0; if (ok) @@ -4980,12 +4767,12 @@ static int yaffs_ReadCheckpointData(yaffs_Device *dev) } -static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) +static void yaffs2_InvalidateCheckpoint(yaffs_Device *dev) { if (dev->isCheckpointed || dev->blocksInCheckpoint > 0) { dev->isCheckpointed = 0; - yaffs_CheckpointInvalidateStream(dev); + yaffs2_CheckpointInvalidateStream(dev); } if (dev->param.markSuperBlockDirty) dev->param.markSuperBlockDirty(dev); @@ -5002,8 +4789,8 @@ int yaffs_CheckpointSave(yaffs_Device *dev) yaffs_VerifyFreeChunks(dev); if (!dev->isCheckpointed) { - yaffs_InvalidateCheckpoint(dev); - yaffs_WriteCheckpointData(dev); + yaffs2_InvalidateCheckpoint(dev); + yaffs2_WriteCheckpointData(dev); } T(YAFFS_TRACE_ALWAYS, (TSTR("save exit: isCheckpointed %d"TENDSTR), dev->isCheckpointed)); @@ -5011,12 +4798,12 @@ int yaffs_CheckpointSave(yaffs_Device *dev) return dev->isCheckpointed; } -int yaffs_CheckpointRestore(yaffs_Device *dev) +int yaffs2_CheckpointRestore(yaffs_Device *dev) { int retval; T(YAFFS_TRACE_CHECKPOINT, (TSTR("restore entry: isCheckpointed %d"TENDSTR), dev->isCheckpointed)); - retval = yaffs_ReadCheckpointData(dev); + retval = yaffs2_ReadCheckpointData(dev); if (dev->isCheckpointed) { yaffs_VerifyObjects(dev); @@ -5310,7 +5097,7 @@ int yaffs_DoWriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset, int yaffs_WriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset, int nBytes, int writeThrough) { - yaffs_HandleHole(in,offset); + yaffs2_HandleHole(in,offset); return yaffs_DoWriteDataToFile(in,buffer,offset,nBytes,writeThrough); } @@ -5391,7 +5178,7 @@ static void yaffs_ResizeDown( yaffs_Object *obj, loff_t newSize) } -static int yaffs_HandleHole(yaffs_Object *obj, loff_t newSize) +static int yaffs2_HandleHole(yaffs_Object *obj, loff_t newSize) { /* if newsSize > oldFileSize. * We're going to be writing a hole. @@ -5469,7 +5256,7 @@ static int yaffs_HandleHole(yaffs_Object *obj, loff_t newSize) obj->parent->objectId != YAFFS_OBJECTID_UNLINKED && obj->parent->objectId != YAFFS_OBJECTID_DELETED){ /* Write a hole start header with the old file size */ - yaffs_UpdateObjectHeader(obj, NULL, 0,1,0); + yaffs_UpdateObjectHeader(obj, NULL, 0, 1, 0, NULL); } return result; @@ -5493,7 +5280,7 @@ int yaffs_ResizeFile(yaffs_Object *in, loff_t newSize) return YAFFS_OK; if(newSize > oldFileSize){ - yaffs_HandleHole(in,newSize); + yaffs2_HandleHole(in,newSize); in->variant.fileVariant.fileSize = newSize; } else { /* newSize < oldFileSize */ @@ -5509,7 +5296,7 @@ int yaffs_ResizeFile(yaffs_Object *in, loff_t newSize) !in->isShadowed && in->parent->objectId != YAFFS_OBJECTID_UNLINKED && in->parent->objectId != YAFFS_OBJECTID_DELETED) - yaffs_UpdateObjectHeader(in, NULL, 0,0,0); + yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0, NULL); return YAFFS_OK; @@ -5553,7 +5340,7 @@ int yaffs_FlushFile(yaffs_Object *in, int updateTime, int dataSync) #endif } - retVal = (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >= + retVal = (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0, NULL) >= 0) ? YAFFS_OK : YAFFS_FAIL; } } else { @@ -5624,7 +5411,7 @@ static int yaffs_UnlinkFileIfNeeded(yaffs_Object *in) int yaffs_DeleteFile(yaffs_Object *in) { int retVal = YAFFS_OK; - int deleted = in->deleted; + int deleted; /* Need to cache value on stack if in is freed */ yaffs_Device *dev = in->myDev; if (dev->param.disableSoftDelete || dev->param.isYaffs2) @@ -5637,6 +5424,8 @@ int yaffs_DeleteFile(yaffs_Object *in) if (!in->unlinked) retVal = yaffs_UnlinkFileIfNeeded(in); + deleted = in->deleted; + if (retVal == YAFFS_OK && in->unlinked && !in->deleted) { in->deleted = 1; deleted = 1; @@ -5886,7 +5675,7 @@ static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList) -static int ybicmp(const void *a, const void *b) +static int yaffs2_ybicmp(const void *a, const void *b) { register int aseq = ((yaffs_BlockIndex *)a)->seq; register int bseq = ((yaffs_BlockIndex *)b)->seq; @@ -6053,7 +5842,7 @@ static void yaffs_EmptyLostAndFound(yaffs_Device *dev) yaffs_DeleteDirectoryContents(dev->lostNFoundDir); } -static int yaffs_Scan(yaffs_Device *dev) +static int yaffs1_Scan(yaffs_Device *dev) { yaffs_ExtendedTags tags; int blk; @@ -6083,7 +5872,7 @@ static int yaffs_Scan(yaffs_Device *dev) T(YAFFS_TRACE_SCAN, - (TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR), + (TSTR("yaffs1_Scan starts intstartblk %d intendblk %d..." TENDSTR), dev->internalStartBlock, dev->internalEndBlock)); chunkData = yaffs_GetTempBuffer(dev, __LINE__); @@ -6476,7 +6265,7 @@ static int yaffs_Scan(yaffs_Device *dev) obj = yaffs_FindObjectByNumber(dev, fixer->objectId); if (obj) - yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0); + yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0, NULL); YFREE(fixer); } @@ -6487,7 +6276,7 @@ static int yaffs_Scan(yaffs_Device *dev) if (alloc_failed) return YAFFS_FAIL; - T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR))); + T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_Scan ends" TENDSTR))); return YAFFS_OK; @@ -6550,7 +6339,7 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in) } } -static int yaffs_ScanBackwards(yaffs_Device *dev) +static int yaffs2_ScanBackwards(yaffs_Device *dev) { yaffs_ExtendedTags tags; int blk; @@ -6584,15 +6373,9 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) yaffs_BlockIndex *blockIndex = NULL; int altBlockIndex = 0; - if (!dev->param.isYaffs2) { - T(YAFFS_TRACE_SCAN, - (TSTR("yaffs_ScanBackwards is only for YAFFS2!" TENDSTR))); - return YAFFS_FAIL; - } - T(YAFFS_TRACE_SCAN, (TSTR - ("yaffs_ScanBackwards starts intstartblk %d intendblk %d..." + ("yaffs2_ScanBackwards starts intstartblk %d intendblk %d..." TENDSTR), dev->internalStartBlock, dev->internalEndBlock)); @@ -6607,7 +6390,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) if (!blockIndex) { T(YAFFS_TRACE_SCAN, - (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR))); + (TSTR("yaffs2_ScanBackwards() could not allocate block index!" TENDSTR))); return YAFFS_FAIL; } @@ -6680,29 +6463,8 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) YYIELD(); - /* Sort the blocks */ -#ifndef CONFIG_YAFFS_USE_OWN_SORT - { - /* Use qsort now. */ - yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp); - } -#else - { - /* Dungy old bubble sort... */ - - yaffs_BlockIndex temp; - int i; - int j; - - for (i = 0; i < nBlocksToScan; i++) - for (j = i + 1; j < nBlocksToScan; j++) - if (blockIndex[i].seq > blockIndex[j].seq) { - temp = blockIndex[j]; - blockIndex[j] = blockIndex[i]; - blockIndex[i] = temp; - } - } -#endif + /* Sort the blocks by sequence number*/ + yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), yaffs2_ybicmp); YYIELD(); @@ -7193,7 +6955,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) if (alloc_failed) return YAFFS_FAIL; - T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR))); + T(YAFFS_TRACE_SCAN, (TSTR("yaffs2_ScanBackwards ends" TENDSTR))); return YAFFS_OK; } @@ -7310,7 +7072,7 @@ static void yaffs_UpdateParent(yaffs_Object *obj) } } else - yaffs_UpdateObjectHeader(obj,NULL,0,0,0); + yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, NULL); } void yaffs_UpdateDirtyDirectories(yaffs_Device *dev) @@ -7333,7 +7095,7 @@ void yaffs_UpdateDirtyDirectories(yaffs_Device *dev) T(YAFFS_TRACE_BACKGROUND, (TSTR("Update directory %d" TENDSTR), obj->objectId)); if(obj->dirty) - yaffs_UpdateObjectHeader(obj,NULL,0,0,0); + yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, NULL); } } @@ -7664,7 +7426,7 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr) if (valid & ATTR_SIZE) yaffs_ResizeFile(obj, attr->ia_size); - yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0); + yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0, NULL); return YAFFS_OK; @@ -7697,6 +7459,104 @@ int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr) #endif + +static int yaffs_DoXMod(yaffs_Object *obj, int set, const char *name, const void *value, int size, int flags) +{ + yaffs_XAttrMod xmod; + + int result; + + xmod.set = set; + xmod.name = name; + xmod.data = value; + xmod.size = size; + xmod.flags = flags; + xmod.result = -ENOSPC; + + result = yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, &xmod); + + if(result > 0) + return xmod.result; + else + return -ENOSPC; +} + +static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod) +{ + int retval = 0; + int x_offs = sizeof(yaffs_ObjectHeader); + int x_size = dev->nDataBytesPerChunk - sizeof(yaffs_ObjectHeader); + + char * x_buffer = buffer + x_offs; + + if(xmod->set) + retval = nval_set(x_buffer, x_size, xmod->name, xmod->data, xmod->size, xmod->flags); + else + retval = nval_del(x_buffer, x_size, xmod->name); + + xmod->result = retval; + + return retval; +} + +static int yaffs_DoXFetch(yaffs_Object *obj, const char *name, void *value, int size) +{ + char *buffer = NULL; + int result; + yaffs_ExtendedTags tags; + yaffs_Device *dev = obj->myDev; + int x_offs = sizeof(yaffs_ObjectHeader); + int x_size = dev->nDataBytesPerChunk - sizeof(yaffs_ObjectHeader); + + __u8 * x_buffer; + + int retval = 0; + + if(obj->hdrChunk < 1) + return -ENODATA; + + buffer = yaffs_GetTempBuffer(dev, __LINE__); + if(!buffer) + return -ENOMEM; + + result = yaffs_ReadChunkWithTagsFromNAND(dev,obj->hdrChunk, buffer, &tags); + + if(result != YAFFS_OK) + retval = -ENOENT; + else{ + x_buffer = buffer + x_offs; + + if(name) + retval = nval_get(x_buffer, x_size, name, value, size); + else + retval = nval_list(x_buffer, x_size, value,size); + } + yaffs_ReleaseTempBuffer(dev,buffer,__LINE__); + return retval; +} + +int yaffs_SetXAttribute(yaffs_Object *obj, const char *name, const void * value, int size, int flags) +{ + return yaffs_DoXMod(obj, 1, name, value, size, flags); +} + +int yaffs_RemoveXAttribute(yaffs_Object *obj, const char *name) +{ + return yaffs_DoXMod(obj, 0, name, NULL, 0, 0); +} + +int yaffs_GetXAttribute(yaffs_Object *obj, const char *name, void *value, int size) +{ + return yaffs_DoXFetch(obj, name, value, size); +} + +int yaffs_ListXAttributes(yaffs_Object *obj, char *buffer, int size) +{ + return yaffs_DoXFetch(obj, NULL, buffer,size); +} + + + #if 0 int yaffs_DumpObject(yaffs_Object *obj) { @@ -7912,6 +7772,9 @@ int yaffs_GutsInitialise(yaffs_Device *dev) else dev->chunkGroupBits = bits - dev->tnodeWidth; + dev->tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; + if(dev->tnodeSize < sizeof(yaffs_Tnode)) + dev->tnodeSize = sizeof(yaffs_Tnode); dev->chunkGroupSize = 1 << dev->chunkGroupBits; @@ -8001,8 +7864,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev) if (!init_failed && !yaffs_InitialiseBlocks(dev)) init_failed = 1; - yaffs_InitialiseTnodes(dev); - yaffs_InitialiseObjects(dev); + yaffs_InitialiseTnodesAndObjects(dev); if (!init_failed && !yaffs_CreateInitialDirectories(dev)) init_failed = 1; @@ -8011,7 +7873,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev) if (!init_failed) { /* Now scan the flash. */ if (dev->param.isYaffs2) { - if (yaffs_CheckpointRestore(dev)) { + if (yaffs2_CheckpointRestore(dev)) { yaffs_CheckObjectDetailsLoaded(dev->rootDir); T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: restored from checkpoint" TENDSTR))); @@ -8021,9 +7883,8 @@ int yaffs_GutsInitialise(yaffs_Device *dev) * and scan backwards. */ yaffs_DeinitialiseBlocks(dev); - yaffs_DeinitialiseTnodes(dev); - yaffs_DeinitialiseObjects(dev); + yaffs_DeinitialiseTnodesAndObjects(dev); dev->nErasedBlocks = 0; dev->nFreeChunks = 0; @@ -8036,16 +7897,15 @@ int yaffs_GutsInitialise(yaffs_Device *dev) if (!init_failed && !yaffs_InitialiseBlocks(dev)) init_failed = 1; - yaffs_InitialiseTnodes(dev); - yaffs_InitialiseObjects(dev); + yaffs_InitialiseTnodesAndObjects(dev); if (!init_failed && !yaffs_CreateInitialDirectories(dev)) init_failed = 1; - if (!init_failed && !yaffs_ScanBackwards(dev)) + if (!init_failed && !yaffs2_ScanBackwards(dev)) init_failed = 1; } - } else if (!yaffs_Scan(dev)) + } else if (!yaffs1_Scan(dev)) init_failed = 1; yaffs_StripDeletedObjects(dev); @@ -8077,7 +7937,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev) /* Clean up any aborted checkpoint data */ if(!dev->isCheckpointed && dev->blocksInCheckpoint > 0) - yaffs_InvalidateCheckpoint(dev); + yaffs2_InvalidateCheckpoint(dev); T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); @@ -8091,8 +7951,7 @@ void yaffs_Deinitialise(yaffs_Device *dev) int i; yaffs_DeinitialiseBlocks(dev); - yaffs_DeinitialiseTnodes(dev); - yaffs_DeinitialiseObjects(dev); + yaffs_DeinitialiseTnodesAndObjects(dev); if (dev->param.nShortOpCaches > 0 && dev->srCache) { @@ -8174,9 +8033,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) nFree -= ((dev->param.nReservedBlocks + 1) * dev->param.nChunksPerBlock); /* Now we figure out how much to reserve for the checkpoint and report that... */ - blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint; - if (blocksForCheckpoint < 0) - blocksForCheckpoint = 0; + blocksForCheckpoint = yaffs2_CalcCheckpointBlocksRequired(dev); nFree -= (blocksForCheckpoint * dev->param.nChunksPerBlock);