3 * - AllocHandle, GetHandle
12 #include <threads.h> // GetMaxFD
13 #include <vfs_threads.h> // Handle maintainance
16 #define MAX_KERNEL_FILES 128
21 tVFS_Handle *gaUserHandles = (void*)MM_PPD_HANDLES;
22 tVFS_Handle *gaKernelHandles = (void*)MM_KERNEL_VFS;
26 * \fn tVFS_Handle *VFS_GetHandle(int FD)
27 * \brief Gets a pointer to the handle information structure
29 tVFS_Handle *VFS_GetHandle(int FD)
33 //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
35 if(FD < 0) return NULL;
37 if(FD & VFS_KERNEL_FLAG) {
38 FD &= (VFS_KERNEL_FLAG - 1);
39 if(FD >= MAX_KERNEL_FILES) return NULL;
40 h = &gaKernelHandles[ FD ];
42 if(FD >= *Threads_GetMaxFD(NULL)) return NULL;
43 h = &gaUserHandles[ FD ];
46 if(h->Node == NULL) return NULL;
47 //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
51 int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode)
56 if( FD & VFS_KERNEL_FLAG ) {
57 FD &= (VFS_KERNEL_FLAG -1);
58 if( FD >= MAX_KERNEL_FILES ) return -1;
59 h = &gaKernelHandles[FD];
62 if( FD >= *Threads_GetMaxFD(NULL)) return -1;
63 h = &gaUserHandles[FD];
70 int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode)
72 // Check for a user open
75 int max_handles = *Threads_GetMaxFD(NULL);
77 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
79 tPage *pageptr = (void*)gaUserHandles;
80 size_t size = max_handles * sizeof(tVFS_Handle);
81 for( size_t ofs = 0; ofs < size; ofs ++)
83 if( !MM_Allocate( pageptr ) )
85 Warning("OOM - VFS_AllocHandle");
86 Threads_Exit(0, 0xFF); // Terminate user
90 memset( gaUserHandles, 0, size );
93 for( int i = 0; i < max_handles; i ++ )
95 if(gaUserHandles[i].Node) continue;
96 gaUserHandles[i].Node = Node;
97 gaUserHandles[i].Position = 0;
98 gaUserHandles[i].Mode = Mode;
104 // Allocate space if not already
105 if( MM_GetPhysAddr( gaKernelHandles ) == 0 )
107 tPage *pageptr = (void*)gaKernelHandles;
108 size_t size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
109 for(size_t ofs = 0; ofs < size; ofs += size)
111 if( !MM_Allocate( pageptr ) )
113 Panic("OOM - VFS_AllocHandle");
117 memset( gaKernelHandles, 0, size );
120 for(int i=0;i<MAX_KERNEL_FILES;i++)
122 if(gaKernelHandles[i].Node) continue;
123 gaKernelHandles[i].Node = Node;
124 gaKernelHandles[i].Position = 0;
125 gaKernelHandles[i].Mode = Mode;
126 return i|VFS_KERNEL_FLAG;
133 void VFS_ReferenceUserHandles(void)
135 const int max_handles = *Threads_GetMaxFD(NULL);
137 // Check if this process has any handles
138 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
141 for( int i = 0; i < max_handles; i ++ )
144 h = &gaUserHandles[i];
147 _ReferenceNode(h->Node);
148 h->Mount->OpenHandleCount ++;
152 void VFS_CloseAllUserHandles(struct sProcess *Process)
154 const int max_handles = *Threads_GetMaxFD(Process);
155 ENTER("pProcess", Process);
157 if( max_handles >= PAGE_SIZE / sizeof(tVFS_Handle) )
158 TODO("More than a page of handles");
160 tVFS_Handle *handles = MM_MapTempFromProc(Process, gaUserHandles);
161 LOG("handles=%p", handles);
162 // Check if this process has any handles
168 for( int i = 0; i < max_handles; i ++ )
170 tVFS_Handle *h = &handles[i];
171 LOG("handles[%i].Node = %p", i, h->Node);
178 MM_FreeTemp(handles);
183 * \brief Take a backup of a set of file descriptors
185 void *VFS_SaveHandles(int NumFDs, int *FDs)
188 const int max_handles = *Threads_GetMaxFD(NULL);
190 // Check if this process has any handles
191 if( MM_GetPhysAddr( gaUserHandles ) == 0 )
195 ret = malloc( NumFDs * sizeof(tVFS_Handle) );
199 if( NumFDs > max_handles )
200 NumFDs = max_handles;
202 // Take copies of the handles
204 memcpy(ret, gaUserHandles, NumFDs * sizeof(tVFS_Handle));
208 for( int i = 0; i < NumFDs; i ++ )
212 Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (%i<0), ignorning",
214 memset(&ret[i], 0, sizeof(tVFS_Handle));
218 int fd = FDs[i] & (VFS_KERNEL_FLAG - 1);
219 tVFS_Handle *h = VFS_GetHandle(fd);
221 Log_Warning("VFS", "VFS_SaveHandles - Invalid FD 0x%x (%i) in slot %i",
226 // Log("%i: Duplicate FD %i (%p)", i, fd, h->Node);
227 memcpy( &ret[i], h, sizeof(tVFS_Handle) );
231 // Reference nodes/mounts
232 for( int i = 0; i < NumFDs; i ++ )
234 tVFS_Handle *h = &ret[i];
238 // Debug("VFS_SaveHandles: %i %p", i, h->Node);
239 _ReferenceNode(h->Node);
240 h->Mount->OpenHandleCount ++;
246 void VFS_RestoreHandles(int NumFDs, void *Handles)
248 tVFS_Handle *handles = Handles;
249 const int max_handles = *Threads_GetMaxFD(NULL);
251 // NULL = nothing to do
255 if( NumFDs > max_handles ) {
256 Log_Notice("VFS", "RestoreHandles: Capping from %i FDs to %i", NumFDs, max_handles);
257 NumFDs = max_handles;
260 // Allocate user handle area (and dereference existing handles)
261 for( int i = 0; i < NumFDs; i ++ )
263 tVFS_Handle *h = &gaUserHandles[i];
265 if( !MM_GetPhysAddr(h) )
267 void *pg = (void*)( (tVAddr)h & ~(PAGE_SIZE-1) );
268 if( !MM_Allocate( pg ) )
273 memset(pg, 0, PAGE_SIZE);
275 // Safe to dereference, as Threads_CloneTCB references handles
282 h->Mount->OpenHandleCount --;
290 memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) );
291 // Reference when copied
292 for( int i = 0; i < NumFDs; i ++ )
294 tVFS_Handle *h = &gaUserHandles[i];
298 // Debug("VFS_RestoreHandles: %i %p", i, h->Node);
299 _ReferenceNode(h->Node);
300 h->Mount->OpenHandleCount ++;
302 for( int i = NumFDs; i < max_handles; i ++ )
304 gaUserHandles[i].Node = NULL;
308 void VFS_FreeSavedHandles(int NumFDs, void *Handles)
310 tVFS_Handle *handles = Handles;
313 // NULL = nothing to do
317 // Dereference all saved nodes
318 for( i = 0; i < NumFDs; i ++ )
320 tVFS_Handle *h = &handles[i];
326 ASSERT(h->Mount->OpenHandleCount > 0);
327 LOG("dec. mntpt '%s' to %i", h->Mount->MountPoint, h->Mount->OpenHandleCount-1);
328 h->Mount->OpenHandleCount --;