diff options
| author | pooka <pooka@NetBSD.org> | 2008-08-01 14:47:28 +0000 |
|---|---|---|
| committer | pooka <pooka@NetBSD.org> | 2008-08-01 14:47:28 +0000 |
| commit | c19f1a2afdb1179e5ef3d25f75cf1caa16510521 (patch) | |
| tree | 1ed394ef4b3644b52a31a0b97f60b55c9c512cdd /lib | |
| parent | b629cd421be01fbb4b302d5e00ba62285b9d18c0 (diff) | |
Support ukfs_modload(), which dlopens and vfs_attaches rump file
system modules for use. Sneakily this solves the problem with the
dynamic linker not wanting to handle the modules link set for
binaries where more than one file system library is included during
the link phase and therefore only one of the file systems getting
vfs_attach()ed in rump "boot". But more importantly, this is really
TRTTD, since now applications can be built, linked and shipped
completely independently of the file systems they support.
tested by Arnaud Ysmal
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libukfs/ukfs.3 | 53 | ||||
| -rw-r--r-- | lib/libukfs/ukfs.c | 171 | ||||
| -rw-r--r-- | lib/libukfs/ukfs.h | 8 |
3 files changed, 225 insertions, 7 deletions
diff --git a/lib/libukfs/ukfs.3 b/lib/libukfs/ukfs.3 index 3965c29866d..fa78c6738d0 100644 --- a/lib/libukfs/ukfs.3 +++ b/lib/libukfs/ukfs.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: ukfs.3,v 1.1 2008/07/29 13:17:41 pooka Exp $ +.\" $NetBSD: ukfs.3,v 1.2 2008/08/01 14:47:28 pooka Exp $ .\" .\" Copyright (c) 2008 Antti Kantee. All rights reserved. .\" @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 28, 2008 +.Dd August 1, 2008 .Dt UKFS 3 .Os .Sh NAME @@ -59,12 +59,21 @@ However, much like system calls, the interfaces of .Nm , are self-contained and require no tracking and release of resources. The only exception is the file system handle -.Ft struct ukfs . +.Ft struct ukfs +which should be released after use. .Sh INITIALIZATION .Ft int .br .Fn ukfs_init .Pp +.Ft int +.br +.Fn ukfs_modload "const char *fname" +.Pp +.Ft int +.br +.Fn ukfs_modload_dir "const char *dirname" +.Pp .Ft struct ukfs * .br .Fo ukfs_mount @@ -80,6 +89,44 @@ The only exception is the file system handle intializes the library and must be called once per process using .Nm . .Pp +.Fn ukfs_modload +is used at runtime to dynamically load a library which contains a +file system module. +For this to succeed, the +.Xr rump 3 +library and the module targetted must be compiled with compatible kernel +versions and the application must be dynamically linked. +Additionally, since this routine does not handle dependencies, all the +dependencies of the library must be loaded beforehand. +The routine returns \-1 for fatal error, 0 for dependency failure and 1 +for success. +.Pp +.Fn ukfs_modload_dir +loads all +.Xr rump 3 +file system modules in directory +.Fa dirname . +It looks for libraries which begin with +.Pa librumpfs_ +and end in +.Pa .so . +The routine tries to handle dependencies by retrying to load libraries +which failed due to dependencies. +.Fn ukfs_modload_dir +returns the number of vfs modules loaded or sets errno and +returns \-1 in case of a fatal error in directory searching. +In case a fatal error occurs after some modules have already been +loaded, the number of loaded module is returned. +Fatal errors in loading the modules themselves are ignored and +.Fn ukfs_modload +should be used directly if finegrained error reporting is desired. +.Pp +It should be noted that the above routines affect the whole process, +not just a specific instance of +.Nm . +It is preferable to call them from only one thread, as the underlying +dynamic library interfaces may not be threadsafe. +.Pp .Fn ukfs_mount intializes a file system image. The handle resulting from the operation is passed to all other routines diff --git a/lib/libukfs/ukfs.c b/lib/libukfs/ukfs.c index 4ce723ec9e1..5219cde0232 100644 --- a/lib/libukfs/ukfs.c +++ b/lib/libukfs/ukfs.c @@ -1,7 +1,7 @@ -/* $NetBSD: ukfs.c,v 1.2 2008/07/29 21:11:17 pooka Exp $ */ +/* $NetBSD: ukfs.c,v 1.3 2008/08/01 14:47:28 pooka Exp $ */ /* - * Copyright (c) 2007 Antti Kantee. All Rights Reserved. + * Copyright (c) 2007, 2008 Antti Kantee. All Rights Reserved. * * Development of this software was supported by the * Finnish Cultural Foundation. @@ -39,9 +39,13 @@ #define _FILE_OFFSET_BITS 64 #endif +#include <sys/param.h> +#include <sys/queue.h> #include <sys/stat.h> #include <assert.h> +#include <dirent.h> +#include <dlfcn.h> #include <err.h> #include <errno.h> #include <pthread.h> @@ -493,6 +497,169 @@ ukfs_lutimes(struct ukfs *ukfs, const char *filename, STDCALL(ukfs, rump_sys_lutimes(filename, tptr, &rv)); } +/* + * Dynamic module support + */ + +/* load one library */ + +/* + * XXX: the dlerror stuff isn't really threadsafe, but then again I + * can't protect against other threads calling dl*() outside of ukfs, + * so just live with it being flimsy + */ +#define UFSLIB "librumpfs_ufs.so" +int +ukfs_modload(const char *fname) +{ + void *handle, *thesym; + struct stat sb; + const char *p; + int error; + + if (stat(fname, &sb) == -1) + return -1; + + handle = dlopen(fname, RTLD_GLOBAL); + if (handle == NULL) { + if (strstr(dlerror(), "Undefined symbol")) + return 0; + warnx("dlopen %s failed: %s\n", fname, dlerror()); + /* XXXerrno */ + return -1; + } + + /* + * XXX: the ufs module is not loaded in the same fashion as the + * others. But we can't do dlclose() for it, since that would + * lead to not being able to load ffs/ext2fs/lfs. Hence hardcode + * and kludge around the issue for now. But this should really + * be fixed by fixing sys/ufs/ufs to be a kernel module. + */ + if ((p = strrchr(fname, '/')) != NULL) + p++; + else + p = fname; + if (strcmp(p, UFSLIB) == 0) + return 1; + + thesym = dlsym(handle, "__start_link_set_modules"); + if (thesym) { + error = rump_vfs_load(thesym); + if (error) + goto errclose; + return 1; + } + error = EINVAL; + + errclose: + dlclose(handle); + errno = error; + return -1; +} + +struct loadfail { + char *pname; + + LIST_ENTRY(loadfail) entries; +}; + +#define RUMPFSMOD_PREFIX "librumpfs_" +#define RUMPFSMOD_SUFFIX ".so" + +int +ukfs_modload_dir(const char *dir) +{ + char nbuf[MAXPATHLEN+1], *p; + struct dirent entry, *result; + DIR *libdir; + struct loadfail *lf, *nlf; + int error, nloaded = 0, redo; + LIST_HEAD(, loadfail) lfs; + + libdir = opendir(dir); + if (libdir == NULL) + return -1; + + LIST_INIT(&lfs); + for (;;) { + if ((error = readdir_r(libdir, &entry, &result)) != 0) + break; + if (!result) + break; + if (strncmp(result->d_name, RUMPFSMOD_PREFIX, + strlen(RUMPFSMOD_PREFIX)) != 0) + continue; + if (((p = strstr(result->d_name, RUMPFSMOD_SUFFIX)) == NULL) + || strlen(p) != strlen(RUMPFSMOD_SUFFIX)) + continue; + strlcpy(nbuf, dir, sizeof(nbuf)); + strlcat(nbuf, "/", sizeof(nbuf)); + strlcat(nbuf, result->d_name, sizeof(nbuf)); + switch (ukfs_modload(nbuf)) { + case 0: + lf = malloc(sizeof(*lf)); + if (lf == NULL) { + error = ENOMEM; + break; + } + lf->pname = strdup(nbuf); + if (lf->pname == NULL) { + free(lf); + error = ENOMEM; + break; + } + LIST_INSERT_HEAD(&lfs, lf, entries); + break; + case 1: + nloaded++; + break; + default: + /* ignore errors */ + break; + } + } + closedir(libdir); + if (error && nloaded != 0) + error = 0; + + /* + * El-cheapo dependency calculator. Just try to load the + * modules n times in a loop + */ + for (redo = 1; redo;) { + redo = 0; + nlf = LIST_FIRST(&lfs); + while ((lf = nlf) != NULL) { + nlf = LIST_NEXT(lf, entries); + if (ukfs_modload(lf->pname) == 1) { + nloaded++; + redo = 1; + LIST_REMOVE(lf, entries); + free(lf->pname); + free(lf); + } + } + } + + while ((lf = LIST_FIRST(&lfs)) != NULL) { + LIST_REMOVE(lf, entries); + free(lf->pname); + free(lf); + } + + if (error && nloaded == 0) { + errno = error; + return -1; + } + + return nloaded; +} + + +/* + * Utilities + */ int ukfs_util_builddirs(struct ukfs *ukfs, const char *pathname, mode_t mode) { diff --git a/lib/libukfs/ukfs.h b/lib/libukfs/ukfs.h index d323f27b7a0..24428735265 100644 --- a/lib/libukfs/ukfs.h +++ b/lib/libukfs/ukfs.h @@ -1,7 +1,7 @@ -/* $NetBSD: ukfs.h,v 1.3 2008/07/30 14:59:47 pooka Exp $ */ +/* $NetBSD: ukfs.h,v 1.4 2008/08/01 14:47:28 pooka Exp $ */ /* - * Copyright (c) 2007 Antti Kantee. All Rights Reserved. + * Copyright (c) 2007, 2008 Antti Kantee. All Rights Reserved. * * Development of this software was supported by the * Finnish Cultural Foundation. @@ -90,6 +90,10 @@ int ukfs_lutimes(struct ukfs *, const char *, struct mount *ukfs_getmp(struct ukfs *); struct vnode *ukfs_getrvp(struct ukfs *); +/* dynamic loading of library modules */ +int ukfs_modload(const char *); +int ukfs_modload_dir(const char *); + /* Utilities */ int ukfs_util_builddirs(struct ukfs *, const char *, mode_t); |
