Skip to content

Commit

Permalink
Skip snapshot in zfs_iter_mounted()
Browse files Browse the repository at this point in the history
The intention of the zfs_iter_mounted() is to traverse the dataset
and its descendants, not the snapshots. The current code can cause
a mounted snapshot to be included and thus zfs_open() on the snapshot
with ZFS_TYPE_FILESYSTEM would print confusing message such as "cannot
open 'rpool/fs@snap': snapshot delimiter '@' is not expected here".

Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Youzhong Yang <[email protected]>
Closes #12447
Closes #12448
  • Loading branch information
youzhongyang committed Oct 20, 2021
1 parent 1886cdf commit ec64fdb
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 6 deletions.
7 changes: 5 additions & 2 deletions lib/libzfs/libzfs_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,8 +575,11 @@ zfs_iter_mounted(zfs_handle_t *zhp, zfs_iter_f func, void *data)

/* Ignore datasets not within the provided dataset */
if (strncmp(entry.mnt_special, zhp->zfs_name, namelen) != 0 ||
(entry.mnt_special[namelen] != '/' &&
entry.mnt_special[namelen] != '@'))
entry.mnt_special[namelen] != '/')
continue;

/* Skip snapshot of any child dataset */
if (strchr(entry.mnt_special, '@') != NULL)
continue;

if ((mtab_zhp = zfs_open(zhp->zfs_hdl, entry.mnt_special,
Expand Down
50 changes: 50 additions & 0 deletions tests/test-runner/include/logapi.shlib
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ function log_must
(( $? != 0 )) && log_fail
}

# Execute a positive test (expecting no stderr) and exit $STF_FAIL
# if test fails
# $@ - command to execute

function log_must_nostderr
{
log_pos_nostderr "$@"
(( $? != 0 )) && log_fail
}

# Execute a positive test but retry the command on failure if the output
# matches an expected pattern. Otherwise behave like log_must and exit
# $STF_FAIL is test fails.
Expand Down Expand Up @@ -292,6 +302,46 @@ function log_pos
return $status
}

# Execute and print command with status where success equals zero result
# and no stderr output
#
# $@ command to execute
#
# return 0 if command succeeds and no stderr output
# return 1 othersie

function log_pos_nostderr
{
typeset out=""
typeset logfile="/tmp/log.$$"

while [[ -e $logfile ]]; do
logfile="$logfile.$$"
done

"$@" 2>$logfile
typeset status=$?
out="cat $logfile"
typeset out_msg=$($out)

if (( $status != 0 )) ; then
print -u2 $out_msg
_printerror "$@" "exited $status"
else
if [[ ! -z "$out_msg" ]]; then
print -u2 $out_msg
_printerror "$@" "message in stderr" \
" exited $status"
status=1
else
[[ -n $LOGAPI_DEBUG ]] && cat $logfile
_printsuccess "$@"
fi
fi
_recursive_output $logfile "false"
return $status
}

# Set an exit handler
#
# $@ - function(s) to perform on exit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ for d in ${test_depths[@]}; do
log_must zfs snapshot $TESTPOOL/$ds@snap
# force snapshot mount in .zfs
log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap
log_must zfs unmount $TESTPOOL/$ds
log_must_nostderr zfs unmount $TESTPOOL/$ds

if ! ismounted $TESTPOOL/$ds_pre; then
log_fail "$ds_pre is not mounted"
Expand Down Expand Up @@ -113,7 +113,7 @@ for d in ${test_depths[@]}; do
log_must zfs snapshot $TESTPOOL/$ds@snap
# force snapshot mount in .zfs
log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap
log_must zfs unmount $TESTPOOL/$ds
log_must_nostderr zfs unmount $TESTPOOL/$ds

if ! ismounted $TESTPOOL/$ds_pre; then
log_fail "$TESTPOOL/$ds_pre (pre) not mounted"
Expand Down Expand Up @@ -143,7 +143,7 @@ for d in ${test_depths[@]}; do
log_must zfs snapshot $TESTPOOL/$ds@snap
# force snapshot mount in .zfs
log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap
log_must zfs unmount $TESTPOOL/$ds
log_must_nostderr zfs unmount $TESTPOOL/$ds

if ! ismounted $TESTPOOL/$ds_pre; then
log_fail "$TESTPOOL/$ds_pre (pre) not mounted"
Expand Down Expand Up @@ -173,7 +173,7 @@ for d in ${test_depths[@]}; do
log_must zfs snapshot $TESTPOOL/$ds@snap
# force snapshot mount in .zfs
log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap
log_must zfs unmount $TESTPOOL/$ds
log_must_nostderr zfs unmount $TESTPOOL/$ds

if ! ismounted $TESTPOOL/$ds_pre; then
log_fail "$ds_pre is not mounted"
Expand Down

0 comments on commit ec64fdb

Please sign in to comment.