yaffs: Cache object xattrib state.
[yaffs2.git] / yaffs_guts.c
index d65c0caa93f377f44c05ba49a7fe7f502d5207ca..6ea5698b5052dd375e15bceba736a183209587cc 100644 (file)
@@ -66,7 +66,7 @@ static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number,
                                        yaffs_ObjectType type);
 
 
-static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod);
+static int yaffs_ApplyXMod(yaffs_Object *obj, char *buffer, yaffs_XAttrMod *xmod);
 
 static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj);
 static int yaffs_CheckStructures(void);
@@ -2106,7 +2106,6 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block,
        int newChunk;
        int markNAND;
        int retVal = YAFFS_OK;
-       int cleanups = 0;
        int i;
        int isCheckpointBlock;
        int matchingChunk;
@@ -2224,14 +2223,15 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block,
                                         * We have to decrement free chunks so this works out properly.
                                         */
                                        dev->nFreeChunks--;
+                                       bi->softDeletions--;
 
                                        object->nDataChunks--;
 
                                        if (object->nDataChunks <= 0) {
                                                /* remeber to clean up the object */
-                                               dev->gcCleanupList[cleanups] =
+                                               dev->gcCleanupList[dev->nCleanups] =
                                                    tags.objectId;
-                                               cleanups++;
+                                               dev->nCleanups++;
                                        }
                                        markNAND = 0;
                                } else if (0) {
@@ -2317,8 +2317,23 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block,
                yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
 
 
+
+       }
+
+       yaffs_VerifyCollectedBlock(dev, bi, block);
+
+
+
+       if (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) {
+               /*
+                * The gc did not complete. Set block state back to FULL
+                * because checkpointing does not restore gc.
+                */
+               bi->blockState = YAFFS_BLOCK_STATE_FULL;
+       } else {
+               /* The gc completed. */
                /* Do any required cleanups */
-               for (i = 0; i < cleanups; i++) {
+               for (i = 0; i < dev->nCleanups; i++) {
                        /* Time to delete the file too */
                        object =
                            yaffs_FindObjectByNumber(dev,
@@ -2338,20 +2353,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block,
 
                }
 
-       }
-
-       yaffs_VerifyCollectedBlock(dev, bi, block);
-
 
-
-       if (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) {
-               /*
-                * The gc did not complete. Set block state back to FULL
-                * because checkpointing does not restore gc.
-                */
-               bi->blockState = YAFFS_BLOCK_STATE_FULL;
-       } else {
-               /* The gc completed. */
                chunksAfter = yaffs_GetErasedChunks(dev);
                if (chunksBefore >= chunksAfter) {
                        T(YAFFS_TRACE_GC,
@@ -2361,6 +2363,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block,
                }
                dev->gcBlock = 0;
                dev->gcChunk = 0;
+               dev->nCleanups = 0;
        }
 
        dev->gcDisable = 0;
@@ -2432,7 +2435,16 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,
                        threshold = dev->param.nChunksPerBlock;
                        iterations = nBlocks;
                } else {
-                       int maxThreshold = dev->param.nChunksPerBlock/2;
+                       int maxThreshold;
+
+                       if(background)
+                               maxThreshold = dev->param.nChunksPerBlock/2;
+                       else
+                               maxThreshold = dev->param.nChunksPerBlock/8;
+
+                       if(maxThreshold <  YAFFS_GC_PASSIVE_THRESHOLD)
+                               maxThreshold = YAFFS_GC_PASSIVE_THRESHOLD;
+
                        threshold = background ?
                                (dev->gcNotDone + 2) * 2 : 0;
                        if(threshold <YAFFS_GC_PASSIVE_THRESHOLD)
@@ -2497,8 +2509,10 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,
                  dev->param.nChunksPerBlock - dev->gcPagesInUse,
                  prioritised));
 
+               dev->nGCBlocks++;
                if(background)
                        dev->backgroundGCs++;
+
                dev->gcDirtiest = 0;
                dev->gcPagesInUse = 0;
                dev->gcNotDone = 0;
@@ -2532,10 +2546,8 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background)
        int aggressive = 0;
        int gcOk = YAFFS_OK;
        int maxTries = 0;
-
        int minErased;
        int erasedChunks;
