VFS - Fixed unmount issues and added filesystem autodetection
authorJohn Hodge <[email protected]>
Sat, 14 Jul 2012 12:25:27 +0000 (20:25 +0800)
committerJohn Hodge <[email protected]>
Sat, 14 Jul 2012 12:25:27 +0000 (20:25 +0800)
KernelLand/Kernel/include/vfs_int.h
KernelLand/Kernel/vfs/mount.c
KernelLand/Kernel/vfs/nodecache.c
KernelLand/Kernel/vfs/open.c

index f48e277..1f67f4b 100644 (file)
@@ -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 ---
index c49e6d9..5ac67a5 100644 (file)
@@ -1,7 +1,7 @@
 /* 
  * Acess Micro - VFS Server version 1
  */
-#define DEBUG  1
+#define DEBUG  0
 #include <acess.h>
 #include <vfs.h>
 #include <vfs_int.h>
@@ -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;
 }
 
index ffad243..0d23894 100644 (file)
@@ -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;
index e7d6e1e..12a8f8d 100644 (file)
@@ -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;

UCC git Repository :: git.ucc.asn.au