This patch removes external/fs/libnfs module and makes nfs support pluggable
by moving it into a module (shared library) that can be added to the image
instead of being compiled into the kernel using nfs=true build option.
The nfs support can be added by adding nfs module to the image.

More specifically:
- external/fs/libnfs is removed and equivalent modules/libnfs gets created
- most fs/nfs code except for fs_null_vfsops.cc gets moved out of a kernel
  into new modules/nfs that is built as a shared library
- vfs mount logic is able to dynamically load extra filesystem
  libraries from /usr/lib/fs

Completes #1078

Signed-off-by: Waldemar Kozaczuk <[email protected]>
---
 .gitmodules                               |  3 --
 Makefile                                  | 32 ++--------------
 external/fs/libnfs                        |  1 -
 fs/nfs/nfs_null_vfsops.cc                 | 11 +++++-
 fs/vfs/main.cc                            | 17 +++++++++
 fs/vfs/vfs_conf.cc                        |  2 +-
 modules/libnfs/.gitignore                 |  1 +
 modules/libnfs/Makefile                   | 19 ++++++++++
 modules/libnfs/usr.manifest               |  9 +++++
 modules/nfs/.gitignore                    |  3 ++
 modules/nfs/Makefile                      | 46 +++++++++++++++++++++++
 modules/nfs/module.py                     |  3 ++
 {fs => modules}/nfs/nfs.cc                |  2 +-
 {fs => modules}/nfs/nfs.hh                |  2 +-
 {fs => modules}/nfs/nfs_vfsops.cc         | 24 ++++++------
 {fs => modules}/nfs/nfs_vnops.cc          |  0
 tools/mount/{mount-nfs.cc => mount-fs.cc} | 13 +++++--
 usr.manifest.skel                         |  2 +-
 usr_ramfs.manifest.skel                   |  2 +-
 usr_rofs.manifest.skel                    |  2 +-
 20 files changed, 139 insertions(+), 55 deletions(-)
 delete mode 160000 external/fs/libnfs
 create mode 100644 modules/libnfs/.gitignore
 create mode 100644 modules/libnfs/Makefile
 create mode 100644 modules/libnfs/usr.manifest
 create mode 100644 modules/nfs/.gitignore
 create mode 100644 modules/nfs/Makefile
 create mode 100644 modules/nfs/module.py
 rename {fs => modules}/nfs/nfs.cc (97%)
 rename {fs => modules}/nfs/nfs.hh (96%)
 rename {fs => modules}/nfs/nfs_vfsops.cc (74%)
 rename {fs => modules}/nfs/nfs_vnops.cc (100%)
 rename tools/mount/{mount-nfs.cc => mount-fs.cc} (70%)

diff --git a/.gitmodules b/.gitmodules
index b6ae6ac1..17a2c18e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -15,6 +15,3 @@
 [submodule "modules/httpserver/osv-gui"]
        path = modules/httpserver-html5-gui/osv-gui
        url = ../../cloudius-systems/osv-gui.git
-[submodule "external/fs/libnfs"]
-       path = external/fs/libnfs
-       url = https://github.com/sahlberg/libnfs.git
diff --git a/Makefile b/Makefile
index 03a17920..9401e809 100644
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,6 @@
 # This work is open source software, licensed under the terms of the
 # BSD license as described in the LICENSE file in the top-level directory.
 
-# The nfs=true flag will build in the NFS client filesystem support
-
 # Delete the builtin make rules, as if "make -r" was used.
 .SUFFIXES:
 
@@ -142,25 +140,10 @@ check:
        ./scripts/build check
 .PHONY: check
 
-libnfs-path = external/fs/libnfs/
-
-$(out)/libnfs.a:
-       cd $(libnfs-path) && \
-       $(call quiet, ./bootstrap) && \
-       $(call quiet, ./configure --enable-shared=no --enable-static=yes 
--enable-silent-rules) && \
-       $(call quiet, make)
-       $(call quiet, cp -a $(libnfs-path)/lib/.libs/libnfs.a $(out)/libnfs.a)
-
-clean-libnfs:
-       if [ -f $(out)/libnfs.a ] ; then \
-       cd $(libnfs-path) && \
-       make distclean; \
-       fi
-
 # Remember that "make clean" needs the same parameters that set $(out) in
 # the first place, so to clean the output of "make mode=debug" you need to
 # do "make mode=debug clean".
