diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index ccdf193182..6ed65df5e4 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -49,6 +49,16 @@ KResult VFS::mount(FS& file_system, Custody& mount_point, int flags) return KSuccess; } +KResult VFS::bind_mount(Custody& source, Custody& mount_point) +{ + dbg() << "VFS: Bind-mounting " << source.absolute_path() << " at " << mount_point.absolute_path(); + // FIXME: check that this is not already a mount point + Mount mount { source.inode(), mount_point }; + m_mounts.append(move(mount)); + mount_point.did_mount_on({}); + return KSuccess; +} + KResult VFS::unmount(InodeIdentifier guest_inode_id) { LOCKER(m_lock); @@ -617,6 +627,14 @@ VFS::Mount::Mount(FS& guest_fs, Custody* host_custody, int flags) { } +VFS::Mount::Mount(Inode& source, Custody& host_custody) + : m_guest(source.identifier()) + , m_guest_fs(source.fs()) + , m_host_custody(host_custody) + , m_flags(MS_BIND) +{ +} + String VFS::Mount::absolute_path() const { if (!m_host_custody) diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index 1a7f580997..c062d7bba1 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -48,6 +48,7 @@ public: class Mount { public: Mount(FS&, Custody* host_custody, int flags); + Mount(Inode& source, Custody& host_custody); InodeIdentifier host() const; InodeIdentifier guest() const { return m_guest; } @@ -73,6 +74,7 @@ public: bool mount_root(FS&); KResult mount(FS&, Custody& mount_point, int flags); + KResult bind_mount(Custody& source, Custody& mount_point); 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 81e382e86e..38b6933edd 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -3602,6 +3602,15 @@ int Process::sys$mount(const Syscall::SC_mount_params* user_params) RefPtr fs; + if (params.flags & MS_BIND) { + // We're doing a bind mount. + auto source_or_error = VFS::the().resolve_path(source, current_directory()); + if (source_or_error.is_error()) + return source_or_error.error(); + auto& source_custody = source_or_error.value(); + return VFS::the().bind_mount(source_custody, target_custody); + } + if (fs_type == "ext2" || fs_type == "Ext2FS") { auto metadata_or_error = VFS::the().lookup_metadata(source, current_directory()); if (metadata_or_error.is_error())