X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fvfs%2Fhandle.c;h=661ced8124adf7df94b85f09bd7600a6a81ad2fc;hb=b7d9f86f7a1c23be18b50d5c647fd5d3c08369c3;hp=d22f96562df5e5a08c28f373e59780e0d0f829c1;hpb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/vfs/handle.c b/KernelLand/Kernel/vfs/handle.c index d22f9656..661ced81 100644 --- a/KernelLand/Kernel/vfs/handle.c +++ b/KernelLand/Kernel/vfs/handle.c @@ -2,6 +2,7 @@ * Acess2 VFS * - AllocHandle, GetHandle */ +#define SANITY 1 #define DEBUG 0 #include #include @@ -15,10 +16,6 @@ #define MAX_KERNEL_FILES 128 // === PROTOTYPES === -#if 0 -tVFS_Handle *VFS_GetHandle(int FD); -#endif - int VFS_AllocHandle(int FD, tVFS_Node *Node, int Mode); // === GLOBALS === tVFS_Handle *gaUserHandles = (void*)MM_PPD_HANDLES; @@ -51,31 +48,49 @@ tVFS_Handle *VFS_GetHandle(int FD) return h; } -int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) +int VFS_SetHandle(int FD, tVFS_Node *Node, int Mode) { - int i; + tVFS_Handle *h; + if(FD < 0) return -1; + if( FD & VFS_KERNEL_FLAG ) { + FD &= (VFS_KERNEL_FLAG -1); + if( FD >= MAX_KERNEL_FILES ) return -1; + h = &gaKernelHandles[FD]; + } + else { + if( FD >= *Threads_GetMaxFD()) return -1; + h = &gaUserHandles[FD]; + } + h->Node = Node; + h->Mode = Mode; + return FD; +} + +int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) +{ // Check for a user open if(bIsUser) { int max_handles = *Threads_GetMaxFD(); // Allocate Buffer - if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 ) + if( MM_GetPhysAddr( gaUserHandles ) == 0 ) { - Uint addr, size; - size = max_handles * sizeof(tVFS_Handle); - for(addr = 0; addr < size; addr += 0x1000) + tPage *pageptr = (void*)gaUserHandles; + size_t size = max_handles * sizeof(tVFS_Handle); + for( size_t ofs = 0; ofs < size; ofs ++) { - if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) ) + if( !MM_Allocate( pageptr ) ) { Warning("OOM - VFS_AllocHandle"); Threads_Exit(0, 0xFF); // Terminate user } + pageptr ++; } memset( gaUserHandles, 0, size ); } // Get a handle - for( i = 0; i < max_handles; i ++ ) + for( int i = 0; i < max_handles; i ++ ) { if(gaUserHandles[i].Node) continue; gaUserHandles[i].Node = Node; @@ -87,22 +102,22 @@ int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode) else { // Allocate space if not already - if( MM_GetPhysAddr( (tVAddr)gaKernelHandles ) == 0 ) + if( MM_GetPhysAddr( gaKernelHandles ) == 0 ) { - Uint addr, size; - size = MAX_KERNEL_FILES * sizeof(tVFS_Handle); - for(addr = 0; addr < size; addr += 0x1000) + tPage *pageptr = (void*)gaKernelHandles; + size_t size = MAX_KERNEL_FILES * sizeof(tVFS_Handle); + for(size_t ofs = 0; ofs < size; ofs += size) { - if( !MM_Allocate( (tVAddr)gaKernelHandles + addr ) ) + if( !MM_Allocate( pageptr ) ) { Panic("OOM - VFS_AllocHandle"); - Threads_Exit(0, 0xFF); // Terminate application (get some space back) } + pageptr ++; } memset( gaKernelHandles, 0, size ); } // Get a handle - for(i=0;iNode ) continue ; - if( h->Node->Type && h->Node->Type->Reference ) - h->Node->Type->Reference( h->Node ); + _ReferenceNode(h->Node); + h->Mount->OpenHandleCount ++; } } void VFS_CloseAllUserHandles(void) { - int i; int max_handles = *Threads_GetMaxFD(); // Check if this process has any handles - if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 ) + if( MM_GetPhysAddr( gaUserHandles ) == 0 ) return ; - for( i = 0; i < max_handles; i ++ ) + for( int i = 0; i < max_handles; i ++ ) { tVFS_Handle *h; h = &gaUserHandles[i]; if( !h->Node ) continue ; - if( h->Node->Type && h->Node->Type->Close ) - h->Node->Type->Close( h->Node ); + _CloseNode(h->Node); } } @@ -161,11 +174,10 @@ void VFS_CloseAllUserHandles(void) void *VFS_SaveHandles(int NumFDs, int *FDs) { tVFS_Handle *ret; - int i; int max_handles = *Threads_GetMaxFD(); // Check if this process has any handles - if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) == 0 ) + if( MM_GetPhysAddr( gaUserHandles ) == 0 ) return NULL; // Allocate @@ -177,27 +189,44 @@ void *VFS_SaveHandles(int NumFDs, int *FDs) NumFDs = max_handles; // Take copies of the handles - for( i = 0; i < NumFDs; i ++ ) + if( FDs == NULL ) { + memcpy(ret, gaUserHandles, NumFDs * sizeof(tVFS_Handle)); + } + else { - tVFS_Handle *h; - if( FDs == NULL ) - h = &gaUserHandles[i]; - else { - h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1)); + for( int i = 0; i < NumFDs; i ++ ) + { + if( FDs[i] < -1 ) + { + Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (%i<0), ignorning", + i, FDs[i]); + memset(&ret[i], 0, sizeof(tVFS_Handle)); + continue ; + } + + int fd = FDs[i] & (VFS_KERNEL_FLAG - 1); + tVFS_Handle *h = VFS_GetHandle(fd); if(!h) { - Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i", - FDs[i] & (VFS_KERNEL_FLAG - 1) ); + Log_Warning("VFS", "VFS_SaveHandles - Invalid FD 0x%x (%i) in slot %i", + fd, FDs[i], i ); free(ret); return NULL; } +// Log("%i: Duplicate FD %i (%p)", i, fd, h->Node); + memcpy( &ret[i], h, sizeof(tVFS_Handle) ); } - memcpy( &ret[i], h, sizeof(tVFS_Handle) ); - + } + + // Reference nodes/mounts + for( int i = 0; i < NumFDs; i ++ ) + { + tVFS_Handle *h = &ret[i]; // Reference node if( !h->Node ) continue ; - if( h->Node->Type && h->Node->Type->Reference ) - h->Node->Type->Reference( h->Node ); +// Debug("VFS_SaveHandles: %i %p", i, h->Node); + _ReferenceNode(h->Node); + h->Mount->OpenHandleCount ++; } return ret; @@ -206,44 +235,57 @@ void *VFS_SaveHandles(int NumFDs, int *FDs) void VFS_RestoreHandles(int NumFDs, void *Handles) { tVFS_Handle *handles = Handles; - int i; + int max_handles = *Threads_GetMaxFD(); // NULL = nothing to do if( !Handles ) return ; - // Check if there is already a set of handles - if( MM_GetPhysAddr( (tVAddr)gaUserHandles ) != 0 ) - return ; - - - // Allocate user handle area + // Allocate user handle area (and dereference existing handles) + for( int i = 0; i < NumFDs; i ++ ) { - Uint addr, size; - int max_handles = *Threads_GetMaxFD(); - size = max_handles * sizeof(tVFS_Handle); - for(addr = 0; addr < size; addr += 0x1000) + tVFS_Handle *h = &gaUserHandles[i]; + + if( !MM_GetPhysAddr(h) ) { - if( !MM_Allocate( (tVAddr)gaUserHandles + addr ) ) + void *pg = (void*)( (tVAddr)h & ~(PAGE_SIZE-1) ); + if( !MM_Allocate( pg ) ) { - Warning("OOM - VFS_AllocHandle"); - Threads_Exit(0, 0xFF); // Terminate user + // OOM? + return ; } + memset(pg, 0, PAGE_SIZE); } - memset( gaUserHandles, 0, size ); + // Safe to dereference, as Threads_CloneTCB references handles + #if 1 + else + { + if(h->Node) + { + _CloseNode(h->Node); + h->Mount->OpenHandleCount --; + } + } + #endif } + // Clean up existing // Restore handles memcpy( gaUserHandles, handles, NumFDs * sizeof(tVFS_Handle) ); // Reference when copied - for( i = 0; i < NumFDs; i ++ ) + for( int i = 0; i < NumFDs; i ++ ) { - tVFS_Handle *h = &handles[i]; + tVFS_Handle *h = &gaUserHandles[i]; if( !h->Node ) continue ; - if( h->Node->Type && h->Node->Type->Reference ) - h->Node->Type->Reference( h->Node ); +// Debug("VFS_RestoreHandles: %i %p", i, h->Node); + _ReferenceNode(h->Node); + h->Mount->OpenHandleCount ++; + } + for( int i = NumFDs; i < max_handles; i ++ ) + { + gaUserHandles[i].Node = NULL; } } @@ -263,8 +305,11 @@ void VFS_FreeSavedHandles(int NumFDs, void *Handles) if( !h->Node ) continue ; - if( h->Node->Type && h->Node->Type->Close ) - h->Node->Type->Close( h->Node ); + _CloseNode(h->Node); + + ASSERT(h->Mount->OpenHandleCount > 0); + LOG("dec. mntpt '%s' to %i", h->Mount->MountPoint, h->Mount->OpenHandleCount-1); + h->Mount->OpenHandleCount --; } free( Handles ); }