*** empty log message ***
[yaffs2.git] / yaffs_guts.c
index a3fce2cddf2dad153058a3ef9c1c4eb24dc0058d..2f899f3ec516e21eca987ce8e2e064404cf1701b 100644 (file)
@@ -1,19 +1,20 @@
+
 /*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- * yaffs_guts.c  The main guts of YAFFS
+ * YAFFS: Yet another FFS. A NAND-flash specific file system. 
  *
  * Copyright (C) 2002 Aleph One Ltd.
  *   for Toby Churchill Ltd and Brightstar Engineering
  *
  * Created by Charles Manning <charles@aleph1.co.uk>
  *
+ * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
  */
  //yaffs_guts.c
 
-const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.1 2004-11-03 08:14:07 charles Exp $";
+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.4 2004-12-17 04:39:04 charles Exp $";
 
 #include "yportenv.h"
 
@@ -201,7 +202,7 @@ int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND)
        return result;
 }
 
-int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
+static int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
 {
        return dev->initialiseNAND(dev);
 }
@@ -475,7 +476,8 @@ int yaffs_CheckFF(__u8 *buffer,int nBytes)
        //Horrible, slow implementation
        while(nBytes--)
        {
-               if(*buffer != 0xFF) return 0; 
+               if(*buffer != 0xFF) return 0;
+               buffer++;
        }
        return 1;
 }
@@ -1194,7 +1196,7 @@ static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk)
 
        yaffs_BlockInfo *theBlock;                                      
        
-       T(YAFFS_TRACE_DELETE,(TSTR("soft delete chunk %d" TENDSTR),chunk));
+       T(YAFFS_TRACE_DELETION,(TSTR("soft delete chunk %d" TENDSTR),chunk));
                                                
        theBlock =      yaffs_GetBlockInfo(dev,  chunk/dev->nChunksPerBlock);
        if(theBlock)
@@ -1529,6 +1531,16 @@ static void yaffs_FreeObject(yaffs_Object *tn)
 
        yaffs_Device *dev = tn->myDev;
        
+#ifdef  __KERNEL__
+       if(tn->myInode)
+       {
+               // We're still hooked up to a cached inode.
+               // Don't delete now, but mark for later deletion
+               tn->deferedFree = 1;
+               return;
+       }
+#endif
+       
        yaffs_UnhashObject(tn);
        
        // Link into the free list.
@@ -1539,6 +1551,19 @@ static void yaffs_FreeObject(yaffs_Object *tn)
 
 
 
