Add canonical mount options zfs-mount-generator

lib/libzfs/libzfs_mount.c:zfs_add_options provides the canonical
mount options used by a `zfs mount` command. Because we cannot call
`zfs mount` directly from a systemd.mount unit, we mirror that logic
in zfs-mount-generator.

The zed script is updated to cache these properties as well.

Include a mini-tutorial in the manual page, properly substitute
configuration paths in zfs-mount-generator.8.in, and standardize the
Makefile.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Richard Laager <rlaager@wiktel.com>
Signed-off-by: Antonio Russo <antonio.e.russo@gmail.com>
Closes #7453
This commit is contained in:
Antonio Russo 2018-05-11 15:44:14 -04:00 committed by Brian Behlendorf
parent 29badadd4e
commit 68fded8146
4 changed files with 146 additions and 38 deletions

View File

@ -44,9 +44,10 @@ case "${ZEVENT_HISTORY_INTERNAL_NAME}" in
;; ;;
set|inherit) set|inherit)
# Only act if the mountpoint or canmount setting is altered. # Only act if one of the tracked properties is altered.
case "${ZEVENT_HISTORY_INTERNAL_STR}" in case "${ZEVENT_HISTORY_INTERNAL_STR%%=*}" in
canmount=*|mountpoint=*) ;; canmount|mountpoint|atime|relatime|devices|exec| \
readonly|setuid|nbmand) ;;
*) exit 0 ;; *) exit 0 ;;
esac esac
;; ;;
@ -60,8 +61,10 @@ esac
zed_lock zfs-list zed_lock zfs-list
trap abort_alter EXIT trap abort_alter EXIT
"${ZFS}" list -H -tfilesystem -oname,mountpoint,canmount -r "${ZEVENT_POOL}" \ PROPS="name,mountpoint,canmount,atime,relatime,devices,exec,readonly"
>"${FSLIST_TMP}" PROPS="${PROPS},setuid,nbmand"
"${ZFS}" list -H -t filesystem -o $PROPS -r "${ZEVENT_POOL}" > "${FSLIST_TMP}"
# Sort the output so that it is stable # Sort the output so that it is stable
sort "${FSLIST_TMP}" -o "${FSLIST_TMP}" sort "${FSLIST_TMP}" -o "${FSLIST_TMP}"

View File