-clean: clean-libnfs
+clean:
        rm -rf $(out)
        rm -f $(outlink) $(outlink2)
 .PHONY: clean
@@ -374,7 +357,7 @@ tools += tools/uush/uush.so
 tools += tools/uush/ls.so
 tools += tools/uush/mkdir.so
 
-tools += tools/mount/mount-nfs.so
+tools += tools/mount/mount-fs.so
 tools += tools/mount/umount.so
 
 ifeq ($(arch),aarch64)
@@ -1849,14 +1832,7 @@ endif
 
 boost-libs := $(boost-lib-dir)/libboost_system$(boost-mt).a
 
-ifeq ($(nfs), true)
-       nfs-lib = $(out)/libnfs.a
-       nfs_o = nfs.o nfs_vfsops.o nfs_vnops.o
-else
-       nfs_o = nfs_null_vfsops.o
-endif
-
-objects += $(addprefix fs/nfs/, $(nfs_o))
+objects += fs/nfs/nfs_null_vfsops.o
 
 # ld has a known bug (https://sourceware.org/bugzilla/show_bug.cgi?id=6468)
 # where if the executable doesn't use shared libraries, its .dynamic section
@@ -1865,7 +1841,7 @@ objects += $(addprefix fs/nfs/, $(nfs_o))
 $(out)/dummy-shlib.so: $(out)/dummy-shlib.o
        $(call quiet, $(CXX) -nodefaultlibs -shared $(gcc-sysroot) -o $@ $^, 
LINK $@)
 
-stage1_targets = $(out)/arch/$(arch)/boot.o $(out)/loader.o $(out)/runtime.o 
$(drivers:%=$(out)/%) $(objects:%=$(out)/%) $(out)/dummy-shlib.so $(nfs-lib)
+stage1_targets = $(out)/arch/$(arch)/boot.o $(out)/loader.o $(out)/runtime.o 
$(drivers:%=$(out)/%) $(objects:%=$(out)/%) $(out)/dummy-shlib.so
 stage1: $(stage1_targets) links
 .PHONY: stage1
 
diff --git a/external/fs/libnfs b/external/fs/libnfs
deleted file mode 160000
index dc8d8662..00000000
--- a/external/fs/libnfs
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit dc8d86628d2f67cb4b7a9e5e5d7a1259f065b3c7
diff --git a/fs/nfs/nfs_null_vfsops.cc b/fs/nfs/nfs_null_vfsops.cc
index eef09fd1..99befba6 100644
--- a/fs/nfs/nfs_null_vfsops.cc
+++ b/fs/nfs/nfs_null_vfsops.cc
@@ -15,6 +15,13 @@
 #define nfs_vget    ((vfsop_vget_t)vfs_nullop)
 #define nfs_statfs  ((vfsop_statfs_t)vfs_nullop)
 
