From 0c6d09361dd8ab83f3193e6d7f398b4d20c9c300 Mon Sep 17 00:00:00 2001 From: Alek P Date: Tue, 2 Oct 2018 15:30:58 -0400 Subject: changelist should be able to iter on mounts Modified changelist_gather()ing for the mountpoint property. Now instead of iterating on all dataset descendants, we read /proc/self/mounts and iterate on the mounted descendant datasets only. Switched changelist implementation from a uu_list_* to uu_avl_* in order to reduce changlist code-path's worst case time complexity. Reviewed by: Don Brady Reviewed-by: Brian Behlendorf Signed-off-by: Alek Pinchuk Closes #7967 --- tests/runfiles/linux.run | 2 +- .../functional/cli_root/zfs_unmount/Makefile.am | 3 +- .../cli_root/zfs_unmount/zfs_unmount_nested.ksh | 189 +++++++++++++++++++++ 3 files changed, 192 insertions(+), 2 deletions(-) create mode 100755 tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_nested.ksh (limited to 'tests') diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run index 95e70f043..32bc9c328 100644 --- a/tests/runfiles/linux.run +++ b/tests/runfiles/linux.run @@ -277,7 +277,7 @@ tags = ['functional', 'cli_root', 'zfs_unload-key'] tests = ['zfs_unmount_001_pos', 'zfs_unmount_002_pos', 'zfs_unmount_003_pos', 'zfs_unmount_004_pos', 'zfs_unmount_005_pos', 'zfs_unmount_006_pos', 'zfs_unmount_007_neg', 'zfs_unmount_008_neg', 'zfs_unmount_009_pos', - 'zfs_unmount_all_001_pos'] + 'zfs_unmount_all_001_pos', 'zfs_unmount_nested'] tags = ['functional', 'cli_root', 'zfs_unmount'] [tests/functional/cli_root/zfs_unshare] diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/Makefile.am index 9ea809f26..34cbb17ae 100644 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/Makefile.am +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/Makefile.am @@ -11,7 +11,8 @@ dist_pkgdata_SCRIPTS = \ zfs_unmount_007_neg.ksh \ zfs_unmount_008_neg.ksh \ zfs_unmount_009_pos.ksh \ - zfs_unmount_all_001_pos.ksh + zfs_unmount_all_001_pos.ksh \ + zfs_unmount_nested.ksh dist_pkgdata_DATA = \ zfs_unmount.cfg \ diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_nested.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_nested.ksh new file mode 100755 index 000000000..73eae6a25 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unmount/zfs_unmount_nested.ksh @@ -0,0 +1,189 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy is of the CDDL is also available via the Internet +# at http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright (c) 2018 Datto Inc. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# zfs unmount should work on nested datasets +# +# STRATEGY: +# 1. Create a set of nested datasets +# 2. Unmount a nested dataset and make sure it is unmounted +# 3. Ensure the dataset deeper than the one above is also unmounted +# 4. Ensure the datasets shallower than the unmounted one is still mounted +# 5. Repeat from step 2 with other mountpoint values and shallower nesting +# + +verify_runnable "both" + +function nesting_cleanup +{ + log_must zfs destroy -fR $TESTPOOL/a + log_must zfs destroy -fR $TESTPOOL/b + log_must zfs destroy -fR $TESTPOOL/c + log_must zfs destroy -fR $TESTPOOL/d +} + +log_onexit nesting_cleanup + +set -A test_depths 30 16 3 + +dsA32=$(printf 'a/%.0s' {1..32})"a" +log_must zfs create -p $TESTPOOL/$dsA32 + +dsB32=$(printf 'b/%.0s' {1..32})"b" +log_must zfs create -o mountpoint=none -p $TESTPOOL/$dsB32 +log_mustnot mount -t zfs $TESTPOOL/$dsB32 /mnt + +dsC32=$(printf 'c/%.0s' {1..32})"c" +log_must zfs create -o mountpoint=legacy -p $TESTPOOL/$dsC32 +log_must mount -t zfs $TESTPOOL/$dsC32 /mnt + +dsD32=$(printf 'd/%.0s' {1..32})"d" +log_must zfs create -o mountpoint=/$TESTPOOL/mnt -p $TESTPOOL/$dsD32 + + +for d in ${test_depths[@]}; do + # default mountpoint + ds_pre=$(printf 'a/%.0s' {1..$(($d-2))})"a" + ds=$(printf 'a/%.0s' {1..$(($d-1))})"a" + ds_post=$(printf 'a/%.0s' {1..$(($d))})"a" + if ! ismounted $TESTPOOL/$ds_pre; then + log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted" + fi + if ! ismounted $TESTPOOL/$ds; then + log_fail "$TESTPOOL/$ds not initially mounted" + fi + if ! ismounted $TESTPOOL/$ds_post; then + log_fail "$TESTPOOL/$ds_post (post) not initially mounted" + fi + + 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 + + if ! ismounted $TESTPOOL/$ds_pre; then + log_fail "$ds_pre is not mounted" + fi + if ismounted $TESTPOOL/$ds; then + log_fail "$ds is mounted" + fi + if ismounted $TESTPOOL/$ds_post; then + log_fail "$ds_post (post) is mounted" + fi + + + # mountpoint=none + ds_pre=$(printf 'b/%.0s' {1..$(($d-2))})"b" + ds=$(printf 'b/%.0s' {1..$(($d-1))})"b" + ds_post=$(printf 'b/%.0s' {1..$(($d))})"b" + if ! ismounted $TESTPOOL/$ds_pre; then + log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted" + fi + if ! ismounted $TESTPOOL/$ds; then + log_fail "$TESTPOOL/$ds not initially mounted" + fi + if ! ismounted $TESTPOOL/$ds_post; then + log_fail "$TESTPOOL/$ds_post (post) not initially mounted" + fi + + 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 + + if ! ismounted $TESTPOOL/$ds_pre; then + log_fail "$TESTPOOL/$ds_pre (pre) not mounted" + fi + if ismounted $TESTPOOL/$ds; then + log_fail "$TESTPOOL/$ds is mounted" + fi + if ismounted $TESTPOOL/$ds_post; then + log_fail "$TESTPOOL/$ds_post (post) is mounted" + fi + + + # mountpoint=legacy + ds_pre=$(printf 'c/%.0s' {1..$(($d-2))})"c" + ds=$(printf 'c/%.0s' {1..$(($d-1))})"c" + ds_post=$(printf 'c/%.0s' {1..$(($d))})"c" + if ! ismounted $TESTPOOL/$ds_pre; then + log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted" + fi + if ! ismounted $TESTPOOL/$ds; then + log_fail "$TESTPOOL/$ds not initially mounted" + fi + if ! ismounted $TESTPOOL/$ds_post; then + log_fail "$TESTPOOL/$ds_post (post) not initially mounted" + fi + + 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 + + if ! ismounted $TESTPOOL/$ds_pre; then + log_fail "$TESTPOOL/$ds_pre (pre) not mounted" + fi + if ismounted $TESTPOOL/$ds; then + log_fail "$TESTPOOL/$ds is mounted" + fi + if ismounted $TESTPOOL/$ds_post; then + log_fail "$TESTPOOL/$ds_post (post) is mounted" + fi + + + # mountpoint=testpool/mnt + ds_pre=$(printf 'd/%.0s' {1..$(($d-2))})"d" + ds=$(printf 'd/%.0s' {1..$(($d-1))})"d" + ds_post=$(printf 'd/%.0s' {1..$(($d))})"d" + if ! ismounted $TESTPOOL/$ds_pre; then + log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted" + fi + if ! ismounted $TESTPOOL/$ds; then + log_fail "$TESTPOOL/$ds not initially mounted" + fi + if ! ismounted $TESTPOOL/$ds_post; then + log_fail "$TESTPOOL/$ds_post (post) not initially mounted" + fi + + 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 + + if ! ismounted $TESTPOOL/$ds_pre; then + log_fail "$ds_pre is not mounted" + fi + if ismounted $TESTPOOL/$ds; then + log_fail "$ds is mounted" + fi + if ismounted $TESTPOOL/$ds_post; then + log_fail "$ds_post (post) is mounted" + fi +done + +log_must zpool export $TESTPOOL +log_must rmdir /testpool/mnt # remove the mountpoint we created +log_must zpool import $TESTPOOL + +log_pass "Verified nested dataset are unmounted." -- cgit v1.2.3