Whamcloud - gitweb
land b_md onto HEAD. the highlights:
[fs/lustre-release.git] / lustre / tests / common.sh
1 #!/bin/sh
2 export PATH=$PATH:/sbin:/usr/sbin
3
4 [ -d /r ] && R=/r
5
6 # check if running in source directory
7 # will probably need to create variable for each module.
8 if [ -f $SRCDIR/Makefile.am ]; then
9         USEDEV=yes
10         PORTALS=$SRCDIR/../../portals
11         LUSTRE=$SRCDIR/..
12
13         PTLCTL=$LUSTRE/utils/lctl
14         DBGCTL=$LUSTRE/utils/lctl
15         ACCEPTOR=$PORTALS/linux/utils/acceptor
16
17         OBDCTL=$LUSTRE/utils/lctl
18 else
19         USEDEV=no
20         # should have configure set the paths here
21         BINDIR=/usr/sbin
22         PORTALS=/lib/modules
23         LUSTRE=/lib/modules
24
25         PTLCTL=$BINDIR/lctl
26         DBGCTL=$BINDIR/lctl
27         ACCEPTOR=$BINDIR/acceptor
28         OBDCTL=$BINDIR/lctl
29 fi
30
31 LOOPNUM=0; export LOOPNUM
32 if [ -b /dev/loop0 ]; then
33         LOOP=/dev/loop
34 elif [ -b /dev/loop/0 ]; then
35         LOOP=/dev/loop/
36 else
37         echo "Cannot find /dev/loop0 or /dev/loop/0" 1>&2 && exit -1
38 fi
39
40 do_insmod() {
41         MODULE=$1
42         BASE=`echo $MODULE | sed -e "s^.*/^^" -e "s/\.o$//"`
43
44         lsmod | grep -q "\<$BASE\>" && return 0
45         [ "$MODULE" ] || fail "usage: $0 <module>"
46
47         if [ "$USEDEV" = "yes" ]; then
48                 [ -f $MODULE ] || echo "$0: module '$MODULE' not found" 1>&2
49                 insmod $MODULE
50         else
51                 modprobe $BASE
52         fi
53 }
54
55 do_rmmod() {
56         MODULE=$1
57         [ "$MODULE" ] || fail "usage: $0 <module>"
58         lsmod | grep -q $MODULE || return 0
59         rmmod $MODULE || lsmod | sed "s/^/$MODULE failed: /"
60 }
61
62 # Return the next unused loop device on stdout and in the $LOOPDEV
63 # environment variable.
64 next_loop_dev() {
65         NEXT=
66         while [ -b ${LOOP}${LOOPNUM} ]; do
67                 LOOPDEV=${LOOP}${LOOPNUM}
68                 losetup ${LOOPDEV} > /dev/null 2>&1 || NEXT=${LOOPDEV}
69                 LOOPNUM=`expr ${LOOPNUM} + 1`
70                 [ "$NEXT" ] && echo ${NEXT} && break
71         done
72 }
73
74 # Create a new filesystem.  If we are using a loopback device, we check
75 # for existing "template" filesystems instead of creating a new one,
76 # because it is _much_ faster to gunzip the empty filesystem instead of
77 # creating a new one from scratch.  Conversely, if we are creating a
78 # filesystem on a device we use mkfs, because that only writes sparsely
79 # to the device.  The empty filesystems are also highly compressed (1000:1)
80 # so they don't take too much space.
81 #
82 new_fs_usage() {
83         echo "new_fs <fstype> {device | file} [size]" 1>&2
84         exit -1
85 }
86 new_fs () {
87         EFILE="$1_$3.gz"
88         MKFS="mkfs.$1"
89         MKFSOPT="-b 4096"
90
91         [ "$1" = "ext3" ] && MKFS="mkfs.ext2 -j"
92         if [ "$1" = "extN" ]; then
93                 MKFS="mkfs.ext2 -j"
94                 EFILE="ext3_$3.gz"
95         fi
96
97         if [ -b "$2" ]; then
98                 [ $# -lt 2 -o $# -gt 3 ] && new_fs_usage
99
100                 PM="/proc/mounts"
101                 [ -r "$PM" ] || PM="/etc/mtab"
102
103                 grep "$2 " $PM 1>&2 && echo "$0: $2 is in $PM!" 1>&2 && exit -1
104
105                 $MKFS $MKFSOPT $2 $3 || exit -1
106                 LOOPDEV=$2      # Not really a loop device
107         else
108                 [ $# -ne 3 ] && new_fs_usage
109
110                 if [ -r "$EFILE" ]; then
111                         echo "using prepared filesystem $EFILE for $2"
112                         zcat "$EFILE" > $2 || exit -1
113                         sync
114                 else
115                         echo "creating new sparse filesystem on $2"
116                         dd if=/dev/zero of=$2 bs=1k seek=$3 count=1 1>&2 || exit -1
117                         $MKFS $MKFSOPT -F $2 1>&2 || exit -1
118                 fi
119                 LOOPDEV=`next_loop_dev`
120                 losetup ${LOOPDEV} $2 1>&2 || exit -1
121         fi
122
123         # Enable hash-indexed directories for extN filesystems
124         [ "$1" = "extN" ] && echo "feature FEATURE_C5" | debugfs -w $2
125 }
126
127 # Set up to use an existing filesystem.  We take the same parameters as
128 # new_fs, even though we only use the <fstype> and <file> parameters, to
129 # make it easy to convert between new_fs and old_fs in testing scripts.
130 old_fs () {
131         [ -e $2 ] || exit -1
132
133         if [ -b "$2" ]; then
134                 LOOPDEV=$2      # Not really a loop device
135         else
136                 LOOPDEV=`next_loop_dev`
137                 losetup ${LOOPDEV} $2 1>&2 || exit -1
138         fi
139 }
140
141 list_mods() {
142         $DBGCTL modules > $R/tmp/ogdb
143         echo "The GDB module script is in $R/tmp/ogdb"
144         [ "$DEBUG_WAIT" = "yes" ] && echo -n "Press ENTER to continue" && read < /dev/tty
145         return 0
146 }
147
148 # start acceptor for a given network and port.
149 # not all networks need an acceptor
150 start_acceptor() {
151         case $NETWORK in
152         elan)   [ "$PORT" ] && fail "$0: NETWORK is elan but PORT is set"
153                 ;;
154         tcp)    [ "$PORT" ] || fail "$0: NETWORK is tcp but PORT is not set"
155                 $ACCEPTOR -r 1048576 -s 1048576 $PORT
156                 ;;
157         *)      fail "$0: unknown NETWORK '$NETWORK'" ;;
158         esac
159
160 }
161
162 # We need at least one setup file to be given.  It can be passed on
163 # the command-line, or it can be found in the home directory, or it
164 # can even be sourced into the current shell environment.
165 setup_opts() {
166         DEF=/etc/lustre/lustre.cfg
167         if [ "$#" = 0 -a -r $DEF ]; then
168                 . $DEF && SETUP=y
169         fi
170
171         for CFG in "$@" ; do
172                 case $CFG  in
173                 *.cfg) [ -r "$CFG" ] && . $CFG && SETUP=y ;;
174                 *) echo "unknown option '$CFG'" 1>&2
175                 esac
176         done
177
178         if [ "$SETUP" != "y" ]; then
179                 echo "error: no config file on command-line and no $DEF" 1>&2
180                 exit -1
181         fi
182         
183         [ "$MDC_NAMES" ] || export MDC_NAMES=MDCDEV
184         [ "$OSC_NAMES" ] || export OSC_NAMES=OSCDEV
185         [ -z "$MOUNT_LIST" -a "$OSCMT" ] && export MOUNT_LIST="MT" && export MT="$OSCMT OSCDEV MDCDEV"
186 }
187
188 setup_variables() {
189         [ -z "$OSTNODE" ] && OSTNODE=$SERVER
190         [ -z "$MDSNODE" ] && MDSNODE=$SERVER
191         [ -z "$DLM" ] && DLM=$SERVER
192 }
193
194 setup_portals() {
195         setup_variables
196
197         if egrep -q "ksocknal|kqswnal" /proc/modules; then
198                 echo "$0: portals already appears to be set up, skipping"
199                 return 0
200         fi
201
202         if [ -z "$NETWORK" -o -z "$LOCALHOST" ]; then
203                 echo "$0: NETWORK or LOCALHOST is not set" 1>&2
204                 exit -1
205         fi
206
207         if [ -z "$OSTNODE" -a -z "$MDSNODE" -a -z "$DLM" ]; then
208                 echo "$0: SERVER (or OSTNODE and MDSNODE and DLM) not set" 1>&2
209                 exit -1
210         fi
211
212         [ -c /dev/portals ] || mknod /dev/portals c 10 240
213
214         do_insmod $PORTALS/linux/oslib/portals.o || exit -1
215         #do_insmod $PORTALS/linux/router/kptlrouter.o || exit -1
216
217         case $NETWORK in
218         elan)  do_insmod $PORTALS/linux/rqswnal/kqswnal.o || exit -1
219                 MYNID=
220                 RECV_MEM=
221                 SEND_MEM=
222                     ;;
223         tcp)   do_insmod $PORTALS/linux/socknal/ksocknal.o || exit -1
224                 MYNID="mynid $LOCALHOST"
225                 RECV_MEM="recv_mem 1048576"
226                 SEND_MEM="send_mem 1048576"
227                    ;;
228         *)      fail "$0: unknown NETWORK '$NETWORK'" ;;
229         esac
230
231         start_acceptor
232
233         $PTLCTL <<- EOF
234         network $NETWORK
235         $SEND_MEM
236         $RECV_MEM
237         $MYNID
238         connect $DLM $PORT
239         add_uuid $DLM $DLM
240         add_uuid self $LOCALHOST
241         quit
242         EOF
243
244         if [ "$SETUP_MDS" -o "$SETUP_MDC" ]; then
245                 $PTLCTL <<- EOF
246                 network $NETWORK
247                 connect $MDSNODE $PORT
248                 add_uuid $MDSNODE $MDSNODE
249                 quit
250                 EOF
251         fi
252
253
254         if [ "$SETUP_OST" -o "$SETUP_OSC" ]; then
255                 $PTLCTL <<- EOF
256                 network $NETWORK
257                 connect $OSTNODE $PORT
258                 add_uuid $OSTNODE $OSTNODE
259                 quit
260                 EOF
261         fi
262 }
263
264 setup_lustre() {
265         [ -c /dev/obd ] || mknod /dev/obd c 10 241
266
267         do_insmod $LUSTRE/obdclass/obdclass.o || exit -1
268         do_insmod $LUSTRE/ptlrpc/ptlrpc.o || exit -1
269         do_insmod $LUSTRE/ldlm/ldlm.o || exit -1
270         do_insmod $LUSTRE/extN/extN.o || \
271                 echo "info: can't load extN.o module, not fatal if using ext3"
272         do_insmod $LUSTRE/mds/mds.o || exit -1
273         #do_insmod $LUSTRE/obdclass/fsfilt_ext2.o || exit -1
274         #do_insmod $LUSTRE/obdclass/fsfilt_ext3.o || exit -1
275         do_insmod $LUSTRE/obdclass/fsfilt_extN.o || \
276                 echo "info: can't load fsfilt_extN.o module, needs extN.o"
277         do_insmod $LUSTRE/obdecho/obdecho.o || exit -1
278         #do_insmod $LUSTRE/obdext2/obdext2.o || exit -1
279         do_insmod $LUSTRE/obdfilter/obdfilter.o || exit -1
280         do_insmod $LUSTRE/ost/ost.o || exit -1
281         do_insmod $LUSTRE/osc/osc.o || exit -1
282         do_insmod $LUSTRE/mdc/mdc.o || exit -1
283                 do_insmod $LUSTRE/lov/lov.o || exit -1
284         do_insmod $LUSTRE/llite/llite.o || exit -1
285
286         echo "$R/tmp/lustre-log" > /proc/sys/portals/debug_path
287
288         if $OBDCTL name2dev RPCDEV > /dev/null 2>&1; then
289                 echo "$0: RPCDEV is already configured, skipping"
290                 return 0
291         fi
292         list_mods
293
294         $OBDCTL <<- EOF || return $?
295         newdev
296         attach ptlrpc RPCDEV
297         setup
298         quit
299         EOF
300
301         [ -d /mnt/lustre ] || mkdir /mnt/lustre
302 }
303
304 setup_ldlm() {
305         [ "$SETUP_LDLM" = "y" ] || return 0
306
307         [ -c /dev/portals ] || mknod /dev/portals c 10 240
308
309         $OBDCTL <<- EOF || return $?
310         newdev
311         attach ldlm LDLMDEV LDLMUUID
312         setup
313         quit
314         EOF
315 }
316
317 find_devno() {
318         if [ -z "$1" ]; then
319                 echo "usage: $0 <devname>" 1>&2
320                 return -1
321         fi
322
323         $OBDCTL name2dev $1
324 }
325
326 setup_mds() {
327         [ "$SETUP_MDS" = "y" ] || return 0
328
329         if [ -z "$MDSFS" -o -z "$MDSDEV" ]; then
330                 echo "error: setup_mds: MDSFS or MDSDEV unset" 1>&2
331                 return -1
332         fi
333
334         [ "$1" ] && DO_FS=$1
335         if [ "$DO_FS" != "new_fs" -a "$DO_FS" != "old_fs" ]; then
336                 echo "usage: setup_mds {new_fs|old_fs}" 1>&2
337                 return -1
338         fi
339
340         if $OBDCTL name2dev MDSDEV > /dev/null 2>&1; then
341                 echo "$0: MDSDEV is already configured"
342                 return 0
343         fi
344
345         $DO_FS ${MDSFS} ${MDSDEV} ${MDSSIZE}
346         MDS=${LOOPDEV}
347
348         $OBDCTL <<- EOF || return $?
349         newdev
350         attach mds MDSDEV MDSUUID
351         setup ${MDS} ${MDSFS}
352         quit
353         EOF
354 }
355
356 setup_mds_lov() { 
357         [ "$SETUP_MDS" = "y" ] || return 0
358
359         if [ -z "$LOVUUID" ]; then
360                 echo "No LOV configured"
361                         return
362         fi
363
364         $OBDCTL <<- EOF || return $?
365         name2dev MDSDEV
366         connect 
367         lov_setconfig ${LOVUUID} 1 65536 0 OSCDEV-`hostname`
368         disconnect
369         quit
370         EOF
371 }
372
373
374 setup_ost() {
375         [ "$SETUP_OST" = "y" ] || return 0
376
377         if [ -z "$OSTTYPE" ]; then
378                 echo "error: setup_ost: OSTTYPE unset" 1>&2
379                 return -1
380         fi
381
382         case $OSTTYPE in
383         obdecho)        OBD=
384                         OBDARG=
385                         NEED_FS=n
386                 ;;
387         obdext2)        OBDARG=
388                         NEED_FS=y
389                 ;;
390         obdfilter)      OBDARG=$OSTFS
391                         NEED_FS=y
392                 ;;
393         *)      echo "error: setup_ost: unknown OSTTYPE '$OSTTYPE'" 1>&2
394                 return -1
395                 ;;
396         esac
397
398         if $OBDCTL name2dev OBDDEV > /dev/null 2>&1; then
399                 echo "$0: OBDDEV is already configured"
400                 return 0
401         fi
402
403         if [ "$NEED_FS" = "y" ]; then
404                 [ "$1" ] && DO_FS=$1
405                 if [ -z "$OSTFS" -o -z "$OSTDEV" ]; then
406                         echo "error: setup_ost: OSTFS or OSTDEV unset" 1>&2
407                         return -1
408                 fi
409
410                 if [ "$DO_FS" != "new_fs" -a "$DO_FS" != "old_fs" ]; then
411                         echo "usage: setup_ost {new_fs|old_fs}" 1>&2
412                         return -1
413                 fi
414
415                 $DO_FS ${OSTFS} ${OSTDEV} ${OSTSIZE}
416                 OBD=${LOOPDEV}
417         fi
418
419         $OBDCTL <<- EOF || return $?
420         newdev
421         attach ${OSTTYPE} OBDDEV OBDUUID
422         setup ${OBD} ${OBDARG}
423         quit
424         EOF
425
426         $OBDCTL <<- EOF || return $?
427         newdev
428         attach ost OSTDEV OSTUUID
429         setup OBDUUID
430         quit
431         EOF
432 }
433
434 setup_server() {
435         #setup_mds $1 && setup_mds_lov $1 && setup_ost $1
436         setup_mds $1 && setup_ost $1
437 }
438
439 setup_osc() {
440         [ "$SETUP_OSC" != "y" ] && return 0
441         [ "$OSC_NAMES" ] || OSC_NAMES=OSCDEV
442
443         for THEOSC in $OSC_NAMES ; do 
444                 if $OBDCTL name2dev $THEOSC > /dev/null 2>&1; then
445                         echo "$0: OSCDEV is already configured"
446                         continue
447                 fi
448
449                 [ -z "$OBD_UUID" ] && OBD_UUID="OBDUUID"
450                 $OBDCTL <<- EOF || return $rc
451                 newdev
452                 attach osc $THEOSC ${THEOSC}-`hostname`
453                 setup $OBD_UUID $OSTNODE
454                 quit
455                 EOF
456         done
457 }
458
459 setup_mdc() {
460         [ "$SETUP_MDC" != "y" ] && return 0
461         [ "$MDC_NAMES" ] || MDC_NAMES=MDCDEV
462
463         for THEMDC in $MDC_NAMES ; do 
464                 if $OBDCTL name2dev $THEMDC > /dev/null 2>&1; then
465                         echo "$0: MDCDEV is already configured"
466                         continue
467                 fi
468
469                 $OBDCTL <<- EOF || return $?
470                 newdev
471                 attach mdc $THEMDC ${THEMDC}-`hostname`
472                 setup MDSUUID $MDSNODE
473                 quit
474                 EOF
475         done
476 }
477
478 setup_lov () { 
479         [ "$SETUP_MDC" != "y" ] && return 0
480
481         if [ -z "$LOVUUID" ]; then
482                 echo "No LOV configured"
483                 return
484         fi
485
486         $OBDCTL <<- EOF || return $?
487         newdev
488         attach lov LOVNAME ${LOVUUID}
489         setup MDCDEV-`hostname`
490         quit
491         EOF
492 }        
493
494
495 setup_mount() {
496         [ "$SETUP_MOUNT" != "y" ] && return 0
497
498         [ "$MOUNT_LIST" ] || fail "error: $0: MOUNT_LIST unset"
499
500         for THEMOUNT in $MOUNT_LIST; do
501             eval "echo \$$THEMOUNT" | while read MTPT THEOSC THEMDC; do
502                 if mount | grep -q $MTPT; then
503                     echo "$0: $MTPT is already mounted"
504                     return 0
505                 fi
506
507                 [ ! -d $MTPT ] && mkdir $MTPT
508                 echo mount -t lustre_lite -o osc=${THEOSC}-`hostname`,mdc=${THEMDC}-`hostname` none $MTPT
509                 mount -t lustre_lite -o osc=${THEOSC}-`hostname`,mdc=${THEMDC}-`hostname` none $MTPT
510             done
511         done
512 }
513
514 setup_client() {
515         # setup_osc && setup_mdc && setup_lov  && setup_mount
516         setup_osc && setup_mdc && setup_mount
517 }
518
519 DEBUG_ON="echo 0xffffffff > /proc/sys/portals/debug"
520 DEBUG_OFF="echo 0 > /proc/sys/portals/debug"
521
522 debug_server_off() {
523         echo "Turn OFF debug" && eval "$DEBUG_OFF"
524 }
525
526 debug_server_on() {
527         echo "Turn ON debug" && eval "$DEBUG_ON"
528 }
529
530 debug_client_off() {
531         echo "Turning OFF debug on client" && eval "$DEBUG_OFF"
532 }
533
534 debug_client_on() {
535         echo "Turning ON debug on client" && eval "$DEBUG_ON"
536 }
537
538 cleanup_portals() {
539         [ -z "$NETWORK" ] && NETWORK=tcp
540
541         setup_variables
542
543         $PTLCTL <<- EOF
544         network $NETWORK
545         disconnect
546         del_uuid self
547         del_uuid $MDSNODE
548         del_uuid $OSTNODE
549         del_uuid $DLM
550         quit
551         EOF
552
553         do_rmmod ldlm
554         do_rmmod ptlrpc
555         do_rmmod obdclass
556
557         do_rmmod kqswnal
558         do_rmmod ksocknal
559         do_rmmod kptlrouter
560
561         [ "$TIME" ] && $DBGCTL debug_kernel $R/tmp/debug.5.$TIME
562
563         do_rmmod portals
564 }
565
566 cleanup_lustre() {
567         killall acceptor
568
569         do_rmmod llite
570         do_rmmod lov
571         do_rmmod mdc
572         do_rmmod osc
573
574         do_rmmod fsfilt_extN
575         do_rmmod fsfilt_ext3
576         do_rmmod fsfilt_ext2
577         do_rmmod mds
578         do_rmmod ost
579         do_rmmod obdecho
580         do_rmmod obdfilter
581         do_rmmod obdext2
582         do_rmmod extN
583
584         losetup -d ${LOOP}0
585         losetup -d ${LOOP}1
586         losetup -d ${LOOP}2
587 }
588
589 cleanup_ldlm() {
590         [ "$SETUP" -a -z "$SETUP_LDLM" ] && return 0
591
592         LDLMDEVNO=`find_devno LDLMDEV`
593         if [ "$LDLMDEVNO" ]; then
594                 $OBDCTL <<- EOF
595                 device $LDLMDEVNO
596                 cleanup
597                 detach
598                 quit
599                 EOF
600         fi
601 }
602
603 cleanup_mds() {
604         [ "$SETUP" -a -z "$SETUP_MDS" ] && return 0
605
606         MDSDEVNO=`find_devno MDSDEV`
607         if [ "$MDSDEVNO" ]; then
608                 $OBDCTL <<- EOF
609                 device $MDSDEVNO
610                 cleanup
611                 detach
612                 quit
613                 EOF
614         fi
615 }
616
617 cleanup_ost() {
618         [ "$SETUP" -a -z "$SETUP_OST" ] && return 0
619
620         OSTDEVNO=`find_devno OSTDEV`
621         if [ "$OSTDEVNO" ]; then
622                 $OBDCTL <<- EOF
623                 device $OSTDEVNO
624                 cleanup
625                 detach
626                 quit
627                 EOF
628         fi
629
630         OBDDEVNO=`find_devno OBDDEV`
631         if [ "$OBDDEVNO" ]; then
632                 $OBDCTL <<- EOF
633                 device $OBDDEVNO
634                 cleanup
635                 detach
636                 quit
637                 EOF
638         fi
639 }
640
641 cleanup_server() {
642         cleanup_ost && cleanup_mds
643 }
644
645 cleanup_mount() {
646         [ "$SETUP_MOUNT" != "y" ] && return 0
647
648         [ "$MOUNT_LIST" ] || fail "error: $0: MOUNT_LIST unset"
649
650         for THEMOUNT in $MOUNT_LIST; do
651                 eval "echo \$$THEMOUNT" | while read MTPT THEOSC THEMDC; do
652                         if [ "`mount | grep $MTPT`" ]; then
653                                 umount $MTPT || fail "unable to unmount $MTPT"
654                         fi
655                 done
656         done
657 }
658
659 cleanup_osc() {
660         [ "$SETUP" -a -z "$SETUP_OSC" ] && return 0
661         [ "$OSC_NAMES" ] || OSC_NAMES=OSCDEV
662
663         for THEOSC in $OSC_NAMES ; do 
664                 OSCDEVNO=`find_devno $THEOSC`
665                 if [ "$OSCDEVNO" ]; then
666                         $OBDCTL <<- EOF
667                         device $OSCDEVNO
668                         cleanup
669                         detach
670                         quit
671                         EOF
672                 fi
673         done
674 }
675
676 cleanup_mdc() {
677         [ "$SETUP" -a -z "$SETUP_MDC" ] && return 0
678         [ "$MDC_NAMES" ] || MDC_NAMES=MDCDEV
679
680         for THEMDC in $MDC_NAMES ; do 
681                 MDCDEVNO=`find_devno $THEMDC`
682                 if [ "$MDCDEVNO" ]; then
683                         $OBDCTL <<- EOF
684                         device $MDCDEVNO
685                         cleanup
686                         detach
687                         quit
688                         EOF
689                 fi
690         done
691 }
692
693 cleanup_rpc() {
694         RPCDEVNO=`find_devno RPCDEV`
695         if [ "$RPCDEVNO" ]; then
696                 $OBDCTL <<- EOF
697                 device $RPCDEVNO
698                 cleanup
699                 detach
700                 quit
701                 EOF
702         fi
703 }
704
705 cleanup_client() {
706         cleanup_mount && cleanup_osc && cleanup_mdc && cleanup_rpc
707 }
708
709 fail() { 
710         echo "ERROR: $1" 1>&2
711         [ $2 ] && RC=$2 || RC=1
712         exit $RC
713 }