Skip to content

Commit

Permalink
Fix a dependency loop
Browse files Browse the repository at this point in the history
When generating units with zfs-mount-generator, if the pool is already
imported, zfs-import.target is not needed.  This avoids a dependency
loop on root-on-ZFS systems:
  systemd-random-seed.service After (via RequiresMountsFor)
  var-lib.mount After
  zfs-import.target After
  zfs-import-{cache,scan}.service After
  cryptsetup.service After
  systemd-random-seed.service

Reviewed-by: Antonio Russo <antonio.e.russo@gmail.com>
Reviewed-by: InsanePrawn <insane.prawny@gmail.com>
Signed-off-by: Richard Laager <rlaager@wiktel.com>
Closes #10388
  • Loading branch information
rlaager authored and behlendorf committed Aug 28, 2020
1 parent 7ddcfe7 commit ec41caf
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 7 deletions.
31 changes: 25 additions & 6 deletions etc/systemd/system-generators/zfs-mount-generator.in
Expand Up @@ -38,8 +38,6 @@ do_fail() {
is_known() {
query="$1"
IFS=' '
# protect against special characters
set -f
for element in $2 ; do
if [ "$query" = "$element" ] ; then
return 0
Expand All @@ -54,8 +52,7 @@ is_known() {
create_dependencies() {
unitfile="$1"
suffix="$2"
# protect against special characters
set -f
IFS=' '
for target in $3 ; do
target_dir="${dest_norm}/${target}.${suffix}/"
mkdir -p "${target_dir}"
Expand All @@ -72,6 +69,7 @@ else
do_fail "zero or three arguments required"
fi

pools=$(zpool list -H -o name || true)

# All needed information about each ZFS is available from
# zfs list -H -t filesystem -o <properties>
Expand All @@ -83,11 +81,11 @@ process_line() {
# zfs list -H -o name,...
# fields are tab separated
IFS="$(printf '\t')"
# protect against special characters in, e.g., mountpoints
set -f
# shellcheck disable=SC2086
set -- $1

dataset="${1}"
pool="${dataset%%/*}"
p_mountpoint="${2}"
p_canmount="${3}"
p_atime="${4}"
Expand Down Expand Up @@ -120,6 +118,25 @@ process_line() {
requiredby=""
noauto="off"

# If the pool is already imported, zfs-import.target is not needed. This
# avoids a dependency loop on root-on-ZFS systems:
# systemd-random-seed.service After (via RequiresMountsFor) var-lib.mount
# After zfs-import.target After zfs-import-{cache,scan}.service After
# cryptsetup.service After systemd-random-seed.service.
#
# Pools are newline-separated and may contain spaces in their names.
# There is no better portable way to set IFS to just a newline. Using
# $(printf '\n') doesn't work because $(...) strips trailing newlines.
IFS="
"
for p in $pools ; do
if [ "$p" = "$pool" ] ; then
after=""
wants=""
break
fi
done

if [ -n "${p_systemd_after}" ] && \
[ "${p_systemd_after}" != "-" ] ; then
after="${p_systemd_after} ${after}"
Expand Down Expand Up @@ -438,6 +455,8 @@ Options=defaults${opts},zfsutil" > "${dest_norm}/${mountfile}"
}

for cachefile in "${FSLIST}/"* ; do
# Disable glob expansion to protect against special characters when parsing.
set -f
# Sort cachefile's lines by canmount, "on" before "noauto"
# and feed each line into process_line
sort -t "$(printf '\t')" -k 3 -r "${cachefile}" | \
Expand Down
1 change: 0 additions & 1 deletion etc/systemd/system/zfs-mount.service.in
Expand Up @@ -6,7 +6,6 @@ After=systemd-udev-settle.service
After=zfs-import.target
After=systemd-remount-fs.service
Before=local-fs.target
Before=systemd-random-seed.service
ConditionPathIsDirectory=/sys/module/zfs

[Service]
Expand Down

0 comments on commit ec41caf

Please sign in to comment.