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 <jwkozac...@gmail.com>
---
 .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 osv-dev+unsubscr...@googlegroups.com.
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