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 <
jwkoz...@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