Whamcloud - gitweb
LU-1548 mdssurvey: fix file_count in mds_survey
[fs/lustre-release.git] / lustre-iokit / mds-survey / mds-survey
1 #!/bin/bash
2 # -*- mode: Bash; tab-width: 4; indent-tabs-mode: t; -*-
3 # vim:shiftwidth=4:softtabstop=4:tabstop=4:
4
5 ######################################################################
6 # customize per survey
7
8 # Prerequisite: For "stripe_count > 0" you need to have ost setup and mounted.
9 #
10 # How to run test:
11 # case 1 (stripe_count=0 default):
12 #   $ thrhi=8 dir_count=4 sh mds-survey
13 #   one can also run test with user defined targets as follows,
14 #   $ thrhi=8 dir_count=4 file_count=50000 targets="lustre-MDT0000" sh mds-survey
15 # case 2 (stripe_count > 0, must have ost mounted):
16 #   $ thrhi=8 dir_count=4 file_count=50000 stripe_count=2
17 #   targets="lustre-MDT0000" sh mds-survey
18 # [ NOTE: It is advised to have automated login (passwordless entry) on server ]
19
20 # include library
21 source $(dirname $0)/libecho
22
23 # Customisation variables
24 #####################################################################
25 # One can change variable values in this section as per requirements
26 # The following variables can be set in the environment, or on the
27 # command line
28 # result file prefix (date/time + hostname makes unique)
29 # NB ensure path to it exists
30 rslt_loc=${rslt_loc:-"/tmp"}
31 rslt=${rslt:-"$rslt_loc/mds_survey_`date +%F@%R`_`uname -n`"}
32
33 # min and max thread count
34 thrlo=${thrlo:-4}
35 thrhi=${thrhi:-32}
36
37 # number of directories to test
38 dir_count=${dir_count:-$thrlo}
39 # number of files per thread
40 file_count=${file_count:-100000}
41
42 targets=${targets:-""}
43 stripe_count=${stripe_count:-0}
44 # what tests to run (first must be create, and last must be destroy)
45 # default=(create lookup md_getattr setxattr destroy)
46 tests_str=${tests_str:-"create lookup md_getattr setxattr destroy"}
47
48 # start number for each thread
49 start_number=${start_number:-2}
50
51 # layer to be tested
52 layer=${layer:-"mdd"}
53 # Customisation variables ends here.
54 #####################################################################
55 # leave the rest of this alone unless you know what you're doing...
56 export LC_ALL=POSIX
57 basedir="tests"
58
59 create_directories () {
60     local host=$1
61     local devno=$2
62     local ndir=$3
63     local rfile=$4
64     local idx
65
66     for ((idx = 0; idx < $ndir; idx++)); do
67         if (( idx == 0 )); then
68             dirname=${basedir}
69         else
70             dirname=${basedir}${idx}
71         fi
72         remote_shell $host $lctl --device $devno test_mkdir /$dirname > $rfile 2>&1
73         while read line; do
74             echo "$line" | grep -q 'error: test_mkdir'
75             if [ $?  -eq 0 ]; then
76                 cat $rfile >&2
77                 echo "ERROR: fail test_mkdir" >&2
78                 echo "ERROR"
79                 return
80             fi
81         done < $rfile
82     done
83     echo $basedir
84 }
85
86 destroy_directories () {
87     local host=$1
88     local devno=$2
89     local ndir=$3
90     local rfile=$4
91     local idx
92
93     for ((idx = 0; idx < $ndir; idx++)); do
94         if (( idx == 0 )); then
95             dirname=${basedir}
96         else
97             dirname=${basedir}${idx}
98         fi
99         remote_shell $host $lctl --device $devno test_rmdir /$dirname > $rfile 2>&1
100     done
101 }
102
103 get_stats () {
104     local rfile=$1
105     gawk < $rfile                                                               \
106     '/starting/ { n=0; next }                                                   \
107      /error/ {n = -1; exit}                                                     \
108      /^Total: total [0-9]+ threads [0-9]+ sec [0-9\.]+ [0-9]+\.[0-9]+\/second$/ \
109      { ave = strtonum($8); n++; next}                                           \
110      /^[0-9]+\/[0-9]+ Total: [0-9]+\.[0-9]+\/second$/                           \
111      {    n++; v = strtonum($3);                                                \
112           if (n == 1 || v < min) min = v;                                       \
113           if (n == 1 || v > max) max = v;                                       \
114           next;                                                                 \
115      }                                                                          \
116      {    if (n != 0) {n = -1; exit } }                                         \
117      END { if (n == 1) { min = ave; max = ave; }                                \
118            printf "%d %f %f %f\n", n, ave, min, max}'
119 }
120
121 get_global_stats () {
122     local rfile=$1
123     awk < $rfile                                               \
124     'BEGIN {n = 0;}                                            \
125     {    n++;                                                  \
126          if (n == 1) { err = $1; ave = $2; min = $3; max = $4} \
127          else                                                  \
128          { if ($1 < err) err = $1;                             \
129            if ($2 < min) min = $2;                             \
130            if ($3 > max) max = $3;                             \
131          }                                                     \
132     }                                                          \
133     END { if (n == 0) err = 0;                                 \
134           printf "%d %f %f %f\n", err, ave, min, max}'
135 }
136
137 print_summary () {
138     if [ "$1" = "-n" ]; then
139         minusn=$1; shift
140     else
141         minusn=""
142     fi
143     echo $minusn "$*" >> $rsltf
144     echo $minusn "$*"
145 }
146
147 declare -a tests
148 count=0
149 for name in $tests_str; do
150     tests[$count]=$name
151     count=$((count+1))
152 done
153
154 # hide a little trick to unset this from the command line
155 if [ "$lustre_root" == " " ]; then
156     unset lustre_root
157 fi
158
159 if [ -z "$lustre_root" ]; then
160     lctl=lctl
161 else
162     lctl=${lustre_root}/utils/lctl
163 fi
164
165 declare -a client_names
166 declare -a host_names
167 if [ -z "$targets" ]; then
168     targets=$($lctl device_list | awk "{if (\$2 == \"UP\" && \
169             \$3 == \"mdt\") {print \$4} }")
170     if [ -z "$targets" ]; then
171         echo "Can't find any MDT to test.  Please set targets=..."
172         exit 1
173     fi
174 fi
175
176 # split out hostnames from mdt names
177 ndevs=0
178 for trgt in $targets; do
179     str=(`split_hostname $trgt`)
180     host_names[$ndevs]=${str[0]}
181     client_names[$ndevs]=${str[1]}
182     ndevs=$((ndevs+1))
183 done
184
185 # check for ost
186 if (( $stripe_count > 0 )); then
187     for ((i=0; i < $ndevs; i++)); do
188         host=${host_names[$i]}
189         obd=$(remote_shell $host $lctl device_list | awk "{if (\$2 == \"UP\" &&
190             \$3 == \"osc\") { print \$4 } }")
191         if [ -z "$obd" ]; then
192             echo "Need obdfilter to test stripe_count"
193             exit 1
194         fi
195     done
196 fi
197
198 # check and insert obdecho module
199 if ! lsmod | grep obdecho > /dev/null; then
200     modprobe obdecho
201 fi
202 count=${#tests[@]}
203 if [ $count -eq 0 -o "${tests[0]}" != "create" -o "${tests[(($count - 1))]}" != "destroy" ]; then
204     echo "tests: ${tests[@]}"
205     echo "First test must be 'create', and last test must be 'destroy'" 1>&2
206     exit 1
207 fi
208
209 rsltf="${rslt}.summary"
210 workf="${rslt}.detail"
211 cmdsf="${rslt}.script"
212 vmstatf="${rslt}.vmstat"
213 echo -n > $rsltf
214 echo -n > $workf
215
216 # get vmstat started
217 # disable portals debug and get obdecho loaded on all relevant hosts
218 unique_hosts=(`unique ${host_names[@]}`)
219 load_obdechos
220 pidcount=0
221 for host in ${unique_hosts[@]}; do
222     host_vmstatf=${vmstatf}_${host}
223     echo -n > $host_vmstatf
224     remote_shell $host "vmstat 5 >> $host_vmstatf" &> /dev/null &
225     pid=$!
226     vmstatpids[$pidcount]=$pid
227     pidcount=$((pidcount+1))
228 done
229 # get all the echo_client device numbers and names
230 for ((i=0; i < $ndevs; i++)); do
231     host=${host_names[$i]}
232     devno=(`get_ec_devno $host "${client_names[$i]}" "${client_names[$i]}" "mdt" $layer`)
233     if ((${#devno[@]} != 3)); then
234         exit 1
235     fi
236     devnos[$i]=${devno[0]}
237     client_names[$i]=${devno[1]}
238     do_teardown_ec[$i]=${devno[2]}
239 done
240 if (($ndevs <= 0 || ${#host_names[@]} <= 0)); then
241     echo "no devices or hosts specified"
242     cleanup 0
243 fi
244 print_summary "$(date) $0 from $(hostname)"
245 # create directories
246 tmpf="${workf}_tmp"
247 for ((idx = 0; idx < $ndevs; idx++)); do
248     host=${host_names[$idx]}
249     devno=${devnos[$idx]}
250     client_name="${host}:${client_names[$idx]}"
251     echo "=============> Create $dir_count directories on $client_name" >> $workf
252     destroy_directories $host $devno $dir_count $tmpf
253     ret=`create_directories $host $devno $dir_count $tmpf`
254     cat $tmpf >> $workf
255     rm $tmpf
256     if [ $ret = "ERROR" ]; then
257         print_summary "created directories on $client_name failed"
258         cleanup 1
259     fi
260 done
261
262 snap=1
263 status=0
264 for ((thr = $thrlo; thr <= $thrhi; thr*=2)); do
265     thr_per_dir=$((${thr}/${dir_count}))
266     # skip if no enough thread
267     if (( thr_per_dir <= 0 )); then
268         continue
269     fi
270     file_count_per_thread=$((${file_count}/${thr}))
271     str=`printf 'mdt %1d file %7d dir %4d thr %4d ' \
272     $ndevs $file_count $dir_count $thr`
273     echo "=======================> $str" >> $workf
274     print_summary -n "$str"
275     # run tests
276     for test in ${tests[@]}; do
277         declare -a pidarray
278         for host in ${unique_hosts[@]}; do
279             echo "starting run for config: $config test: $test file: \
280             $file_count threads: $thr directories: $dir_count" >> ${vmstatf}_${host}
281         done
282         print_summary -n "$test "
283         # create per-host script files
284         for host in ${unique_hosts[@]}; do
285             echo -n > ${cmdsf}_${host}
286         done
287         for ((idx = 0; idx < $ndevs; idx++)); do
288             host=${host_names[$idx]}
289             devno=${devnos[$idx]}
290             tmpfi="${tmpf}_$idx"
291             [ $test = "create" ] && test="create -c $stripe_count"
292             echo >> ${cmdsf}_${host}                                                     \
293                 "$lctl > $tmpfi 2>&1                                                     \
294                  --threads $thr -$snap $devno test_$test -d /$basedir -D $dir_count      \
295                  -b $start_number -n $file_count_per_thread"
296         done
297         pidcount=0
298         for host in ${unique_hosts[@]}; do
299             echo "wait" >> ${cmdsf}_${host}
300             pidarray[$pidcount]=0
301             pidcount=$((pidcount+1))
302         done
303         pidcount=0
304         for host in ${unique_hosts[@]}; do
305             remote_shell $host bash < ${cmdsf}_${host} &
306             pidarray[$pidcount]=$!
307             pidcount=$((pidcount+1))
308         done
309         pidcount=0
310         for host in ${unique_hosts[@]}; do
311             wait ${pidarray[$pidcount]}
312             pidcount=$((pidcount+1))
313         done
314         #wait
315         # clean up per-host script files
316         for host in ${unique_hosts[@]}; do
317             rm ${cmdsf}_${host}
318         done
319
320         # collect/check individual MDT stats
321         echo -n > $tmpf
322         for ((idx = 0; idx < $ndevs; idx++)); do
323             client_name="${host_names[$idx]}:${client_names[$idx]}"
324             tmpfi="${tmpf}_$idx"
325             echo "=============> $test $client_name" >> $workf
326             host="${host_names[$idx]}"
327             remote_shell $host cat $tmpfi > ${tmpfi}_local
328             cat ${tmpfi}_local >> $workf
329             get_stats ${tmpfi}_local >> $tmpf
330             rm -f $tmpfi ${tmpfi}_local
331         done
332         # compute/display global min/max stats
333         echo "=============> $test global" >> $workf
334         cat $tmpf >> $workf
335         stats=(`get_global_stats $tmpf`)
336         rm $tmpf
337         if ((stats[0] <= 0)); then
338             str=`printf "%17s " ERROR`
339             status=1
340         else
341             str=`awk "BEGIN {printf \"%7.2f [%7.2f,%7.2f] \", \
342             ${stats[1]}, ${stats[2]}, ${stats[3]}; exit}"`
343         fi
344         print_summary -n "$str"
345     done
346     print_summary ""
347 done
348 # destroy directories
349 tmpf="${workf}_tmp"
350 for ((idx = 0; idx < $ndevs; idx++)); do
351     host=${host_names[$idx]}
352     devno=${devnos[$idx]}
353     client_name="${host}:${client_names[$idx]}"
354     echo "=============> Destroy $dir_count directories on $client_name" >> $workf
355     destroy_directories $host $devno $dir_count $tmpf
356 done
357
358 cleanup $status
359 exit $status