Skip to content

Commit

Permalink
New service that waits on zvol links to be created
Browse files Browse the repository at this point in the history
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 openzfs#8975
  • Loading branch information
pzakha authored and TulsiJain committed Jul 20, 2019
1 parent 9381a37 commit 9719379
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 3 deletions.
2 changes: 1 addition & 1 deletion cmd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions cmd/zvol_wait/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist_bin_SCRIPTS = zvol_wait
93 changes: 93 additions & 0 deletions cmd/zvol_wait/zvol_wait
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions etc/systemd/system/50-zfs.preset.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions etc/systemd/system/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 = \
Expand All @@ -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

Expand Down
13 changes: 13 additions & 0 deletions etc/systemd/system/zfs-volume-wait.service.in
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions etc/systemd/system/zfs-volumes.target.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Unit]
Description=ZFS volumes are ready
After=zfs-volume-wait.service
Requires=zfs-volume-wait.service

[Install]
WantedBy=zfs.target
2 changes: 1 addition & 1 deletion man/man1/Makefile.am
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
21 changes: 21 additions & 0 deletions man/man1/zvol_wait.1
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion rpm/generic/zfs.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 9719379

Please sign in to comment.