diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp index 599eb681..d4453e9c 100644 --- a/kernel/src/fs/VFS.cpp +++ b/kernel/src/fs/VFS.cpp @@ -150,7 +150,7 @@ namespace VFS auto parent_path = TRY(parser.dirname()); auto child = TRY(parser.basename()); - kdbgln("vfs: mounting filesystem on target %s, parent dir %s", child.chars(), parent_path.chars()); + kdbgln("vfs: Mounting filesystem on target %s", path); auto parent_inode = TRY(resolve_path(parent_path.chars(), auth, working_directory)); @@ -164,4 +164,26 @@ namespace VFS return {}; } + + Result umount(const char* path, Credentials auth, SharedPtr working_directory) + { + auto parser = TRY(PathParser::create(path)); + auto parent_path = TRY(parser.dirname()); + auto child = TRY(parser.basename()); + + kdbgln("vfs: Unmounting filesystem on target %s", path); + + auto parent_inode = TRY(resolve_path(parent_path.chars(), auth, working_directory)); + + auto inode = TRY(parent_inode->find(child.chars())); + if (!inode->is_mountpoint()) return err(EINVAL); + + // There are still open file descriptors referencing files within this file system. + if (inode->fs()->handles() != 0) return err(EBUSY); + + auto mount = (MountInode*)inode.ptr(); + TRY(parent_inode->replace_entry(mount->source(), child.chars())); + + return {}; + } } diff --git a/kernel/src/fs/VFS.h b/kernel/src/fs/VFS.h index a44d3096..8d57a43e 100644 --- a/kernel/src/fs/VFS.h +++ b/kernel/src/fs/VFS.h @@ -260,4 +260,6 @@ namespace VFS Result mount_root(SharedPtr fs); Result mount(const char* path, SharedPtr fs, Credentials auth, SharedPtr working_directory = {}); + + Result umount(const char* path, Credentials auth, SharedPtr working_directory = {}); } diff --git a/kernel/src/fs/devices/DeviceRegistry.cpp b/kernel/src/fs/devices/DeviceRegistry.cpp index 9f8689be..fa487beb 100644 --- a/kernel/src/fs/devices/DeviceRegistry.cpp +++ b/kernel/src/fs/devices/DeviceRegistry.cpp @@ -34,6 +34,15 @@ namespace DeviceRegistry return err(ENODEV); } + Result create_special_device_inode(DeviceDescriptor& descriptor) + { + auto inode = TRY(g_device_fs->create_device_inode(descriptor.major, descriptor.minor)); + inode->chmod(descriptor.mode); + TRY(g_device_fs->root_inode()->add_entry(inode, descriptor.name)); + + return {}; + } + Result register_special_device(u32 major, u32 minor, SharedPtr device, const char* name, mode_t mode) { for (const auto& descriptor : g_available_devices) @@ -52,15 +61,6 @@ namespace DeviceRegistry return {}; } - Result create_special_device_inode(DeviceDescriptor& descriptor) - { - auto inode = TRY(g_device_fs->create_device_inode(descriptor.major, descriptor.minor)); - inode->chmod(descriptor.mode); - TRY(g_device_fs->root_inode()->add_entry(inode, descriptor.name)); - - return {}; - } - Result init() { auto device_fs = TRY(TmpFS::FileSystem::create()); diff --git a/kernel/src/thread/Thread.cpp b/kernel/src/thread/Thread.cpp index 4a45ebde..493286f9 100644 --- a/kernel/src/thread/Thread.cpp +++ b/kernel/src/thread/Thread.cpp @@ -66,6 +66,22 @@ Result> Thread::resolve_atfile(int dirfd, const String& pa return VFS::resolve_path(path.chars(), this->auth, descriptor->inode); } +FileDescriptor::FileDescriptor(SharedPtr _inode, usize _offset, int _flags) + : inode(_inode), offset(_offset), flags(_flags) +{ + inode->fs()->add_handle(); +} + +FileDescriptor::FileDescriptor(const FileDescriptor& f) : inode(f.inode), offset(f.offset), flags(f.flags) +{ + inode->fs()->add_handle(); +} + +FileDescriptor::~FileDescriptor() +{ + inode->fs()->remove_handle(); +} + bool FileDescriptor::should_append() { return flags & O_APPEND; diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index e50fa45e..62baf50c 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -33,6 +33,10 @@ struct FileDescriptor usize offset { 0 }; int flags { 0 }; + FileDescriptor(SharedPtr inode, usize offset, int flags); + FileDescriptor(const FileDescriptor& f); + ~FileDescriptor(); + bool should_append(); bool should_block(); bool is_writable();