]> granicus.if.org Git - zfs/commitdiff
Make commands load zfs module on demand
authorNed Bass <bass6@llnl.gov>
Thu, 7 Oct 2010 01:00:55 +0000 (18:00 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 11 Oct 2010 19:22:36 +0000 (12:22 -0700)
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 <behlendorf1@llnl.gov>
lib/libzfs/libzfs_util.c

index 3c4fae5aa29a23db2e98c7b2d6ae1c907ec4542b..d72b7c0fcdfb4bbaded5b77dd764fc9f05ea79e3 100644 (file)
@@ -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);
        }