Skip to content

Commit 9cc49b3

Browse files
committed
vfs: support mounting ZFS from non-root partition
This patch mainly enhances VFS layer to support dynamically loading the ZFS library libsolaris.so from other root filesystem like ROFS and mounting ZFS filesystem from devices different than /dev/vblk0.1. The supported scenarios include specifying a loader option '--mount-fs' or adding an entry to /etc/fstab. In this patch we take advantage of the existing logic in VFS pivot_rootfs() that implicitly loads shared libraries from the directory /usr/lib/fs which is where we place libsolaris.so in the image. This was done as part of the commit 4ffb0fa to support dynamically loading NFS filesystem library. To support similar scenario with ZFS we need to on top of this enhance the mount_fs() to detect ZFS case and call zfsdev_init() and initialize BSD shrinker. We also enhance unmount_rootfs() to make it unmount ZFS from non-root mount points. This patch also add new module - zfs - which is intended to be used when building two types of images as described by #1200. Please note the next patch will enhance the build script to support building such images. 1. Run OSv from a single disk with two partitions: ROFS + ZFS (on /dev/vblk0.2) ./scripts/run.py --execute='--mount-fs=zfs,/dev/vblk0.2,/data /zpool.so list' 2. Run OSv with 2 disks: 1st one with ROFS and second one with ZFS (/dev/vblk1.1): ./scripts/run.py --execute='--mount-fs=zfs,/dev/vblk1.1,/data /zpool.so list' --second-disk-image build/release/zfs_disk.img Refs #1200 Signed-off-by: Waldemar Kozaczuk <[email protected]>
1 parent ce9d642 commit 9cc49b3

File tree

13 files changed

+100
-22
lines changed

13 files changed

+100
-22
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2383,7 +2383,7 @@ $(out)/bsd/cddl/contrib/opensolaris/lib/libzfs/common/zprop_common.o: bsd/sys/cd
23832383

23842384
$(out)/libzfs.so: $(libzfs-objects) $(out)/libuutil.so $(out)/libsolaris.so
23852385
$(makedir)
2386-
$(call quiet, $(CC) $(CFLAGS) -o $@ $(libzfs-objects) -L$(out) -luutil -lsolaris, LINK libzfs.so)
2386+
$(call quiet, $(CC) $(CFLAGS) -o $@ $(libzfs-objects) -L$(out) -luutil, LINK libzfs.so)
23872387

23882388
#include $(src)/bsd/cddl/contrib/opensolaris/cmd/zpool/build.mk:
23892389
zpool-cmd-file-list = zpool_iter zpool_main zpool_util zpool_vdev

bootfs.manifest.skel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[manifest]
2-
/libsolaris.so: libsolaris.so
2+
/usr/lib/fs/libsolaris.so: libsolaris.so

drivers/zfs.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,24 @@ zfs_device::~zfs_device()
6161
device_destroy(_zfs_dev);
6262
}
6363

64+
static bool zfsdev_initialized = false;
65+
6466
void zfsdev_init(void)
6567
{
66-
new zfs_device();
68+
if (!zfsdev_initialized) {
69+
new zfs_device();
70+
zfsdev_initialized = true;
71+
}
6772
}
6873

6974
}
7075

7176
extern "C" OSV_LIBSOLARIS_API void zfsdev_init()
7277
{
73-
new zfsdev::zfs_device();
78+
if (!zfsdev::zfsdev_initialized) {
79+
new zfsdev::zfs_device();
80+
zfsdev::zfsdev_initialized = true;
81+
}
7482
}
7583

7684

exported_symbols/osv_libsolaris.so.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,5 @@ vrele
9191
vttoif_tab
9292
wakeup
9393
zfsdev_init
94+
zfs_driver_initialized
9495
zfs_update_vfsops

fs/vfs/main.cc

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include <osv/ioctl.h>
6363
#include <osv/trace.hh>
6464
#include <osv/run.hh>
65+
#include <osv/mount.h>
6566
#include <drivers/console.hh>
6667

6768
#include "vfs.h"
@@ -83,6 +84,9 @@
8384
#include <api/utime.h>
8485
#include <chrono>
8586

87+
#include "drivers/zfs.hh"
88+
#include "bsd/porting/shrinker.h"
89+
8690
using namespace std;
8791

8892

@@ -2493,6 +2497,18 @@ static void mount_fs(mntent *m)
24932497
return;
24942498
}
24952499