+#ifdef __KERNEL__
+
+void yaffs_HandleDeferedFree(yaffs_Object *obj)
+{
+       if(obj->deferedFree)
+       {
+          yaffs_FreeObject(obj);
+       }
+}
+
+#endif
+
+
 
 static void yaffs_DeinitialiseObjects(yaffs_Device *dev)
 {
@@ -1723,11 +1748,7 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectTyp
 
 #else
 
-#if defined(CONFIG_KERNEL_2_5)
-               theObject->st_atime = theObject->st_mtime =     theObject->st_ctime = CURRENT_TIME.tv_sec;              
-#else
-               theObject->st_atime = theObject->st_mtime =     theObject->st_ctime = CURRENT_TIME;             
-#endif
+               theObject->st_atime = theObject->st_mtime = theObject->st_ctime = Y_CURRENT_TIME;               
 #endif
                switch(type)
                {
@@ -1831,11 +1852,8 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type,
                in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1];
                
 #else
-#if defined(CONFIG_KERNEL_2_5)
-               in->st_atime = in->st_mtime = in->st_ctime = CURRENT_TIME.tv_sec;
-#else
-               in->st_atime = in->st_mtime = in->st_ctime = CURRENT_TIME;
-#endif
+               in->st_atime = in->st_mtime = in->st_ctime = Y_CURRENT_TIME;
+
                in->st_rdev  = rdev;
                in->st_uid   = uid;
                in->st_gid   = gid;
@@ -1974,7 +1992,7 @@ int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, yaffs_Object
        int force = 0;
        
 #ifdef CONFIG_YAFFS_CASE_INSENSITIVE
-       // Special case for WinCE.
+       // Special case for case insemsitive systems (eg. WinCE).
        // While look-up is case insensitive, the name isn't.
        // THerefore we might want to change x.txt to X.txt
        if(oldDir == newDir && yaffs_strcmp(oldName,newName) == 0)
@@ -2719,7 +2737,7 @@ int yaffs_CheckGarbageCollection(yaffs_Device *dev)
 {
        int block;
        int aggressive; 
-       int gcOk;
+       int gcOk = YAFFS_OK;
        int maxTries = 0;
        
        //yaffs_DoUnlinkedFileDeletion(dev);
@@ -4168,11 +4186,9 @@ int yaffs_FlushFile(yaffs_Object *in, int updateTime)
 #ifdef CONFIG_YAFFS_WINCE
                        yfsd_WinFileTimeNow(in->win_mtime);
 #else
-#if defined(CONFIG_KERNEL_2_5)
-                       in->st_mtime = CURRENT_TIME.tv_sec;
-#else
-                       in->st_mtime = CURRENT_TIME;
-#endif
+
+                       in->st_mtime = Y_CURRENT_TIME;
+
 #endif
                }
 
@@ -4510,6 +4526,8 @@ static int yaffs_Scan(yaffs_Device *dev)
        __u8 *chunkData;
 
        yaffs_BlockIndex *blockIndex = NULL;
+
+       T(YAFFS_TRACE_SCAN,(TSTR("yaffs_Scan starts  startblk %d endblk %d..." TENDSTR),dev->startBlock,dev->endBlock));
        
        chunkData = yaffs_GetTempBuffer(dev,__LINE__);
        
@@ -4534,6 +4552,8 @@ static int yaffs_Scan(yaffs_Device *dev)
                
                bi->blockState = state;
                bi->sequenceNumber = sequenceNumber;
+
+               T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block scanning block %d state %d seq %d" TENDSTR),blk,state,sequenceNumber));
                
                if(state == YAFFS_BLOCK_STATE_DEAD)
                {
@@ -4541,6 +4561,7 @@ static int yaffs_Scan(yaffs_Device *dev)
                }
                else if(state == YAFFS_BLOCK_STATE_EMPTY)
                {
+                       T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block empty " TENDSTR)));
                        dev->nErasedBlocks++;
                        dev->nFreeChunks += dev->nChunksPerBlock;
                }
@@ -4596,6 +4617,7 @@ static int yaffs_Scan(yaffs_Device *dev)
        {
                startIterator = 0;
                endIterator = nBlocksToScan-1;
+               T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan));
        }
        else
        {
@@ -4933,6 +4955,9 @@ static int yaffs_Scan(yaffs_Device *dev)
        }
        
        yaffs_ReleaseTempBuffer(dev,chunkData,__LINE__);
+
+       T(YAFFS_TRACE_SCAN,(TSTR("yaffs_Scan ends" TENDSTR)));
+
        return YAFFS_OK;
 }
 
@@ -5183,15 +5208,9 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr)
        if(valid & ATTR_UID) obj->st_uid = attr->ia_uid;
        if(valid & ATTR_GID) obj->st_gid = attr->ia_gid;
        
-#if defined(CONFIG_KERNEL_2_5)
-       if(valid & ATTR_ATIME) obj->st_atime = attr->ia_atime.tv_sec;
-       if(valid & ATTR_CTIME) obj->st_ctime = attr->ia_ctime.tv_sec;
-       if(valid & ATTR_MTIME) obj->st_mtime = attr->ia_mtime.tv_sec;
-#else
-       if(valid & ATTR_ATIME) obj->st_atime = attr->ia_atime;
-       if(valid & ATTR_CTIME) obj->st_ctime = attr->ia_ctime;
-       if(valid & ATTR_MTIME) obj->st_mtime = attr->ia_mtime;
-#endif
+       if(valid & ATTR_ATIME) obj->st_atime = Y_TIME_CONVERT(attr->ia_atime);
+       if(valid & ATTR_CTIME) obj->st_ctime = Y_TIME_CONVERT(attr->ia_ctime);
+       if(valid & ATTR_MTIME) obj->st_mtime = Y_TIME_CONVERT(attr->ia_mtime);
        
        if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size);
        
