Whamcloud - gitweb
LU-4883 lmv: disable sub-stripe access from .lustre/fid
[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 mdtbasedir="MDT%04x-"
59
60 create_directories () {
61     local host=$1
62     local devno=$2
63     local ndir=$3
64     local rfile=$4
65     local mdtidx=$5
66     local idx
67
68     for ((idx = 0; idx < $ndir; idx++)); do
69         if (( idx == 0 )); then
70             dirname="$(printf "${mdtbasedir}" $mdtidx)${basedir}"
71         else
72             dirname="$(printf "${mdtbasedir}" $mdtidx)${basedir}${idx}"
73         fi
74         remote_shell $host $lctl --device $devno test_mkdir /$dirname > $rfile 2>&1
75         while read line; do
76             echo "$line" | grep -q 'error: test_mkdir'
77             if [ $?  -eq 0 ]; then
78                 cat $rfile >&2
79                 echo "ERROR: fail test_mkdir" >&2
80                 echo "ERROR"
81                 return
82             fi
83         done < $rfile
84     done
85     echo $basedir
86 }
87
88 destroy_directories () {
89     local host=$1
90     local devno=$2
91     local ndir=$3
92     local rfile=$4
93     local mdtidx=$5
94     local idx
95
96     for ((idx = 0; idx < $ndir; idx++)); do
97         if (( idx == 0 )); then
98             dirname="$(printf "${mdtbasedir}" $mdtidx)${basedir}"
99         else
100             dirname="$(printf "${mdtbasedir}" $mdtidx)${basedir}${idx}"
101         fi
102         remote_shell $host $lctl --device $devno test_rmdir /$dirname > $rfile 2>&1
103     done
104 }
105
106 get_stats () {
107     local rfile=$1
108     gawk < $rfile                                                               \
109     '/starting/ { n=0; next }                                                   \
110      /error/ {n = -1; exit}                                                     \
111      /^Total: total [0-9]+ threads [0-9]+ sec [0-9\.]+ [0-9]+\.[0-9]+\/second$/ \
112      { ave = strtonum($8); n++; next}                                           \
113      /^[0-9]+\/[0-9]+ Total: [0-9]+\.[0-9]+\/second$/                           \
114      {    n++; v = strtonum($3);                                                \
115           if (n == 1 || v < min) min = v;                                       \
116           if (n == 1 || v > max) max = v;                                       \
117           next;                                                                 \
118      }                                                                          \
119      {    if (n != 0) {n = -1; exit } }                                         \
120      END { if (n == 1) { min = ave; max = ave; }                                \
121            printf "%d %f %f %f\n", n, ave, min, max}'
122 }
123
124 get_global_stats () {
125     local rfile=$1
126     awk < $rfile                                               \
127     'BEGIN {n = 0;}                                            \
128     {    n++;                                                  \
129          if (n == 1) { err = $1; ave = $2; min = $3; max = $4} \
130          else                                                  \
131          { if ($1 < err) err = $1;                             \
132            ave += $2;                                          \
133            if ($3 < min) min = $3;                             \
134            if ($4 > max) max = $4;                             \
135          }                                                     \
136     }                                                          \
137     END { if (n == 0) err = 0;                                 \
138           printf "%d %f %f %f\n", err, ave/n, min, max}'
139 }
140
141 print_summary () {
142     if [ "$1" = "-n" ]; then
143         minusn=$1; shift
144     else
145         minusn=""
146     fi
147     echo $minusn "$*" >> $rsltf
148     echo $minusn "$*"
149 }
150
151 declare -a tests
152 count=0
153 for name in $tests_str; do
154     tests[$count]=$name
155     count=$((count+1))
156 done
157
158 # hide a little trick to unset this from the command line
159 if [ "$lustre_root" == " " ]; then
160     unset lustre_root
161 fi
162
163 if [ -z "$lustre_root" ]; then
164     lctl=lctl
165 else
166     lctl=${lustre_root}/utils/lctl
167 fi
168
169 declare -a client_names
170 declare -a host_names
171 declare -a client_indexes
172 if [ -z "$targets" ]; then
173     targets=$($lctl device_list | awk "{if (\$2 == \"UP\" && \
174             \$3 == \"mdt\") {print \$4} }")
175     if [ -z "$targets" ]; then
176         echo "Can't find any MDT to test.  Please set targets=..."
177         exit 1
178     fi
179 fi
180
181 # split out hostnames from mdt names
182 ndevs=0
183 for trgt in $targets; do
184     str=(`split_hostname $trgt`)
185     host_names[$ndevs]=${str[0]}
186     client_names[$ndevs]=${str[1]}
187     client_indexes[$ndevs]=0x$(echo ${str[1]} |
188             sed 's/.*MDT\([0-9a-f][0-9a-f][0-9a-f][0-9a-f]\).*/\1/')
189     ndevs=$((ndevs+1))
190 done
191
192 # check for ost
193 if (( $stripe_count > 0 )); then
194     for ((i=0; i < $ndevs; i++)); do
195         host=${host_names[$i]}
196         obd=$(remote_shell $host $lctl device_list | awk "{if (\$2 == \"UP\" &&
197             (\$3 == \"osc\" || \$3 == \"osp\")) { print \$4 } }")
198         if [ -z "$obd" ]; then
199             echo "Need obdfilter to test stripe_count"
200             exit 1
201         fi
202     done
203 fi
204
205 # check and insert obdecho module
206 if ! lsmod | grep obdecho > /dev/null; then
207     modprobe obdecho
208 fi
209 count=${#tests[@]}
210 if [ $count -eq 0 -o "${tests[0]}" != "create" -o "${tests[(($count - 1))]}" != "destroy" ]; then
211     echo "tests: ${tests[@]}"
212     echo "First test must be 'create', and last test must be 'destroy'" 1>&2
213     exit 1
214 fi
215
216 rsltf="${rslt}.summary"
217 workf="${rslt}.detail"
218 cmdsf="${rslt}.script"
219 vmstatf="${rslt}.vmstat"
220 echo -n > $rsltf
221 echo -n > $workf
222
223 # get vmstat started
224 # disable portals debug and get obdecho loaded on all relevant hosts
225 unique_hosts=(`unique ${host_names[@]}`)
226 load_obdechos
227 pidcount=0
228 for host in ${unique_hosts[@]}; do
229     host_vmstatf=${vmstatf}_${host}
230     echo -n > $host_vmstatf
231     remote_shell $host "vmstat 5 >> $host_vmstatf" &> /dev/null &
232     pid=$!
233     vmstatpids[$pidcount]=$pid
234     pidcount=$((pidcount+1))
235 done
236 # get all the echo_client device numbers and names
237 for ((i=0; i < $ndevs; i++)); do
238     host=${host_names[$i]}
239     devno=(`get_ec_devno $host "${client_names[$i]}" "${client_names[$i]}" "mdt" $layer`)
240     if ((${#devno[@]} != 3)); then
241         exit 1
242     fi
243     devnos[$i]=${devno[0]}
244     client_names[$i]=${devno[1]}
245     do_teardown_ec[$i]=${devno[2]}
246 done
247 if (($ndevs <= 0 || ${#host_names[@]} <= 0)); then
248     echo "no devices or hosts specified"
249     cleanup 0
250 fi
251 print_summary "$(date) $0 from $(hostname)"
252 # create directories
253 tmpf="${workf}_tmp"
254 for ((idx = 0; idx < $ndevs; idx++)); do
255     host=${host_names[$idx]}
256     devno=${devnos[$idx]}
257     client_name="${host}:${client_names[$idx]}"
258     mdtidx=${client_indexes[$idx]}
259     echo "=============> Create $dir_count directories on $client_name" >> $workf
260     destroy_directories $host $devno $dir_count $tmpf $mdtidx
261     ret=`create_directories $host $devno $dir_count $tmpf $mdtidx`
262     cat $tmpf >> $workf
263     rm $tmpf
264     if [ $ret = "ERROR" ]; then
265         print_summary "created directories on $client_name failed"
266         cleanup 1
267     fi
268 done
269
270 snap=1
271 status=0
272 for ((thr = $thrlo; thr <= $thrhi; thr*=2)); do
273     thr_per_dir=$((${thr}/${dir_count}))
274     # skip if no enough thread
275     if (( thr_per_dir <= 0 )); then
276         continue
277     fi
278     file_count_per_thread=$((${file_count}/${thr}))
279     str=`printf 'mdt %1d file %7d dir %4d thr %4d ' \
280     $ndevs $file_count $dir_count $thr`
281     echo "=======================> $str" >> $workf
282     print_summary -n "$str"
283     # run tests
284     for test in ${tests[@]}; do
285         declare -a pidarray
286         for host in ${unique_hosts[@]}; do
287             echo "starting run for config: $config test: $test file: \
288             $file_count threads: $thr directories: $dir_count" >> ${vmstatf}_${host}
289         done
290         print_summary -n "$test "
291         # create per-host script files
292         for host in ${unique_hosts[@]}; do
293             echo -n > ${cmdsf}_${host}
294         done
295         for ((idx = 0; idx < $ndevs; idx++)); do
296             host=${host_names[$idx]}
297             devno=${devnos[$idx]}
298             dirname="$(printf "${mdtbasedir}" ${client_indexes[$idx]})$basedir"
299             tmpfi="${tmpf}_$idx"
300             [ "$test" = "create" ] && test="create -c $stripe_count"
301             echo >> ${cmdsf}_${host}                                                     \
302                 "$lctl > $tmpfi 2>&1                                                     \
303                  --threads $thr -$snap $devno test_$test -d /$dirname -D $dir_count      \
304                  -b $start_number -n $file_count_per_thread"
305         done
306         pidcount=0
307         for host in ${unique_hosts[@]}; do
308             echo "wait" >> ${cmdsf}_${host}
309             pidarray[$pidcount]=0
310             pidcount=$((pidcount+1))
311         done
312         pidcount=0
313         for host in ${unique_hosts[@]}; do
314             remote_shell $host bash < ${cmdsf}_${host} &
315             pidarray[$pidcount]=$!
316             pidcount=$((pidcount+1))
317         done
318         pidcount=0
319         for host in ${unique_hosts[@]}; do
320             wait ${pidarray[$pidcount]}
321             pidcount=$((pidcount+1))
322         done
323         #wait
324         # clean up per-host script files
325         for host in ${unique_hosts[@]}; do
326             rm ${cmdsf}_${host}
327         done
328
329         # collect/check individual MDT stats
330         echo -n > $tmpf
331         for ((idx = 0; idx < $ndevs; idx++)); do
332             client_name="${host_names[$idx]}:${client_names[$idx]}"
333             tmpfi="${tmpf}_$idx"
334             echo "=============> $test $client_name" >> $workf
335             host="${host_names[$idx]}"
336             remote_shell $host cat $tmpfi > ${tmpfi}_local
337             cat ${tmpfi}_local >> $workf
338             get_stats ${tmpfi}_local >> $tmpf
339             rm -f $tmpfi ${tmpfi}_local
340         done
341         # compute/display global min/max stats
342         echo "=============> $test global" >> $workf
343         cat $tmpf >> $workf
344         stats=(`get_global_stats $tmpf`)
345         rm $tmpf
346         if ((stats[0] <= 0)); then
347             str=`printf "%17s " ERROR`
348             status=1
349         else
350             str=`awk "BEGIN {printf \"%7.2f [ %7.2f, %7.2f] \", \
351             ${stats[1]}, ${stats[2]}, ${stats[3]}; exit}"`
352         fi
353         print_summary -n "$str"
354     done
355     print_summary ""
356 done
357 # destroy directories
358 tmpf="${workf}_tmp"
359 for ((idx = 0; idx < $ndevs; idx++)); do
360     host=${host_names[$idx]}
361     devno=${devnos[$idx]}
362     mdtidx=${client_indexes[$idx]}
363     client_name="${host}:${client_names[$idx]}"
364     echo "=============> Destroy $dir_count directories on $client_name" >> $workf
365     destroy_directories $host $devno $dir_count $tmpf $mdtidx
366 done
367
368 cleanup $status
369 exit $status