2500+
bool zfs = strcmp(m->mnt_type, "zfs") == 0;
2501+
if (zfs) {
2502+
// Ignore if ZFS root pool is already mounted because we can only have one root pool
2503+
std::vector<osv::mount_desc> mounts = osv::current_mounts();
2504+
for (auto &mount : mounts) {
2505+
if (mount.type == "zfs" && mount.special.rfind("/dev")) {
2506+
kprintf("ZFS root pool is already mounted at %s\n", m->mnt_dir);
2507+
return;
2508+
}
2509+
}
2510+
}
2511+
24962512
auto mount_dir = opendir(m->mnt_dir);
24972513
if (!mount_dir) {
24982514
if (mkdir(m->mnt_dir, 0755) < 0) {
@@ -2505,14 +2521,23 @@ static void mount_fs(mntent *m)
25052521
closedir(mount_dir);
25062522
}
25072523

2508-
if ((m->mnt_opts != nullptr) && strcmp(m->mnt_opts, MNTOPT_DEFAULTS)) {
2509-
printf("Warning: opts %s, ignored for fs %s\n", m->mnt_opts, m->mnt_type);
2524+
if (zfs) {
2525+
m->mnt_opts = "osv/zfs";
2526+
} else {
2527+
if ((m->mnt_opts != nullptr) && strcmp(m->mnt_opts, MNTOPT_DEFAULTS)) {
2528+
printf("Warning: opts %s, ignored for fs %s\n", m->mnt_opts, m->mnt_type);
2529+
}
2530+
m->mnt_opts = nullptr;
25102531
}
25112532

2512-
// FIXME: Right now, ignoring mntops. In the future we may have an option parser
2513-
auto ret = sys_mount(m->mnt_fsname, m->mnt_dir, m->mnt_type, 0, nullptr);
2533+
// FIXME: Right now, ignoring mntops except for ZFS. In the future we may have an option parser
2534+
auto ret = sys_mount(m->mnt_fsname, m->mnt_dir, m->mnt_type, 0, (void*)m->mnt_opts);
25142535
if (ret) {
25152536
printf("failed to mount %s, error = %s\n", m->mnt_type, strerror(ret));
2537+
} else {
2538+
if (zfs) {
2539+
bsd_shrinker_init();
2540+
}
25162541
}
25172542
}
25182543

@@ -2531,8 +2556,12 @@ extern "C" void pivot_rootfs(const char* path)
25312556
if (len >= 3 && strcmp(dirent->d_name + (len - 3), ".so") == 0) {
25322557
auto lib_path = std::string("/usr/lib/fs/") + dirent->d_name;
25332558
auto module = dlopen(lib_path.c_str(), RTLD_LAZY);
2534-
if (module)
2535-
debugf("VFS: Initialized filesystem library: %s\n", lib_path.c_str());
2559+
if (module) {
2560+
if (strcmp(dirent->d_name, "libsolaris.so") == 0) {
2561+
zfsdev::zfsdev_init();
2562+
}
2563+
debugf("VFS: initialized filesystem library: %s\n", lib_path.c_str());
2564+
}
25362565
}
25372566
}
25382567

@@ -2647,6 +2676,17 @@ extern "C" void unmount_rootfs(void)
26472676
"error = %s\n", strerror(ret));
26482677
}
26492678

