1#!/bin/ksh -p 2# SPDX-License-Identifier: CDDL-1.0 3# 4# CDDL HEADER START 5# 6# The contents of this file are subject to the terms of the 7# Common Development and Distribution License (the "License"). 8# You may not use this file except in compliance with the License. 9# 10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11# or https://opensource.org/licenses/CDDL-1.0. 12# See the License for the specific language governing permissions 13# and limitations under the License. 14# 15# When distributing Covered Code, include this CDDL HEADER in each 16# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17# If applicable, add the following below this CDDL HEADER, with the 18# fields enclosed by brackets "[]" replaced with your own identifying 19# information: Portions Copyright [yyyy] [name of copyright owner] 20# 21# CDDL HEADER END 22# 23 24# 25# Copyright (c) 2020 by Delphix. All rights reserved. 26# 27 28. $STF_SUITE/include/libtest.shlib 29 30# 31# DESCRIPTION: 32# Verify that 'zfs set sharenfs=on', 'zfs share', and 'zfs unshare' can 33# run concurrently. The test creates 50 filesystem and 50 threads. 34# Each thread will run through the test strategy in parallel. 35# 36# STRATEGY: 37# 1. Verify that the file system is not shared. 38# 2. Enable the 'sharenfs' property 39# 3. Invoke 'zfs unshare' and verify filesystem is no longer shared 40# 4. Invoke 'zfs share'. 41# 4. Verify that the file system is shared. 42# 5. Verify that a shared filesystem cannot be shared again. 43# 6. Verify that share -a succeeds. 44# 45 46verify_runnable "global" 47 48function cleanup 49{ 50 wait 51 for fs in {0..50} 52 do 53 for pfs in $TESTFS1 $TESTFS2 $TESTFS3 54 do 55 log_must zfs set sharenfs=off $TESTPOOL/$pfs/$fs 56 unshare_fs $TESTPOOL/$pfs/$fs 57 58 if mounted $TESTPOOL/$pfs/$fs; then 59 log_must zfs unmount $TESTPOOL/$pfs/$fs 60 fi 61 62 datasetexists $TESTPOOL/$pfs/$fs && \ 63 destroy_dataset $TESTPOOL/$pfs/$fs -f 64 done 65 done 66 67 log_must zfs share -a 68} 69 70function create_filesystems 71{ 72 for fs in {0..50} 73 do 74 log_must zfs create -p $TESTPOOL/$TESTFS1/$fs 75 log_must zfs create -p $TESTPOOL/$TESTFS2/$fs 76 log_must zfs create -p $TESTPOOL/$TESTFS3/$fs 77 done 78} 79 80function sub_fail 81{ 82 log_note $$: "$@" 83 exit 1 84} 85 86# 87# Main test routine. 88# 89# Given a file system this routine will attempt 90# share the mountpoint and then verify it has been shared. 91# 92function test_share # filesystem 93{ 94 typeset filesystem=$1 95 typeset mntp=$(get_prop mountpoint $filesystem) 96 97 not_shared $mntp || \ 98 sub_fail "File system $filesystem is already shared." 99 100 zfs set sharenfs=on $filesystem || \ 101 sub_fail "zfs set sharenfs=on $filesystem failed." 102 103 # 104 # Verify 'zfs share' results in a shared mount. We check this 105 # multiple times because of Fedora 37+ it's been observed in 106 # the CI that the share may not be immediately reported. 107 # 108 for retry in $(seq 1 10); do 109 is_shared $mntp && break 110 111 log_note "Wait $retry / 10 for is_shared $mntp (set sharenfs)" 112 113 if [[ $retry -eq 10 ]]; then 114 sub_fail "File system $filesystem is not shared (set sharenfs)." 115 fi 116 117 sleep 1 118 done 119 120 # 121 # Verify 'zfs unshare' works as well. 122 # 123 zfs unshare $filesystem || \ 124 sub_fail "zfs unshare $filesystem failed." 125 is_shared $mntp && \ 126 sub_fail "File system $filesystem is still shared." 127 128 129 zfs share $filesystem || \ 130 sub_fail "zfs share $filesystem failed." 131 132 # 133 # Verify 'zfs share' results in a shared mount. We check this 134 # multiple times because of Fedora 37+ it's been observed in 135 # the CI that the share may not be immediately reported. 136 # 137 for retry in $(seq 1 10); do 138 is_shared $mntp && break 139 140 log_note "Wait $retry / 10 for is_shared $mntp (zfs share)" 141 142 if [[ $retry -eq 10 ]]; then 143 sub_fail "File system $filesystem is not shared (zfs share)." 144 fi 145 146 sleep 1 147 done 148 149 #log_note "Sharing a shared file system fails." 150 zfs share $filesystem && \ 151 sub_fail "zfs share $filesystem did not fail" 152 153 return 0 154} 155 156function unshare_fs_nolog 157{ 158 typeset fs=$1 159 160 if is_shared $fs || is_shared_smb $fs; then 161 zfs unshare $fs || 162 sub_fail "zfs unshare $fs: $?" 163 fi 164} 165 166# 167# Set the main process id so that we know to capture 168# failures from child processes and allow the parent process 169# to report the failure. 170# 171set_main_pid $$ 172log_assert "Verify that 'zfs share' succeeds as root." 173log_onexit cleanup 174 175create_filesystems 176 177child_pids=() 178for fs in {0..50} 179do 180 for pfs in $TESTFS1 $TESTFS2 $TESTFS3 181 do 182 test_share $TESTPOOL/$pfs/$fs & 183 child_pids+=($!) 184 log_note "$TESTPOOL/$pfs/$fs ==> $!" 185 done 186done 187log_must wait_for_children "${child_pids[@]}" 188 189log_note "Verify 'zfs share -a' succeeds." 190 191# 192# Unshare each of the file systems. 193# 194child_pids=() 195for fs in {0..50} 196do 197 for pfs in $TESTFS1 $TESTFS2 $TESTFS3 198 do 199 unshare_fs_nolog $TESTPOOL/$pfs/$fs & 200 child_pids+=($!) 201 log_note "$TESTPOOL/$pfs/$fs (unshare) ==> $!" 202 done 203done 204log_must wait_for_children "${child_pids[@]}" 205 206# 207# Try a zfs share -a and verify all file systems are shared. 208# 209log_must zfs share -a 210 211# 212# We need to unset __ZFS_POOL_EXCLUDE so that we include all file systems 213# in the os-specific zfs exports file. This will be reset by the next test. 214# 215unset __ZFS_POOL_EXCLUDE 216 217for fs in {0..50} 218do 219 for pfs in $TESTFS1 $TESTFS2 $TESTFS3 220 do 221 log_must is_shared $TESTPOOL/$pfs/$fs 222 log_must is_exported $TESTPOOL/$pfs/$fs 223 done 224done 225 226log_pass "'zfs share [-a] <filesystem>' succeeds as root." 227