@@ -5208,15 +5227,10 @@ int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr)
        attr->ia_uid = obj->st_uid;             valid |= ATTR_UID;
        attr->ia_gid = obj->st_gid;             valid |= ATTR_GID;
        
-#if defined(CONFIG_KERNEL_2_5)
-       attr->ia_atime.tv_sec = obj->st_atime;  valid |= ATTR_ATIME;
-       attr->ia_ctime.tv_sec = obj->st_ctime;  valid |= ATTR_CTIME;
-       attr->ia_mtime.tv_sec = obj->st_mtime;  valid |= ATTR_MTIME;
-#else  
-       attr->ia_atime = obj->st_atime; valid |= ATTR_ATIME;
-       attr->ia_ctime = obj->st_ctime; valid |= ATTR_CTIME;
-       attr->ia_mtime = obj->st_mtime; valid |= ATTR_MTIME;
-#endif 
+       Y_TIME_CONVERT(attr->ia_atime)= obj->st_atime;  valid |= ATTR_ATIME;
+       Y_TIME_CONVERT(attr->ia_ctime) = obj->st_ctime; valid |= ATTR_CTIME;
+       Y_TIME_CONVERT(attr->ia_mtime) = obj->st_mtime; valid |= ATTR_MTIME;
+
        attr->ia_size = yaffs_GetFileSize(obj); valid |= ATTR_SIZE;
        
        attr->ia_valid = valid;
@@ -5279,6 +5293,8 @@ int yaffs_CheckDevFunctions(const yaffs_Device *dev)
        if(!dev->eraseBlockInNAND ||
           !dev->initialiseNAND) return 0;
 
+#ifdef CONFIG_YAFFS_YAFFS2
+
        // Can use the "with tags" style interface for yaffs1 or yaffs2
        if(dev->writeChunkWithTagsToNAND &&
           dev->readChunkWithTagsFromNAND &&
@@ -5286,6 +5302,7 @@ int yaffs_CheckDevFunctions(const yaffs_Device *dev)
           !dev->readChunkFromNAND &&
           dev->markNANDBlockBad &&
           dev->queryNANDBlock) return 1;
+#endif
 
        // Can use the "spare" style interface for yaffs1
        if(!dev->isYaffs2 &&
@@ -5307,11 +5324,12 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        int extraBits;
        int nBlocks;
 
+       T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR)));
        // Check stuff that must be set
 
        if(!dev)
        {
-               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Need a device\n" TENDSTR)));
+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Need a device" TENDSTR)));
                return YAFFS_FAIL;
        }
 
@@ -5326,10 +5344,16 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
                dev->endBlock <= (dev->startBlock + dev->nReservedBlocks + 2) // otherwise it is too small
          )
        {
-               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: nand geometry problems\n" TENDSTR)));
+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s " TENDSTR),
+                  dev->nBytesPerChunk, dev->isYaffs2 ? "2" : ""));
                return YAFFS_FAIL;
        }
 
+       if(yaffs_InitialiseNAND(dev) != YAFFS_OK)
+       {
+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
+               return YAFFS_FAIL;
+       }
 
        // Got the right mix of functions?
        //
@@ -5436,7 +5460,6 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        
 
        
-       
        yaffs_InitialiseBlocks(dev,nBlocks);
        
        yaffs_InitialiseTnodes(dev);
@@ -5496,7 +5519,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
 
        dev->nRetiredBlocks = 0;
 
-       
+       T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
        return YAFFS_OK;
                
 }
@@ -5680,4 +5703,3 @@ void yaffs_GutsTest(yaffs_Device *dev)
 #endif
 
 
-