From 82348a3d91e9a846d6997c16ddca3add6a5bf21b Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 14 Jul 2012 20:25:27 +0800 Subject: [PATCH] VFS - Fixed unmount issues and added filesystem autodetection --- KernelLand/Kernel/include/vfs_int.h | 1 + KernelLand/Kernel/vfs/mount.c | 111 ++++++++++++++++++++-------- KernelLand/Kernel/vfs/nodecache.c | 9 ++- KernelLand/Kernel/vfs/open.c | 1 + 4 files changed, 87 insertions(+), 35 deletions(-) diff --git a/KernelLand/Kernel/include/vfs_int.h b/KernelLand/Kernel/include/vfs_int.h index f48e277b..1f67f4b9 100644 --- a/KernelLand/Kernel/include/vfs_int.h +++ b/KernelLand/Kernel/include/vfs_int.h @@ -48,6 +48,7 @@ typedef struct sVFS_MMapPage { // === GLOBALS === extern tRWLock glVFS_MountList; extern tVFS_Mount *gVFS_Mounts; +extern tVFS_Driver *gVFS_Drivers; // === PROTOTYPES === // --- open.c --- diff --git a/KernelLand/Kernel/vfs/mount.c b/KernelLand/Kernel/vfs/mount.c index c49e6d95..5ac67a58 100644 --- a/KernelLand/Kernel/vfs/mount.c +++ b/KernelLand/Kernel/vfs/mount.c @@ -1,7 +1,7 @@ /* * Acess Micro - VFS Server version 1 */ -#define DEBUG 1 +#define DEBUG 0 #include #include #include @@ -15,6 +15,7 @@ extern char *gsVFS_MountFile; #if 0 int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem, const char *Options); #endif +void VFS_int_Unmount(tVFS_Mount *Mount); void VFS_UpdateMountFile(void); // === GLOBALS === @@ -45,18 +46,43 @@ int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem int argLen = strlen(Options); // Get the filesystem - fs = VFS_GetFSByName(Filesystem); - if(!fs) { - Log_Warning("VFS", "VFS_Mount - Unknown FS Type '%s'", Filesystem); - return -1; + if( Filesystem && Filesystem[0] ) + { + fs = VFS_GetFSByName(Filesystem); + if(!fs) { + Log_Warning("VFS", "VFS_Mount - Unknown FS Type '%s'", Filesystem); + return -ENOENT; + } } - - // Create mount information - mnt = malloc( sizeof(tVFS_Mount)+deviceLen+1+mountLen+1+argLen+1 ); - if(!mnt) { - return -2; + else + { + int fd = VFS_Open(Device, VFS_OPENFLAG_READ); + if( fd == -1 ) { + Log_Warning("VFS", "VFS_Mount - Unable to open '%s' for autodetect", Device); + return -ENOENT; + } + + tVFS_Driver *bestfs = NULL; + int bestrank, rank; + for( fs = gVFS_Drivers; fs; fs = fs->Next ) + { + if(!fs->Detect) continue ; + rank = fs->Detect(fd); + if(!rank) continue ; + if(!bestfs || rank > bestrank) { + bestfs = fs; + bestrank = rank; + } + } + VFS_Close(fd); + if( bestfs == NULL ) { + Log_Warning("VFS", "VFS_Mount - Filesystem autodetection failed"); + return -1; + } + + fs = bestfs; } - + // Validate the mountpoint target // - Only if / is mounted if( gVFS_Mounts ) @@ -75,6 +101,13 @@ int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem } } + // Create mount information + mnt = malloc( sizeof(tVFS_Mount)+deviceLen+1+mountLen+1+argLen+1 ); + if(!mnt) { + parent_mnt->OpenHandleCount --; + return -2; + } + // HACK: Forces VFS_ParsePath to fall back on root if(mountLen == 1 && MountPoint[0] == '/') mnt->MountPointLen = 0; @@ -149,13 +182,41 @@ int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem } RWLock_Release( &glVFS_MountList ); - Log_Log("VFS", "Mounted '%s' to '%s' ('%s')", Device, MountPoint, Filesystem); + Log_Log("VFS", "Mounted '%s' to '%s' ('%s')", Device, MountPoint, fs->Name); VFS_UpdateMountFile(); return 0; } +void VFS_int_Unmount(tVFS_Mount *Mount) +{ + // Decrease the open handle count for the mountpoint filesystem. + if( Mount != gVFS_RootMount ) + { + tVFS_Mount *mpmnt; + for( mpmnt = gVFS_Mounts; mpmnt; mpmnt = mpmnt->Next ) + { + if( strncmp(mpmnt->MountPoint, Mount->MountPoint, mpmnt->MountPointLen) != 0 ) + continue ; + if( Mount->MountPoint[ mpmnt->MountPointLen ] != '/' ) + continue ; + break; + } + if(mpmnt) { + mpmnt->OpenHandleCount -= 1; + } + else { + Log_Notice("VFS", "Mountpoint '%s' has no parent", Mount->MountPoint); + } + } + + if( Mount->Filesystem->Unmount ) + Mount->Filesystem->Unmount( Mount->RootNode ); + LOG("%p (%s) unmounted", Mount, Mount->MountPoint); + free(Mount); +} + int VFS_Unmount(const char *Mountpoint) { tVFS_Mount *mount, *prev = NULL; @@ -180,20 +241,11 @@ int VFS_Unmount(const char *Mountpoint) LOG("Mountpoint not found"); return ENOENT; } - - Log_Warning("VFS", "TODO: Impliment unmount"); - - // Decrease the open handle count for the mountpoint filesystem. - tVFS_Mount *mpmnt; - tVFS_Node *mpnode = VFS_ParsePath(mount->MountPoint, NULL, &mpmnt); - if(mpnode) - { - mpmnt->OpenHandleCount -= 2; // -1 for _ParsePath here, -1 for in _Mount - } - mount->Filesystem->Unmount( mount->RootNode ); - free(mount); + VFS_int_Unmount(mount); + VFS_UpdateMountFile(); + return EOK; } @@ -224,19 +276,14 @@ int VFS_UnmountAll(void) else gVFS_Mounts = mount->Next; - if( mount->Filesystem->Unmount ) { - mount->Filesystem->Unmount( mount->RootNode ); - } - else { - Log_Error("VFS", "%s (%s) does not have an unmount method, not calling it", - mount->MountPoint, mount->Filesystem->Name); - } - free(mount); + VFS_int_Unmount(mount); mount = prev; nUnmounted ++; } RWLock_Release( &glVFS_MountList ); + VFS_UpdateMountFile(); + return nUnmounted; } diff --git a/KernelLand/Kernel/vfs/nodecache.c b/KernelLand/Kernel/vfs/nodecache.c index ffad2437..0d238941 100644 --- a/KernelLand/Kernel/vfs/nodecache.c +++ b/KernelLand/Kernel/vfs/nodecache.c @@ -142,7 +142,7 @@ int Inode_UncacheNode(int Handle, Uint64 Inode) // Search Cache ent = cache->FirstNode; - prev = (tCachedInode*) &cache->FirstNode; // Special case removal + prev = NULL; for( ; ent; prev = ent, ent = ent->Next ) { if(ent->Node.Inode < Inode) continue; @@ -164,10 +164,13 @@ int Inode_UncacheNode(int Handle, Uint64 Inode) // Check if node needs to be freed if(ent->Node.ReferenceCount == 0) { - prev->Next = ent->Next; + if( prev ) + prev->Next = ent->Next; + else + cache->FirstNode = ent->Next; if(ent->Node.Inode == cache->MaxCached) { - if(ent != cache->FirstNode) + if(ent != cache->FirstNode && prev) cache->MaxCached = prev->Node.Inode; else cache->MaxCached = 0; diff --git a/KernelLand/Kernel/vfs/open.c b/KernelLand/Kernel/vfs/open.c index e7d6e1e8..12a8f8d1 100644 --- a/KernelLand/Kernel/vfs/open.c +++ b/KernelLand/Kernel/vfs/open.c @@ -201,6 +201,7 @@ restart_parse: *TruePath = malloc( gVFS_RootMount->MountPointLen+1 ); strcpy(*TruePath, gVFS_RootMount->MountPoint); } + gVFS_RootMount->OpenHandleCount ++; if(MountPoint) *MountPoint = gVFS_RootMount; LEAVE('p', gVFS_RootMount->RootNode); return gVFS_RootMount->RootNode; -- 2.20.1