1 #! /usr/bin/ksh -p
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License (the "License").
   7 # You may not use this file except in compliance with the License.
   8 #
   9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10 # or http://www.opensolaris.org/os/licensing.
  11 # See the License for the specific language governing permissions
  12 # and limitations under the License.
  13 #
  14 # When distributing Covered Code, include this CDDL HEADER in each
  15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16 # If applicable, add the following below this CDDL HEADER, with the
  17 # fields enclosed by brackets "[]" replaced with your own identifying
  18 # information: Portions Copyright [yyyy] [name of copyright owner]
  19 #
  20 # CDDL HEADER END
  21 #
  22 
  23 #
  24 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  25 # Use is subject to license terms.
  26 #
  27 
  28 #
  29 # NFSv4 client recovery:
  30 # a: Verify that CLIENT continues to write data after nfs communication (between SERVER and CLIENT)
  31 #    disable-enable cycle on SERVER
  32 # b: Verify that CLIENT continues to read data after nfs communication (between SERVER and CLIENT)
  33 #    disable-enable cycle on SERVER
  34 # c: Verify that CLIENT continues to write data after nfs communication (between SERVER and CLIENT)
  35 #    disable-enable cycle on SERVER. During the period of communication disabled, CLIENT try to do 
  36 #    IO (will hang)
  37 # d: Verify that CLIENT continues to read data after nfs communication (between SERVER and CLIENT)
  38 #    disable-enable cycle on SERVER. During the period of communication disabled, CLIENT try to do 
  39 #    IO (will hang)
  40 #
  41 
  42 . ${STF_SUITE}/include/nfsgen.kshlib
  43 
  44 NAME=$(basename $0)
  45 
  46 [[ :$NFSGEN_DEBUG: = *:${NAME}:* || :${NFSGEN_DEBUG}: = *:all:* ]] && set -x
  47 
  48 DIR=$(dirname $0)
  49 prog=$STF_SUITE/bin/file_operator
  50 
  51 if [[ ! -x $prog ]]; then
  52         echo "$NAME: the executible program '$prog' not found."
  53         echo "\t Test FAIL"
  54         return $STF_FAIL
  55 fi
  56 
  57 function internalCleanup
  58 {
  59         [[ :$NFSGEN_DEBUG: = *:${NAME}:* || :${NFSGEN_DEBUG}: = *:all:* ]] \
  60                 && set -x
  61         filelist="$STF_TMPDIR/$NAME.out.$$ \
  62                 $STF_TMPDIR/$NAME.out2.$$"
  63         rm -f $filelist $*
  64 }
  65 
  66 # For READ test, in order to avoid reading data from cache wrotten by WRITE test
  67 # here we intended to prepare a file for read later
  68 function internalSetup
  69 {
  70         [[ :$NFSGEN_DEBUG: = *:${NAME}:* || :${NFSGEN_DEBUG}: = *:all:* ]] \
  71                 && set -x
  72 
  73         typeset testfile=$1
  74         rm -f $testfile
  75         $prog -W -c -o 4 -e $RANDOM -B "32768 2048 -1" $testfile > \
  76                 $STF_TMPDIR/$NAME.out.$$ 2>&1
  77         if (( $? != 0 )); then
  78                 internalCleanup $testfile
  79                 echo "\tTest FAIL"
  80                 exit $STF_FAIL
  81         fi
  82 }
  83 
  84 
  85 # main function
  86 function assertion_func
  87 {
  88         [[ :$NFSGEN_DEBUG: = *:${NAME}:* || :${NFSGEN_DEBUG}: = *:all:* ]] \
  89                 && set -x
  90 
  91         if (( $# < 5 )); then
  92                 echo "Invalid arguments: $*"
  93                 return $STF_FAIL
  94         fi
  95 
  96         typeset testfile=$1
  97         typeset iooption=$2
  98         typeset testseed=$3
  99         typeset buffoption=$4
 100         typeset ioduringblock=$5
 101         typeset timeout=250
 102         typeset pid=""
 103         typeset pidnw=""
 104         typeset nwret=""
 105 
 106 
 107         # start to write or read
 108         $prog $iooption -c -o 4 -e $testseed "$buffoption" $testfile \
 109                 > $STF_TMPDIR/$NAME.out.$$ 2>&1 & 
 110         pid=$!
 111 
 112         # make sure the process is ready
 113         wait_now $timeout "grep \"I am ready\" $STF_TMPDIR/$NAME.out.$$" \
 114                 > $STF_TMPDIR/$NAME.err.$$ 2>&1
 115         if (( $? != 0 )); then
 116                 echo "failed to get 'READY' sign from IO process"
 117                 cat $STF_TMPDIR/$NAME.err.$$
 118                 kill -9 $pid
 119                 internalCleanup $testfile
 120                 echo "\t Test FAIL"
 121                 return $STF_FAIL
 122         fi
 123 
 124 
 125         # ipfilter doesn't support shared stack zones, so we can't
 126         # set rules locally, and need to rsh to server to set it
 127         # on the server.
 128         if [[ `zonename` != global ]]; then
 129                 IPF_DIR=in
 130                 HOSTOPT="-s $SERVER"
 131         else
 132                 IPF_DIR=out
 133                 HOSTOPT=""
 134         fi
 135 
 136         [[ $IS_IPV6 == 1 ]] && IPOPT="-v ipv6" || IPOPT=""
 137         if (( $ioduringblock == 1 )); then
 138                 # touch block flag for ipfilter
 139                 $CMD touch $TMPDIR/network_block_flag
 140                 if (( $? != 0 )); then
 141                         echo "failed to touch $STF_TMPDIR/network_block_flag"
 142                         kill -9 $pid
 143                         internalCleanup $testfile
 144                         echo "\t Test FAIL"
 145                         return $STF_FAIL
 146                 fi
 147                 # block the nfs communication between CLIENT and SERVER
 148                 if [[ $IS_ZONE == 0 ]]; then
 149                     ipf_network $IPOPT \
 150                         -t $timeout -f $STF_TMPDIR/network_block_flag \
 151                         -r "block $IPF_DIR from $CLIENT to $SERVER port=2049" \
 152                         > $STF_TMPDIR/$NAME.reset_nw.$$ 2>&1 &
 153                     pidnw=$!
 154                 else
 155                     # RSH doesn't support to run commands in background
 156                     ssh root@$SERVER /usr/bin/ksh -c \
 157                         "'. $TMPDIR/nfs-util.kshlib; \
 158                         . $TMPDIR/libsmf.shlib; \
 159                         ipf_network $IPOPT \
 160                         -t $timeout -f $STF_TMPDIR/network_block_flag \
 161                         -r \"block $IPF_DIR from $CLIENT to $SERVER port=2049\" \
 162                         '" > $STF_TMPDIR/$NAME.reset_nw.$$ 2>&1 &
 163                     pidnw=$!
 164                 fi
 165 
 166                 # make sure the network is blocked before IO.
 167                 wait_now $timeout "$CMD ipfstat -oi | grep \"port = 2049\" > /dev/null" 
 168                 if (( $? !=0 )); then
 169                         echo "Failed to block the network"
 170                         cat $STF_TMPDIR/$NAME.reset_nw.$$
 171                         kill -9 $pid $pidnw
 172                         internalCleanup $testfile
 173                         echo "\t Test FAIL"
 174                         return $STF_FAIL
 175                 fi
 176 
 177                 # conti to do IO during block perod
 178                 kill -16 $pid
 179 
 180                 # sleep for a while before restore the network communication
 181                 sleep 10
 182 
 183                 # remove block flag file to restore ipfilter settings on $SERVER
 184                 RUN_CHECK $CMD rm $TMPDIR/network_block_flag
 185                 wait $pidnw
 186                 # make sure ipf_network() work well.
 187                 wait_now 240 "grep \"ipf_network finished\" \
 188                         $STF_TMPDIR/$NAME.reset_nw.$$ > /dev/null"
 189                 nwret=$?
 190         else
 191                 if [[ $IS_ZONE == 0 ]]; then
 192                     ipf_network $IPOPT -t 30 \
 193                         -r "block $IPF_DIR from $CLIENT to $SERVER port=2049" \
 194                         > $STF_TMPDIR/$NAME.reset_nw.$$ 2>&1
 195                     nwret=$?
 196                 else
 197                     RSH root $SERVER \
 198                         "export STF_TMPDIR=$SRV_TMPDIR; \
 199                         . $TMPDIR/nfs-util.kshlib; \
 200                         . $TMPDIR/libsmf.shlib; \
 201                         ipf_network $IPOPT -t 30 \
 202                         -r \"block $IPF_DIR from $CLIENT to $SERVER port=2049\"" \
 203                         > $STF_TMPDIR/$NAME.reset_nw.$$ 2>&1
 204                     nwret=$?
 205                 fi
 206         fi
 207 
 208         if (( $nwret != 0 )); then
 209                 echo "block nfs communication return failure"
 210                 RUN_CHECK $CMD rm -f $TMPDIR/network_block_flag
 211                 kill $pid
 212                 cat $STF_TMPDIR/$NAME.reset_nw.$$
 213                 internalCleanup $testfile
 214                 echo "\t Test FAIL"
 215                 return $STF_FAIL
 216         fi
 217 
 218         (( $ioduringblock == 0 )) && kill -16 $pid
 219 
 220         # wait the io process to finish
 221         wait $pid
 222 
 223         internalCleanup $testfile
 224         if (( $? == 0 )); then
 225                 echo "\tTest PASS"
 226                 return $STF_PASS
 227         else
 228                 echo "\tTest FAIL"
 229                 return $STF_FAIL
 230         fi
 231 }
 232 
 233 
 234 # Start main program here:
 235 # ----------------------------------------------------------------------
 236 
 237 # ipfilter doesn't support shared stack zones, so we can't set rules
 238 # in non-global zone,  we need to set ipfilter rule in the server. 
 239 # For SETUP=none, we can't execute the command in the server.
 240 # So in that case UNSUPPORTED is returned.
 241 if [[ `zonename` != global ]]; then
 242         if [[ $SETUP == none ]]; then
 243                 echo "The test doesn't support local zone with SETUP=none config"
 244                 return $STF_UNSUPPORTED
 245         else
 246                 IS_ZONE=1
 247                 CMD="RSH root $SERVER"
 248                 TMPDIR=$SRV_TMPDIR
 249         fi
 250 else
 251         IS_ZONE=0
 252         CMD=""
 253         TMPDIR=$STF_TMPDIR
 254 fi
 255 
 256 internalSetup $MNTDIR/openfile_r.$$
 257 retcode=0
 258 
 259 ASSERTION_A="Verify that client continues to write data after network disable-enable \
 260            cycle on SERVER, expect success"
 261 ASSERTION_B="Verify that client continues to read data after network disable-enable \
 262            cycle on SERVER, expect success"
 263 ASSERTION_C="Verify that client continues to write data after network disable-enable \
 264             cycle on SERVER, expect success. During the period of network disabled, \
 265             CLIENT try to do IO" 
 266 ASSERTION_D="Verify that client continues to read data after network disable-enable \
 267             cycle on SERVER, expect success. During the period of network disabled, \
 268             CLIENT try to do IO" 
 269 
 270 echo "$NAME{a}: $ASSERTION_A"
 271 assertion_func $MNTDIR/openfile_w.$$ -W $RANDOM "-B \"32768 2048 0\"" 0
 272 retcode=$(($retcode+$?))
 273 
 274 echo "$NAME{b}: $ASSERTION_B"
 275 assertion_func $MNTDIR/openfile_r.$$ -R $RANDOM "-B \"32768 2048 0\"" 0
 276 retcode=$(($retcode+$?))
 277 
 278 echo "$NAME{c}: $ASSERTION_C"
 279 assertion_func $MNTDIR/openfile_w2.$$ -W $RANDOM "-B \"32768 2048 0\"" 1
 280 retcode=$(($retcode+$?))
 281 
 282 echo "$NAME{d}: $ASSERTION_D"
 283 assertion_func $MNTDIR/openfile_r.$$ -R $RANDOM "-B \"32768 2048 0\"" 1
 284 retcode=$(($retcode+$?))
 285 
 286 
 287 internalCleanup $MNTDIR/openfile_r.$$ $MNTDIR/openfile_w.$$ \
 288         $MNTDIR/openfile_w2.$$
 289 
 290 (( $retcode == $STF_PASS )) && cleanup $STF_PASS || cleanup $STF_FAIL