From: Waldemar Kozaczuk <[email protected]>
Committer: Waldemar Kozaczuk <[email protected]>
Branch: master

loader: add option to mount extra filesystem

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 <[email protected]>

---
diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
--- 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
--- 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);

-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/00000000000062321205a4b34385%40google.com.

Reply via email to