1#!/bin/ksh -p 2# 3# CDDL HEADER START 4# 5# This file and its contents are supplied under the terms of the 6# Common Development and Distribution License ("CDDL"), version 1.0. 7# You may only use this file in accordance with the terms of version 8# 1.0 of the CDDL. 9# 10# A full copy of the text of the CDDL should have accompanied this 11# source. A copy is of the CDDL is also available via the Internet 12# at http://www.illumos.org/license/CDDL. 13# 14# CDDL HEADER END 15# 16 17# 18# Copyright (c) 2018 Datto Inc. 19# 20 21. $STF_SUITE/include/libtest.shlib 22 23# 24# DESCRIPTION: 25# zfs unmount should work on nested datasets 26# 27# STRATEGY: 28# 1. Create a set of nested datasets 29# 2. Unmount a nested dataset and make sure it is unmounted 30# 3. Ensure the dataset deeper than the one above is also unmounted 31# 4. Ensure the datasets shallower than the unmounted one is still mounted 32# 5. Repeat from step 2 with other mountpoint values and shallower nesting 33# 34 35verify_runnable "both" 36 37function nesting_cleanup 38{ 39 log_must zfs destroy -fR $TESTPOOL/a 40 log_must zfs destroy -fR $TESTPOOL/b 41 log_must zfs destroy -fR $TESTPOOL/c 42 log_must zfs destroy -fR $TESTPOOL/d 43} 44 45log_onexit nesting_cleanup 46 47set -A test_depths 30 16 3 48typeset mountpoint=/$TESTPOOL/mnt 49 50dsA32=$(printf 'a/%.0s' {1..32})"a" 51log_must zfs create -p $TESTPOOL/$dsA32 52 53dsB32=$(printf 'b/%.0s' {1..32})"b" 54log_must zfs create -o mountpoint=none -p $TESTPOOL/$dsB32 55# FreeBSD's mount command ignores the mountpoint property. 56if ! is_freebsd; then 57 log_mustnot mount -t zfs $TESTPOOL/$dsB32 /mnt 58fi 59 60dsC32=$(printf 'c/%.0s' {1..32})"c" 61log_must zfs create -o mountpoint=legacy -p $TESTPOOL/$dsC32 62log_must mount -t zfs $TESTPOOL/$dsC32 /mnt 63 64dsD32=$(printf 'd/%.0s' {1..32})"d" 65log_must zfs create -o mountpoint=$mountpoint -p $TESTPOOL/$dsD32 66 67 68for d in ${test_depths[@]}; do 69 # default mountpoint 70 ds_pre=$(printf 'a/%.0s' {1..$(($d-2))})"a" 71 ds=$(printf 'a/%.0s' {1..$(($d-1))})"a" 72 ds_post=$(printf 'a/%.0s' {1..$(($d))})"a" 73 if ! ismounted $TESTPOOL/$ds_pre; then 74 log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted" 75 fi 76 if ! ismounted $TESTPOOL/$ds; then 77 log_fail "$TESTPOOL/$ds not initially mounted" 78 fi 79 if ! ismounted $TESTPOOL/$ds_post; then 80 log_fail "$TESTPOOL/$ds_post (post) not initially mounted" 81 fi 82 83 log_must zfs snapshot $TESTPOOL/$ds@snap 84 # force snapshot mount in .zfs 85 log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap 86 log_must_nostderr zfs unmount $TESTPOOL/$ds 87 88 if ! ismounted $TESTPOOL/$ds_pre; then 89 log_fail "$ds_pre is not mounted" 90 fi 91 if ismounted $TESTPOOL/$ds; then 92 log_fail "$ds is mounted" 93 fi 94 if ismounted $TESTPOOL/$ds_post; then 95 log_fail "$ds_post (post) is mounted" 96 fi 97 98 99 # mountpoint=none 100 ds_pre=$(printf 'b/%.0s' {1..$(($d-2))})"b" 101 ds=$(printf 'b/%.0s' {1..$(($d-1))})"b" 102 ds_post=$(printf 'b/%.0s' {1..$(($d))})"b" 103 if ! ismounted $TESTPOOL/$ds_pre; then 104 log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted" 105 fi 106 if ! ismounted $TESTPOOL/$ds; then 107 log_fail "$TESTPOOL/$ds not initially mounted" 108 fi 109 if ! ismounted $TESTPOOL/$ds_post; then 110 log_fail "$TESTPOOL/$ds_post (post) not initially mounted" 111 fi 112 113 log_must zfs snapshot $TESTPOOL/$ds@snap 114 # force snapshot mount in .zfs 115 log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap 116 log_must_nostderr zfs unmount $TESTPOOL/$ds 117 118 if ! ismounted $TESTPOOL/$ds_pre; then 119 log_fail "$TESTPOOL/$ds_pre (pre) not mounted" 120 fi 121 if ismounted $TESTPOOL/$ds; then 122 log_fail "$TESTPOOL/$ds is mounted" 123 fi 124 if ismounted $TESTPOOL/$ds_post; then 125 log_fail "$TESTPOOL/$ds_post (post) is mounted" 126 fi 127 128 129 # mountpoint=legacy 130 ds_pre=$(printf 'c/%.0s' {1..$(($d-2))})"c" 131 ds=$(printf 'c/%.0s' {1..$(($d-1))})"c" 132 ds_post=$(printf 'c/%.0s' {1..$(($d))})"c" 133 if ! ismounted $TESTPOOL/$ds_pre; then 134 log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted" 135 fi 136 if ! ismounted $TESTPOOL/$ds; then 137 log_fail "$TESTPOOL/$ds not initially mounted" 138 fi 139 if ! ismounted $TESTPOOL/$ds_post; then 140 log_fail "$TESTPOOL/$ds_post (post) not initially mounted" 141 fi 142 143 log_must zfs snapshot $TESTPOOL/$ds@snap 144 # force snapshot mount in .zfs 145 log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap 146 log_must_nostderr zfs unmount $TESTPOOL/$ds 147 148 if ! ismounted $TESTPOOL/$ds_pre; then 149 log_fail "$TESTPOOL/$ds_pre (pre) not mounted" 150 fi 151 if ismounted $TESTPOOL/$ds; then 152 log_fail "$TESTPOOL/$ds is mounted" 153 fi 154 if ismounted $TESTPOOL/$ds_post; then 155 log_fail "$TESTPOOL/$ds_post (post) is mounted" 156 fi 157 158 159 # mountpoint=/testpool/mnt 160 ds_pre=$(printf 'd/%.0s' {1..$(($d-2))})"d" 161 ds=$(printf 'd/%.0s' {1..$(($d-1))})"d" 162 ds_post=$(printf 'd/%.0s' {1..$(($d))})"d" 163 if ! ismounted $TESTPOOL/$ds_pre; then 164 log_fail "$TESTPOOL/$ds_pre (pre) not initially mounted" 165 fi 166 if ! ismounted $TESTPOOL/$ds; then 167 log_fail "$TESTPOOL/$ds not initially mounted" 168 fi 169 if ! ismounted $TESTPOOL/$ds_post; then 170 log_fail "$TESTPOOL/$ds_post (post) not initially mounted" 171 fi 172 173 log_must zfs snapshot $TESTPOOL/$ds@snap 174 # force snapshot mount in .zfs 175 log_must ls /$TESTPOOL/$ds/.zfs/snapshot/snap 176 log_must_nostderr zfs unmount $TESTPOOL/$ds 177 178 if ! ismounted $TESTPOOL/$ds_pre; then 179 log_fail "$ds_pre is not mounted" 180 fi 181 if ismounted $TESTPOOL/$ds; then 182 log_fail "$ds is mounted" 183 fi 184 if ismounted $TESTPOOL/$ds_post; then 185 log_fail "$ds_post (post) is mounted" 186 fi 187done 188 189log_must rmdir $mountpoint # remove the mountpoint we created 190log_must zpool export $TESTPOOL 191log_must zpool import $TESTPOOL 192 193log_pass "Verified nested dataset are unmounted." 194