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 # This is a regression test for 6248250. In this test, we will generate 
  30 # an OPEN_DOWNGRADE operation on a stale file handler. Without the fix, nfs 
  31 # client code didn't check NFS4ERR_STALE error and re-sent OPEN_DOWNGRADE 
  32 # again and again. On user level, it could be observed the user process 
  33 # was hang.
  34 #
  35 
  36 . ${STF_SUITE}/include/nfsgen.kshlib
  37 
  38 NAME=$(basename $0)
  39 
  40 [[ :$NFSGEN_DEBUG: = *:${NAME}:* || :${NFSGEN_DEBUG}: = *:all:* ]] && set -x
  41 
  42 DIR=$(dirname $0)
  43 OPENDG_ASSERTIONS=${OPENDG_ASSERTIONS:-"a"}
  44 
  45 export RECOVERY_EXECUTE_PATH=$DIR
  46 export RECOVERY_STAT_PATH=$STF_SUITE/bin/
  47 
  48 # Wait until grace period ends
  49 echo "xxx" > $MNTDIR/wait_for_grace
  50 rm -rf $MNTDIR/wait_for_grace > /dev/null 2>&1
  51 
  52 TESTFILE=$NAME.$$.test
  53 LOGFILE=$STF_TMPDIR/$NAME.$$.err
  54 
  55 function setup 
  56 {
  57         [[ :$NFSGEN_DEBUG: = *:${NAME}:* || :${NFSGEN_DEBUG}: = *:all:* ]] && set -x
  58 
  59         # execute $SERVER root \
  60         RSH root $SERVER \
  61             "cd $SHRDIR; touch $TESTFILE; chmod 666 $TESTFILE" 1>/dev/null \
  62             2>$LOGFILE
  63         ckresult $? "failed to create $TESTFILE ERROR" $LOGFILE || return 1
  64 }
  65 
  66 # Start test assertions here
  67 # ----------------------------------------------------------------------
  68 # a: generate an OPEN_DOWNGRADE operation on a stale file handler
  69 function assertion_a
  70 {
  71         [[ :$NFSGEN_DEBUG: = *:${NAME}:* || :${NFSGEN_DEBUG}: = *:all:* ]] && set -x
  72 
  73         ASSERTION="Client tries to generate an OPEN_DOWNGRADE operation"
  74         ASSERTION="$ASSERTION on a stale file handler,"
  75         ASSERTION="$ASSERTION expect NFS4ERR_STALE error be handled properly"
  76         echo "$NAME{a}: $ASSERTION"
  77 
  78         PROG=$STF_SUITE/bin/open_dg
  79         INTERVAL=8
  80         STF_WARNING="\tSTF_WARNING: The failure of this case was known to cause"
  81         STF_WARNING="$STF_WARNING NFS client kept looping and didn't response to any"
  82         STF_WARNING="$STF_WARNING further NFS operations. So you many need to re-setup"
  83         STF_WARNING="$STF_WARNING the test environment and continue the rest tests."
  84 
  85         # start test program
  86         $PROG $MNTDIR/$TESTFILE 1>$LOGFILE 2>&1 &
  87         pid=$!
  88         sleep $INTERVAL
  89         grep "fd1 and fd2 were opened" $LOGFILE > /dev/null
  90         ckresult -n $? "failed to open test file STF_UNRESOLVED" $LOGFILE
  91         if (( $? != 0 )); then
  92                 kill -9 $pid
  93                 rm -f $LOGFILE
  94                 return $STF_UNRESOLVED
  95         fi
  96 
  97 
  98         # do the following steps on server to help to generate 
  99         # NFS4ERR_STALE error when client sends OPEN_DOWNGRADE
 100         # below. Note that the step of removing the file is necessary.
 101         # Or else server returns NFS4ERR_EXPIRED error, which is 
 102         # not what we want to test in this case.
 103         # execute $SERVER root "rm -f $SHRDIR/$TESTFILE && \
 104         RSH root $SERVER "rm -f $SHRDIR/$TESTFILE && \
 105             unshare $SHRDIR && share $SHRDIR" 1>/dev/null 2>$STF_TMPDIR/$NAME.$$.rsh
 106         ckresult $? "failed to execute commands on server STF_UNRESOLVED" $STF_TMPDIR/$NAME.$$.rsh 
 107         if (( $? != 0 )); then
 108                 kill -9 $pid 
 109                 rm -f $LOGFILE $STF_TMPDIR/$NAME.$$.rsh
 110                 return $STF_UNRESOLVED
 111         fi
 112 
 113         # close fd1 to generate OPEN_DOWNGRADE
 114         kill -USR1 $pid 
 115         sleep $INTERVAL
 116         grep "NFS4ERR_STALE" $LOGFILE | grep fd1 > /dev/null
 117         ckresult -n $? "Unknown error on closing fd1 STF_FAIL" $LOGFILE
 118         if (( $? != 0 )); then
 119                 echo $STF_WARNING
 120                 kill -9 $pid 
 121                 rm -f $LOGFILE $STF_TMPDIR/$NAME.$$.rsh
 122                 return $STF_FAIL
 123         fi
 124 
 125         # close fd2
 126         kill -USR2 $pid 
 127         sleep $INTERVAL
 128         grep "NFS4ERR_STALE" $LOGFILE | grep fd2 > /dev/null
 129         ckresult $? "Unknown error on closing fd2 STF_FAIL" $LOGFILE 
 130         if (( $? != 0 )); then
 131                 echo $STF_WARNING
 132                 kill -9 $pid 
 133                 rm -f $LOGFILE $STF_TMPDIR/$NAME.$$.rsh
 134                 return $STF_FAIL
 135         fi
 136 
 137         rm -f $LOGFILE $STF_TMPDIR/$NAME.$$.rsh
 138 
 139         echo "\t Test PASS"
 140         return $STF_PASS
 141 }
 142 
 143 # Start main program here:
 144 # ----------------------------------------------------------------------
 145 
 146 setup || cleanup $STF_UNINITIATED "" "$MNTDIR/$TESTFILE $LOGFILE $STF_TMPDIR/$NAME.$$.rsh"
 147 
 148 retcode=0
 149 for t in $OPENDG_ASSERTIONS; do
 150         assertion_$t
 151         retcode=$(($retcode+$?))
 152 done
 153 
 154 (( $retcode == $STF_PASS )) \
 155         && cleanup $STF_PASS "" "$MNTDIR/$TESTFILE $LOGFILE $STF_TMPDIR/$NAME.$$.rsh" \
 156         || cleanup $STF_FAIL "" "$MNTDIR/$TESTFILE $LOGFILE $STF_TMPDIR/$NAME.$$.rsh"
 157