From 4ffb0fa9329849cd587d62f91b6979bc0e0ce6d1 Mon Sep 17 00:00:00 2001 From: Waldemar Kozaczuk Date: Sun, 22 Mar 2020 12:14:27 -0400 Subject: [PATCH] fs: move nfs support out of kernel in lieu of a separate pluggable module 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 --- .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 b6ae6ac14d..17a2c18e08 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 03a1792063..9401e809c0 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 dc8d86628d..0000000000 --- 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 eef09fd17c..99befba64e 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 6f224347a9..46dcb62f3a 100644 --- a/fs/vfs/main.cc +++ b/fs/vfs/main.cc @@ -53,6 +53,7 @@ #include #undef open #undef fcntl +#include #include #include @@ -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 a23ea48fe1..4a54cb9781 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 0000000000..045951300c --- /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 0000000000..66a5a230b4 --- /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 0000000000..847ae5371b --- /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 0000000000..db4f6ea758 --- /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 0000000000..fa86780d11 --- /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 &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 0000000000..e337949278 --- /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 61740251ed..6fd8bd1642 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 a078c72331..f38b13b1d1 100644 --- a/fs/nfs/nfs.hh +++ b/modules/nfs/nfs.hh @@ -27,7 +27,7 @@ #include -#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 8ad1c2dd38..9d879b1580 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 9c3da84a2f..6e6324c057 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:///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 32fa8056fb..3c072d01fd 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 36c5e6627e..4bdfdd321d 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 ecca8110f7..b7d477ec6b 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/&