#!/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 typeset mountpoint=/$TESTPOOL/mnt 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 # FreeBSD's mount command ignores the mountpoint property. if ! is_freebsd; then log_mustnot mount -t zfs $TESTPOOL/$dsB32 /mnt fi 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=$mountpoint -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_nostderr 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_nostderr 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_nostderr 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_nostderr 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 rmdir $mountpoint # remove the mountpoint we created log_must zpool export $TESTPOOL log_must zpool import $TESTPOOL log_pass "Verified nested dataset are unmounted."