@ -49,38 +49,123 @@ req_dir="${dest_norm}/local-fs.target.wants/"
mkdir -p "${req_dir}" mkdir -p "${req_dir}"
# All needed information about each ZFS is available from # All needed information about each ZFS is available from
# zfs list -H -t filesystem -oname,mountpoint,canmount # zfs list -H -t filesystem -o <properties>
# cached in $FSLIST, and each line is processed by the following function: # cached in $FSLIST, and each line is processed by the following function:
# See the list below for the properties and their order
process_line() { process_line() {
# -o name
dataset="${1}"
p_mountpoint="${2}"
p_canmount="${3}"
p_atime="${4}"
p_relatime="${5}"
p_devices="${6}"
p_exec="${7}"
p_readonly="${8}"
p_setuid="${9}"
p_nbmand="${10}"
# Check for canmount=off . # Check for canmount=off .
if [ "${3}" = "off" ] ; then if [ "${p_canmount}" = "off" ] ; then
return return
elif [ "${3}" = "noauto" ] ; then elif [ "${p_canmount}" = "noauto" ] ; then
# Don't let a noauto marked mountpoint block an "auto" market mountpoint # Don't let a noauto marked mountpoint block an "auto" market mountpoint
return return
elif [ "${3}" = "on" ] ; then elif [ "${p_canmount}" = "on" ] ; then
: # This is OK : # This is OK
else else
do_fail "invalid canmount" do_fail "invalid canmount"
fi fi
# Check for legacy and blank mountpoints. # Check for legacy and blank mountpoints.
if [ "${2}" = "legacy" ] ; then if [ "${p_mountpoint}" = "legacy" ] ; then
return return
elif [ "${2}" = "none" ] ; then elif [ "${p_mountpoint}" = "none" ] ; then
return return
elif [ "${2%"${2#?}"}" != "/" ] ; then elif [ "${p_mountpoint%"${p_mountpoint#?}"}" != "/" ] ; then
do_fail "invalid mountpoint $*" do_fail "invalid mountpoint $*"
fi fi
# Escape the mountpoint per systemd policy. # Escape the mountpoint per systemd policy.
mountfile="$(systemd-escape "${2#?}").mount" mountfile="$(systemd-escape "${p_mountpoint#?}").mount"
# Parse options
# see lib/libzfs/libzfs_mount.c:zfs_add_options
opts=""
# atime
if [ "${p_atime}" = on ] ; then
# relatime
if [ "${p_relatime}" = on ] ; then
opts="${opts},atime,relatime"
elif [ "${p_relatime}" = off ] ; then
opts="${opts},atime,strictatime"
else
printf 'zfs-mount-generator.sh: (%s) invalid relatime\n' \
"${dataset}" >/dev/kmsg
fi
elif [ "${p_atime}" = off ] ; then
opts="${opts},noatime"
else
printf 'zfs-mount-generator.sh: (%s) invalid atime\n' \
"${dataset}" >/dev/kmsg
fi
# devices
if [ "${p_devices}" = on ] ; then
opts="${opts},dev"
elif [ "${p_devices}" = off ] ; then
opts="${opts},nodev"
else
printf 'zfs-mount-generator.sh: (%s) invalid devices\n' \
"${dataset}" >/dev/kmsg
fi
# exec
if [ "${p_exec}" = on ] ; then
opts="${opts},exec"
elif [ "${p_exec}" = off ] ; then
opts="${opts},noexec"
else
printf 'zfs-mount-generator.sh: (%s) invalid exec\n' \
"${dataset}" >/dev/kmsg
fi
# readonly
if [ "${p_readonly}" = on ] ; then
opts="${opts},ro"
elif [ "${p_readonly}" = off ] ; then
opts="${opts},rw"
else
printf 'zfs-mount-generator.sh: (%s) invalid readonly\n' \
"${dataset}" >/dev/kmsg
fi
# setuid
if [ "${p_setuid}" = on ] ; then
opts="${opts},suid"
elif [ "${p_setuid}" = off ] ; then
opts="${opts},nosuid"
else
printf 'zfs-mount-generator.sh: (%s) invalid setuid\n' \
"${dataset}" >/dev/kmsg
fi
# nbmand
if [ "${p_nbmand}" = on ] ; then
opts="${opts},mand"
elif [ "${p_nbmand}" = off ] ; then
opts="${opts},nomand"
else
printf 'zfs-mount-generator.sh: (%s) invalid nbmand\n' \
"${dataset}" >/dev/kmsg
fi
# If the mountpoint has already been created, give it precedence. # If the mountpoint has already been created, give it precedence.
if [ -e "${dest_norm}/${mountfile}" ] ; then if [ -e "${dest_norm}/${mountfile}" ] ; then
printf 'zfs-mount-generator.sh: %s.mount already exists\n' "${2}" \ printf 'zfs-mount-generator.sh: %s already exists\n' "${mountfile}" \
>/dev/kmsg >/dev/kmsg
return return
fi fi
@ -97,14 +182,14 @@ After=zfs-import.target
Wants=zfs-import.target Wants=zfs-import.target
[Mount] [Mount]
Where=${2} Where=${p_mountpoint}
What=${1} What=${dataset}
Type=zfs Type=zfs
Options=zfsutil,auto Options=defaults${opts},zfsutil
EOF EOF
# Finally, create the appropriate dependencies based on the ZFS properties. # Finally, create the appropriate dependency
[ "$3" = "on" ] & ln -s "../${mountfile}" "${req_dir}" ln -s "../${mountfile}" "${req_dir}"
} }
# Feed each line into process_line # Feed each line into process_line

View File

@ -4,7 +4,6 @@ dist_man_MANS = \
vdev_id.8 \ vdev_id.8 \
zdb.8 \ zdb.8 \
zfs.8 \ zfs.8 \
zfs-mount-generator.8 \
zfs-program.8 \ zfs-program.8 \
zgenhostid.8 \ zgenhostid.8 \
zinject.8 \ zinject.8 \
@ -12,24 +11,18 @@ dist_man_MANS = \
zstreamdump.8 zstreamdump.8
nodist_man_MANS = \ nodist_man_MANS = \
zed.8 zed.8 \
zfs-mount-generator.8
EXTRA_DIST = \ EXTRA_DIST = \
zed.8.in zed.8.in \
zfs-mount-generator.8.in
zed.8: $(srcdir)/zed.8.in $(nodist_man_MANS): %: %.in
-$(SED) -e 's,@libexecdir\@,$(libexecdir),g' \
do_subst = $(SED) \ -e 's,@runstatedir\@,$(runstatedir),g' \
-e 's|@libexecdir[@]|$(libexecdir)|g' \ -e 's,@sysconfdir\@,$(sysconfdir),g' \
-e 's|@runstatedir[@]|$(runstatedir)|g' \ $< >'$@'
-e 's|@sysconfdir[@]|$(sysconfdir)|g'
$(nodist_man_MANS): Makefile
$(RM) $@ $@.tmp
srcdir=''; \
test -f ./$@.in || srcdir=$(srcdir)/; \
$(do_subst) $${srcdir}$@.in >$@.tmp
mv $@.tmp $@
install-data-local: install-data-local:
$(INSTALL) -d -m 0755 "$(DESTDIR)$(mandir)/man8" $(INSTALL) -d -m 0755 "$(DESTDIR)$(mandir)/man8"

View File

@ -1,11 +1,11 @@
.TH "ZFS\-MOUNT\-GENERATOR" "8" "ZFS" "zfs-mount-generator" "\"" .TH "ZFS\-MOUNT\-GENERATOR" "8" "ZFS" "zfs-mount-generator" "\""
.SH "NAME" .SH "NAME"
zfs\-mount\-generator \- generates systemd mount units for zfs zfs\-mount\-generator \- generates systemd mount units for ZFS
.SH SYNOPSIS .SH SYNOPSIS
.B /lib/systemd/system-generators/zfs\-mount\-generator .B /lib/systemd/system-generators/zfs\-mount\-generator
.sp .sp
.SH DESCRIPTION .SH DESCRIPTION
The zfs\-mount\-generator implements the \fBGenerators Specification\fP zfs\-mount\-generator implements the \fBGenerators Specification\fP
of of
.BR systemd (1), .BR systemd (1),
and is called during early boot to generate and is called during early boot to generate
@ -26,7 +26,7 @@ information on ZFS mountpoints must be stored separately. The output
of the command of the command
.PP .PP
.RS 4 .RS 4
zfs list -H -oname,mountpoint,canmount zfs list -H -o name,mountpoint,canmount,atime,relatime,devices,exec,readonly,setuid,nbmand
.RE .RE
.PP .PP
for datasets that should be mounted by systemd, should be kept for datasets that should be mounted by systemd, should be kept
@ -45,6 +45,33 @@ history_event-zfs-list-cacher.sh .
.RE .RE
.PP .PP
.sp .sp
.SH EXAMPLE
To begin, enable tracking for the pool:
.PP
.RS 4
touch
.RI @sysconfdir@/zfs/zfs-list.cache/ POOLNAME
.RE
.PP
Then, enable the tracking ZEDLET:
.PP
.RS 4
ln -s "@libexecdir@/zfs/zed.d/history_event-zfs-list-cacher.sh" "@sysconfdir@/zfs/zed.d/"
systemctl enable zed.service
systemctl restart zed.service
.RE
.PP
Force the running of the ZEDLET by setting canmount=on for at least one dataset in the pool:
.PP
.RS 4
zfs set canmount=on
.I DATASET
.RE
.PP
This forces an update to the stale cache file.
.sp
.SH SEE ALSO .SH SEE ALSO
.BR zfs (5) .BR zfs (5)
.BR zfs-events (5) .BR zfs-events (5)