]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Add kernel module auto-loading
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 13 Mar 2018 17:45:55 +0000 (10:45 -0700)
committerGitHub <noreply@github.com>
Tue, 13 Mar 2018 17:45:55 +0000 (10:45 -0700)
Historically a dynamic misc minor number was registered for the
/dev/zfs device in order to prevent minor number collisions.  This
was fine but it prevented us from being able to use the kernel
module auto-loaded which requires a known reserved value.

Resolve this issue by adding a configure test to find an available
misc minor number which can then be used in MODULE_ALIAS_MISCDEV at
build time.  By adding this alias the zfs kmod is added to the list
of known static-nodes and the systemd-tmpfiles-setup-dev service
will create a /dev/zfs character device at boot time.

This in turn allows us to update the 90-zfs.rules file to make it
aware this is a static node.  The upshot of this is that whenever
a process (zpool, zfs, zed) opens the /dev/zfs the kmods will be
automatic loaded.  This even works for unprivileged users so there
is no longer a need to manually load the modules at boot time.

As an additional bonus the zed now no longer needs to start after
the zfs-import.service since it will trigger the module load.

In the unlikely event the minor number we selected conflicts with
another out of tree unregistered minor number the code falls back
to dynamically allocating it.  In this case the modules again
must be manually loaded.

Note that due to the change in the method of registering the minor
number the zimport.sh test case may incorrectly fail when the
static node for the installed packages is created instead of the
dynamic one.  This issue will only transiently impact zimport.sh
for this single commit when we transition and are mixing and
matching methods.

Reviewed-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
TEST_ZIMPORT_SKIP="yes"
Closes #7287

config/kernel-misc-minor.m4 [new file with mode: 0644]
config/kernel.m4
etc/modules-load.d/zfs.conf.in
etc/systemd/system/zfs-import-cache.service.in
etc/systemd/system/zfs-import-scan.service.in
etc/systemd/system/zfs-zed.service.in
lib/libzfs/libzfs_util.c
module/zfs/zfs_ioctl.c
rpm/generic/zfs.spec.in
udev/rules.d/90-zfs.rules.in

diff --git a/config/kernel-misc-minor.m4 b/config/kernel-misc-minor.m4
new file mode 100644 (file)
index 0000000..3917e28
--- /dev/null
@@ -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.])
+       ])
+])
index b80e57b1c03782ffdb3defb0ec5f8bd1ee42b7f7..1887b178c0d2b00c7db4428d21d031d9f2fec629 100644 (file)
@@ -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
index 8b41baa300cbfb80f1b68d324a993e683670ec45..44e1bb3ed906b18eaafb6376471380b669590357 100644 (file)
@@ -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
index 23c725d7131515b5173538ff413962d81cb2f064..44c26802b1107295f4fac76e9d411cb3bfe27902 100644 (file)
@@ -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}')"
 
index 851d96cbc978b354c5f74ecb0cff96b7c857fce1..44a50a76b6038a9a438d495a1410fe32d43291ed 100644 (file)
@@ -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}')"
 
index 31751500302def448a979a54c5c08c934043027b..f4313625ee5eccd216c9654197c8bc958b5ff426 100644 (file)
@@ -1,7 +1,6 @@
 [Unit]
 Description=ZFS Event Daemon (zed)
 Documentation=man:zed(8)
-After=zfs-import.target
 
 [Service]
 ExecStart=@sbindir@/zed -F
index ee8d09b118b8c0b60b864e32d6952608ee9755cf..6b9cfc27201b571f39bb585748e9e6452b371877 100644 (file)
@@ -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
index 994b3af36c1f693919f4c3e345cfc409a391245c..92bdec4b960038a4ea3b11078cc1384bdbc4b692 100644 (file)
@@ -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
index 27a2424df898e8f812e863ccf1f88ce2a8c2299e..52dc80a4ef95be85c7005c90ce3ab1663c8898e4 100644 (file)
@@ -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}
index 855c154040f5a9b17fe67c8d6e22f15c1f0cf3d3..82f8cf1cf5ec2877f925592fa76367925336fe6a 100644 (file)
@@ -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"