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 # start multiple nfsh scripts on background to generate simultaneous
28 # SETATTR requests
29 #
30 # Usage:
31 # uidmapping_stress02 <number_of_process> <number_of_requests_per_process>
32 # number_of_process - number of send_setattr_reqs process. 60 by default
33 # number_of_requests_per_process - number of SETATTR sent by each
34 # process. 400 by default
35
36 [ -n "$DEBUG" ] && [ "$DEBUG" != "0" ] && set -x
37
38 NAME=${0##*/}
39 CDIR=`pwd`
40
41 UIDMAPENV="./uid_proc"
42 UNINITIATED=6
43
44 # set up script running environment
45 if [ ! -f $UIDMAPENV ]; then
46 echo "$NAME: UIDMAPENV[$UIDMAPENV] not found; test UNINITIATED."
47 exit $UNINITIATED
48 fi
49 . $UIDMAPENV
50
51 NUM_OF_PROCS=${1:-60}
52 NUM_OF_REQS=${2:-400}
53 TESTDIR="$ZONE_PATH/$NAME"
54
55 function setup
56 {
57 # Create mount point directory
58 mkdir -p "$TESTDIR" 2>$ERRLOG
59 ckreturn $? "failed to create $TESTDIR" $ERRLOG "ERROR" || \
60 return 1
61
62 # Mount file system shared with root access("anon=0" option)
63 mountit "$SERVER" "$ROOTDIR" "$TESTDIR" 4 1>$ERRLOG 2>&1
64 ckreturn $? "failed to mount directory." $ERRLOG "ERROR"
65 if [ $? -ne 0 ]; then
66 rm -rf $TESTDIR
67 return 1
68 fi
69
70 # Create test files
71 typeset -i x=1
72 while (( $x <= $NUM_OF_PROCS ))
73 do
74 echo "test file for nfsmapid stress test" > $TESTDIR/mapid.$$.$x
75 if [[ ! -f $TESTDIR/mapid.$$.$x ]]; then
76 echo "\t Test UNINITIATED: \c"
77 echo "failed to create $TESTDIR/mapid.$$.$x file"
78 cleanup $UNINITIATED
79 fi
80 x=$(($x+1))
81 done
82 }
83
84 function cleanup {
85 echo "\t END TIME: `date`"
86
87 # Remove test files
88 #
89 # Although removing files doesn't use nfsmapid service directly, it
90 # actually need that. The reason is when accesing a directory or a
91 # file, Solaris performs access permission checking, which in turn
92 # need nfsmapid service. For this reason, the following command may
93 # hang if nfsmapid service is stressed:
94 #
95 # rm -f $TESTDIR/mapid.$$.$x
96 #
97 # Instead it is better to use the following r-command in this case.
98 #
99 execute $SERVER root "rm -f $ROOTDIR/mapid.$$.*"
100
101 # Unmount file system
102 umountit "$TESTDIR" 1>$ERRLOG 2>&1
103 ckreturn $? "failed to unmount $TESTDIR" $ERRLOG "WARNING"
104
105 # remove mount point
106 rm -rf $TESTDIR 1>$ERRLOG 2>&1
107 ckreturn $? "failed to remove $TESTDIR" $ERRLOG "WARNING"
108
109 # remove temporary files
110 rm -f $TMPDIR/$NAME.$$.*
111
112 exit $1
113 }
114
115 # must run as root
116 is_root $NAME "NFSv4 mapid stress test"
117
118 setup || exit $UNINITIATED
119
120 echo "$NAME{1}: generating simultaneous kernel upcall to stress nfsmapid\n"
121 echo "\t START TIME: `date`"
122
123 # export the common domain for the test
124 Cdomain=$(cat /var/run/nfs4_domain)
125
126 # Start children processes to stress nfsmapid
127 x=1
128 while [ $x -le $NUM_OF_PROCS ]
129 do
130 # start the x-th instance of send_setattr_reqs.tcl
131 $TESTROOT/nfsh send_setattr_reqs $ROOTDIR/mapid.$$.$x $NUM_OF_REQS \
132 >$TMPDIR/$NAME.$$.$x 2>&1 &
133
134 # record the child's pid
135 pid_list[$x]=$!
136
137 x=$(($x+1))
138 done
139
140 [ "$DEBUG" -eq "1" ] && echo "$NUM_OF_PROCS processes started: ${pid_list[*]}"
141
142 # Check if the server is overcome by the requests from the client.
143 #
144 # For each rpc call, there is a timer associated with it. If the client
145 # doesn't get reply from server and the timer expires, the rpc call fails.
146 # In that case, Solaris nfs client will keep trying until that it succeeds.
147 # If the server keeps not responding, the client hangs.(notes: a simple
148 # experiment shows the default timeout value of a rpc call on solaris is
149 # 120 seconds)
150 #
151 # nfsh is different from Solaris nfs client in that it doesn't retry. Instead,
152 # the Compound command just fails and returns. That means, nfsh client never
153 # really hangs. In the worst situation(no reply from server), it exits after
154 # the rpc call timer expires.
155 #
156 # To check if the server works well with nfsh clients, we can check the clients'
157 # exit status. If a client gets reply from the server, it exits successfully.
158 # Otherwise, the RPC call timer expires and we think the client "hangs".
159 x=1
160 failed=0
161 while [ $x -le $NUM_OF_PROCS ]
162 do
163 # get the x-th child's pid
164 pid=${pid_list[$x]}
165
166 # wait until it exits and get its exit status
167 wait $pid
168 status=$?
169
170 if [ "$status" != "0" ]; then
171 if [ "$DEBUG" == "1" -o "$failed" == "0" ]; then
172 echo "\nERROR: process $pid failed!"
173 echo "------------- $TMPDIR/$NAME.$$.$x -------------"
174 cat $TMPDIR/$NAME.$$.$x
175 echo "-------------------- END ----------------------"
176 fi
177 failed=$(( failed + 1))
178 fi
179
180 x=$(($x+1))
181 done
182
183 # Print all out log files in debug mode
184
185 if [ "$DEBUG" -eq "1" ]; then
186 x=1
187 while [ $x -le $NUM_OF_PROCS ]
188 do
189 echo "------------- $TMPDIR/$NAME.$$.$x -------------"
190 cat $TMPDIR/$NAME.$$.$x
191 echo "-------------------- END ----------------------"
192 x=$(($x+1))
193 done
194 fi
195
196
197 # Print test result
198
199 if [ "$failed" -eq 0 ]; then
200 echo "\t Test PASS: test run completed successfully"
201 cleanup $PASS
202 else
203 echo "\t Test FAIL: Total <$failed> children processes failed"
204 cleanup $FAIL
205 fi
206