Skip to content

Commit

Permalink
fs: move nfs support out of kernel in lieu of a separate pluggable mo…
Browse files Browse the repository at this point in the history
…dule

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]>
  • Loading branch information
wkozaczuk committed Mar 27, 2020
1 parent 69ea100 commit 4ffb0fa
Show file tree
Hide file tree
Showing 20 changed files with 139 additions and 55 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -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
32 changes: 4 additions & 28 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
1 change: 0 additions & 1 deletion external/fs/libnfs
Submodule libnfs deleted from dc8d86
11 changes: 9 additions & 2 deletions fs/nfs/nfs_null_vfsops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,22 @@
#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
*
* This desactivate the NFS file system when libnfs is not compiled in.
*
*/
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 */
Expand Down
17 changes: 17 additions & 0 deletions fs/vfs/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include <fcntl.h>
#undef open
#undef fcntl
#include <dlfcn.h>

#include <osv/prex.h>
#include <osv/vnode.h>
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/vfs/vfs_conf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down
1 change: 1 addition & 0 deletions modules/libnfs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
upstream
19 changes: 19 additions & 0 deletions modules/libnfs/Makefile
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions modules/libnfs/usr.manifest
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions modules/nfs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
obj
*.so
usr.manifest
46 changes: 46 additions & 0 deletions modules/nfs/Makefile
Original file line number Diff line number Diff line change
@@ -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)
3 changes: 3 additions & 0 deletions modules/nfs/module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from osv.modules import api

api.require('libnfs')
2 changes: 1 addition & 1 deletion fs/nfs/nfs.cc → modules/nfs/nfs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/nfs.hh → modules/nfs/nfs.hh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

#include <osv/mutex.h>

#include "../../external/fs/libnfs/include/nfsc/libnfs.h"
#include "nfsc/libnfs.h"

class mount_context {
public:
Expand Down
24 changes: 13 additions & 11 deletions fs/nfs/nfs_vfsops.cc → modules/nfs/nfs_vfsops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

File renamed without changes.
13 changes: 9 additions & 4 deletions tools/mount/mount-nfs.cc → tools/mount/mount-fs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
2 changes: 1 addition & 1 deletion usr.manifest.skel
Original file line number Diff line number Diff line change
Expand Up @@ -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/&
Expand Down
2 changes: 1 addition & 1 deletion usr_ramfs.manifest.skel
Original file line number Diff line number Diff line change
@@ -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/&
Expand Down
2 changes: 1 addition & 1 deletion usr_rofs.manifest.skel
Original file line number Diff line number Diff line change
@@ -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/&
Expand Down

0 comments on commit 4ffb0fa

Please sign in to comment.