diff --git a/cmd/mount_zfs/mount_zfs.c b/cmd/mount_zfs/mount_zfs.c index 6cdb668f54..0f4995943c 100644 --- a/cmd/mount_zfs/mount_zfs.c +++ b/cmd/mount_zfs/mount_zfs.c @@ -473,8 +473,10 @@ main(int argc, char **argv) if (zfsflags & ZS_ZFSUTIL) zfsutil = 1; - if ((g_zfs = libzfs_init()) == NULL) + if ((g_zfs = libzfs_init()) == NULL) { + (void) fprintf(stderr, "%s", libzfs_error_init(errno)); return (MOUNT_SYSERR); + } /* try to open the dataset to access the mount point */ if ((zhp = zfs_open(g_zfs, dataset, diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index fc6e3fff0c..6e75d0c216 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -3699,8 +3699,10 @@ main(int argc, char **argv) zfs_vdev_async_read_max_active = 10; kernel_init(FREAD); - if ((g_zfs = libzfs_init()) == NULL) + if ((g_zfs = libzfs_init()) == NULL) { + (void) fprintf(stderr, "%s", libzfs_error_init(errno)); return (1); + } if (dump_all) verbose = MAX(verbose, 1); diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 32b9239b7d..cd3bab9e17 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -6708,8 +6708,10 @@ main(int argc, char **argv) (strcmp(cmdname, "--help") == 0)) usage(B_TRUE); - if ((g_zfs = libzfs_init()) == NULL) + if ((g_zfs = libzfs_init()) == NULL) { + (void) fprintf(stderr, "%s", libzfs_error_init(errno)); return (1); + } mnttab_file = g_zfs->libzfs_mnttab; diff --git a/cmd/zinject/zinject.c b/cmd/zinject/zinject.c index f6c89159e5..f64e504627 100644 --- a/cmd/zinject/zinject.c +++ b/cmd/zinject/zinject.c @@ -572,8 +572,10 @@ main(int argc, char **argv) int ret; int flags = 0; - if ((g_zfs = libzfs_init()) == NULL) + if ((g_zfs = libzfs_init()) == NULL) { + (void) fprintf(stderr, "%s", libzfs_error_init(errno)); return (1); + } libzfs_print_on_error(g_zfs, B_TRUE); diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index bf323ee087..5c28e8bb13 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -5919,8 +5919,10 @@ main(int argc, char **argv) if ((strcmp(cmdname, "-?") == 0) || strcmp(cmdname, "--help") == 0) usage(B_TRUE); - if ((g_zfs = libzfs_init()) == NULL) + if ((g_zfs = libzfs_init()) == NULL) { + (void) fprintf(stderr, "%s", libzfs_error_init(errno)); return (1); + } libzfs_print_on_error(g_zfs, B_TRUE); diff --git a/include/libzfs.h b/include/libzfs.h index c4e30c5d4d..db8ee7167e 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -203,6 +203,7 @@ extern void zfs_save_arguments(int argc, char **, char *, int); extern int zpool_log_history(libzfs_handle_t *, const char *); extern int libzfs_errno(libzfs_handle_t *); +extern const char *libzfs_error_init(int); extern const char *libzfs_error_action(libzfs_handle_t *); extern const char *libzfs_error_description(libzfs_handle_t *); extern int zfs_standard_error(libzfs_handle_t *, int, const char *); @@ -749,7 +750,6 @@ extern int zfs_nicestrtonum(libzfs_handle_t *, const char *, uint64_t *); #define STDERR_VERBOSE 0x02 int libzfs_run_process(const char *, char **, int flags); -int libzfs_load_module(const char *); /* * Given a device or file, determine if it is part of a pool. diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 9d68756bec..678eeadc04 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -58,6 +58,31 @@ libzfs_errno(libzfs_handle_t *hdl) return (hdl->libzfs_error); } +const char * +libzfs_error_init(int error) +{ + switch (error) { + case ENXIO: + return (dgettext(TEXT_DOMAIN, "The ZFS modules are not " + "loaded.\nTry running '/sbin/modprobe zfs' as root " + "to load them.\n")); + case ENOENT: + return (dgettext(TEXT_DOMAIN, "The /dev/zfs device is " + "missing and must be created.\nTry running 'udevadm " + "trigger' as root to create it.\n")); + case ENOEXEC: + return (dgettext(TEXT_DOMAIN, "The ZFS modules cannot be " + "auto-loaded.\nTry running '/sbin/modprobe zfs' as " + "root to manually load them.\n")); + case EACCES: + return (dgettext(TEXT_DOMAIN, "Permission denied the " + "ZFS utilities must be run as root.\n")); + default: + return (dgettext(TEXT_DOMAIN, "Failed to initialize the " + "libzfs library.\n")); + } +} + const char * libzfs_error_action(libzfs_handle_t *hdl) { @@ -628,7 +653,7 @@ int libzfs_run_process(const char *path, char *argv[], int flags) { pid_t pid; - int rc, devnull_fd; + int error, devnull_fd; pid = vfork(); if (pid == 0) { @@ -650,9 +675,9 @@ libzfs_run_process(const char *path, char *argv[], int flags) } else if (pid > 0) { int status; - while ((rc = waitpid(pid, &status, 0)) == -1 && + while ((error = waitpid(pid, &status, 0)) == -1 && errno == EINTR); - if (rc < 0 || !WIFEXITED(status)) + if (error < 0 || !WIFEXITED(status)) return (-1); return (WEXITSTATUS(status)); @@ -670,7 +695,7 @@ libzfs_run_process(const char *path, char *argv[], int flags) * - ZFS_MODULE_LOADING="YES|yes|ON|on" - Attempt to load modules. * - ZFS_MODULE_TIMEOUT="" - Seconds to wait for ZFS_DEV */ -int +static int libzfs_load_module(const char *module) { char *argv[4] = {"/sbin/modprobe", "-q", (char *)module, (char *)0}; @@ -739,9 +764,7 @@ libzfs_init(void) error = libzfs_load_module(ZFS_DRIVER); if (error) { - (void) fprintf(stderr, gettext("Failed to load ZFS module " - "stack.\nLoad the module manually by running " - "'insmod /zfs.ko' as root.\n")); + errno = error; return (NULL); } @@ -750,13 +773,6 @@ libzfs_init(void) } if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) { - (void) fprintf(stderr, gettext("Unable to open %s: %s.\n"), - ZFS_DEV, strerror(errno)); - if (errno == ENOENT) - (void) fprintf(stderr, - gettext("Verify the ZFS module stack is " - "loaded by running '/sbin/modprobe zfs'.\n")); - free(hdl); return (NULL); } @@ -767,8 +783,6 @@ libzfs_init(void) if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) { #endif (void) close(hdl->libzfs_fd); - (void) fprintf(stderr, - gettext("mtab is not present at %s.\n"), MNTTAB); free(hdl); return (NULL); }