+static int nfs_noop_mount(struct mount *mp, const char *dev, int flags,
+                          const void *data)
+{
+    printf("The nfs module is in-active!. Please add nfs module to the 
image.\n");
+    return -1;
+}
+
 /*
  * File system operations
  *
@@ -22,8 +29,8 @@
  *
  */
 struct vfsops nfs_vfsops = {
-    nfs_mount,      /* mount */
-    nfs_umount,    /* umount */
+    nfs_noop_mount,      /* mount */
+    nfs_umount,     /* umount */
     nfs_sync,       /* sync */
     nfs_vget,       /* vget */
     nfs_statfs,     /* statfs */
diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index 6f224347..46dcb62f 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -53,6 +53,7 @@
 #include <fcntl.h>
 #undef open
 #undef fcntl
+#include <dlfcn.h>
 
 #include <osv/prex.h>
 #include <osv/vnode.h>
@@ -2305,6 +2306,22 @@ void pivot_rootfs(const char* path)
     if (ret)
         kprintf("failed to pivot root, error = %s\n", strerror(ret));
 
+    // Initialize other filesystem libraries if present
+    auto fs_lib_dir = opendir("/usr/lib/fs");
+    if (fs_lib_dir) {
+        while (auto dirent = readdir(fs_lib_dir)) {
+            auto len = strlen(dirent->d_name);
+            if (len >= 3 && strcmp(dirent->d_name + (len - 3), ".so") == 0) {
+                auto lib_path = std::string("/usr/lib/fs/") + dirent->d_name;
+                auto module = dlopen(lib_path.c_str(), RTLD_LAZY);
+                if (module)
+                    debugf("VFS: Initialized filesystem library: %s\n", 
lib_path.c_str());
+            }
+        }
+
+        closedir(fs_lib_dir);
+    }
+
     auto ent = setmntent("/etc/fstab", "r");
     if (!ent) {
         return;
diff --git a/fs/vfs/vfs_conf.cc b/fs/vfs/vfs_conf.cc
index a23ea48f..4a54cb97 100644
--- a/fs/vfs/vfs_conf.cc
+++ b/fs/vfs/vfs_conf.cc
@@ -71,7 +71,7 @@ const struct vfssw vfssw[] = {
        {"devfs",       devfs_init,     &devfs_vfsops},
        {"nfs",         nfs_init,       &nfs_vfsops},
        {"procfs",      procfs_init,    &procfs_vfsops},
-    {"sysfs",  sysfs_init,     &sysfs_vfsops},
+       {"sysfs",       sysfs_init,     &sysfs_vfsops},
        {"zfs",         zfs_init,       &zfs_vfsops},
        {"rofs",        rofs_init,      &rofs_vfsops},
        {"virtiofs",    virtiofs_init,  &virtiofs_vfsops},
diff --git a/modules/libnfs/.gitignore b/modules/libnfs/.gitignore
new file mode 100644
index 00000000..04595130
--- /dev/null
+++ b/modules/libnfs/.gitignore
@@ -0,0 +1 @@
+upstream
diff --git a/modules/libnfs/Makefile b/modules/libnfs/Makefile
new file mode 100644
index 00000000..66a5a230
--- /dev/null
+++ b/modules/libnfs/Makefile
@@ -0,0 +1,19 @@
+src = $(shell readlink -f ../..)
+module-dir = $(src)/modules/libnfs
+
+all: module
+module: libnfs
+
+libnfs: upstream/libnfs/.git upstream/libnfs/lib/libnfs.so.4.0.0
+
+.PHONY: libnfs
+
+upstream/libnfs/.git:
+       mkdir -p $(module-dir)/upstream && cd $(module-dir)/upstream && \
+       git clone --depth 1 https://github.com/sahlberg/libnfs.git
+
+upstream/libnfs/lib/libnfs.so.4.0.0:
+       cd $(module-dir)/upstream/libnfs && cmake . && make
+
+clean:
+       cd $(module-dir) && rm -rf upstream
diff --git a/modules/libnfs/usr.manifest b/modules/libnfs/usr.manifest
new file mode 100644
index 00000000..847ae537
--- /dev/null
+++ b/modules/libnfs/usr.manifest
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2018 Waldemar Kozaczuk
+#
+# This work is open source software, licensed under the terms of the
+# BSD license as described in the LICENSE file in the top-level directory.
+#
+
+[manifest]
+/usr/lib/libnfs.so.11.0.0: ${MODULE_DIR}/upstream/libnfs/lib/libnfs.so.4.0.0
diff --git a/modules/nfs/.gitignore b/modules/nfs/.gitignore
new file mode 100644
index 00000000..db4f6ea7
--- /dev/null
+++ b/modules/nfs/.gitignore
@@ -0,0 +1,3 @@
+obj
+*.so
+usr.manifest
diff --git a/modules/nfs/Makefile b/modules/nfs/Makefile
new file mode 100644
index 00000000..fa86780d
--- /dev/null
+++ b/modules/nfs/Makefile
@@ -0,0 +1,46 @@
+INCLUDES = -I. -I../libnfs/upstream/libnfs/include -I../../include
+INCLUDES += -I../../arch/$(ARCH) -I../.. -I../../build/$(mode)/gen/include
+INCLUDES += -isystem ../../include/glibc-compat
+#Only for host, not external
+INCLUDES += $(shell $(CXX) -E -xc++ - -v </dev/null 2>&1 | awk '/^End/ {exit} 
/^ .*c\+\+/ {print "-isystem" $$0}')
+#
+INCLUDES += -isystem ../../include/api -isystem ../../include/api/$(ARCH) 
-isystem ../../build/$(mode)/gen/include
+INCLUDES += -isystem ../../bsd/sys -isystem ../../bsd/ -isystem 
../../bsd/$(ARCH)
+
+autodepend = -MD -MT $@ -MP
+CXXFLAGS  = -g -rdynamic -Wall -std=c++11 -fPIC $(INCLUDES) -D_KERNEL 
-D_GNU_SOURCE $(autodepend)
+
+# the build target executable:
+TARGET = nfs
+CPP_FILES := $(wildcard *.cc)
+OBJ_FILES := $(addprefix obj/,$(CPP_FILES:.cc=.o))
+DEPS := $(OBJ_FILES:.o=.d)
+
+LIBS = -L../libnfs/upstream/libnfs/lib -lnfs
+ifndef ARCH
+       ARCH = x64
+endif
+ifndef mode
+       mode = release
+endif
+
+quiet = $(if $V, $1, @echo " $2"; $1)
+very-quiet = $(if $V, $1, @$1)
+
+$(TARGET).so: $(OBJ_FILES)
+       $(call quiet, $(CXX) $(CXXFLAGS) -shared -o $(TARGET).so $^ $(LIBS), 
LINK $@)
+
+obj/%.o: %.cc
+       $(call quiet, $(CXX) $(CXXFLAGS) -c -o $@ $<, CXX $@)
+
+init:
+       @echo "  MKDIRS"
+       $(call very-quiet, mkdir -p obj)
+.PHONY: init
+
+module: init $(TARGET).so
+       echo '/usr/lib/fs/nfs.so: $${MODULE_DIR}/nfs.so' > usr.manifest
+
+clean:
+       rm -f $(TARGET)*.so usr.manifest
+       $(call very-quiet, $(RM) -rf obj)
diff --git a/modules/nfs/module.py b/modules/nfs/module.py
new file mode 100644
index 00000000..e3379492
--- /dev/null
+++ b/modules/nfs/module.py
@@ -0,0 +1,3 @@
+from osv.modules import api
+
+api.require('libnfs')
diff --git a/fs/nfs/nfs.cc b/modules/nfs/nfs.cc
similarity index 97%
rename from fs/nfs/nfs.cc
rename to modules/nfs/nfs.cc
index 61740251..6fd8bd16 100644
--- a/fs/nfs/nfs.cc
+++ b/modules/nfs/nfs.cc
@@ -31,7 +31,7 @@ mount_context::mount_context(const char *url)
     // parse the url while taking care of freeing it when needed
     _url.reset(nfs_parse_url_dir(_nfs.get(), url));
     if (!_url) {
-        debug(std::string("mount_context():g: ") +
+        debug(std::string("mount_context(): ") +
               nfs_get_error(_nfs.get()) + "\n");
         _errno = EINVAL;
         return;
diff --git a/fs/nfs/nfs.hh b/modules/nfs/nfs.hh
similarity index 96%
rename from fs/nfs/nfs.hh
rename to modules/nfs/nfs.hh
index a078c723..f38b13b1 100644
--- a/fs/nfs/nfs.hh
+++ b/modules/nfs/nfs.hh
@@ -27,7 +27,7 @@
 
 #include <osv/mutex.h>
 
-#include "../../external/fs/libnfs/include/nfsc/libnfs.h"
+#include "nfsc/libnfs.h"
 
 class mount_context {
 public:
diff --git a/fs/nfs/nfs_vfsops.cc b/modules/nfs/nfs_vfsops.cc
similarity index 74%
rename from fs/nfs/nfs_vfsops.cc
rename to modules/nfs/nfs_vfsops.cc
index 8ad1c2dd..9d879b15 100644
--- a/fs/nfs/nfs_vfsops.cc
+++ b/modules/nfs/nfs_vfsops.cc
@@ -69,15 +69,17 @@ int nfs_init(void)
 #define nfs_op_vget    ((vfsop_vget_t)vfs_nullop)
 #define nfs_op_statfs  ((vfsop_statfs_t)vfs_nullop)
 
-/*
- * File system operations
- */
-struct vfsops nfs_vfsops = {
-    nfs_op_mount,      /* mount */
-    nfs_op_unmount,    /* unmount */
-    nfs_op_sync,       /* sync */
-    nfs_op_vget,       /* vget */
-    nfs_op_statfs,     /* statfs */
-    &nfs_vnops,        /* vnops */
-};
+// We are relying on vfsops structure defined in kernel
+extern struct vfsops nfs_vfsops;
+
+// Overwrite "null" vfsops structure fields with "real"
+// functions upon loading nfs.so shared object
+void __attribute__((constructor)) initialize_vfsops() {
+    nfs_vfsops.vfs_mount = nfs_op_mount;
+    nfs_vfsops.vfs_unmount = nfs_op_unmount;
+    nfs_vfsops.vfs_sync = nfs_op_sync;
+    nfs_vfsops.vfs_vget = nfs_op_vget;
+    nfs_vfsops.vfs_statfs = nfs_op_statfs;
+    nfs_vfsops.vfs_vnops = &nfs_vnops;
+}
 
diff --git a/fs/nfs/nfs_vnops.cc b/modules/nfs/nfs_vnops.cc
similarity index 100%
rename from fs/nfs/nfs_vnops.cc
rename to modules/nfs/nfs_vnops.cc
diff --git a/tools/mount/mount-nfs.cc b/tools/mount/mount-fs.cc
similarity index 70%
rename from tools/mount/mount-nfs.cc
rename to tools/mount/mount-fs.cc
index 9c3da84a..6e6324c0 100644
--- a/tools/mount/mount-nfs.cc
+++ b/tools/mount/mount-fs.cc
@@ -9,28 +9,33 @@
 int main(int argc, char **argv)
 {
     // Check number of arguments
-    if (argc != 3) {
+    if (argc != 4) {
         std::cout << "Usage:" << std::endl;
         std::cout << "\t" << argv[0] <<
+                     " nfs" <<
                      " nfs://<server|ipv4|ipv6>/path[?arg=val[&arg=val]*]" <<
                      " /mount_point" << std::endl;
         return(1);
     }
 
     // fetch arguments
-    std::string url(argv[1]);
-    std::string mount_point(argv[2]);
+    std::string fs_type(argv[1]);
+    std::string url(argv[2]);
+    std::string mount_point(argv[3]);
 
     // create the mount point as a convenience if it does not already exists
     mkdir(mount_point.c_str(), 0777);
     // Mount and process error
-    int ret = mount(url.c_str(), mount_point.c_str(), "nfs", 0, nullptr);
+    int ret = mount(url.c_str(), mount_point.c_str(), fs_type.c_str(), 0, 
nullptr);
     if (ret) {
         int my_errno = errno;
         std::cout << "Error in mount(): " << strerror(my_errno) << "(" << 
my_errno << ")"
                   << std::endl;
         return(1);
     }
+    else {
+        std::cout << "Mounted " << url << " at " << mount_point << std::endl;
+    }
 
     return(0);
 }
diff --git a/usr.manifest.skel b/usr.manifest.skel
index 32fa8056..3c072d01 100644
--- a/usr.manifest.skel
+++ b/usr.manifest.skel
@@ -7,7 +7,7 @@
 /zfs.so: zfs.so
 /tools/mkfs.so: tools/mkfs/mkfs.so
 /tools/cpiod.so: tools/cpiod/cpiod.so
-/tools/mount-nfs.so: tools/mount/mount-nfs.so
+/tools/mount-fs.so: tools/mount/mount-fs.so
 /tools/umount.so: tools/mount/umount.so
 /usr/lib/libgcc_s.so.1: %(libgcc_s_dir)s/libgcc_s.so.1
 /&/etc/hosts: ../../static/&
diff --git a/usr_ramfs.manifest.skel b/usr_ramfs.manifest.skel
index 36c5e662..4bdfdd32 100644
--- a/usr_ramfs.manifest.skel
+++ b/usr_ramfs.manifest.skel
@@ -1,7 +1,7 @@
 [manifest]
 /libenviron.so: libenviron.so
 /libvdso.so: libvdso.so
-/tools/mount-nfs.so: tools/mount/mount-nfs.so
+/tools/mount-fs.so: tools/mount/mount-fs.so
 /tools/umount.so: tools/mount/umount.so
 /usr/lib/libgcc_s.so.1: %(libgcc_s_dir)s/libgcc_s.so.1
 /&/etc/hosts: ../../static/&
diff --git a/usr_rofs.manifest.skel b/usr_rofs.manifest.skel
index ecca8110..b7d477ec 100644
--- a/usr_rofs.manifest.skel
+++ b/usr_rofs.manifest.skel
@@ -1,7 +1,7 @@
 [manifest]
 /libenviron.so: libenviron.so
 /libvdso.so: libvdso.so
-/tools/mount-nfs.so: tools/mount/mount-nfs.so
+/tools/mount-fs.so: tools/mount/mount-fs.so
 /tools/umount.so: tools/mount/umount.so
 /usr/lib/libgcc_s.so.1: %(libgcc_s_dir)s/libgcc_s.so.1
 /&/etc/hosts: ../../static/&
-- 
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20200322163158.13376-1-jwkozaczuk%40gmail.com.

Reply via email to