Kernel: Implement bind mounts

You can now bind-mount files and directories. This essentially exposes an
existing part of the file system in another place, and can be used as an
alternative to symlinks or hardlinks.

Here's an example of doing this:

    # mkdir /tmp/foo
    # mount /home/anon/myfile.txt /tmp/foo -o bind
    # cat /tmp/foo
    This is anon's file.
This commit is contained in:
Sergey Bugaev 2020-01-11 19:08:35 +03:00 committed by Andreas Kling
parent 71f1d3f819
commit 0cb0f54783
Notes: sideshowbarker 2024-07-19 10:11:16 +09:00
3 changed files with 29 additions and 0 deletions

View File

@ -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)

View File

@ -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<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> = {});

View File

@ -3602,6 +3602,15 @@ int Process::sys$mount(const Syscall::SC_mount_params* user_params)
RefPtr<FS> 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())