X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fvfs%2Fnodecache.c;h=5fdebb6b655b240cf64f901485ba6b9279b3ccfd;hb=9c4eedf4893f851bd1ba60ce541c8d098a9ef7f7;hp=0d238941be80a52f40903417982dc6f1b83182ee;hpb=d0b4559f2936f6d9f06be0f7c3c51527a480ec0d;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/vfs/nodecache.c b/KernelLand/Kernel/vfs/nodecache.c index 0d238941..5fdebb6b 100644 --- a/KernelLand/Kernel/vfs/nodecache.c +++ b/KernelLand/Kernel/vfs/nodecache.c @@ -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,21 +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) { - tInodeCache *cache; - tCachedInode *newEnt, *ent, *prev; - - cache = Inode_int_GetFSCache(Handle); - if(!cache) return NULL; + return Inode_CacheNodeEx(Handle, Node, sizeof(*Node)); +} + +tVFS_Node *Inode_CacheNodeEx(tInodeCache *Cache, tVFS_Node *Node, size_t Size) +{ + tCachedInode *newEnt, *prev = NULL; + + ASSERT(Size >= sizeof(tVFS_Node)); - if(Node->Inode > cache->MaxCached) - cache->MaxCached = Node->Inode; + if(Node->Inode > Cache->MaxCached) + Cache->MaxCached = Node->Inode; // Search Cache - ent = cache->FirstNode; - prev = (tCachedInode*) &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) { @@ -107,10 +101,13 @@ tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node) } // Create new entity - newEnt = malloc(sizeof(tCachedInode)); + newEnt = malloc(sizeof(tCachedInode) + (Size - sizeof(tVFS_Node))); newEnt->Next = ent; - memcpy(&newEnt->Node, Node, sizeof(tVFS_Node)); - prev->Next = newEnt; + memcpy(&newEnt->Node, Node, Size); + if( prev ) + prev->Next = newEnt; + else + Cache->FirstNode = newEnt; newEnt->Node.ReferenceCount = 1; LOG("Cached %llx as %p", Node->Inode, &newEnt->Node); @@ -122,28 +119,20 @@ tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node) * \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("iHandle XInode", Handle, Inode); + ENTER("pHandle XInode", Cache, 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) { @@ -167,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); @@ -194,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; -}