summaryrefslogtreecommitdiffstats
path: root/lib/libzfs/libzfs_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libzfs/libzfs_util.c')
-rw-r--r--lib/libzfs/libzfs_util.c70
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);
}