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;
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 prev = (tCachedInode*) &cache->FirstNode;
99 for( ; ent; prev = ent, ent = ent->Next )
101 if(ent->Node.Inode < Node->Inode) continue;
102 if(ent->Node.Inode == Node->Inode) {
103 ent->Node.ReferenceCount ++;
110 newEnt = malloc(sizeof(tCachedInode));
112 memcpy(&newEnt->Node, Node, sizeof(tVFS_Node));
114 newEnt->Node.ReferenceCount = 1;
116 LOG("Cached %llx as %p", Node->Inode, &newEnt->Node);
118 return &newEnt->Node;
122 * \fn void Inode_UncacheNode(int Handle, Uint64 Inode)
123 * \brief Dereferences/Removes a cached node
125 int Inode_UncacheNode(int Handle, Uint64 Inode)
128 tCachedInode *ent, *prev;
130 cache = Inode_int_GetFSCache(Handle);
132 Log_Notice("Inode", "Invalid cache handle %i used", Handle);
136 ENTER("iHandle XInode", Handle, Inode);
138 if(Inode > cache->MaxCached) {
144 ent = cache->FirstNode;
146 for( ; ent; prev = ent, ent = ent->Next )
148 if(ent->Node.Inode < Inode) continue;
149 if(ent->Node.Inode > Inode) {
156 LOG("ent = %p", ent);
163 ent->Node.ReferenceCount --;
164 // Check if node needs to be freed
165 if(ent->Node.ReferenceCount == 0)
168 prev->Next = ent->Next;
170 cache->FirstNode = ent->Next;
171 if(ent->Node.Inode == cache->MaxCached)
173 if(ent != cache->FirstNode && prev)
174 cache->MaxCached = prev->Node.Inode;
176 cache->MaxCached = 0;
180 free(ent->Node.Data);
194 * \fn void Inode_ClearCache(int Handle)
195 * \brief Removes a cache
197 void Inode_ClearCache(int Handle)
200 tInodeCache *prev = NULL;
201 tCachedInode *ent, *next;
205 cache = gVFS_InodeCache;
206 cache && cache->Handle < Handle;
207 prev = cache, cache = cache->Next
209 if(!cache || cache->Handle != Handle) return;
212 ent = cache->FirstNode;
215 ent->Node.ReferenceCount = 1;
218 if(ent->Node.Type && ent->Node.Type->Close)
219 ent->Node.Type->Close( &ent->Node );
227 gVFS_InodeCache = cache->Next;
229 prev->Next = cache->Next;
234 * \fn tInodeCache *Inode_int_GetFSCache(int Handle)
235 * \brief Gets a cache given it's handle
237 tInodeCache *Inode_int_GetFSCache(int Handle)
239 tInodeCache *cache = gVFS_InodeCache;
241 for( ; cache; cache = cache->Next )
243 if(cache->Handle > Handle) continue;
244 if(cache->Handle < Handle) {
245 Warning("Inode_int_GetFSCache - Handle %i not in cache\n", Handle);
251 Warning("Inode_int_GetFSCache - Handle %i not in cache [NULL]\n", Handle);