2679+
std::vector<osv::mount_desc> mounts = osv::current_mounts();
2680+
for (auto &m : mounts) {
2681+
if (m.type == "zfs" && m.special.rfind("/dev") == 0 && m.path != "/") {
2682+
ret = sys_umount2(m.path.c_str(), MNT_FORCE);
2683+
if (ret) {
2684+
kprintf("Warning: unmount_rootfs: failed to unmount %s, "
2685+
"error = %s\n", m.path.c_str(), strerror(ret));
2686+
}
2687+
}
2688+
}
2689+
26502690
ret = sys_umount2("/", MNT_FORCE);
26512691
if (ret) {
26522692
kprintf("Warning: unmount_rootfs: failed to unmount /, "

fs/zfs/zfs_initialize.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,16 @@ extern void zfs_update_vfsops(struct vfsops* _vfsops);
5252
extern void start_pagecache_access_scanner();
5353

5454
extern int zfs_init(void);
55+
extern bool zfs_driver_initialized;
5556

5657
//This init function gets called on loading of libsolaris.so
5758
//and it initializes all necessary resources (threads, etc) used by the code in
5859
//libsolaris.so. This initialization is necessary before ZFS can be mounted.
5960
void __attribute__((constructor)) zfs_initialize(void) {
61+
if (zfs_driver_initialized) {
62+
debug("zfs: driver has been ALREADY initialized!\n");
63+
return;
64+
}
6065
// These 3 functions used to be called at the end of bsd_init()
6166
// and are intended to initialize various resources, mainly thread pools
6267
// (threads named 'system_taskq_*' and 'solthread-0x*')
@@ -85,6 +90,7 @@ void __attribute__((constructor)) zfs_initialize(void) {
8590
//functions in the kernel
8691
zfs_init();
8792

93+
zfs_driver_initialized = true;
8894
debug("zfs: driver has been initialized!\n");
8995
}
9096

fs/zfs/zfs_null_vfsops.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ struct vfsops zfs_vfsops = {
3636
nullptr, /* vnops */
3737
};
3838

39-
extern "C" int zfs_init(void)
39+
extern "C" {
40+
OSV_LIBSOLARIS_API bool zfs_driver_initialized = false;
41+
int zfs_init(void)
4042
{
4143
return 0;
4244
}
45+
}
4346

4447
//Normally (without ZFS enabled) the zfs_vfsops points to dummy
4548
//noop functions. So when libsolaris.so is loaded, we provide the

loader.cc

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ int main(int loader_argc, char **loader_argv)
143143
sched::init([=] { main_cont(loader_argc, loader_argv); });
144144
}
145145

146+
static bool opt_preload_zfs_library = false;
146147
static bool opt_extra_zfs_pools = false;
147148
static bool opt_disable_rofs_cache = false;
148149
static bool opt_leak = false;
@@ -202,7 +203,8 @@ static void usage()
202203
std::cout << " --disable_rofs_cache disable ROFS memory cache\n";
203204
std::cout << " --nopci disable PCI enumeration\n";
204205
std::cout << " --extra-zfs-pools import extra ZFS pools\n";
205-
std::cout << " --mount-fs=arg mount extra filesystem, format:<fs_type,url,path>\n\n";
206+
std::cout << " --mount-fs=arg mount extra filesystem, format:<fs_type,url,path>\n";
207+
std::cout << " --preload-zfs-library preload ZFS library from /usr/lib/fs\n\n";
206208
}
207209

208210
static void handle_parse_error(const std::string &message)
@@ -233,6 +235,10 @@ static void parse_options(int loader_argc, char** loader_argv)
233235
opt_disable_rofs_cache = true;
234236
}
235237

238+
if (extract_option_flag(options_values, "preload-zfs-library")) {
239+
opt_preload_zfs_library = true;
240+
}
241+
236242
if (extract_option_flag(options_values, "extra-zfs-pools")) {
237243
opt_extra_zfs_pools = true;
238244
}
@@ -406,12 +412,22 @@ static void stop_all_remaining_app_threads()
406412
}
407413
}
408414

409-
static void load_zfs_library_and_mount_zfs_root(const char* mount_error_msg, bool pivot_when_error = false)
415+
static void load_zfs_library(std::function<void()> on_load_fun = nullptr)
410416
{
411417
// Load and initialize ZFS filesystem driver implemented in libsolaris.so
412-
const auto libsolaris_file_name = "libsolaris.so";
413-
//TODO: Consider calling dlclose() somewhere after ZFS is unmounted
414-
if (dlopen(libsolaris_file_name, RTLD_LAZY)) {
418+
const auto libsolaris_path = "/usr/lib/fs/libsolaris.so";
419+
if (dlopen(libsolaris_path, RTLD_LAZY)) {
420+
if (on_load_fun) {
421+
on_load_fun();
422+
}
423+
} else {
424+
debug("Could not load and/or initialize %s.\n", libsolaris_path);
425+
}
426+
}
427+
428+
static void load_zfs_library_and_mount_zfs_root(const char* mount_error_msg, bool pivot_when_error = false)
429+
{
430+
load_zfs_library([mount_error_msg, pivot_when_error]() {
415431
zfsdev::zfsdev_init();
416432
auto error = mount_zfs_rootfs(opt_pivot, opt_extra_zfs_pools);
417433
if (error) {
@@ -426,9 +442,7 @@ static void load_zfs_library_and_mount_zfs_root(const char* mount_error_msg, boo
426442
bsd_shrinker_init();
427443
boot_time.event("ZFS mounted");
428444
}
429-
} else {
430-
debug("Could not load and/or initialize %s.\n", libsolaris_file_name);
431-
}
445+
});
432446
}
433447

434448
void* do_main_thread(void *_main_args)
@@ -492,6 +506,10 @@ void* do_main_thread(void *_main_args)
492506
}
493507
}
494508

509+
if (opt_preload_zfs_library) {
510+
load_zfs_library();
511+
}
512+
495513
bool has_if = false;
496514
osv::for_each_if([&has_if] (std::string if_name) {
497515
if (if_name == "lo0")

modules/zfs-tools/usr.manifest

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@
22
/zpool.so: zpool.so
33
/libzfs.so: libzfs.so
44
/libuutil.so: libuutil.so
5-
/libsolaris.so: libsolaris.so

modules/zfs/usr.manifest

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[manifest]
2+
/usr/lib/fs/libsolaris.so: libsolaris.so

0 commit comments

Comments
 (0)