mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-01 20:10:28 +00:00
Kernel: Added unmount ability to VFS
It is now possible to unmount file systems from the VFS via `umount`. It works via looking up the `fsid` of the filesystem from the `Inode`'s metatdata so I'm not sure how fragile it is. It seems to work for now though as something to get us going.
This commit is contained in:
parent
f7251c74a9
commit
bc22456f89
Notes:
sideshowbarker
2024-07-19 12:40:05 +09:00
Author: https://github.com/Quaker762 Commit: https://github.com/SerenityOS/serenity/commit/bc22456f89b Pull-request: https://github.com/SerenityOS/serenity/pull/440
13 changed files with 98 additions and 3 deletions
|
@ -1395,3 +1395,16 @@ unsigned Ext2FS::free_inode_count() const
|
|||
LOCKER(m_lock);
|
||||
return super_block().s_free_inodes_count;
|
||||
}
|
||||
|
||||
KResult Ext2FS::prepare_to_unmount() const
|
||||
{
|
||||
LOCKER(m_lock); // Acquire lock for this FS
|
||||
for (auto it = m_inode_cache.begin(); it != m_inode_cache.end(); ++it) {
|
||||
if (it->value.ptr()->ref_count() > 1)
|
||||
return KResult(-EBUSY);
|
||||
}
|
||||
|
||||
dbg() << "here!";
|
||||
m_inode_cache.clear();
|
||||
return KSuccess;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,8 @@ public:
|
|||
virtual unsigned total_inode_count() const override;
|
||||
virtual unsigned free_inode_count() const override;
|
||||
|
||||
virtual KResult prepare_to_unmount() const override;
|
||||
|
||||
private:
|
||||
typedef unsigned BlockIndex;
|
||||
typedef unsigned GroupIndex;
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
#include <AK/Function.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/WeakPtr.h>
|
||||
#include <AK/kstdio.h>
|
||||
#include <Kernel/Devices/DiskDevice.h>
|
||||
|
@ -45,6 +45,8 @@ public:
|
|||
virtual unsigned total_inode_count() const { return 0; }
|
||||
virtual unsigned free_inode_count() const { return 0; }
|
||||
|
||||
virtual KResult prepare_to_unmount() const { return KSuccess; }
|
||||
|
||||
struct DirectoryEntry {
|
||||
DirectoryEntry(const char* name, InodeIdentifier, u8 file_type);
|
||||
DirectoryEntry(const char* name, int name_length, InodeIdentifier, u8 file_type);
|
||||
|
|
|
@ -49,6 +49,7 @@ KResult VFS::mount(NonnullRefPtr<FS>&& file_system, Custody& mount_point)
|
|||
|
||||
KResult VFS::mount(NonnullRefPtr<FS>&& file_system, StringView path)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
auto result = resolve_path(path, root_custody());
|
||||
if (result.is_error()) {
|
||||
dbg() << "VFS: mount can't resolve mount point '" << path << "'";
|
||||
|
@ -57,6 +58,28 @@ KResult VFS::mount(NonnullRefPtr<FS>&& file_system, StringView path)
|
|||
return mount(move(file_system), result.value());
|
||||
}
|
||||
|
||||
KResult VFS::unmount(NonnullRefPtr<FS>&& file_system)
|
||||
{
|
||||
LOCKER(m_lock);
|
||||
dbg() << "VFS: unmount called with fsid " << file_system.ptr()->fsid();
|
||||
|
||||
for (auto i = 0; i < m_mounts.size(); i++) {
|
||||
auto mount = m_mounts.at(i);
|
||||
if (mount.guest_fs().fsid() == file_system.ptr()->fsid()) {
|
||||
if (mount.guest_fs().prepare_to_unmount() != KSuccess) {
|
||||
dbg() << "VFS: Failed to unmount! Device busy";
|
||||
return KResult(-EBUSY);
|
||||
}
|
||||
dbg() << "VFS: found fs " << file_system.ptr()->fsid() << " at mount " << i << "! Unmounting...";
|
||||
m_mounts.remove(i);
|
||||
return KSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
dbg() << "VFS: unmount unable to find fsid in m_mounts!";
|
||||
return KResult(-ENODEV);
|
||||
}
|
||||
|
||||
bool VFS::mount_root(NonnullRefPtr<FS>&& file_system)
|
||||
{
|
||||
if (m_root_inode) {
|
||||
|
|
|
@ -59,6 +59,7 @@ public:
|
|||
bool mount_root(NonnullRefPtr<FS>&&);
|
||||
KResult mount(NonnullRefPtr<FS>&&, StringView path);
|
||||
KResult mount(NonnullRefPtr<FS>&&, Custody& mount_point);
|
||||
KResult unmount(NonnullRefPtr<FS>&&);
|
||||
|
||||
KResultOr<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base);
|
||||
KResultOr<NonnullRefPtr<FileDescription>> create(StringView path, int options, mode_t mode, Custody& parent_custody);
|
||||
|
@ -105,6 +106,8 @@ private:
|
|||
Mount* find_mount_for_host(InodeIdentifier);
|
||||
Mount* find_mount_for_guest(InodeIdentifier);
|
||||
|
||||
Lock m_lock { "VFSLock" };
|
||||
|
||||
RefPtr<Inode> m_root_inode;
|
||||
NonnullOwnPtrVector<Mount> m_mounts;
|
||||
HashMap<u32, Device*> m_devices;
|
||||
|
|
|
@ -2786,6 +2786,25 @@ int Process::sys$mount(const char* device_path, const char* mountpoint)
|
|||
return result;
|
||||
}
|
||||
|
||||
int Process::sys$umount(const char* mountpoint)
|
||||
{
|
||||
if (!is_superuser())
|
||||
return -EPERM;
|
||||
|
||||
if (!validate_read_str(mountpoint))
|
||||
return -EFAULT;
|
||||
|
||||
auto metadata_or_error = VFS::the().lookup_metadata(mountpoint, current_directory());
|
||||
if (metadata_or_error.is_error())
|
||||
return metadata_or_error.error();
|
||||
|
||||
auto fsid = metadata_or_error.value().inode.fsid();
|
||||
auto fs = Ext2FS::from_fsid(fsid);
|
||||
auto ret = VFS::the().unmount(*fs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ProcessTracer& Process::ensure_tracer()
|
||||
{
|
||||
if (!m_tracer)
|
||||
|
|
|
@ -187,6 +187,7 @@ public:
|
|||
int sys$symlink(const char* target, const char* linkpath);
|
||||
int sys$rmdir(const char* pathname);
|
||||
int sys$mount(const char* device, const char* mountpoint);
|
||||
int sys$umount(const char* mountpoint);
|
||||
int sys$read_tsc(u32* lsw, u32* msw);
|
||||
int sys$chmod(const char* pathname, mode_t);
|
||||
int sys$fchmod(int fd, mode_t);
|
||||
|
|
|
@ -189,7 +189,7 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3
|
|||
case Syscall::SC_sigprocmask:
|
||||
return current->process().sys$sigprocmask((int)arg1, (const sigset_t*)arg2, (sigset_t*)arg3);
|
||||
case Syscall::SC_pipe:
|
||||
return current->process().sys$pipe((int*)arg1, (int) arg2);
|
||||
return current->process().sys$pipe((int*)arg1, (int)arg2);
|
||||
case Syscall::SC_killpg:
|
||||
return current->process().sys$killpg((int)arg1, (int)arg2);
|
||||
case Syscall::SC_setuid:
|
||||
|
@ -297,6 +297,8 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3
|
|||
case Syscall::SC_reboot: {
|
||||
return current->process().sys$reboot();
|
||||
}
|
||||
case Syscall::SC_umount:
|
||||
return current->process().sys$umount((const char*)arg1);
|
||||
case Syscall::SC_dump_backtrace:
|
||||
return current->process().sys$dump_backtrace();
|
||||
case Syscall::SC_watch_file:
|
||||
|
|
|
@ -117,6 +117,7 @@ struct timeval;
|
|||
__ENUMERATE_SYSCALL(halt) \
|
||||
__ENUMERATE_SYSCALL(reboot) \
|
||||
__ENUMERATE_SYSCALL(mount) \
|
||||
__ENUMERATE_SYSCALL(umount) \
|
||||
__ENUMERATE_SYSCALL(dump_backtrace) \
|
||||
__ENUMERATE_SYSCALL(dbgputch) \
|
||||
__ENUMERATE_SYSCALL(dbgputstr) \
|
||||
|
|
|
@ -15,7 +15,7 @@ if [ $(id -u) != 0 ]; then
|
|||
fi
|
||||
|
||||
echo -n "creating initial filesystem structure... "
|
||||
mkdir -p mnt/{bin,etc,proc,tmp}
|
||||
mkdir -p mnt/{bin,etc,proc,mnt,tmp}
|
||||
chmod 1777 mnt/tmp
|
||||
echo "done"
|
||||
|
||||
|
|
|
@ -557,6 +557,12 @@ int mount(const char* device, const char* mountpoint)
|
|||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
|
||||
int umount(const char* mountpoint)
|
||||
{
|
||||
int rc = syscall(SC_umount, mountpoint);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
|
||||
void dump_backtrace()
|
||||
{
|
||||
syscall(SC_dump_backtrace);
|
||||
|
|
|
@ -101,6 +101,7 @@ int ftruncate(int fd, off_t length);
|
|||
int halt();
|
||||
int reboot();
|
||||
int mount(const char* device, const char* mountpoint);
|
||||
int umount(const char* mountpoint);
|
||||
|
||||
enum {
|
||||
_PC_NAME_MAX,
|
||||
|
|
22
Userland/umount.cpp
Normal file
22
Userland/umount.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <LibCore/CArgsParser.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
CArgsParser args_parser("umount");
|
||||
args_parser.add_arg("mountpoint", "mount point");
|
||||
CArgsParserResult args = args_parser.parse(argc, argv);
|
||||
|
||||
if (argc == 2) {
|
||||
if (umount(argv[1]) < 0) {
|
||||
perror("umount");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
args_parser.print_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue