Whamcloud - gitweb
b=16551 (att 19784)
[fs/lustre-release.git] / lustre / tests / sanity-gss.sh
1 #!/bin/bash
2 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
3 #
4 # Run select tests by setting ONLY, or as arguments to the script.
5 # Skip specific tests by setting EXCEPT.
6 #
7 # e.g. ONLY="22 23" or ONLY="`seq 32 39`" or EXCEPT="31"
8 set -e
9
10 ONLY=${ONLY:-"$*"}
11 # bug number for skipped test:
12 ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"$SANITY_GSS_EXCEPT"}
13 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
14
15 # Tests that fail on uml
16 CPU=`awk '/model/ {print $4}' /proc/cpuinfo`
17 [ "$CPU" = "UML" ] && EXCEPT="$EXCEPT"
18
19 case `uname -r` in
20 2.6*) FSTYPE=${FSTYPE:-ldiskfs}; ALWAYS_EXCEPT="$ALWAYS_EXCEPT " ;;
21 *) error "unsupported kernel (gss only works with 2.6.x)" ;;
22 esac
23
24 SRCDIR=`dirname $0`
25 export PATH=$PWD/$SRCDIR:$SRCDIR:$SRCDIR/../utils:$SRCDIR/../utils/gss:$PATH:/sbin
26 export NAME=${NAME:-local}
27 SAVE_PWD=$PWD
28
29 CLEANUP=${CLEANUP:-""}
30 SETUP=${SETUP:-""}
31
32 LUSTRE=${LUSTRE:-`dirname $0`/..}
33 . $LUSTRE/tests/test-framework.sh
34 init_test_env $@
35 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
36
37 remote_mds_nodsh && skip "remote MDS with nodsh" && exit 0
38
39 [ "$SLOW" = "no" ] && EXCEPT_SLOW="100 101"
40
41 # $RUNAS_ID may get set incorrectly somewhere else
42 [ $UID -eq 0 -a $RUNAS_ID -eq 0 ] && error "\$RUNAS_ID set to 0, but \$UID is also 0!"
43
44 # remove $SEC, we'd like to control everything by ourselves
45 unset SEC
46
47 #
48 # global variables of this sanity
49 #
50 KRB5_CCACHE_DIR=/tmp
51 KRB5_CRED=$KRB5_CCACHE_DIR/krb5cc_$RUNAS_ID
52 KRB5_CRED_SAVE=$KRB5_CCACHE_DIR/krb5cc.sanity.save
53 CLICOUNT=2
54 cnt_mdt2ost=0
55 cnt_mdt2mdt=0
56 cnt_cli2ost=0
57 cnt_cli2mdt=0
58 cnt_all2ost=0
59 cnt_all2mdt=0
60 cnt_all2all=0
61 DBENCH_PID=0
62 PROC_CLI="srpc.info"
63 # Escape "." to use lctl
64 PROC_CLI=${PROC_CLI//\./\*} 
65
66 # set manually
67 GSS=true
68 GSS_KRB5=true
69
70 prepare_krb5_creds() {
71     echo prepare krb5 cred
72     rm -f $KRB5_CRED_SAVE
73     echo RUNAS=$RUNAS
74     $RUNAS krb5_login.sh || exit 1
75     [ -f $KRB5_CRED ] || exit 2
76     echo CRED=$KRB5_CRED
77     cp $KRB5_CRED $KRB5_CRED_SAVE
78 }
79
80 prepare_krb5_creds
81
82 # we want double mount
83 MOUNT_2=${MOUNT_2:-"yes"}
84 cleanup_and_setup_lustre
85
86 rm -rf $DIR/[df][0-9]*
87
88 check_runas_id $RUNAS_ID $RUNAS
89
90 build_test_filter
91
92 combination()
93 {
94     local M=$1
95     local N=$2
96     local R=1
97
98     if [ $M -lt $N ]; then
99         R=0
100     else
101         N=$((N + 1))
102         while [ $N -le $M ]; do
103             R=$((R * N))
104             N=$((N + 1))
105         done
106     fi
107
108     echo $R
109     return 0
110 }
111
112 calc_connection_cnt() {
113     # MDT->MDT = 2 * C(M, 2)
114     # MDT->OST = M * O
115     # CLI->OST = C * O
116     # CLI->MDT = C * M
117     comb_m2=$(combination $MDSCOUNT 2)
118
119     cnt_mdt2mdt=$((comb_m2 * 2))
120     cnt_mdt2ost=$((MDSCOUNT * OSTCOUNT))
121     cnt_cli2ost=$((CLICOUNT * OSTCOUNT))
122     cnt_cli2mdt=$((CLICOUNT * MDSCOUNT))
123     cnt_all2ost=$((cnt_mdt2ost + cnt_cli2ost))
124     cnt_all2mdt=$((cnt_mdt2mdt + cnt_cli2mdt))
125     cnt_all2all=$((cnt_mdt2ost + cnt_mdt2mdt + cnt_cli2ost + cnt_cli2mdt))
126 }
127
128 set_rule()
129 {
130     local tgt=$1
131     local net=$2
132     local dir=$3
133     local flavor=$4
134     local cmd="$tgt.srpc.flavor"
135
136     if [ $net == "any" ]; then
137         net="default"
138     fi
139     cmd="$cmd.$net"
140
141     if [ $dir != "any" ]; then
142         cmd="$cmd.$dir"
143     fi
144
145     cmd="$cmd=$flavor"
146     log "Setting sptlrpc rule: $cmd"
147     do_facet mgs "$LCTL conf_param $cmd"
148 }
149
150 count_flvr()
151 {
152     local output=$1
153     local flavor=$2
154     local count=0
155
156     rpc_flvr=`echo $flavor | awk -F - '{ print $1 }'`
157     bulkspec=`echo $flavor | awk -F - '{ print $2 }'`
158
159     count=`echo "$output" | grep "rpc flavor" | grep $rpc_flvr | wc -l`
160
161     if [ "x$bulkspec" != "x" ]; then
162         algs=`echo $bulkspec | awk -F : '{ print $2 }'`
163
164         if [ "x$algs" != "x" ]; then
165             bulk_count=`echo "$output" | grep "bulk flavor" | grep $algs | wc -l`
166         else
167             bulk=`echo $bulkspec | awk -F : '{ print $1 }'`
168             if [ $bulk == "bulkn" ]; then
169                 bulk_count=`echo "$output" | grep "bulk flavor" \
170                             | grep "null/null" | wc -l`
171             elif [ $bulk == "bulki" ]; then
172                 bulk_count=`echo "$output" | grep "bulk flavor" \
173                             | grep "/null" | grep -v "null/" | wc -l`
174             else
175                 bulk_count=`echo "$output" | grep "bulk flavor" \
176                             | grep -v "/null" | grep -v "null/" | wc -l`
177             fi
178         fi
179
180         [ $bulk_count -lt $count ] && count=$bulk_count
181     fi
182
183     echo $count
184 }
185
186 flvr_cnt_cli2mdt()
187 {
188     local flavor=$1
189
190     output=`do_facet client lctl get_param -n mdc.*-MDT*-mdc-*.$PROC_CLI 2>/dev/null`
191     count_flvr "$output" $flavor
192 }
193
194 flvr_cnt_cli2ost()
195 {
196     local flavor=$1
197
198     output=`do_facet client lctl get_param -n osc.*OST*-osc-[^M][^D][^T]*.$PROC_CLI 2>/dev/null`
199     count_flvr "$output" $flavor
200 }
201
202 flvr_cnt_mdt2mdt()
203 {
204     local flavor=$1
205     local cnt=0
206
207     if [ $MDSCOUNT -le 1 ]; then
208         echo 0
209         return
210     fi
211
212     for num in `seq $MDSCOUNT`; do
213         output=`do_facet mds$num lctl get_param -n mdc.*-MDT*-mdc[0-9]*.$PROC_CLI 2>/dev/null`
214         tmpcnt=`count_flvr "$output" $flavor`
215         cnt=$((cnt + tmpcnt))
216     done
217     echo $cnt;
218 }
219
220 flvr_cnt_mdt2ost()
221 {
222     local flavor=$1
223     local cnt=0
224
225     for num in `seq $MDSCOUNT`; do
226         output=`do_facet mds$num lctl get_param -n osc.*OST*-osc-MDT*.$PROC_CLI 2>/dev/null`
227         tmpcnt=`count_flvr "$output" $flavor`
228         cnt=$((cnt + tmpcnt))
229     done
230     echo $cnt;
231 }
232
233 do_check_flavor()
234 {
235     local dir=$1        # from to
236     local flavor=$2     # flavor expected
237     local res=0
238
239     if [ $dir == "cli2mdt" ]; then
240         res=`flvr_cnt_cli2mdt $flavor`
241     elif [ $dir == "cli2ost" ]; then
242         res=`flvr_cnt_cli2ost $flavor`
243     elif [ $dir == "mdt2mdt" ]; then
244         res=`flvr_cnt_mdt2mdt $flavor`
245     elif [ $dir == "mdt2ost" ]; then
246         res=`flvr_cnt_mdt2ost $flavor`
247     elif [ $dir == "all2ost" ]; then
248         res1=`flvr_cnt_mdt2ost $flavor`
249         res2=`flvr_cnt_cli2ost $flavor`
250         res=$((res1 + res2))
251     elif [ $dir == "all2mdt" ]; then
252         res1=`flvr_cnt_mdt2mdt $flavor`
253         res2=`flvr_cnt_cli2mdt $flavor`
254         res=$((res1 + res2))
255     elif [ $dir == "all2all" ]; then
256         res1=`flvr_cnt_mdt2ost $flavor`
257         res2=`flvr_cnt_cli2ost $flavor`
258         res3=`flvr_cnt_mdt2mdt $flavor`
259         res4=`flvr_cnt_cli2mdt $flavor`
260         res=$((res1 + res2 + res3 + res4))
261     fi
262
263     echo $res
264 }
265
266 wait_flavor()
267 {
268     local dir=$1        # from to
269     local flavor=$2     # flavor expected
270     local expect=$3     # number expected
271     local res=0
272
273     for ((i=0;i<20;i++)); do
274         echo -n "checking..."
275         res=$(do_check_flavor $dir $flavor)
276         if [ $res -eq $expect ]; then
277             echo "found $res $flavor connections of $dir, OK"
278             return 0
279         else
280             echo "found $res $flavor connections of $dir, not ready ($expect)"
281             sleep 4
282         fi
283     done
284
285     echo "Error checking $flavor of $dir: expect $expect, actual $res"
286     return 1
287 }
288
289 restore_to_default_flavor()
290 {
291     local proc="mgs.MGS.live.$FSNAME"
292
293     echo "restoring to default flavor..."
294
295     nrule=`do_facet mgs lctl get_param -n $proc 2>/dev/null | grep ".srpc.flavor." | wc -l`
296
297     # remove all existing rules if any
298     if [ $nrule -ne 0 ]; then
299         echo "$nrule existing rules"
300         for rule in `do_facet mgs lctl get_param -n $proc 2>/dev/null | grep ".srpc.flavor."`; do
301             echo "remove rule: $rule"
302             spec=`echo $rule | awk -F = '{print $1}'`
303             do_facet mgs "$LCTL conf_param $spec="
304         done
305     fi
306
307     # verify no rules left
308     nrule=`do_facet mgs lctl get_param -n $proc 2>/dev/null | grep ".srpc.flavor." | wc -l`
309     [ $nrule -ne 0 ] && error "still $nrule rules left"
310
311     # wait for default flavor to be applied
312     # currently default flavor for all connections are 'null'
313     wait_flavor all2all null $cnt_all2all
314     echo "now at default flavor settings"
315 }
316
317 set_flavor_all()
318 {
319     local flavor=$1
320
321     echo "setting all flavor to $flavor"
322
323     res=$(do_check_flavor all2all $flavor)
324     if [ $res -eq $cnt_all2all ]; then
325         echo "already have total $res $flavor connections"
326         return
327     fi
328
329     echo "found $res $flavor out of total $cnt_all2all connections"
330     restore_to_default_flavor
331
332     set_rule $FSNAME any any $flavor
333     wait_flavor all2all $flavor $cnt_all2all
334 }
335
336 start_dbench()
337 {
338     NPROC=`cat /proc/cpuinfo 2>/dev/null | grep ^processor | wc -l`
339     [ $NPROC -gt 2 ] && NPROC=2
340     sh rundbench $NPROC 1>/dev/null &
341     DBENCH_PID=$!
342     sleep 2
343
344     num=`ps --no-headers -p $DBENCH_PID 2>/dev/null | wc -l`
345     if [ $num -ne 1 ]; then
346         error "failed to start dbench $NPROC"
347     else
348         echo "started dbench with $NPROC processes at background"
349     fi
350
351     return 0
352 }
353
354 check_dbench()
355 {
356     num=`ps --no-headers -p $DBENCH_PID 2>/dev/null | wc -l`
357     if [ $num -eq 0 ]; then
358         echo "dbench $DBENCH_PID already finished"
359         wait $DBENCH_PID || error "dbench $PID exit with error"
360         start_dbench
361     elif [ $num -ne 1 ]; then
362         killall -9 dbench
363         error "found $num instance of pid $DBENCH_PID ???"
364     fi
365
366     return 0
367 }
368
369 stop_dbench()
370 {
371     for ((;;)); do
372         killall dbench 2>/dev/null
373         num=`ps --no-headers -p $DBENCH_PID | wc -l`
374         if [ $num -eq 0 ]; then
375             echo "dbench finished"
376             break
377         fi
378         echo "dbench $DBENCH_PID is still running, waiting 2s..."
379         sleep 2
380     done
381
382     wait $DBENCH_PID || true
383     sync || true
384 }
385
386 restore_krb5_cred() {
387     cp $KRB5_CRED_SAVE $KRB5_CRED
388     chown $RUNAS_ID:$RUNAS_ID $KRB5_CRED
389     chmod 0600 $KRB5_CRED
390 }
391
392 check_multiple_gss_daemons() {
393     local facet=$1
394     local gssd=$2
395     local gssd_name=`basename $gssd`
396
397     for ((i=0;i<10;i++)); do
398         do_facet $facet "$gssd -v &"
399     done
400
401     # wait daemons entering "stable" status
402     sleep 5
403
404     num=`do_facet $facet ps -o cmd -C $gssd_name | grep $gssd_name | wc -l`
405     echo "$num instance(s) of $gssd_name are running"
406
407     if [ $num -ne 1 ]; then
408         error "$gssd_name not unique"
409     fi
410 }
411
412 calc_connection_cnt
413 umask 077
414
415 test_0() {
416     local my_facet=mds
417
418     echo "bring up gss daemons..."
419     start_gss_daemons
420
421     echo "check with someone already running..."
422     check_multiple_gss_daemons $my_facet $LSVCGSSD
423     if $GSS_PIPEFS; then
424         check_multiple_gss_daemons $my_facet $LGSSD
425     fi
426
427     echo "check with someone run & finished..."
428     do_facet $my_facet killall -q -2 lgssd lsvcgssd || true
429     sleep 5 # wait fully exit
430     check_multiple_gss_daemons $my_facet $LSVCGSSD
431     if $GSS_PIPEFS; then
432         check_multiple_gss_daemons $my_facet $LGSSD
433     fi
434
435     echo "check refresh..."
436     do_facet $my_facet killall -q -2 lgssd lsvcgssd || true
437     sleep 5 # wait fully exit
438     do_facet $my_facet ipcrm -S 0x3b92d473
439     check_multiple_gss_daemons $my_facet $LSVCGSSD
440     if $GSS_PIPEFS; then
441         do_facet $my_facet ipcrm -S 0x3a92d473
442         check_multiple_gss_daemons $my_facet $LGSSD
443     fi
444 }
445 run_test 0 "start multiple gss daemons"
446
447 set_flavor_all krb5p
448
449 test_1() {
450     local file=$DIR/$tfile
451
452     chmod 0777 $DIR || error "chmod $DIR failed"
453     # access w/o cred
454     $RUNAS kdestroy
455     $RUNAS touch $file && error "unexpected success"
456
457     # access w/ cred
458     restore_krb5_cred
459     $RUNAS touch $file || error "should not fail"
460     [ -f $file ] || error "$file not found"
461 }
462 run_test 1 "access with or without krb5 credential"
463
464 test_2() {
465     local file1=$DIR/$tfile-1
466     local file2=$DIR/$tfile-2
467
468     chmod 0777 $DIR || error "chmod $DIR failed"
469     # current access should be ok
470     $RUNAS touch $file1 || error "can't touch $file1"
471     [ -f $file1 ] || error "$file1 not found"
472
473     # cleanup all cred/ctx and touch
474     $RUNAS kdestroy
475     $RUNAS $LFS flushctx || error "can't flush ctx"
476     $RUNAS touch $file2 && error "unexpected success"
477
478     # restore and touch
479     restore_krb5_cred
480     $RUNAS touch $file2 || error "should not fail"
481     [ -f $file2 ] || error "$file2 not found"
482 }
483 run_test 2 "lfs flushctx"
484
485 test_3() {
486     local file=$DIR/$tfile
487
488     # create file
489     echo "aaaaaaaaaaaaaaaaa" > $file
490     chmod 0666 $file
491     $CHECKSTAT -p 0666 $file || error "$UID checkstat error"
492     $RUNAS $CHECKSTAT -p 0666 $file || error "$RUNAS_ID checkstat error"
493     $RUNAS cat $file > /dev/null || error "$RUNAS_ID cat error"
494
495     # start multiop
496     $RUNAS multiop $file o_r &
497     OPPID=$!
498     # wait multiop finish its open()
499     sleep 1
500
501     # cleanup all cred/ctx and check
502     # metadata check should fail, but file data check should success
503     # because we always use root credential to OSTs
504     $RUNAS kdestroy
505     $RUNAS $LFS flushctx
506     echo "destroied credentials/contexs for $RUNAS_ID"
507     $RUNAS $CHECKSTAT -p 0666 $file && error "checkstat succeed"
508     kill -s 10 $OPPID
509     wait $OPPID || error "read file data failed"
510     echo "read file data OK"
511
512     # restore and check again
513     restore_krb5_cred
514     echo "restored credentials for $RUNAS_ID"
515     $RUNAS $CHECKSTAT -p 0666 $file || error "$RUNAS_ID checkstat (2) error"
516     echo "$RUNAS_ID checkstat OK"
517     $CHECKSTAT -p 0666 $file || error "$UID checkstat (2) error"
518     echo "$UID checkstat OK"
519     $RUNAS cat $file > /dev/null || error "$RUNAS_ID cat (2) error"
520     echo "$RUNAS_ID read file data OK"
521 }
522 run_test 3 "local cache under DLM lock"
523
524 test_4() {
525     local file1=$DIR/$tfile-1
526     local file2=$DIR/$tfile-2
527
528     ! $GSS_PIPEFS && skip "pipefs not used" && return
529
530     chmod 0777 $DIR || error "chmod $DIR failed"
531     # current access should be ok
532     $RUNAS touch $file1 || error "can't touch $file1"
533     [ -f $file1 ] || error "$file1 not found"
534
535     # stop lgssd
536     send_sigint client lgssd
537     sleep 5
538     check_gss_daemon_facet client lgssd && error "lgssd still running"
539
540     # flush context, and touch
541     $RUNAS $LFS flushctx
542     $RUNAS touch $file2 &
543     TOUCHPID=$!
544     echo "waiting touch pid $TOUCHPID"
545     wait $TOUCHPID && error "touch should fail"
546
547     # restart lgssd
548     do_facet client "$LGSSD -v"
549     sleep 5
550     check_gss_daemon_facet client lgssd
551
552     # touch new should succeed
553     $RUNAS touch $file2 || error "can't touch $file2"
554     [ -f $file2 ] || error "$file2 not found"
555 }
556 run_test 4 "lgssd dead, operations should wait timeout and fail"
557
558 test_5() {
559     local file1=$DIR/$tfile-1
560     local file2=$DIR/$tfile-2
561     local wait_time=$((TIMEOUT + TIMEOUT / 2))
562
563     chmod 0777 $DIR || error "chmod $DIR failed"
564     # current access should be ok
565     $RUNAS touch $file1 || error "can't touch $file1"
566     [ -f $file1 ] || error "$file1 not found"
567
568     # stop lsvcgssd
569     send_sigint mds lsvcgssd
570     sleep 5
571     check_gss_daemon_facet mds lsvcgssd && error "lsvcgssd still running"
572
573     # flush context, and touch
574     $RUNAS $LFS flushctx
575     $RUNAS touch $file2 &
576     TOUCHPID=$!
577
578     # wait certain time
579     echo "waiting $wait_time seconds for touch pid $TOUCHPID"
580     sleep $wait_time
581     num=`ps --no-headers -p $TOUCHPID | wc -l`
582     [ $num -eq 1 ] || error "touch already ended ($num)"
583     echo "process $TOUCHPID still hanging there... OK"
584
585     # restart lsvcgssd, expect touch suceed
586     echo "restart lsvcgssd and recovering"
587     do_facet mds "$LSVCGSSD -v"
588     sleep 5
589     check_gss_daemon_facet mds lsvcgssd
590     wait $TOUCHPID || error "touch fail"
591     [ -f $file2 ] || error "$file2 not found"
592 }
593 run_test 5 "lsvcgssd dead, operations lead to recovery"
594
595 test_6() {
596     local nfile=10
597
598     mkdir $DIR/d6 || error "mkdir $DIR/d6 failed"
599     for ((i=0; i<$nfile; i++)); do
600         dd if=/dev/zero of=$DIR/d6/file$i bs=8k count=1 || error "dd file$i failed"
601     done
602     ls -l $DIR/d6/* > /dev/null || error "ls failed"
603     rm -rf $DIR2/d6/* || error "rm failed"
604     rmdir $DIR2/d6/ || error "rmdir failed"
605 }
606 run_test 6 "test basic DLM callback works"
607
608 test_7() {
609     local tdir=$DIR/d7
610     local num_osts
611
612     #
613     # for open(), client only reserve space for default stripe count lovea,
614     # and server may return larger lovea in reply (because of larger stripe
615     # count), client need call enlarge_reqbuf() and save the replied lovea
616     # in request for future possible replay.
617     #
618     # Note: current script does NOT guarantee enlarge_reqbuf() will be in
619     # the path, however it does work in local test which has 2 OSTs and
620     # default stripe count is 1.
621     #
622     num_osts=`$LFS getstripe $MOUNT | egrep "^[0-9]*:.*ACTIVE" | wc -l`
623     echo "found $num_osts active OSTs"
624     [ $num_osts -lt 2 ] && echo "skipping $TESTNAME (must have >= 2 OSTs)" && return
625
626     mkdir $tdir || error
627     $LFS setstripe $tdir 0 -1 -1 || error
628
629     echo "creating..."
630     for ((i=0;i<20;i++)); do
631         dd if=/dev/zero of=$tdir/f$i bs=4k count=16 2>/dev/null
632     done
633     echo "reading..."
634     for ((i=0;i<20;i++)); do
635         dd if=$tdir/f$i of=/dev/null bs=4k count=16 2>/dev/null
636     done
637     rm -rf $tdir
638 }
639 run_test 7 "exercise enlarge_reqbuf()"
640
641 test_8()
642 {
643     debugsave
644     sysctl -w lnet.debug="other"
645     $LCTL dk > /dev/null
646
647     # sleep sometime in ctx handle
648     do_facet mds sysctl -w lustre.fail_val=60
649 #define OBD_FAIL_SEC_CTX_HDL_PAUSE       0x1204
650     do_facet mds sysctl -w lustre.fail_loc=0x1204
651
652     $RUNAS $LFS flushctx || error "can't flush ctx"
653
654     $RUNAS df $DIR &
655     DFPID=$!
656     echo "waiting df (pid $TOUCHPID) to finish..."
657     sleep 2 # give df a chance to really trigger context init rpc
658     do_facet mds sysctl -w lustre.fail_loc=0
659     wait $DFPID || error "df should have succeeded"
660
661     $LCTL dk | grep "Early reply #" || error "No early reply"
662     debugrestore
663 }
664 run_test 8 "Early reply sent for slow gss context negotiation"
665
666 #
667 # following tests will manipulate flavors and may end with any flavor set,
668 # so each test should not assume any start flavor.
669 #
670
671 test_50() {
672     local sample=$TMP/sanity-gss-8
673     local tdir=$MOUNT/dir8
674     local iosize="256K"
675     local hash_algs="adler32 crc32 md5 sha1 sha256 sha384 sha512 wp256 wp384 wp512"
676
677     # create sample file with aligned size for direct i/o
678     dd if=/dev/zero of=$sample bs=$iosize count=1 || error
679     dd conv=notrunc if=/etc/termcap of=$sample bs=$iosize count=1 || error
680
681     rm -rf $tdir
682     mkdir $tdir || error "create dir $tdir"
683
684     restore_to_default_flavor
685
686     for alg in $hash_algs; do
687         echo "Testing $alg..."
688         flavor=krb5i-bulki:$alg/null
689         set_rule $FSNAME any cli2ost $flavor
690         wait_flavor cli2ost $flavor $cnt_cli2ost
691
692         dd if=$sample of=$tdir/$alg oflag=direct,dsync bs=$iosize || error "$alg write"
693         diff $sample $tdir/$alg || error "$alg read"
694     done
695
696     rm -rf $tdir
697     rm -f $sample
698 }
699 run_test 50 "verify bulk hash algorithms works"
700
701 test_51() {
702     local s1=$TMP/sanity-gss-9.1
703     local s2=$TMP/sanity-gss-9.2
704     local s3=$TMP/sanity-gss-9.3
705     local s4=$TMP/sanity-gss-9.4
706     local tdir=$MOUNT/dir9
707     local s1_size=4194304   # n * pagesize (4M)
708     local s2_size=512       # n * blksize
709     local s3_size=111       # n * blksize + m
710     local s4_size=5         # m
711     local cipher_algs="arc4 aes128 aes192 aes256 cast128 cast256 twofish128 twofish256"
712
713     # create sample files for each situation
714     rm -f $s1 $s2 $s2 $s4
715     dd if=/dev/urandom of=$s1 bs=1M count=4 || error
716     dd if=/dev/urandom of=$s2 bs=$s2_size count=1 || error
717     dd if=/dev/urandom of=$s3 bs=$s3_size count=1 || error
718     dd if=/dev/urandom of=$s4 bs=$s4_size count=1 || error
719
720     rm -rf $tdir
721     mkdir $tdir || error "create dir $tdir"
722
723     restore_to_default_flavor
724
725     #
726     # different bulk data alignment will lead to different behavior of
727     # the implementation: (n > 0; 0 < m < encryption_block_size)
728     #  - full page i/o
729     #  - partial page, size = n * encryption_block_size
730     #  - partial page, size = n * encryption_block_size + m
731     #  - partial page, size = m
732     #
733     for alg in $cipher_algs; do
734         echo "Testing $alg..."
735         flavor=krb5p-bulkp:sha1/$alg
736         set_rule $FSNAME any cli2ost $flavor
737         wait_flavor cli2ost $flavor $cnt_cli2ost
738
739         # sync write
740         dd if=$s1 of=$tdir/$alg.1 oflag=dsync bs=1M || error "write $alg.1"
741         dd if=$s2 of=$tdir/$alg.2 oflag=dsync || error "write $alg.2"
742         dd if=$s3 of=$tdir/$alg.3 oflag=dsync || error "write $alg.3"
743         dd if=$s4 of=$tdir/$alg.4 oflag=dsync || error "write $alg.4"
744
745         # remount client
746         umount_client $MOUNT
747         umount_client $MOUNT2
748         mount_client $MOUNT
749         mount_client $MOUNT2
750
751         # read & compare
752         diff $tdir/$alg.1 $s1 || error "read $alg.1"
753         diff $tdir/$alg.2 $s2 || error "read $alg.2"
754         diff $tdir/$alg.3 $s3 || error "read $alg.3"
755         diff $tdir/$alg.4 $s4 || error "read $alg.4"
756     done
757
758     rm -rf $tdir
759     rm -f $sample
760 }
761 run_test 51 "bulk data alignment test under encryption mode"
762
763 test_90() {
764     if [ "$SLOW" = "no" ]; then
765         total=10
766     else
767         total=60
768     fi
769
770     restore_to_default_flavor
771     set_rule $FSNAME any any krb5p
772     wait_flavor all2all krb5p $cnt_all2all
773
774     start_dbench
775
776     for ((n=0;n<$total;n++)); do
777         sleep 2
778         check_dbench
779         echo "flush ctx ($n/$total) ..."
780         $LFS flushctx
781     done
782     check_dbench
783     stop_dbench
784 }
785 run_test 90 "recoverable from losing contexts under load"
786
787 test_99() {
788     local nrule_old=0
789     local nrule_new=0
790     local max=32
791
792     #
793     # general rules
794     #
795     nrule_old=`do_facet mgs lctl get_param -n mgs.MGS.live.$FSNAME 2>/dev/null \
796                | grep "$FSNAME.srpc.flavor." | wc -l`
797     echo "original general rules: $nrule_old"
798
799     for ((i = $nrule_old; i < $max; i++)); do
800         set_rule $FSNAME elan$i any krb5n || error "set rule $i"
801     done
802     set_rule $FSNAME elan100 any krb5n && error "set $max rule should fail"
803     for ((i = $nrule_old; i < $max; i++)); do
804         set_rule $FSNAME elan$i any || error "remove rule $i"
805     done
806
807     nrule_new=`do_facet mgs lctl get_param -n mgs.MGS.live.$FSNAME 2>/dev/null \
808                | grep "$FSNAME.srpc.flavor." | wc -l`
809     if [ $nrule_new != $nrule_old ]; then
810         error "general rule: $nrule_new != $nrule_old"
811     fi
812
813     #
814     # target-specific rules
815     #
816     nrule_old=`do_facet mgs lctl get_param -n mgs.MGS.live.$FSNAME 2>/dev/null \
817                | grep "$FSNAME-MDT0000.srpc.flavor." | wc -l`
818     echo "original target rules: $nrule_old"
819
820     for ((i = $nrule_old; i < $max; i++)); do
821         set_rule $FSNAME-MDT0000 elan$i any krb5i || error "set rule $i"
822     done
823     set_rule $FSNAME-MDT0000 elan100 any krb5i && error "set $max rule should fail"
824     for ((i = $nrule_old; i < $max; i++)); do
825         set_rule $FSNAME-MDT0000 elan$i any || error "remove rule $i"
826     done
827
828     nrule_new=`do_facet mgs lctl get_param -n mgs.MGS.live.$FSNAME 2>/dev/null \
829                | grep "$FSNAME-MDT0000.srpc.flavor." | wc -l`
830     if [ $nrule_new != $nrule_old ]; then
831         error "general rule: $nrule_new != $nrule_old"
832     fi
833 }
834 run_test 99 "maximum sptlrpc rules limitation"
835
836 error_dbench()
837 {
838     local err_str=$1
839
840     killall -9 dbench
841     sleep 1
842
843     error $err_str
844 }
845
846 test_100() {
847     # started from default flavors
848     restore_to_default_flavor
849
850     # running dbench background
851     start_dbench
852
853     #
854     # all: null -> krb5n -> krb5a -> krb5i -> krb5p -> plain
855     #
856     set_rule $FSNAME any any krb5n
857     wait_flavor all2all krb5n $cnt_all2all || error_dbench "1"
858     check_dbench
859
860     set_rule $FSNAME any any krb5a
861     wait_flavor all2all krb5a $cnt_all2all || error_dbench "2"
862     check_dbench
863
864     set_rule $FSNAME any any krb5i
865     wait_flavor all2all krb5i $cnt_all2all || error_dbench "3"
866     check_dbench
867
868     set_rule $FSNAME any any krb5p
869     wait_flavor all2all krb5p $cnt_all2all || error_dbench "4"
870     check_dbench
871
872     set_rule $FSNAME any any plain
873     wait_flavor all2all plain $cnt_all2all || error_dbench "5"
874     check_dbench
875
876     #
877     # M - M: krb5a
878     # C - M: krb5i
879     # M - O: krb5p
880     # C - O: krb5n
881     #
882     set_rule $FSNAME any mdt2mdt krb5a
883     wait_flavor mdt2mdt krb5a $cnt_mdt2mdt || error_dbench "6"
884     check_dbench
885
886     set_rule $FSNAME any cli2mdt krb5i
887     wait_flavor cli2mdt krb5i $cnt_cli2mdt || error_dbench "7"
888     check_dbench
889
890     set_rule $FSNAME any mdt2ost krb5p
891     wait_flavor mdt2ost krb5p $cnt_mdt2ost || error_dbench "8"
892     check_dbench
893
894     set_rule $FSNAME any cli2ost krb5n
895     wait_flavor cli2ost krb5n $cnt_cli2ost || error_dbench "9"
896     check_dbench
897
898     #
899     # * - MDT0: krb5p
900     # * - OST0: krb5i
901     #
902     # nothing should be changed because they are override by above dir rules
903     #
904     set_rule $FSNAME-MDT0000 any any krb5p
905     set_rule $FSNAME-OST0000 any any krb5i
906     wait_flavor mdt2mdt krb5a $cnt_mdt2mdt || error_dbench "10"
907     wait_flavor cli2mdt krb5i $cnt_cli2mdt || error_dbench "11"
908     check_dbench
909     wait_flavor mdt2ost krb5p $cnt_mdt2ost || error_dbench "12"
910     wait_flavor cli2ost krb5n $cnt_cli2ost || error_dbench "13"
911
912     #
913     # delete all dir-specific rules
914     #
915     set_rule $FSNAME any mdt2mdt
916     set_rule $FSNAME any cli2mdt
917     set_rule $FSNAME any mdt2ost
918     set_rule $FSNAME any cli2ost
919     wait_flavor mdt2mdt krb5p $((MDSCOUNT - 1)) || error_dbench "14"
920     wait_flavor cli2mdt krb5p $CLICOUNT || error_dbench "15"
921     check_dbench
922     wait_flavor mdt2ost krb5i $MDSCOUNT || error_dbench "16"
923     wait_flavor cli2ost krb5i $CLICOUNT || error_dbench "17"
924     check_dbench
925
926     #
927     # remove:
928     #  * - MDT0: krb5p
929     #  * - OST0: krb5i
930     #
931     set_rule $FSNAME-MDT0000 any any
932     set_rule $FSNAME-OST0000 any any || error_dbench "18"
933     wait_flavor all2all plain $cnt_all2all || error_dbench "19"
934     check_dbench
935
936     stop_dbench
937 }
938 run_test 100 "change security flavor on the fly under load"
939
940 switch_sec_test()
941 {
942     local count=$1
943     local flavor0=$2
944     local flavor1=$3
945     local flavor2=$4
946     local df_pid=0
947     local wait_time=$((TIMEOUT + TIMEOUT / 4))
948     local num
949
950     #
951     # stop gss daemon, then switch to flavor1 (which should be a gss flavor),
952     # and run a 'df' which should hanging, wait the request timeout and
953     # resend, then switch the flavor to another one. To exercise the code of
954     # switching ctx/sec for a resend request.
955     #
956     echo ">>>>>>>>>>>>>>> Testing $flavor0 -> $flavor1 -> $flavor2..."
957
958     echo "(0) set base flavor $flavor0"
959     set_rule $FSNAME any cli2mdt $flavor0
960     wait_flavor cli2mdt $flavor0 $count
961     df $MOUNT
962     if [ $? -ne 0 ]; then
963         error "initial df failed"
964     fi
965
966     stop_gss_daemons
967     sleep 1
968
969     echo "(1) $flavor0 -> $flavor1"
970     set_rule $FSNAME any cli2mdt $flavor1
971     wait_flavor cli2mdt $flavor1 $count
972     df $MOUNT &
973     df_pid=$!
974     sleep 1
975
976     echo "waiting $wait_time seconds for df ($df_pid)"
977     sleep $wait_time
978     num=`ps --no-headers -p $df_pid 2>/dev/null | wc -l`
979     [ $num -eq 1 ] || error "df already ended ($num)"
980     echo "process $df_pid is still hanging there... OK"
981
982     echo "(2) set end flavor $flavor2"
983     set_rule $FSNAME any cli2mdt $flavor2
984     wait_flavor cli2mdt $flavor2 $count
985     start_gss_daemons
986     wait $df_pid || error "df returned error"
987 }
988
989 test_101()
990 {
991     # started from default flavors
992     restore_to_default_flavor
993
994     switch_sec_test $cnt_cli2mdt null krb5n null
995     switch_sec_test $cnt_cli2mdt null krb5a null
996     switch_sec_test $cnt_cli2mdt null krb5i null
997     switch_sec_test $cnt_cli2mdt null krb5p null
998     switch_sec_test $cnt_cli2mdt null krb5i plain
999     switch_sec_test $cnt_cli2mdt plain krb5p plain
1000     switch_sec_test $cnt_cli2mdt plain krb5n krb5a
1001     switch_sec_test $cnt_cli2mdt krb5a krb5i krb5p
1002     switch_sec_test $cnt_cli2mdt krb5p krb5a krb5n
1003     switch_sec_test $cnt_cli2mdt krb5n krb5p krb5i
1004 }
1005 run_test 101 "switch ctx as well as sec for resending request"
1006
1007 error_102()
1008 {
1009     local err_str=$1
1010
1011     killall -9 dbench
1012     sleep 1
1013
1014     error $err_str
1015 }
1016
1017 test_102() {
1018     # started from default flavors
1019     restore_to_default_flavor
1020
1021     # run dbench background
1022     start_dbench
1023
1024     echo "Testing null->krb5n->krb5a->krb5i->krb5p->plain->null"
1025     set_rule $FSNAME any any krb5n
1026     set_rule $FSNAME any any krb5a
1027     set_rule $FSNAME any any krb5i
1028     set_rule $FSNAME any any krb5p
1029     set_rule $FSNAME any any plain
1030     set_rule $FSNAME any any null
1031
1032     check_dbench
1033     wait_flavor all2all null $cnt_all2all || error_dbench "1"
1034     check_dbench
1035
1036     echo "waiting for 15s and check again"
1037     sleep 15
1038     check_dbench
1039
1040     echo "Testing null->krb5i->null->krb5i->null..."
1041     for ((i=0; i<10; i++)); do
1042         set_rule $FSNAME any any krb5i
1043         set_rule $FSNAME any any null
1044     done
1045     set_rule $FSNAME any any krb5i
1046
1047     check_dbench
1048     wait_flavor all2all krb5i $cnt_all2all || error_dbench "2"
1049     check_dbench
1050
1051     echo "waiting for 15s and check again"
1052     sleep 15
1053     check_dbench
1054
1055     stop_dbench
1056 }
1057 run_test 102 "survive from insanely fast flavor switch"
1058
1059 equals_msg `basename $0`: test complete, cleaning up
1060 check_and_cleanup_lustre
1061 [ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG || true