summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2020-01-11 19:08:35 +0300
committerAndreas Kling <awesomekling@gmail.com>2020-01-11 18:57:53 +0100
commit0cb0f54783aa9d0880e2b85edc9540d4331feb91 (patch)
tree888a3a6055b6c392bbc1dcfe3e69d6fed9975e5a /Kernel
parent71f1d3f819b4ad4c1e602f4f0f7cfe3e4e6c23b6 (diff)
downloadserenity-0cb0f54783aa9d0880e2b85edc9540d4331feb91.zip
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.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/FileSystem/VirtualFileSystem.cpp18
-rw-r--r--Kernel/FileSystem/VirtualFileSystem.h2
-rw-r--r--Kernel/Process.cpp9
3 files changed, 29 insertions, 0 deletions
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<NonnullRefPtr<FileDescription>> open(StringView path, int options, mode_t mode, Custody& base, Optional<UidAndGid> = {});
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> 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())