Skip snapshot in zfs_iter_mounted()

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 <behlendorf1@llnl.gov>
Signed-off-by: Youzhong Yang <yyang@mathworks.com>
Closes #12447
Closes #12448
This commit is contained in:
youzhongyang 2021-10-20 19:07:19 -04:00 committed by GitHub
parent 1886cdfcfb
commit ec64fdb93d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 6 deletions

View File

@ -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,

View File

@ -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.
@ -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

View File

@ -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"
@ -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"
@ -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"
@ -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"