From 4566c2d811ce170361dc690bfcf04c5b642021e4 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Sat, 11 Jan 2020 18:25:26 +0300 Subject: [PATCH] Kernel+LibC: Add support for mount flags At the moment, the actual flags are ignored, but we correctly propagate them all the way from the original mount() syscall to each custody that resides on the mounted FS. --- Kernel/FileSystem/Custody.cpp | 7 ++++--- Kernel/FileSystem/Custody.h | 13 ++++++++----- Kernel/FileSystem/ProcFS.cpp | 7 ++++--- Kernel/FileSystem/VirtualFileSystem.cpp | 23 ++++++++++++++--------- Kernel/FileSystem/VirtualFileSystem.h | 9 ++++++--- Kernel/Process.cpp | 7 ++++--- Kernel/Syscall.h | 7 ++++--- Libraries/LibC/unistd.cpp | 9 +++++++-- Libraries/LibC/unistd.h | 2 +- Userland/mount.cpp | 4 ++-- 10 files changed, 54 insertions(+), 34 deletions(-) diff --git a/Kernel/FileSystem/Custody.cpp b/Kernel/FileSystem/Custody.cpp index 6dbdbbec5a..4c301af71c 100644 --- a/Kernel/FileSystem/Custody.cpp +++ b/Kernel/FileSystem/Custody.cpp @@ -26,7 +26,7 @@ Custody* Custody::get_if_cached(Custody* parent, const StringView& name) return nullptr; } -NonnullRefPtr Custody::get_or_create(Custody* parent, const StringView& name, Inode& inode) +NonnullRefPtr Custody::get_or_create(Custody* parent, const StringView& name, Inode& inode, int mount_flags) { if (RefPtr cached_custody = get_if_cached(parent, name)) { if (&cached_custody->inode() != &inode) { @@ -35,13 +35,14 @@ NonnullRefPtr Custody::get_or_create(Custody* parent, const StringView& ASSERT(&cached_custody->inode() == &inode); return *cached_custody; } - return create(parent, name, inode); + return create(parent, name, inode, mount_flags); } -Custody::Custody(Custody* parent, const StringView& name, Inode& inode) +Custody::Custody(Custody* parent, const StringView& name, Inode& inode, int mount_flags) : m_parent(parent) , m_name(name) , m_inode(inode) + , m_mount_flags(mount_flags) { LOCKER(all_custodies().lock()); all_custodies().resource().append(this); diff --git a/Kernel/FileSystem/Custody.h b/Kernel/FileSystem/Custody.h index 8df1c746a7..3b5b31e098 100644 --- a/Kernel/FileSystem/Custody.h +++ b/Kernel/FileSystem/Custody.h @@ -1,10 +1,10 @@ #pragma once -#include #include #include #include #include +#include class Inode; class VFS; @@ -15,10 +15,10 @@ class Custody : public RefCounted , public InlineLinkedListNode { public: static Custody* get_if_cached(Custody* parent, const StringView& name); - static NonnullRefPtr get_or_create(Custody* parent, const StringView& name, Inode&); - static NonnullRefPtr create(Custody* parent, const StringView& name, Inode& inode) + static NonnullRefPtr get_or_create(Custody* parent, const StringView& name, Inode&, int mount_flags); + static NonnullRefPtr create(Custody* parent, const StringView& name, Inode& inode, int mount_flags) { - return adopt(*new Custody(parent, name, inode)); + return adopt(*new Custody(parent, name, inode, mount_flags)); } ~Custody(); @@ -33,6 +33,8 @@ public: bool is_deleted() const { return m_deleted; } bool is_mounted_on() const { return m_mounted_on; } + int mount_flags() const { return m_mount_flags; } + void did_delete(Badge); void did_mount_on(Badge); void did_rename(Badge, const String& name); @@ -42,11 +44,12 @@ public: Custody* m_prev { nullptr }; private: - Custody(Custody* parent, const StringView& name, Inode&); + Custody(Custody* parent, const StringView& name, Inode&, int mount_flags); RefPtr m_parent; String m_name; NonnullRefPtr m_inode; bool m_deleted { false }; bool m_mounted_on { false }; + int m_mount_flags { 0 }; }; diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 4a5c2c7130..48ad237893 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -78,10 +78,10 @@ enum ProcFileType { FI_PID_stack, FI_PID_regs, FI_PID_fds, - FI_PID_exe, // symlink - FI_PID_cwd, // symlink + FI_PID_exe, // symlink + FI_PID_cwd, // symlink FI_PID_root, // symlink - FI_PID_fd, // directory + FI_PID_fd, // directory __FI_PID_End, FI_MaxStaticFileIndex, @@ -651,6 +651,7 @@ Optional procfs$df(InodeIdentifier) fs_object.add("mount_point", mount.absolute_path()); fs_object.add("block_size", fs.block_size()); fs_object.add("readonly", fs.is_readonly()); + fs_object.add("mount_flags", mount.flags()); if (fs.is_disk_backed()) fs_object.add("device", static_cast(fs).device().absolute_path()); diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index a1ab0af591..293959f8fb 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -38,12 +38,12 @@ InodeIdentifier VFS::root_inode_id() const return m_root_inode->identifier(); } -KResult VFS::mount(FS& file_system, Custody& mount_point) +KResult VFS::mount(FS& file_system, Custody& mount_point, int flags) { auto& inode = mount_point.inode(); - dbg() << "VFS: Mounting " << file_system.class_name() << " at " << mount_point.absolute_path() << " (inode: " << inode.identifier() << ")"; + dbg() << "VFS: Mounting " << file_system.class_name() << " at " << mount_point.absolute_path() << " (inode: " << inode.identifier() << ") with flags " << flags; // FIXME: check that this is not already a mount point - Mount mount { file_system, &mount_point }; + Mount mount { file_system, &mount_point, flags }; m_mounts.append(move(mount)); mount_point.did_mount_on({}); return KSuccess; @@ -79,7 +79,7 @@ bool VFS::mount_root(FS& file_system) return false; } - Mount mount { file_system, nullptr }; + Mount mount { file_system, nullptr, 0 }; auto root_inode_id = mount.guest().fs()->root_inode(); auto root_inode = mount.guest().fs()->get_inode(root_inode_id); @@ -283,7 +283,7 @@ KResultOr> VFS::create(StringView path, int optio if (!new_file) return KResult(error); - auto new_custody = Custody::create(&parent_custody, p.basename(), *new_file); + auto new_custody = Custody::create(&parent_custody, p.basename(), *new_file, parent_custody.mount_flags()); return FileDescription::create(*new_custody); } @@ -603,10 +603,11 @@ RefPtr VFS::get_inode(InodeIdentifier inode_id) return inode_id.fs()->get_inode(inode_id); } -VFS::Mount::Mount(FS& guest_fs, Custody* host_custody) +VFS::Mount::Mount(FS& guest_fs, Custody* host_custody, int flags) : m_guest(guest_fs.root_inode()) , m_guest_fs(guest_fs) , m_host_custody(host_custody) + , m_flags(flags) { } @@ -639,7 +640,7 @@ void VFS::sync() Custody& VFS::root_custody() { if (!m_root_custody) - m_root_custody = Custody::create(nullptr, "", *m_root_inode); + m_root_custody = Custody::create(nullptr, "", *m_root_inode, 0); return *m_root_custody; } @@ -674,6 +675,8 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba if (parent_custody) *parent_custody = custody_chain.last(); + int mount_flags = custody_chain.last().mount_flags(); + for (int i = 0; i < parts.size(); ++i) { bool inode_was_root_at_head_of_loop = current_root.inode().identifier() == crumb_id; auto crumb_inode = get_inode(crumb_id); @@ -704,8 +707,10 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba } return KResult(-ENOENT); } - if (auto mount = find_mount_for_host(crumb_id)) + if (auto mount = find_mount_for_host(crumb_id)) { crumb_id = mount->guest(); + mount_flags = mount->flags(); + } if (inode_was_root_at_head_of_loop && crumb_id.is_root_inode() && crumb_id != current_root.inode().identifier() && part == "..") { auto mount = find_mount_for_guest(crumb_id); auto dir_inode = get_inode(mount->host()); @@ -715,7 +720,7 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba crumb_inode = get_inode(crumb_id); ASSERT(crumb_inode); - custody_chain.append(Custody::create(&custody_chain.last(), part, *crumb_inode)); + custody_chain.append(Custody::create(&custody_chain.last(), part, *crumb_inode, mount_flags)); metadata = crumb_inode->metadata(); if (metadata.is_directory()) { diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index 38b5b54b4b..05997e362a 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -1,12 +1,12 @@ #pragma once -#include #include #include #include #include #include #include +#include #include #include #include @@ -41,7 +41,7 @@ class VFS { public: class Mount { public: - Mount(FS&, Custody* host_custody); + Mount(FS&, Custody* host_custody, int flags); InodeIdentifier host() const; InodeIdentifier guest() const { return m_guest; } @@ -50,11 +50,14 @@ public: String absolute_path() const; + int flags() const { return m_flags; } + private: InodeIdentifier m_host; InodeIdentifier m_guest; NonnullRefPtr m_guest_fs; RefPtr m_host_custody; + int m_flags; }; static VFS& the(); @@ -63,7 +66,7 @@ public: ~VFS(); bool mount_root(FS&); - KResult mount(FS&, Custody& mount_point); + KResult mount(FS&, Custody& mount_point, int flags); KResult unmount(InodeIdentifier guest_inode_id); KResultOr> open(StringView path, int options, mode_t mode, Custody& base, Optional = {}); diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index efb3c39e33..8ab6f731a2 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -3642,7 +3642,7 @@ int Process::sys$mount(const Syscall::SC_mount_params* user_params) return -ENODEV; } - auto result = VFS::the().mount(fs.release_nonnull(), target_custody); + auto result = VFS::the().mount(fs.release_nonnull(), target_custody, params.flags); dbg() << "mount: successfully mounted " << source << " on " << target; return result; } @@ -4170,8 +4170,9 @@ int Process::sys$chroot(const char* user_path, size_t path_length) auto directory_or_error = VFS::the().open_directory(path.value(), current_directory()); if (directory_or_error.is_error()) return directory_or_error.error(); - m_root_directory_for_procfs = directory_or_error.value(); - set_root_directory(Custody::create(nullptr, "", directory_or_error.value()->inode())); + auto directory = directory_or_error.value(); + m_root_directory_for_procfs = directory; + set_root_directory(Custody::create(nullptr, "", directory->inode(), directory->mount_flags())); return 0; } diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index bad2bc1092..70d056f993 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -332,9 +332,9 @@ struct SC_link_params { }; struct SC_chown_params { - StringArgument path; - u32 uid; - u32 gid; + StringArgument path; + u32 uid; + u32 gid; }; struct SC_mknod_params { @@ -357,6 +357,7 @@ struct SC_mount_params { StringArgument source; StringArgument target; StringArgument fs_type; + int flags; }; void initialize(); diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index 30e1bf13cf..f6a5fad173 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -610,13 +610,18 @@ int reboot() __RETURN_WITH_ERRNO(rc, rc, -1); } -int mount(const char* source, const char* target, const char* fs_type) +int mount(const char* source, const char* target, const char* fs_type, int flags) { if (!source || !target || !fs_type) { errno = EFAULT; return -1; } - Syscall::SC_mount_params params { { source, strlen(source) }, { target, strlen(target) }, { fs_type, strlen(fs_type) } }; + Syscall::SC_mount_params params { + { source, strlen(source) }, + { target, strlen(target) }, + { fs_type, strlen(fs_type) }, + flags + }; int rc = syscall(SC_mount, ¶ms); __RETURN_WITH_ERRNO(rc, rc, -1); } diff --git a/Libraries/LibC/unistd.h b/Libraries/LibC/unistd.h index feafa57f3b..bfecbbfbdf 100644 --- a/Libraries/LibC/unistd.h +++ b/Libraries/LibC/unistd.h @@ -111,7 +111,7 @@ int fchown(int fd, uid_t, gid_t); int ftruncate(int fd, off_t length); int halt(); int reboot(); -int mount(const char* source, const char* target, const char* fs_type); +int mount(const char* source, const char* target, const char* fs_type, int flags); int umount(const char* mountpoint); enum { diff --git a/Userland/mount.cpp b/Userland/mount.cpp index ec99287ae1..c1d422195d 100644 --- a/Userland/mount.cpp +++ b/Userland/mount.cpp @@ -45,7 +45,7 @@ bool mount_all() dbg() << "Mounting " << devname << "(" << fstype << ")" << " on " << mountpoint; - int rc = mount(devname, mountpoint, fstype); + int rc = mount(devname, mountpoint, fstype, 0); if (rc != 0) { fprintf(stderr, "Failed to mount %s (%s) on %s: %s\n", devname, fstype, mountpoint, strerror(errno)); all_ok = false; @@ -101,7 +101,7 @@ int main(int argc, char** argv) String mountpoint = args.get_single_values()[1]; String fstype = args.is_present("t") ? args.get("t") : "ext2"; - if (mount(devname.characters(), mountpoint.characters(), fstype.characters()) < 0) { + if (mount(devname.characters(), mountpoint.characters(), fstype.characters(), 0) < 0) { perror("mount"); return 1; }