This patch adds new loader option '--mount-fs=arg' where arg is in format
'<fs_type,url,path>'. It allows adding arbitrary mount points for filesystems
like NFS, Virtio-FS or even ramfs on top of functionality based on /etc/fstab.
This options becomes more handy than appending to /etc/fstab or using 
/tools/mountfs
which has to be already present in the image.

Here is a cmdline example of mounting virtio-fs filesystem:

'--mount-fs=virtiofs,/dev/virtiofs1,/tmp/virtiofs /tmp/virtiofs/hello'

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
---
 fs/vfs/main.cc | 56 ++++++++++++++++++++++++++++++++++----------------
 loader.cc      | 24 +++++++++++++++++++++-
 2 files changed, 61 insertions(+), 19 deletions(-)

diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index 46dcb62f..3c8b327b 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -2300,6 +2300,36 @@ static void import_extra_zfs_pools(void)
     }
 }
 
+static void mount_fs(mntent *m)
+{
+    if (!strcmp(m->mnt_dir, "/")) {
+        return;
+    }
+
+    auto mount_dir = opendir(m->mnt_dir);
+    if (!mount_dir) {
+        if (mkdir(m->mnt_dir, 0755) < 0) {
+            kprintf("failed to create missing mount point %s, error = %s\n", 
m->mnt_dir, strerror(errno));
+            return;
+        } else {
+            kprintf("created missing mount point %s\n", m->mnt_dir);
+        }
+    } else {
+        closedir(mount_dir);
+    }
+
+    if ((m->mnt_opts != nullptr) && strcmp(m->mnt_opts, MNTOPT_DEFAULTS)) {
+        printf("Warning: opts %s, ignored for fs %s\n", m->mnt_opts, 
m->mnt_type);
+    }
+
+    // FIXME: Right now, ignoring mntops. In the future we may have an option 
parser
+    auto ret = sys_mount(m->mnt_fsname, m->mnt_dir, m->mnt_type, 0, nullptr);
+    if (ret) {
+        printf("failed to mount %s, error = %s\n", m->mnt_type, strerror(ret));
+    }
+}
+
+extern std::vector<mntent> opt_mount_fs;
 void pivot_rootfs(const char* path)
 {
     int ret = sys_pivot_root(path, "/");
@@ -2323,27 +2353,17 @@ void pivot_rootfs(const char* path)
     }
 
     auto ent = setmntent("/etc/fstab", "r");
-    if (!ent) {
-        return;
-    }
-
-    struct mntent *m = nullptr;
-    while ((m = getmntent(ent)) != nullptr) {
-        if (!strcmp(m->mnt_dir, "/")) {
-            continue;
-        }
-
-        if ((m->mnt_opts != nullptr) && strcmp(m->mnt_opts, MNTOPT_DEFAULTS)) {
-            printf("Warning: opts %s, ignored for fs %s\n", m->mnt_opts, 
m->mnt_type);
+    if (ent) {
+        struct mntent *m = nullptr;
+        while ((m = getmntent(ent)) != nullptr) {
+            mount_fs(m);
         }
+        endmntent(ent);
+    }
 
-        // FIXME: Right now, ignoring mntops. In the future we may have an 
option parser
-        ret = sys_mount(m->mnt_fsname, m->mnt_dir, m->mnt_type, 0, nullptr);
-        if (ret) {
-            printf("failed to mount %s, error = %s\n", m->mnt_type, 
strerror(ret));
-        }
+    for (auto m: opt_mount_fs) {
+        mount_fs(&m);
     }
-    endmntent(ent);
 }
 
 extern "C" void unmount_devfs()
diff --git a/loader.cc b/loader.cc
index 758e4bf9..66bfb52c 100644
--- a/loader.cc
+++ b/loader.cc
@@ -48,6 +48,7 @@
 #include <dirent.h>
 #include <iostream>
 #include <fstream>
+#include <mntent.h>
 
 #include "drivers/zfs.hh"
 #include "drivers/random.hh"
@@ -144,6 +145,7 @@ static std::string opt_defaultgw;
 static std::string opt_nameserver;
 static std::string opt_redirect;
 static std::chrono::nanoseconds boot_delay;
+std::vector<mntent> opt_mount_fs;
 bool opt_maxnic = false;
 int maxnic;
 bool opt_pci_disabled = false;
@@ -180,7 +182,8 @@ static void usage()
     std::cout << "  --redirect=arg        redirect stdout and stderr to 
file\n";
     std::cout << "  --disable_rofs_cache  disable ROFS memory cache\n";
     std::cout << "  --nopci               disable PCI enumeration\n";
-    std::cout << "  --extra-zfs-pools     import extra ZFS pools\n\n";
+    std::cout << "  --extra-zfs-pools     import extra ZFS pools\n";
+    std::cout << "  --mount-fs=arg        mount extra filesystem, 
format:<fs_type,url,path>\n\n";
 }
 
 static void handle_parse_error(const std::string &message)
@@ -271,6 +274,25 @@ static void parse_options(int loader_argc, char** 
loader_argv)
         debug("console=%s\n", opt_console);
     }
 
+    if (options::option_value_exists(options_values, "mount-fs")) {
+        auto mounts = options::extract_option_values(options_values, 
"mount-fs");
+        for (auto m : mounts) {
+            std::vector<std::string> tmp;
+            boost::split(tmp, m, boost::is_any_of(","), 
boost::token_compress_on);
+            if (tmp.size() != 3 || tmp[0].empty() || tmp[1].empty() || 
tmp[2].empty()) {
+                printf("Ignoring value: '%s' for option mount-fs, expected in 
format: <fs_type,url,path>\n", m.c_str());
+                continue;
+            }
+            mntent mount = {
+                .mnt_fsname = strdup(tmp[1].c_str()),
+                .mnt_dir = strdup(tmp[2].c_str()),
+                .mnt_type = strdup(tmp[0].c_str()),
+                .mnt_opts = nullptr
+            };
+            opt_mount_fs.push_back(mount);
+        }
+    }
+
     if (options::option_value_exists(options_values, "env")) {
         for (auto t : options::extract_option_values(options_values, "env")) {
             debug("Setting in environment: %s\n", t);
-- 
2.20.1

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20200501201505.25226-1-jwkozaczuk%40gmail.com.

Reply via email to