+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;
+ RWLock_AcquireWrite( &glVFS_MountList );
+ for( mount = gVFS_Mounts; mount; prev = mount, mount = mount->Next )
+ {
+ if( strcmp(Mountpoint, mount->MountPoint) == 0 ) {
+ 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)
+ prev->Next = mount->Next;
+ else
+ gVFS_Mounts = mount->Next;
+ break;
+ }
+ }
+ RWLock_Release( &glVFS_MountList );
+ if( !mount ) {
+ LOG("Mountpoint not found");
+ return ENOENT;
+ }
+
+ VFS_int_Unmount(mount);
+
+ VFS_UpdateMountFile();
+
+ return EOK;
+}
+
+int VFS_UnmountAll(void)
+{
+ int nUnmounted = 0;
+ tVFS_Mount *mount, *prev = NULL, *next;
+
+ RWLock_AcquireWrite( &glVFS_MountList );
+ // 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)",
+ mount, mount->MountPoint, mount->OpenHandleCount);
+ continue;
+ }
+
+ if(prev)
+ prev->Next = mount->Next;
+ else
+ gVFS_Mounts = mount->Next;
+
+ VFS_int_Unmount(mount);
+ mount = prev;
+ nUnmounted ++;
+ }
+ RWLock_Release( &glVFS_MountList );
+
+ VFS_UpdateMountFile();
+
+ return nUnmounted;
+}
+