KernelLand - Better node chaching code
authorJohn Hodge <[email protected]>
Wed, 26 Jun 2013 10:15:48 +0000 (18:15 +0800)
committerJohn Hodge <[email protected]>
Wed, 26 Jun 2013 10:15:48 +0000 (18:15 +0800)
KernelLand/Kernel/include/vfs.h
KernelLand/Kernel/vfs/nodecache.c
KernelLand/Modules/Filesystems/Ext2/ext2.c
KernelLand/Modules/Filesystems/Ext2/ext2_common.h
KernelLand/Modules/Filesystems/NTFS/common.h
KernelLand/Modules/Filesystems/NTFS/dir.c
KernelLand/Modules/Filesystems/NTFS/io.c
KernelLand/Modules/Filesystems/NTFS/main.c

index d2cdf20..f766613 100644 (file)
@@ -496,12 +496,17 @@ extern int        VFS_MarkError(tVFS_Node *Node, BOOL IsErrorState);
  * fast cleanup when a filesystem is unmounted.
  * \{
  */
+
+typedef struct sInodeCache     tInodeCache;
+
+typedef void   (*tInode_CleanUpNode)(tVFS_Node *Node);
+
 /**
  * \fn int Inode_GetHandle(void)
  * \brief Gets a unique handle to the Node Cache
  * \return A unique handle for use for the rest of the Inode_* functions
  */
-extern int     Inode_GetHandle(void);
+extern tInodeCache     *Inode_GetHandle(tInode_CleanUpNode CleanUpNode);
 /**
  * \fn tVFS_Node *Inode_GetCache(int Handle, Uint64 Inode)
  * \brief Gets an inode from the node cache
@@ -509,7 +514,7 @@ extern int  Inode_GetHandle(void);
  * \param Inode        Value of the Inode field of the ::tVFS_Node you want
  * \return A pointer to the cached node
  */
-extern tVFS_Node       *Inode_GetCache(int Handle, Uint64 Inode);
+extern tVFS_Node       *Inode_GetCache(tInodeCache *Handle, Uint64 Inode);
 /**
  * \fn tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node)
  * \brief Caches a node in the Node Cache
@@ -517,8 +522,8 @@ extern tVFS_Node    *Inode_GetCache(int Handle, Uint64 Inode);
  * \param Node A pointer to the node to be cached (a copy is taken)
  * \return A pointer to the node in the node cache
  */
-extern tVFS_Node       *Inode_CacheNode(int Handle, tVFS_Node *Node);
-extern tVFS_Node       *Inode_CacheNodeEx(int Handle, tVFS_Node *Node, size_t Size);
+extern tVFS_Node       *Inode_CacheNode(tInodeCache *Handle, tVFS_Node *Node);
+extern tVFS_Node       *Inode_CacheNodeEx(tInodeCache *Handle, tVFS_Node *Node, size_t Size);
 /**
  * \fn int Inode_UncacheNode(int Handle, Uint64 Inode)
  * \brief Dereferences (and removes if needed) a node from the cache
@@ -526,13 +531,13 @@ extern tVFS_Node  *Inode_CacheNodeEx(int Handle, tVFS_Node *Node, size_t Size);
  * \param Inode        Value of the Inode field of the ::tVFS_Node you want to remove
  * \return -1: Error (not present), 0: Not freed, 1: Freed
  */
-extern int     Inode_UncacheNode(int Handle, Uint64 Inode);
+extern int     Inode_UncacheNode(tInodeCache *Handle, Uint64 Inode);
 /**
  * \fn void Inode_ClearCache(int Handle)
  * \brief Clears the cache for a handle
  * \param Handle       A handle returned by Inode_GetHandle()
  */
-extern void    Inode_ClearCache(int Handle);
+extern void    Inode_ClearCache(tInodeCache *Handle);
 
 /**
  * \}
index aee1826..5fdebb6 100644 (file)
@@ -15,33 +15,30 @@ typedef struct sCachedInode {
        struct sCachedInode     *Next;
        tVFS_Node       Node;
 } tCachedInode;
-typedef struct sInodeCache {
+struct sInodeCache
+{
        struct sInodeCache      *Next;
-        int    Handle;
+       tInode_CleanUpNode      CleanUpNode;
        tCachedInode    *FirstNode;     // Sorted List
        Uint64  MaxCached;              // Speeds up Searching
-} tInodeCache;
-
-// === PROTOTYPES ===
-tInodeCache    *Inode_int_GetFSCache(int Handle);
+};
 
 // === GLOBALS ===
- int   gVFS_NextInodeHandle = 1;
 tShortSpinlock glVFS_InodeCache;
 tInodeCache    *gVFS_InodeCache = NULL;
 
 // === CODE ===
-/**
- * \fn int Inode_GetHandle()
- */
-int Inode_GetHandle()
+
+// Create a new inode cache
+tInodeCache *Inode_GetHandle(tInode_CleanUpNode CleanUpNode)
 {
        tInodeCache     *ent;
        
        ent = malloc( sizeof(tInodeCache) );
        ent->MaxCached = 0;
-       ent->Handle = gVFS_NextInodeHandle++;
-       ent->Next = NULL;       ent->FirstNode = NULL;
+       ent->Next = NULL;
+       ent->FirstNode = NULL;
+       ent->CleanUpNode = CleanUpNode;
        
        // Add to list
        SHORTLOCK( &glVFS_InodeCache );
@@ -49,26 +46,21 @@ int Inode_GetHandle()
        gVFS_InodeCache = ent;
        SHORTREL( &glVFS_InodeCache );
        
-       return ent->Handle;
+       return ent;
 }
 
 /**
  * \fn tVFS_Node *Inode_GetCache(int Handle, Uint64 Inode)
  * \brief Gets a node from the cache
  */
-tVFS_Node *Inode_GetCache(int Handle, Uint64 Inode)
+tVFS_Node *Inode_GetCache(tInodeCache *Cache, Uint64 Inode)
 {
-       tInodeCache     *cache;
        tCachedInode    *ent;
        
-       cache = Inode_int_GetFSCache(Handle);
-       if(!cache)      return NULL;
-       
-       if(Inode > cache->MaxCached)    return NULL;
+       if(Inode > Cache->MaxCached)    return NULL;
        
        // Search Cache
-       ent = cache->FirstNode;
-       for( ; ent; ent = ent->Next )
+       for( ent = Cache->FirstNode; ent; ent = ent->Next )
        {
                if(ent->Node.Inode < Inode)     continue;
                if(ent->Node.Inode > Inode)     return NULL;
@@ -82,27 +74,23 @@ tVFS_Node *Inode_GetCache(int Handle, Uint64 Inode)
 /**
  * \fn tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node)
  */
-tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node)
+tVFS_Node *Inode_CacheNode(tInodeCache *Handle, tVFS_Node *Node)
 {
        return Inode_CacheNodeEx(Handle, Node, sizeof(*Node));
 }
 
-tVFS_Node *Inode_CacheNodeEx(int Handle, tVFS_Node *Node, size_t Size)
+tVFS_Node *Inode_CacheNodeEx(tInodeCache *Cache, tVFS_Node *Node, size_t Size)
 {
-       tInodeCache     *cache;
-       tCachedInode    *newEnt, *ent, *prev = NULL;
+       tCachedInode    *newEnt, *prev = NULL;
 
        ASSERT(Size >= sizeof(tVFS_Node));      
-
-       cache = Inode_int_GetFSCache(Handle);
-       if(!cache)      return NULL;
        
-       if(Node->Inode > cache->MaxCached)
-               cache->MaxCached = Node->Inode;
+       if(Node->Inode > Cache->MaxCached)
+               Cache->MaxCached = Node->Inode;
        
        // Search Cache
-       ent = cache->FirstNode;
-       for( ; ent; prev = ent, ent = ent->Next )
+       tCachedInode *ent;
+       for( ent = Cache->FirstNode; ent; prev = ent, ent = ent->Next )
        {
                if(ent->Node.Inode < Node->Inode)       continue;
                if(ent->Node.Inode == Node->Inode) {
@@ -119,7 +107,7 @@ tVFS_Node *Inode_CacheNodeEx(int Handle, tVFS_Node *Node, size_t Size)
        if( prev )
                prev->Next = newEnt;
        else
-               cache->FirstNode = newEnt;
+               Cache->FirstNode = newEnt;
        newEnt->Node.ReferenceCount = 1;
 
        LOG("Cached %llx as %p", Node->Inode, &newEnt->Node);
@@ -131,28 +119,20 @@ tVFS_Node *Inode_CacheNodeEx(int Handle, tVFS_Node *Node, size_t Size)
  * \fn void Inode_UncacheNode(int Handle, Uint64 Inode)
  * \brief Dereferences/Removes a cached node
  */
-int Inode_UncacheNode(int Handle, Uint64 Inode)
+int Inode_UncacheNode(tInodeCache *Cache, Uint64 Inode)
 {
-       tInodeCache     *cache;
        tCachedInode    *ent, *prev;
        
-       cache = Inode_int_GetFSCache(Handle);
-       if(!cache) {
-               Log_Notice("Inode", "Invalid cache handle %i used", Handle);
-               return -1;
-       }
+       ENTER("pHandle XInode", Cache, Inode);
 
-       ENTER("iHandle XInode", Handle, Inode);
-
-       if(Inode > cache->MaxCached) {
+       if(Inode > Cache->MaxCached) {
                LEAVE('i', -1);
                return -1;
        }
        
        // Search Cache
-       ent = cache->FirstNode;
        prev = NULL;
-       for( ; ent; prev = ent, ent = ent->Next )
+       for( ent = Cache->FirstNode; ent; prev = ent, ent = ent->Next )
        {
                if(ent->Node.Inode < Inode)     continue;
                if(ent->Node.Inode > Inode) {
@@ -176,15 +156,17 @@ int Inode_UncacheNode(int Handle, Uint64 Inode)
                if( prev )
                        prev->Next = ent->Next;
                else
-                       cache->FirstNode = ent->Next;
-               if(ent->Node.Inode == cache->MaxCached)
+                       Cache->FirstNode = ent->Next;
+               if(ent->Node.Inode == Cache->MaxCached)
                {
-                       if(ent != cache->FirstNode && prev)
-                               cache->MaxCached = prev->Node.Inode;
+                       if(ent != Cache->FirstNode && prev)
+                               Cache->MaxCached = prev->Node.Inode;
                        else
-                               cache->MaxCached = 0;
+                               Cache->MaxCached = 0;
                }
-               
+       
+               if(Cache->CleanUpNode)
+                       Cache->CleanUpNode(&ent->Node);
                if(ent->Node.Data)
                        free(ent->Node.Data);   
                free(ent);
@@ -203,63 +185,38 @@ int Inode_UncacheNode(int Handle, Uint64 Inode)
  * \fn void Inode_ClearCache(int Handle)
  * \brief Removes a cache
  */
-void Inode_ClearCache(int Handle)
+void Inode_ClearCache(tInodeCache *Cache)
 {
-       tInodeCache     *cache;
        tInodeCache     *prev = NULL;
        tCachedInode    *ent, *next;
        
        // Find the cache
-       for(
-               cache = gVFS_InodeCache;
-               cache && cache->Handle < Handle;
-               prev = cache, cache = cache->Next
-               );
-       if(!cache || cache->Handle != Handle)   return;
+       for( prev = (void*)&gVFS_InodeCache; prev && prev->Next != Cache; prev = prev->Next )
+               ;
+       if( !prev ) {
+               // Oops?
+               return;
+       }
        
        // Search Cache
-       ent = cache->FirstNode;
-       while( ent )
+       for( ent = Cache->FirstNode; ent; ent = next )
        {
-               ent->Node.ReferenceCount = 1;
                next = ent->Next;
+               ent->Node.ReferenceCount = 1;
                
+               // Usually has the side-effect of freeing this node
+               // TODO: Ensure that node is freed
                if(ent->Node.Type && ent->Node.Type->Close)
                        ent->Node.Type->Close( &ent->Node );
-               free(ent);
-               
-               ent = next;
+               else
+                       free(ent);
        }
        
        // Free Cache
        if(prev == NULL)
-               gVFS_InodeCache = cache->Next;
+               gVFS_InodeCache = Cache->Next;
        else
-               prev->Next = cache->Next;
-       free(cache);
+               prev->Next = Cache->Next;
+       free(Cache);
 }
 
-/**
- * \fn tInodeCache *Inode_int_GetFSCache(int Handle)
- * \brief Gets a cache given it's handle
- */
-tInodeCache *Inode_int_GetFSCache(int Handle)
-{
-       tInodeCache     *cache = gVFS_InodeCache;
-       // Find Cache
-       for( ; cache; cache = cache->Next )
-       {
-               if(cache->Handle > Handle)      continue;
-               if(cache->Handle < Handle) {
-                       Warning("Inode_int_GetFSCache - Handle %i not in cache\n", Handle);
-                       return NULL;
-               }
-               break;
-       }
-       if(!cache) {
-               Warning("Inode_int_GetFSCache - Handle %i not in cache [NULL]\n", Handle);
-               return NULL;
-       }
-       
-       return cache;
-}
index 4d13f1e..516fe0b 100644 (file)
@@ -139,7 +139,7 @@ tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options)
        disk->GroupCount = groupCount;\r
        \r
        // Get an inode cache handle\r
-       disk->CacheID = Inode_GetHandle();\r
+       disk->CacheID = Inode_GetHandle(NULL);\r
        \r
        // Get Block Size\r
        if( sb.s_log_block_size > MAX_BLOCK_LOG_SIZE ) {\r
index b4c9547..04fcae4 100644 (file)
@@ -13,7 +13,7 @@
 // === STRUCTURES ===
 typedef struct {
         int    FD;
-        int    CacheID;
+       tInodeCache     *CacheID;
        tVFS_Node       RootNode;
        
        tExt2_SuperBlock        SuperBlock;
index e8dbe7d..3ef8109 100644 (file)
@@ -40,7 +40,7 @@ struct sNTFS_Directory
 struct sNTFS_Disk
 {
         int    FD;
-        int    CacheHandle;
+       tInodeCache     *InodeCache;
         
         int    ClusterSize;
        
@@ -50,8 +50,6 @@ struct sNTFS_Disk
        tNTFS_Attrib    *MFTDataAttr;
        tNTFS_Attrib    *MFTBitmapAttr;
 
-        int    InodeCache;
-       
        tNTFS_Directory RootDir;
 };
 
index dc5fb7c..5697252 100644 (file)
@@ -273,6 +273,7 @@ tVFS_Node *NTFS_int_CreateNode(tNTFS_Disk *Disk, Uint64 MFTEntry)
                ret = &types.tpl_file.Node;
                ret->Type = &gNTFS_FileType;
                types.tpl_file.Data = NTFS_GetAttrib(Disk, MFTEntry, NTFS_FileAttrib_Data, "", 0); 
+               ret->Size = types.tpl_file.Data->DataSize;
        }
        ret->Inode = MFTEntry;
        ret->ImplPtr = Disk;
index d0f7088..014dc70 100644 (file)
 size_t NTFS_ReadFile(tVFS_Node *Node, Uint64 Offset, size_t Length, void *Buffer, Uint Flags)
 {
        tNTFS_File      *File = (void*)Node;
-       
-       return NTFS_ReadAttribData(File->Data, Offset, Length, Buffer);
+
+       ENTER("XNode->Inode XOffset xLength pBuffer xFlags",
+               Node->Inode, Offset, Length, Buffer, Flags);    
+
+       size_t  ret =  NTFS_ReadAttribData(File->Data, Offset, Length, Buffer);
+       LEAVE('x', ret);
+       return ret;
 }
 
 
index 4586e12..3b17e17 100644 (file)
@@ -137,7 +137,7 @@ tVFS_Node *NTFS_InitDevice(const char *Device, const char **Options)
        //NTFS_DumpEntry(disk, 0);      // $MFT
        //NTFS_DumpEntry(disk, 3);      // $VOLUME
 
-       disk->InodeCache = Inode_GetHandle();
+       disk->InodeCache = Inode_GetHandle(NTFS_FreeNode);
        
        disk->MFTDataAttr = NULL;
        disk->MFTDataAttr = NTFS_GetAttrib(disk, 0, NTFS_FileAttrib_Data, "", 0);
@@ -223,6 +223,9 @@ int NTFS_int_ApplyUpdateSequence(void *Buffer, size_t BufLen, const Uint16 *Sequ
 
 tNTFS_FILE_Header *NTFS_GetMFT(tNTFS_Disk *Disk, Uint32 MFTEntry)
 {
+       // TODO: Cache MFT allocation for short-term    
+
+       // 
        tNTFS_FILE_Header       *ret = malloc( Disk->MFTRecSize );
        if(!ret) {
                Log_Warning("FS_NTFS", "malloc() fail!");
@@ -332,8 +335,12 @@ tNTFS_Attrib *NTFS_GetAttrib(tNTFS_Disk *Disk, Uint32 MFTEntry, int Type, const
                if( attr->Type != Type )
                        continue;
                if( Name ) {
-                       LOG("Name check = '%s'", Name);
+                       if( attr->NameOffset + attr->NameLength*2 > attr->Size ) {
+                               break;
+                       }
                        const void      *name16 = (char*)attr + attr->NameOffset;
+                       LOG("Name check: '%s' == '%.*ls'",
+                               Name, attr->NameLength, name16);
                        if( UTF16_CompareWithUTF8(attr->NameLength, name16, Name) != 0 )
                                continue ;
                }
@@ -345,11 +352,10 @@ tNTFS_Attrib *NTFS_GetAttrib(tNTFS_Disk *Disk, Uint32 MFTEntry, int Type, const
                ASSERT(attr->NameOffset % 1 == 0);
                Uint16  *name16 = (Uint16*)attr + attr->NameOffset/2;
                size_t  namelen = UTF16_ConvertToUTF8(0, NULL, attr->NameLength, name16);
-               size_t  edatalen = (attr->NonresidentFlag ? 0 : attr->Resident.AttribLen*4);
+               size_t  edatalen = (attr->NonresidentFlag ? 0 : attr->Resident.AttribLen);
                tNTFS_Attrib *ret = malloc( sizeof(tNTFS_Attrib) + namelen + 1 + edatalen );
                if(!ret) {
-                       LEAVE('n');
-                       return NULL;
+                       goto _error;
                }
                if( attr->NonresidentFlag )
                        ret->Name = (void*)(ret + 1);
@@ -396,12 +402,15 @@ tNTFS_Attrib *NTFS_GetAttrib(tNTFS_Disk *Disk, Uint32 MFTEntry, int Type, const
                {
                        ret->DataSize = edatalen;
                        memcpy(ret->ResidentData, (char*)attr + attr->Resident.AttribOfs, edatalen);
+                       Debug_HexDump("GetAttrib Resident", ret->ResidentData, edatalen);
                }
                
+               NTFS_ReleaseMFT(Disk, MFTEntry, hdr);
                LEAVE('p', ret);
                return ret;
        }
 
+_error:
        NTFS_ReleaseMFT(Disk, MFTEntry, hdr);
        LEAVE('n');
        return NULL;

UCC git Repository :: git.ucc.asn.au