diff options
author | Ned Bass <[email protected]> | 2010-10-06 18:00:55 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2010-10-11 12:22:36 -0700 |
commit | 4b1abce9f5c20e298ddaa3368b3fb6a529c71459 (patch) | |
tree | 339482333841bbbb106debffa9ff3373f186fe13 | |
parent | 83c62c939938ca5915a61022208a31c4ab3faa1c (diff) |
Make commands load zfs module on demand
This commit modifies libzfs_init() to attempt to load the zfs kernel module if
it is not already loaded. This is done to simplify initialization by letting
users simply import their zpools without having to first load the module.
Signed-off-by: Brian Behlendorf <[email protected]>
-rw-r--r-- | lib/libzfs/libzfs_util.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 3c4fae5aa..d72b7c0fc 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -40,6 +40,7 @@ #include <sys/mnttab.h> #include <sys/mntent.h> #include <sys/types.h> +#include <wait.h> #include <libzfs.h> @@ -604,11 +605,80 @@ libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) hdl->libzfs_printerr = printerr; } +static int +libzfs_module_loaded(const char *module) +{ + FILE *f; + int result = 0; + char name[256]; + + f = fopen("/proc/modules", "r"); + if (f == NULL) + return -1; + + while (fgets(name, sizeof(name), f)) { + char *c = strchr(name, ' '); + if (!c) + continue; + *c = 0; + if (strcmp(module, name) == 0) { + result = 1; + break; + } + } + fclose(f); + + return result; +} + +static int +libzfs_run_process(const char *path, char *argv[]) +{ + pid_t pid; + int rc; + + pid = vfork(); + if (pid == 0) { + close(1); + close(2); + (void) execvp(path, argv); + _exit(-1); + } else if (pid > 0) { + int status; + + while ((rc = waitpid(pid, &status, 0)) == -1 && + errno == EINTR); + if (rc < 0 || !WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); + } + + return -1; +} + +static int +libzfs_load_module(const char *module) +{ + char *argv[4] = {"/sbin/modprobe", "-q", (char *)module, (char *)0}; + + if (libzfs_module_loaded(module)) + return 0; + return libzfs_run_process("modprobe", argv); +} + libzfs_handle_t * libzfs_init(void) { libzfs_handle_t *hdl; + if (libzfs_load_module("zfs") != 0) { + (void) fprintf(stderr, gettext("Failed to load ZFS module " + "stack.\nLoad the module manually by running " + "'insmod <location>/zfs.ko' as root.\n")); + return (NULL); + } + if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) { return (NULL); } |