]> git.proxmox.com Git - mirror_zfs.git/commitdiff
New service that waits on zvol links to be created
authorPavel Zakharov <pavel.zakharov@delphix.com>
Wed, 17 Jul 2019 22:33:05 +0000 (18:33 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 17 Jul 2019 22:33:05 +0000 (15:33 -0700)
The zfs-volume-wait.service scans existing zvols and waits for their
links under /dev to be created. Any service that depends on zvol
links to be there should add a dependency on zfs-volumes.target.
By default, this target is not enabled.

Reviewed-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
Reviewed-by: Antonio Russo <antonio.e.russo@gmail.com>
Reviewed-by: Richard Laager <rlaager@wiktel.com>
Reviewed-by: loli10K <ezomori.nozomu@gmail.com>
Reviewed-by: John Gallagher <john.gallagher@delphix.com>
Reviewed-by: George Wilson <gwilson@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Pavel Zakharov <pzakharov@delphix.com>
Closes #8975

cmd/Makefile.am
cmd/zvol_wait/Makefile.am [new file with mode: 0644]
cmd/zvol_wait/zvol_wait [new file with mode: 0755]
configure.ac
etc/systemd/system/50-zfs.preset.in
etc/systemd/system/Makefile.am
etc/systemd/system/zfs-volume-wait.service.in [new file with mode: 0644]
etc/systemd/system/zfs-volumes.target.in [new file with mode: 0644]
man/man1/Makefile.am
man/man1/zvol_wait.1 [new file with mode: 0644]
rpm/generic/zfs.spec.in

index 0d990789b0c6bcb4fe802d2937aab9c234cf73c3..88609e455f2b62e148c5573caa896acfa8cc97fb 100644 (file)
@@ -5,4 +5,4 @@ if USING_PYTHON
 SUBDIRS += arcstat arc_summary dbufstat
 endif
 
-SUBDIRS += mount_zfs zed zvol_id
+SUBDIRS += mount_zfs zed zvol_id zvol_wait
diff --git a/cmd/zvol_wait/Makefile.am b/cmd/zvol_wait/Makefile.am
new file mode 100644 (file)
index 0000000..564031c
--- /dev/null
@@ -0,0 +1 @@
+dist_bin_SCRIPTS = zvol_wait
diff --git a/cmd/zvol_wait/zvol_wait b/cmd/zvol_wait/zvol_wait
new file mode 100755 (executable)
index 0000000..d512be4
--- /dev/null
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+count_zvols() {
+       if [ -z "$zvols" ]; then
+               echo 0
+       else
+               echo "$zvols" | wc -l
+       fi
+}
+
+filter_out_zvols_with_links() {
+       while read -r zvol; do
+               if [ ! -L "/dev/zvol/$zvol" ]; then
+                       echo "$zvol"
+               fi
+       done
+}
+
+filter_out_deleted_zvols() {
+       while read -r zvol; do
+               if zfs list "$zvol" >/dev/null 2>&1; then
+                       echo "$zvol"
+               fi
+       done
+}
+
+list_zvols() {
+       zfs list -t volume -H -o name,volmode | while read -r zvol_line; do
+               name=$(echo "$zvol_line" | awk '{print $1}')
+               volmode=$(echo "$zvol_line" | awk '{print $2}')
+               # /dev links are not created for zvols with volmode = "none".
+               [ "$volmode" = "none" ] || echo "$name"
+       done
+}
+
+zvols=$(list_zvols)
+zvols_count=$(count_zvols)
+if [ "$zvols_count" -eq 0 ]; then
+       echo "No zvols found, nothing to do."
+       exit 0
+fi
+
+echo "Testing $zvols_count zvol links"
+
+outer_loop=0
+while [ "$outer_loop" -lt 20 ]; do
+       outer_loop=$((outer_loop + 1))
+
+       old_zvols_count=$(count_zvols)
+
+       inner_loop=0
+       while [ "$inner_loop" -lt 30 ]; do
+               inner_loop=$((inner_loop + 1))
+
+               zvols="$(echo "$zvols" | filter_out_zvols_with_links)"
+
+               zvols_count=$(count_zvols)
+               if [ "$zvols_count" -eq 0 ]; then
+                       echo "All zvol links are now present."
+                       exit 0
+               fi
+               sleep 1
+       done
+
+       echo "Still waiting on $zvols_count zvol links ..."
+       #
+       # Although zvols should normally not be deleted at boot time,
+       # if that is the case then their links will be missing and
+       # we would stall.
+       #
+       if [ "$old_zvols_count" -eq "$zvols_count" ]; then
+               echo "No progress since last loop."
+               echo "Checking if any zvols were deleted."
+
+               zvols=$(echo "$zvols" | filter_out_deleted_zvols)
+               zvols_count=$(count_zvols)
+
+               if [ "$old_zvols_count" -ne "$zvols_count" ]; then
+                       echo "$((old_zvols_count - zvols_count)) zvol(s) deleted."
+               fi
+
+               if [ "$zvols_count" -ne 0 ]; then
+                       echo "Remaining zvols:"
+                       echo "$zvols"
+               else
+                       echo "All zvol links are now present."
+                       exit 0
+               fi
+       fi
+done
+
+echo "Timed out waiting on zvol links"
+exit 1
index f1d3ddc20cfaf0bc0a733d15c104bda856788bc2..9e4f8ff1183098993ab9aa8e834317da3f1c683a 100644 (file)
@@ -123,6 +123,7 @@ AC_CONFIG_FILES([
        cmd/zed/zed.d/Makefile
        cmd/raidz_test/Makefile
        cmd/zgenhostid/Makefile
+       cmd/zvol_wait/Makefile
        contrib/Makefile
        contrib/bash_completion.d/Makefile
        contrib/dracut/Makefile
index 884a69b5b68371849000136d2bea0959d5b0ad66..e4056a92cd985380aa7346f4b291e4c3f1446fee 100644 (file)
@@ -5,4 +5,5 @@ enable zfs-import.target
 enable zfs-mount.service
 enable zfs-share.service
 enable zfs-zed.service
+enable zfs-volume-wait.service
 enable zfs.target
index 1586209caa6dd0f4484cc27b6b555fdf30006fd4..9249f15eb45538393b5bb2487f731dfc8d6ca691 100644 (file)
@@ -7,7 +7,9 @@ systemdunit_DATA = \
        zfs-import-scan.service \
        zfs-mount.service \
        zfs-share.service \
+       zfs-volume-wait.service \
        zfs-import.target \
+       zfs-volumes.target \
        zfs.target
 
 EXTRA_DIST = \
@@ -17,6 +19,8 @@ EXTRA_DIST = \
        $(top_srcdir)/etc/systemd/system/zfs-mount.service.in \
        $(top_srcdir)/etc/systemd/system/zfs-share.service.in \
        $(top_srcdir)/etc/systemd/system/zfs-import.target.in \
+       $(top_srcdir)/etc/systemd/system/zfs-volume-wait.service.in \
+       $(top_srcdir)/etc/systemd/system/zfs-volumes.target.in \
        $(top_srcdir)/etc/systemd/system/zfs.target.in \
        $(top_srcdir)/etc/systemd/system/50-zfs.preset.in
 
diff --git a/etc/systemd/system/zfs-volume-wait.service.in b/etc/systemd/system/zfs-volume-wait.service.in
new file mode 100644 (file)
index 0000000..75bd9fc
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=Wait for ZFS Volume (zvol) links in /dev
+DefaultDependencies=no
+After=systemd-udev-settle.service
+After=zfs-import.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=@bindir@/zvol_wait
+
+[Install]
+WantedBy=zfs-volumes.target
diff --git a/etc/systemd/system/zfs-volumes.target.in b/etc/systemd/system/zfs-volumes.target.in
new file mode 100644 (file)
index 0000000..5cb9a10
--- /dev/null
@@ -0,0 +1,7 @@
+[Unit]
+Description=ZFS volumes are ready
+After=zfs-volume-wait.service
+Requires=zfs-volume-wait.service
+
+[Install]
+WantedBy=zfs.target
index bd78be1452a8451673da33b651cd0d9431f8329b..2af917fa5c2efdf63fb5393f0396d14ac694bad6 100644 (file)
@@ -1,4 +1,4 @@
-dist_man_MANS = zhack.1 ztest.1 raidz_test.1
+dist_man_MANS = zhack.1 ztest.1 raidz_test.1 zvol_wait.1
 EXTRA_DIST = cstyle.1
 
 install-data-local:
diff --git a/man/man1/zvol_wait.1 b/man/man1/zvol_wait.1
new file mode 100644 (file)
index 0000000..0366da5
--- /dev/null
@@ -0,0 +1,21 @@
+.Dd July 5, 2019
+.Dt ZVOL_WAIT 1 SMM
+.Os Linux
+.Sh NAME
+.Nm zvol_wait
+.Nd Wait for ZFS volume links in
+.Em /dev
+to be created.
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+When a ZFS pool is imported, ZFS will register each ZFS volume
+(zvol) as a disk device with the system. As the disks are registered,
+.Xr \fBudev 7\fR
+will asynchronously create symlinks under
+.Em /dev/zvol
+using the zvol's name.
+.Nm
+will wait for all those symlinks to be created before returning.
+.Sh SEE ALSO
+.Xr \fBudev 7\fR
index 0864a72a11552081f2c30fc51fe1204ea17b52ab..4fdf7bb69ec7431c019be8338278c590536e6a57 100644 (file)
@@ -322,7 +322,7 @@ image which is ZFS aware.
 
 %if 0%{?_systemd}
     %define systemd --enable-systemd --with-systemdunitdir=%{_unitdir} --with-systemdpresetdir=%{_presetdir} --with-systemdmodulesloaddir=%{_modulesloaddir} --with-systemdgeneratordir=%{_systemdgeneratordir} --disable-sysvinit
-    %define systemd_svcs zfs-import-cache.service zfs-import-scan.service zfs-mount.service zfs-share.service zfs-zed.service zfs.target zfs-import.target
+    %define systemd_svcs zfs-import-cache.service zfs-import-scan.service zfs-mount.service zfs-share.service zfs-zed.service zfs.target zfs-import.target zfs-volume-wait.service zfs-volumes.target
 %else
     %define systemd --enable-sysvinit --disable-systemd
 %endif
@@ -419,6 +419,7 @@ systemctl --system daemon-reload >/dev/null || true
 %{_sbindir}/*
 %{_bindir}/raidz_test
 %{_bindir}/zgenhostid
+%{_bindir}/zvol_wait
 # Optional Python 2/3 scripts
 %{_bindir}/arc_summary
 %{_bindir}/arcstat