-
        int checkpointBlockAdjust;
 
        if(dev->param.gcControl &&
@@ -2563,6 +2575,9 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background)
                if (dev->nErasedBlocks < minErased)
                        aggressive = 1;
                else {
+                       if(!background && erasedChunks > (dev->nFreeChunks / 4))
+                               break;
+
                        if(dev->gcSkip > 20)
                                dev->gcSkip = 20;
                        if(erasedChunks < dev->nFreeChunks/2 ||
@@ -2582,10 +2597,12 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background)
                if (dev->gcBlock < 1 && !aggressive) {
                        dev->gcBlock = yaffs2_FindRefreshBlock(dev);
                        dev->gcChunk = 0;
+                       dev->nCleanups=0;
                }
                if (dev->gcBlock < 1) {
                        dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive, background);
                        dev->gcChunk = 0;
+                       dev->nCleanups=0;
                }
 
                if (dev->gcBlock > 0) {
@@ -3095,7 +3112,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force,
 
                /* process any xattrib modifications */
                if(xmod)
-                       yaffs_ApplyXMod(dev, (char *)buffer, xmod);
+                       yaffs_ApplyXMod(in, (char *)buffer, xmod);
 
 
                /* Tags */
@@ -4185,6 +4202,9 @@ static void yaffs_StripDeletedObjects(yaffs_Device *dev)
        struct ylist_head *n;
        yaffs_Object *l;
 
+       if (dev->readOnly)
+               return;
+
        /* Soft delete all the unlinked files */
        ylist_for_each_safe(i, n,
                &dev->unlinkedDir->variant.directoryVariant.children) {
@@ -4238,6 +4258,8 @@ static void yaffs_FixHangingObjects(yaffs_Device *dev)
        int depthLimit;
        int hanging;
 
+       if (dev->readOnly)
+               return;
 
        /* Iterate through the objects in each hash entry,
         * looking at each object.
@@ -4367,7 +4389,7 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)
                in->yst_rdev = oh->yst_rdev;
 
 #endif
-               yaffs_SetObjectName(in, oh->name);
+               yaffs_SetObjectNameFromOH(in, oh);
 
                if (in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
                        in->variant.symLinkVariant.alias =
@@ -4896,7 +4918,7 @@ 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)
+static int yaffs_DoXMod(yaffs_Object *obj, int set, const YCHAR *name, const void *value, int size, int flags)
 {
        yaffs_XAttrMod xmod;
 
@@ -4917,10 +4939,11 @@ static int yaffs_DoXMod(yaffs_Object *obj, int set, const char *name, const void
                return -ENOSPC;
 }
 
-static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod)
+static int yaffs_ApplyXMod(yaffs_Object *obj, char *buffer, yaffs_XAttrMod *xmod)
 {
        int retval = 0;
        int x_offs = sizeof(yaffs_ObjectHeader);
+       yaffs_Device *dev = obj->myDev;
        int x_size = dev->nDataBytesPerChunk - sizeof(yaffs_ObjectHeader);
 
        char * x_buffer = buffer + x_offs;
@@ -4930,12 +4953,15 @@ static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod
        else
                retval = nval_del(x_buffer, x_size, xmod->name);
 
+       obj->hasXattr = nval_hasvalues(x_buffer, x_size);
+       obj->xattrKnown = 1;
+
        xmod->result = retval;
 
        return retval;
 }
 
-static int yaffs_DoXFetch(yaffs_Object *obj, const char *name, void *value, int size)
+static int yaffs_DoXFetch(yaffs_Object *obj, const YCHAR *name, void *value, int size)
 {
        char *buffer = NULL;
        int result;
@@ -4951,6 +4977,16 @@ static int yaffs_DoXFetch(yaffs_Object *obj, const char *name, void *value, int
        if(obj->hdrChunk < 1)
                return -ENODATA;
 
+       /* If we know that the object has no xattribs then don't do all the
+        * reading and parsing.
+        */
+       if(obj->xattrKnown && !obj->hasXattr){
+               if(name)
+                       return -ENODATA;
+               else
+                       return 0;
+       }
+
        buffer = yaffs_GetTempBuffer(dev, __LINE__);
        if(!buffer)
                return -ENOMEM;
@@ -4962,6 +4998,11 @@ static int yaffs_DoXFetch(yaffs_Object *obj, const char *name, void *value, int
        else{
                x_buffer =  buffer + x_offs;
 
+               if (!obj->xattrKnown){
+                       obj->hasXattr = nval_hasvalues(x_buffer, x_size);
+                       obj->xattrKnown = 1;
+               }
+
                if(name)
                        retval = nval_get(x_buffer, x_size, name, value, size);
                else
@@ -4971,17 +5012,17 @@ static int yaffs_DoXFetch(yaffs_Object *obj, const char *name, void *value, int
        return retval;
 }
 
-int yaffs_SetXAttribute(yaffs_Object *obj, const char *name, const void * value, int size, int flags)
+int yaffs_SetXAttribute(yaffs_Object *obj, const YCHAR *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)
+int yaffs_RemoveXAttribute(yaffs_Object *obj, const YCHAR *name)
 {
        return yaffs_DoXMod(obj, 0, name, NULL, 0, 0);
 }
 
-int yaffs_GetXAttribute(yaffs_Object *obj, const char *name, void *value, int size)
+int yaffs_GetXAttribute(yaffs_Object *obj, const YCHAR *name, void *value, int size)
 {
        return yaffs_DoXFetch(obj, name, value, size);
 }