diff --git a/config/kernel-misc-minor.m4 b/config/kernel-misc-minor.m4 new file mode 100644 index 0000000000..3917e28ff6 --- /dev/null +++ b/config/kernel-misc-minor.m4 @@ -0,0 +1,26 @@ +dnl # +dnl # Determine an available miscellaneous minor number which can be used +dnl # for the /dev/zfs device. This is needed because kernel module +dnl # auto-loading depends on registering a reserved non-conflicting minor +dnl # number. Start with a large known available unreserved minor and work +dnl # our way down to lower value if a collision is detected. +dnl # +AC_DEFUN([ZFS_AC_KERNEL_MISC_MINOR], [ + AC_MSG_CHECKING([for available /dev/zfs minor]) + + for i in $(seq 249 -1 200); do + if ! grep -q "^#define\s\+.*_MINOR\s\+.*$i" \ + ${LINUX}/include/linux/miscdevice.h; then + ZFS_MINOR="$i" + AC_MSG_RESULT($ZFS_MINOR) + AC_DEFINE_UNQUOTED([ZFS_MINOR], [$ZFS_MINOR], + [/dev/zfs minor]) + break + fi + done + + AS_IF([ test -z "$ZFS_MINOR"], [ + AC_MSG_ERROR([ + *** No available misc minor numbers available for use.]) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index b80e57b1c0..1887b178c0 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -6,6 +6,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ ZFS_AC_SPL ZFS_AC_QAT ZFS_AC_TEST_MODULE + ZFS_AC_KERNEL_MISC_MINOR ZFS_AC_KERNEL_OBJTOOL ZFS_AC_KERNEL_CONFIG ZFS_AC_KERNEL_DECLARE_EVENT_CLASS diff --git a/etc/modules-load.d/zfs.conf.in b/etc/modules-load.d/zfs.conf.in index 8b41baa300..44e1bb3ed9 100644 --- a/etc/modules-load.d/zfs.conf.in +++ b/etc/modules-load.d/zfs.conf.in @@ -1,3 +1,3 @@ -# Always load kernel modules at boot. The default behavior is to load the -# kernel modules in the zfs-import-*.service or when blkid(8) detects a pool. +# The default behavior is to allow udev to load the kernel modules on demand. +# Uncomment the following line to unconditionally load them at boot. #zfs diff --git a/etc/systemd/system/zfs-import-cache.service.in b/etc/systemd/system/zfs-import-cache.service.in index 23c725d713..44c26802b1 100644 --- a/etc/systemd/system/zfs-import-cache.service.in +++ b/etc/systemd/system/zfs-import-cache.service.in @@ -12,7 +12,6 @@ ConditionPathExists=@sysconfdir@/zfs/zpool.cache [Service] Type=oneshot RemainAfterExit=yes -ExecStartPre=-/sbin/modprobe zfs ExecStart=@sbindir@/zpool import -c @sysconfdir@/zfs/zpool.cache -aN ExecStartPost=/bin/bash -c "/bin/systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | /bin/awk '$1 != \"-\" {print; exit}')" diff --git a/etc/systemd/system/zfs-import-scan.service.in b/etc/systemd/system/zfs-import-scan.service.in index 851d96cbc9..44a50a76b6 100644 --- a/etc/systemd/system/zfs-import-scan.service.in +++ b/etc/systemd/system/zfs-import-scan.service.in @@ -11,7 +11,6 @@ ConditionPathExists=!@sysconfdir@/zfs/zpool.cache [Service] Type=oneshot RemainAfterExit=yes -ExecStartPre=-/sbin/modprobe zfs ExecStart=@sbindir@/zpool import -aN -o cachefile=none ExecStartPost=/bin/bash -c "/bin/systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | /bin/awk '$1 != \"-\" {print; exit}')" diff --git a/etc/systemd/system/zfs-zed.service.in b/etc/systemd/system/zfs-zed.service.in index 3175150030..f4313625ee 100644 --- a/etc/systemd/system/zfs-zed.service.in +++ b/etc/systemd/system/zfs-zed.service.in @@ -1,7 +1,6 @@ [Unit] Description=ZFS Event Daemon (zed) Documentation=man:zed(8) -After=zfs-import.target [Service] ExecStart=@sbindir@/zed -F diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index ee8d09b118..6b9cfc2720 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -965,13 +965,14 @@ libzfs_load_module(const char *module) load = 0; } - if (load && libzfs_run_process("/sbin/modprobe", argv, 0)) - return (ENOEXEC); - } + if (load) { + if (libzfs_run_process("/sbin/modprobe", argv, 0)) + return (ENOEXEC); - /* Module loading is synchronous it must be available */ - if (!libzfs_module_loaded(module)) - return (ENXIO); + if (!libzfs_module_loaded(module)) + return (ENXIO); + } + } /* * Device creation by udev is asynchronous and waiting may be diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 994b3af36c..92bdec4b96 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -6947,11 +6947,14 @@ static const struct file_operations zfsdev_fops = { }; static struct miscdevice zfs_misc = { - .minor = MISC_DYNAMIC_MINOR, + .minor = ZFS_MINOR, .name = ZFS_DRIVER, .fops = &zfsdev_fops, }; +MODULE_ALIAS_MISCDEV(ZFS_MINOR); +MODULE_ALIAS("devname:zfs"); + static int zfs_attach(void) { @@ -6962,12 +6965,24 @@ zfs_attach(void) zfsdev_state_list->zs_minor = -1; error = misc_register(&zfs_misc); - if (error != 0) { - printk(KERN_INFO "ZFS: misc_register() failed %d\n", error); - return (error); + if (error == -EBUSY) { + /* + * Fallback to dynamic minor allocation in the event of a + * collision with a reserved minor in linux/miscdevice.h. + * In this case the kernel modules must be manually loaded. + */ + printk(KERN_INFO "ZFS: misc_register() with static minor %d " + "failed %d, retrying with MISC_DYNAMIC_MINOR\n", + ZFS_MINOR, error); + + zfs_misc.minor = MISC_DYNAMIC_MINOR; + error = misc_register(&zfs_misc); } - return (0); + if (error) + printk(KERN_INFO "ZFS: misc_register() failed %d\n", error); + + return (error); } static void diff --git a/rpm/generic/zfs.spec.in b/rpm/generic/zfs.spec.in index 27a2424df8..52dc80a4ef 100644 --- a/rpm/generic/zfs.spec.in +++ b/rpm/generic/zfs.spec.in @@ -284,6 +284,15 @@ fi %endif exit 0 +# On RHEL/CentOS 7 the static nodes aren't refreshed by default after +# installing a package. This is the default behavior for Fedora. +%posttrans +%if 0%{?rhel} == 7 || 0%{?centos} == 7 +systemctl restart kmod-static-nodes +systemctl restart systemd-tmpfiles-setup-dev +udevadm trigger +%endif + %preun %if 0%{?_systemd} %if 0%{?systemd_preun:1} diff --git a/udev/rules.d/90-zfs.rules.in b/udev/rules.d/90-zfs.rules.in index 855c154040..82f8cf1cf5 100644 --- a/udev/rules.d/90-zfs.rules.in +++ b/udev/rules.d/90-zfs.rules.in @@ -7,6 +7,6 @@ ENV{ID_FS_TYPE}=="zfs_member", RUN+="/sbin/modprobe zfs" KERNEL=="null", SYMLINK+="root" SYMLINK=="null", SYMLINK+="root" -SUBSYSTEM=="misc", KERNEL=="zfs", MODE="0666" +KERNEL=="zfs", MODE="0666", OPTIONS+="static_node=zfs" LABEL="zfs_end"