3 * - By John Hodge (thePowersGang)
6 * - VFS Node Caching facility
14 typedef struct sCachedInode {
15 struct sCachedInode *Next;
18 typedef struct sInodeCache {
19 struct sInodeCache *Next;
21 tCachedInode *FirstNode; // Sorted List
22 Uint64 MaxCached; // Speeds up Searching
26 tInodeCache *Inode_int_GetFSCache(int Handle);
29 int gVFS_NextInodeHandle = 1;
30 tShortSpinlock glVFS_InodeCache;
31 tInodeCache *gVFS_InodeCache = NULL;
35 * \fn int Inode_GetHandle()
41 ent = malloc( sizeof(tInodeCache) );
43 ent->Handle = gVFS_NextInodeHandle++;
44 ent->Next = NULL; ent->FirstNode = NULL;
47 SHORTLOCK( &glVFS_InodeCache );
48 ent->Next = gVFS_InodeCache;
49 gVFS_InodeCache = ent;
50 SHORTREL( &glVFS_InodeCache );
56 * \fn tVFS_Node *Inode_GetCache(int Handle, Uint64 Inode)
57 * \brief Gets a node from the cache
59 tVFS_Node *Inode_GetCache(int Handle, Uint64 Inode)
64 cache = Inode_int_GetFSCache(Handle);
65 if(!cache) return NULL;
67 if(Inode > cache->MaxCached) return NULL;
70 ent = cache->FirstNode;
71 for( ; ent; ent = ent->Next )
73 if(ent->Node.Inode < Inode) continue;
74 if(ent->Node.Inode > Inode) return NULL;
75 ent->Node.ReferenceCount ++;
79 return NULL; // Should never be reached
83 * \fn tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node)
85 tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node)
88 tCachedInode *newEnt, *ent, *prev = NULL;
90 cache = Inode_int_GetFSCache(Handle);
91 if(!cache) return NULL;
93 if(Node->Inode > cache->MaxCached)
94 cache->MaxCached = Node->Inode;
97 ent = cache->FirstNode;
98 for( ; ent; prev = ent, ent = ent->Next )
100 if(ent->Node.Inode < Node->Inode) continue;
101 if(ent->Node.Inode == Node->Inode) {
102 ent->Node.ReferenceCount ++;
109 newEnt = malloc(sizeof(tCachedInode));
111 memcpy(&newEnt->Node, Node, sizeof(tVFS_Node));
115 cache->FirstNode = newEnt;
116 newEnt->Node.ReferenceCount = 1;
118 LOG("Cached %llx as %p", Node->Inode, &newEnt->Node);
120 return &newEnt->Node;
124 * \fn void Inode_UncacheNode(int Handle, Uint64 Inode)
125 * \brief Dereferences/Removes a cached node
127 int Inode_UncacheNode(int Handle, Uint64 Inode)
130 tCachedInode *ent, *prev;
132 cache = Inode_int_GetFSCache(Handle);
134 Log_Notice("Inode", "Invalid cache handle %i used", Handle);
138 ENTER("iHandle XInode", Handle, Inode);
140 if(Inode > cache->MaxCached) {
146 ent = cache->FirstNode;
148 for( ; ent; prev = ent, ent = ent->Next )
150 if(ent->Node.Inode < Inode) continue;
151 if(ent->Node.Inode > Inode) {
158 LOG("ent = %p", ent);
165 ent->Node.ReferenceCount --;
166 // Check if node needs to be freed
167 if(ent->Node.ReferenceCount == 0)
170 prev->Next = ent->Next;
172 cache->FirstNode = ent->Next;
173 if(ent->Node.Inode == cache->MaxCached)
175 if(ent != cache->FirstNode && prev)
176 cache->MaxCached = prev->Node.Inode;
178 cache->MaxCached = 0;
182 free(ent->Node.Data);
196 * \fn void Inode_ClearCache(int Handle)
197 * \brief Removes a cache
199 void Inode_ClearCache(int Handle)
202 tInodeCache *prev = NULL;
203 tCachedInode *ent, *next;
207 cache = gVFS_InodeCache;
208 cache && cache->Handle < Handle;
209 prev = cache, cache = cache->Next
211 if(!cache || cache->Handle != Handle) return;
214 ent = cache->FirstNode;
217 ent->Node.ReferenceCount = 1;
220 if(ent->Node.Type && ent->Node.Type->Close)
221 ent->Node.Type->Close( &ent->Node );
229 gVFS_InodeCache = cache->Next;
231 prev->Next = cache->Next;
236 * \fn tInodeCache *Inode_int_GetFSCache(int Handle)
237 * \brief Gets a cache given it's handle
239 tInodeCache *Inode_int_GetFSCache(int Handle)
241 tInodeCache *cache = gVFS_InodeCache;
243 for( ; cache; cache = cache->Next )
245 if(cache->Handle > Handle) continue;
246 if(cache->Handle < Handle) {
247 Warning("Inode_int_GetFSCache - Handle %i not in cache\n", Handle);
253 Warning("Inode_int_GetFSCache - Handle %i not in cache [NULL]\n", Handle);