X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fvfs%2Fmount.c;h=1823857f57552fa223de2ac20722d93865d73a61;hb=097d17ad093701091b0925aa7b13378cb9aed9df;hp=c49e6d952b3a73557d80438c6cf6b3f5e323f51f;hpb=4842e2d6740bcb81da4e94019285bfd2c45425b8;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/vfs/mount.c b/KernelLand/Kernel/vfs/mount.c index c49e6d95..1823857f 100644 --- a/KernelLand/Kernel/vfs/mount.c +++ b/KernelLand/Kernel/vfs/mount.c @@ -1,7 +1,8 @@ /* * Acess Micro - VFS Server version 1 */ -#define DEBUG 1 +#define SANITY 1 +#define DEBUG 0 #include #include #include @@ -15,6 +16,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 +47,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 = 0, 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 +102,14 @@ 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) { + ASSERT(parent_mnt->OpenHandleCount > 0); + parent_mnt->OpenHandleCount --; + return -2; + } + // HACK: Forces VFS_ParsePath to fall back on root if(mountLen == 1 && MountPoint[0] == '/') mnt->MountPointLen = 0; @@ -115,6 +150,7 @@ int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem mnt->RootNode = fs->InitDevice(Device, (const char **)args); if(!mnt->RootNode) { free(mnt); + ASSERT(parent_mnt->OpenHandleCount>0); parent_mnt->OpenHandleCount --; return -2; } @@ -149,13 +185,42 @@ 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) { + ASSERT(mpmnt->OpenHandleCount>0); + mpmnt->OpenHandleCount --; + } + 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; @@ -166,6 +231,8 @@ int VFS_Unmount(const char *Mountpoint) if( mount->OpenHandleCount ) { LOG("Mountpoint busy"); RWLock_Release(&glVFS_MountList); + Log_Log("VFS", "Unmount of '%s' deferred, still busy (%i open handles)", + Mountpoint, mount->OpenHandleCount); return EBUSY; } if(prev) @@ -180,20 +247,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; } @@ -206,12 +264,18 @@ int VFS_UnmountAll(void) // If we've unmounted the final filesystem, all good if( gVFS_Mounts == NULL) { RWLock_Release( &glVFS_MountList ); + + // Final unmount means VFS completely deinited + VFS_Deinit(); return -1; } for( mount = gVFS_Mounts; mount; prev = mount, mount = next ) { next = mount->Next; + + ASSERT(mount->OpenHandleCount >= 0); + // Can't unmount stuff with open handles if( mount->OpenHandleCount > 0 ) { LOG("%p (%s) has open handles (%i of them)", @@ -224,19 +288,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; }