154cde14b9d3d471d54048b20d5caf6b3b47a2c8
[xfstests-dev.git] / common / rc
1 ##/bin/bash
2 #-----------------------------------------------------------------------
3 #  Copyright (c) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
4 #  This program is free software; you can redistribute it and/or modify
5 #  it under the terms of the GNU General Public License as published by
6 #  the Free Software Foundation; either version 2 of the License, or
7 #  (at your option) any later version.
8 #
9 #  This program is distributed in the hope that it will be useful,
10 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #  GNU General Public License for more details.
13 #
14 #  You should have received a copy of the GNU General Public License
15 #  along with this program; if not, write to the Free Software
16 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17 #  USA
18 #
19 #  Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
20 #  Mountain View, CA 94043, USA, or: http://www.sgi.com
21 #-----------------------------------------------------------------------
22
23 BC=$(which bc 2> /dev/null) || BC=
24
25 _require_math()
26 {
27         if [ -z "$BC" ]; then
28                 _notrun "this test requires 'bc' tool for doing math operations"
29         fi
30 }
31
32 _math()
33 {
34         [ $# -le 0 ] && return
35         if [ "$BC" ]; then
36                 result=$(LANG=C echo "scale=0; $@" | "$BC" -q 2> /dev/null)
37         else
38                 _notrun "this test requires 'bc' tool for doing math operations"
39         fi
40         echo "$result"
41 }
42
43 dd()
44 {
45    if [ "$HOSTOS" == "Linux" ]
46    then 
47         command dd --help | grep noxfer > /dev/null 2>&1
48         
49         if [ "$?" -eq 0 ]
50             then
51                 command dd status=noxfer $@
52             else
53                 command dd $@
54         fi
55    else
56         command dd $@
57    fi
58 }
59
60 _btrfs_get_subvolid()
61 {
62         mnt=$1
63         name=$2
64
65         $BTRFS_UTIL_PROG sub list $mnt | grep $name | awk '{ print $2 }'
66 }
67
68 # Prints the md5 checksum of a given file
69 _md5_checksum()
70 {
71         md5sum $1 | cut -d ' ' -f1
72 }
73
74
75 # ls -l w/ selinux sometimes puts a dot at the end:
76 # -rwxrw-r--. id1 id2 file1
77 # Also filter out lost+found directory on extN file system if present
78
79 _ls_l()
80 {
81         ls -l $* | sed "s/\(^[-rwxdlbcpsStT]*\)\. /\1 /" | grep -v 'lost+found'
82 }
83
84 # we need common/config
85 if [ "$iam" != "check" ]
86 then
87     if ! . ./common/config
88         then
89         echo "$iam: failed to source common/config"
90         exit 1
91     fi
92 fi
93
94 # check for correct setup
95 case "$FSTYP" in
96     xfs)
97          [ "$XFS_LOGPRINT_PROG" = "" ] && _fatal "xfs_logprint not found"
98          [ "$XFS_REPAIR_PROG" = "" ] && _fatal "xfs_repair not found"
99          [ "$XFS_DB_PROG" = "" ] && _fatal "xfs_db not found"
100          [ "$MKFS_XFS_PROG" = "" ] && _fatal "mkfs_xfs not found"
101          ;;
102     udf)
103          [ "$MKFS_UDF_PROG" = "" ] && _fatal "mkfs_udf/mkudffs not found"
104          ;;
105     btrfs)
106          [ "$MKFS_BTRFS_PROG" = "" ] && _fatal "mkfs.btrfs not found"
107          ;;
108     nfs)
109          ;;
110 esac
111
112 # make sure we have a standard umask
113 umask 022
114
115 _mount()
116 {
117     $MOUNT_PROG `_mount_ops_filter $*`
118 }
119
120 _scratch_options()
121 {
122     type=$1
123     SCRATCH_OPTIONS=""
124
125     if [ "$FSTYP" != "xfs" ]; then
126         return
127     fi
128
129     case $type in
130     mkfs)
131         [ "$HOSTOS" != "IRIX" ] && SCRATCH_OPTIONS="$SCRATCH_OPTIONS -f"
132         rt_opt="-r"
133         log_opt="-l"
134         ;;
135     mount)
136         rt_opt="-o"
137         log_opt="-o"
138         ;;
139     esac
140     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
141         SCRATCH_OPTIONS="$SCRATCH_OPTIONS ${rt_opt}rtdev=$SCRATCH_RTDEV"
142     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
143         SCRATCH_OPTIONS="$SCRATCH_OPTIONS ${log_opt}logdev=$SCRATCH_LOGDEV"
144 }
145
146 _test_options()
147 {
148     type=$1
149     TEST_OPTIONS=""
150
151     if [ "$FSTYP" != "xfs" ]; then
152         return
153     fi
154
155     case $type in
156     mkfs)
157         rt_opt="-r"
158         log_opt="-l"
159         ;;
160     mount)
161         rt_opt="-o"
162         log_opt="-o"
163         ;;
164     esac
165     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \
166         TEST_OPTIONS="$TEST_OPTIONS ${rt_opt}rtdev=$TEST_RTDEV"
167     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
168         TEST_OPTIONS="$TEST_OPTIONS ${log_opt}logdev=$TEST_LOGDEV"
169 }
170
171 _mount_ops_filter()
172 {
173     params="$*"
174     
175     #get mount point to handle dmapi mtpt option correctly
176     let last_index=$#-1
177     [ $last_index -gt 0 ] && shift $last_index
178     FS_ESCAPED=$1
179     
180     # irix is fussy about how it is fed its mount options
181     # - multiple -o's are not allowed
182     # - no spaces between comma delimitered options
183     # the sed script replaces all -o's (except the first) with a comma
184     # not required for linux, but won't hurt
185     
186     echo $params | sed -e 's/[[:space:]]\+-o[[:space:]]*/UnIqUe/1; s/[[:space:]]\+-o[[:space:]]*/,/g; s/UnIqUe/ -o /1' \
187         | sed -e 's/dmapi/dmi/' \
188         | $PERL_PROG -ne "s#mtpt=[^,|^\n|^\s]*#mtpt=$FS_ESCAPED\1\2#; print;"
189
190 }
191
192 _scratch_mount_options()
193 {
194     _scratch_options mount
195
196     echo $SCRATCH_OPTIONS $MOUNT_OPTIONS $SELINUX_MOUNT_OPTIONS $* $SCRATCH_DEV $SCRATCH_MNT
197 }
198
199 _scratch_mount()
200 {
201     _mount -t $FSTYP `_scratch_mount_options $*`
202 }
203
204 _scratch_unmount()
205 {
206     $UMOUNT_PROG $SCRATCH_DEV
207 }
208
209 _scratch_remount()
210 {
211     _scratch_unmount
212     _scratch_mount
213 }
214
215 _test_mount()
216 {
217     _test_options mount
218     _mount -t $FSTYP $TEST_OPTIONS $TEST_FS_MOUNT_OPTS $SELINUX_MOUNT_OPTIONS $* $TEST_DEV $TEST_DIR
219 }
220
221 _scratch_mkfs_options()
222 {
223     _scratch_options mkfs
224     echo $SCRATCH_OPTIONS $MKFS_OPTIONS $* $SCRATCH_DEV
225 }
226
227 _scratch_metadump()
228 {
229         dumpfile=$1
230         options=
231
232         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
233                 options="-l $SCRATCH_LOGDEV"
234
235         xfs_metadump $options $SCRATCH_DEV $dumpfile
236 }
237
238 _setup_large_xfs_fs()
239 {
240         fs_size=$1
241         local tmp_dir=/tmp/
242
243         [ "$LARGE_SCRATCH_DEV" != yes ] && return 0
244         [ -z "$SCRATCH_DEV_EMPTY_SPACE" ] && SCRATCH_DEV_EMPTY_SPACE=0
245         [ $SCRATCH_DEV_EMPTY_SPACE -ge $fs_size ] && return 0
246
247         # calculate the size of the file we need to allocate.
248         # Default free space in the FS is 50GB, but you can specify more via
249         # SCRATCH_DEV_EMPTY_SPACE
250         file_size=$(($fs_size - 50*1024*1024*1024))
251         file_size=$(($file_size - $SCRATCH_DEV_EMPTY_SPACE))
252
253         # mount the filesystem, create the file, unmount it
254         _scratch_mount 2>&1 >$tmp_dir/mnt.err
255         local status=$?
256         if [ $status -ne 0 ]; then
257                 echo "mount failed"
258                 cat $tmp_dir/mnt.err >&2
259                 rm -f $tmp_dir/mnt.err
260                 return $status
261         fi
262         rm -f $tmp_dir/mnt.err
263
264         xfs_io -F -f \
265                 -c "truncate $file_size" \
266                 -c "falloc -k 0 $file_size" \
267                 -c "chattr +d" \
268                 $SCRATCH_MNT/.use_space 2>&1 > /dev/null
269         export NUM_SPACE_FILES=1
270         status=$?
271         umount $SCRATCH_MNT
272         if [ $status -ne 0 ]; then
273                 echo "large file prealloc failed"
274                 cat $tmp_dir/mnt.err >&2
275                 return $status
276         fi
277         return 0
278 }
279
280 _scratch_mkfs_xfs_opts()
281 {
282         mkfs_opts=$*
283
284         _scratch_options mkfs
285
286         $MKFS_XFS_PROG $SCRATCH_OPTIONS $mkfs_opts $SCRATCH_DEV
287 }
288
289
290 _scratch_mkfs_xfs_supported()
291 {
292         mkfs_opts=$*
293
294         _scratch_options mkfs
295
296         $MKFS_XFS_PROG -N $MKFS_OPTIONS $SCRATCH_OPTIONS $mkfs_opts $SCRATCH_DEV
297 }
298
299 _scratch_mkfs_xfs()
300 {
301         # extra mkfs options can be added by tests
302         local extra_mkfs_options=$*
303
304         local tmp_dir=/tmp/
305
306         # save mkfs output in case conflict means we need to run again.
307         # only the output for the mkfs that applies should be shown
308         _scratch_mkfs_xfs_opts $MKFS_OPTIONS $extra_mkfs_options \
309                 2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
310         local mkfs_status=$?
311
312
313         # a mkfs failure may be caused by conflicts between
314         # $MKFS_OPTIONS and $extra_mkfs_options
315         if [ $mkfs_status -ne 0 -a ! -z "$extra_mkfs_options" ]; then
316                 (
317                 echo -n "** mkfs failed with extra mkfs options "
318                 echo "added to \"$MKFS_OPTIONS\" by test $seq **"
319                 echo -n "** attempting to mkfs using only test $seq "
320                 echo "options: $extra_mkfs_options **"
321                 ) >> $seqres.full
322
323                 # running mkfs again. overwrite previous mkfs output files
324                 _scratch_mkfs_xfs_opts $extra_mkfs_options \
325                         2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
326                 local mkfs_status=$?
327         fi
328
329         if [ $mkfs_status -eq 0 -a "$LARGE_SCRATCH_DEV" = yes ]; then
330                 # manually parse the mkfs output to get the fs size in bytes
331                 local fs_size
332                 fs_size=`cat $tmp_dir.mkfsstd | perl -ne '
333                         if (/^data\s+=\s+bsize=(\d+)\s+blocks=(\d+)/) {
334                                 my $size = $1 * $2;
335                                 print STDOUT "$size\n";
336                         }'`
337                 _setup_large_xfs_fs $fs_size
338                 mkfs_status=$?
339         fi
340
341         # output stored mkfs output
342         cat $tmp_dir.mkfserr >&2
343         cat $tmp_dir.mkfsstd
344         rm -f $tmp_dir.mkfserr $tmp_dir.mkfsstd
345
346         return $mkfs_status
347 }
348
349 # xfs_check script is planned to be deprecated. But, we want to
350 # be able to invoke "xfs_check" behavior in xfstests in order to
351 # maintain the current verification levels.
352 _xfs_check()
353 {
354     OPTS=" "
355     DBOPTS=" "
356     USAGE="Usage: xfs_check [-fsvV] [-l logdev] [-i ino]... [-b bno]... special"
357
358     while getopts "b:fi:l:stvV" c
359     do
360         case $c in
361             s) OPTS=$OPTS"-s ";;
362             t) OPTS=$OPTS"-t ";;
363             v) OPTS=$OPTS"-v ";;
364             i) OPTS=$OPTS"-i "$OPTARG" ";;
365             b) OPTS=$OPTS"-b "$OPTARG" ";;
366             f) DBOPTS=$DBOPTS" -f";;
367             l) DBOPTS=$DBOPTS" -l "$OPTARG" ";;
368             V) $XFS_DB_PROG -p xfs_check -V
369                 return $?
370                 ;;
371         esac
372     done
373     set -- extra $@
374     shift $OPTIND
375     case $# in
376         1)    ${XFS_DB_PROG}${DBOPTS} -F -i -p xfs_check -c "check$OPTS" $1
377                status=$?
378                ;;
379         2)    echo $USAGE 1>&1
380               status=2
381               ;;
382     esac
383     return $status
384 }
385
386 _setup_large_ext4_fs()
387 {
388         fs_size=$1
389         local tmp_dir=/tmp/
390
391         [ "$LARGE_SCRATCH_DEV" != yes ] && return 0
392         [ -z "$SCRATCH_DEV_EMPTY_SPACE" ] && SCRATCH_DEV_EMPTY_SPACE=0
393         [ $SCRATCH_DEV_EMPTY_SPACE -ge $fs_size ] && return 0
394
395         # Default free space in the FS is 50GB, but you can specify more via
396         # SCRATCH_DEV_EMPTY_SPACE
397         space_to_consume=$(($fs_size - 50*1024*1024*1024 - $SCRATCH_DEV_EMPTY_SPACE))
398
399         # mount the filesystem and create 16TB - 4KB files until we consume
400         # all the necessary space.
401         _scratch_mount 2>&1 >$tmp_dir/mnt.err
402         local status=$?
403         if [ $status -ne 0 ]; then
404                 echo "mount failed"
405                 cat $tmp_dir/mnt.err >&2
406                 rm -f $tmp_dir/mnt.err
407                 return $status
408         fi
409         rm -f $tmp_dir/mnt.err
410
411         file_size=$((16*1024*1024*1024*1024 - 4096))
412         nfiles=0
413         while [ $space_to_consume -gt $file_size ]; do
414
415                 xfs_io -F -f \
416                         -c "truncate $file_size" \
417                         -c "falloc -k 0 $file_size" \
418                         $SCRATCH_MNT/.use_space.$nfiles 2>&1
419                 status=$?
420                 if [ $status -ne 0 ]; then
421                         break;
422                 fi
423
424                 space_to_consume=$(( $space_to_consume - $file_size ))
425                 nfiles=$(($nfiles + 1))
426         done
427
428         # consume the remaining space.
429         if [ $space_to_consume -gt 0 ]; then
430                 xfs_io -F -f \
431                         -c "truncate $space_to_consume" \
432                         -c "falloc -k 0 $space_to_consume" \
433                         $SCRATCH_MNT/.use_space.$nfiles 2>&1
434                 status=$?
435         fi
436         export NUM_SPACE_FILES=$nfiles
437
438         umount $SCRATCH_MNT
439         if [ $status -ne 0 ]; then
440                 echo "large file prealloc failed"
441                 cat $tmp_dir/mnt.err >&2
442                 return $status
443         fi
444         return 0
445 }
446
447 _scratch_mkfs_ext4()
448 {
449         local tmp_dir=/tmp/
450
451         /sbin/mkfs -t $FSTYP -- -F $MKFS_OPTIONS $* $SCRATCH_DEV \
452                         2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
453         local mkfs_status=$?
454
455         if [ $mkfs_status -eq 0 -a "$LARGE_SCRATCH_DEV" = yes ]; then
456                 # manually parse the mkfs output to get the fs size in bytes
457                 fs_size=`cat $tmp_dir.mkfsstd | awk ' \
458                         /^Block size/ { split($2, a, "="); bs = a[2] ; } \
459                         / inodes, / { blks = $3 } \
460                         /reserved for the super user/ { resv = $1 } \
461                         END { fssize = bs * blks - resv; print fssize }'`
462
463                 _setup_large_ext4_fs $fs_size
464                 mkfs_status=$?
465         fi
466
467         # output stored mkfs output
468         cat $tmp_dir.mkfserr >&2
469         cat $tmp_dir.mkfsstd
470         rm -f $tmp_dir.mkfserr $tmp_dir.mkfsstd
471
472         return $mkfs_status
473 }
474
475 _test_mkfs()
476 {
477     case $FSTYP in
478     nfs*)
479         # do nothing for nfs
480         ;;
481     udf)
482         $MKFS_UDF_PROG $MKFS_OPTIONS $* $TEST_DEV > /dev/null
483         ;;
484     btrfs)
485         $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $TEST_DEV > /dev/null
486         ;;
487     *)
488         yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $TEST_DEV
489         ;;
490     esac
491 }
492
493 _scratch_mkfs()
494 {
495     case $FSTYP in
496     xfs)
497         _scratch_mkfs_xfs $*
498         ;;
499     nfs*)
500         # do nothing for nfs
501         ;;
502     udf)
503         $MKFS_UDF_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
504         ;;
505     btrfs)
506         $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV > /dev/null
507         ;;
508     ext4)
509         _scratch_mkfs_ext4 $*
510         ;;
511     tmpfs)
512         # do nothing for tmpfs
513         ;;
514     *)
515         yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $SCRATCH_DEV
516         ;;
517     esac
518 }
519
520 _scratch_pool_mkfs()
521 {
522     case $FSTYP in
523     btrfs)
524         $MKFS_BTRFS_PROG $MKFS_OPTIONS $* $SCRATCH_DEV_POOL > /dev/null
525         ;;
526     *)
527         echo "_scratch_pool_mkfs is not implemented for $FSTYP" 1>&2
528         ;;
529     esac
530 }
531
532 # Create fs of certain size on scratch device
533 # _scratch_mkfs_sized <size in bytes> [optional blocksize]
534 _scratch_mkfs_sized()
535 {
536     fssize=$1
537     blocksize=$2
538     [ -z "$blocksize" ] && blocksize=4096
539
540     re='^[0-9]+$'
541     if ! [[ $fssize =~ $re ]] ; then
542         _notrun "error: _scratch_mkfs_sized: fs size \"$fssize\" not an integer."
543     fi
544     if ! [[ $blocksize =~ $re ]] ; then
545         _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
546     fi
547
548     blocks=`expr $fssize / $blocksize`
549
550     if [ "$HOSTOS" == "Linux" ]; then
551         devsize=`blockdev --getsize64 $SCRATCH_DEV`
552         [ "$fssize" -gt "$devsize" ] && _notrun "Scratch device too small"
553     fi
554
555     case $FSTYP in
556     xfs)
557         # don't override MKFS_OPTIONS that set a block size.
558         echo $MKFS_OPTIONS |egrep -q "b?size="
559         if [ $? -eq 0 ]; then
560                 _scratch_mkfs_xfs -d size=$fssize
561         else
562                 _scratch_mkfs_xfs -d size=$fssize -b size=$blocksize
563         fi
564         ;;
565     ext2|ext3|ext4|ext4dev)
566         yes | ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
567         ;;
568     udf)
569         $MKFS_UDF_PROG $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
570         ;;
571     btrfs)
572         $MKFS_BTRFS_PROG $MKFS_OPTIONS -b $fssize $SCRATCH_DEV
573         ;;
574     *)
575         _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
576         ;;
577     esac
578 }
579
580 # Emulate an N-data-disk stripe w/ various stripe units
581 # _scratch_mkfs_geom <sunit bytes> <swidth multiplier> [optional blocksize]
582 _scratch_mkfs_geom()
583 {
584     sunit_bytes=$1
585     swidth_mult=$2
586     blocksize=$3
587     [ -z "$blocksize" ] && blocksize=4096
588
589     let sunit_blocks=$sunit_bytes/$blocksize
590     let swidth_blocks=$sunit_blocks*$swidth_mult
591
592     case $FSTYP in
593     xfs)
594         MKFS_OPTIONS+=" -b size=$blocksize, -d su=$sunit_bytes,sw=$swidth_mult"
595         ;;
596     ext4|ext4dev)
597         MKFS_OPTIONS+=" -b $blocksize -E stride=$sunit_blocks,stripe_width=$swidth_blocks"
598         ;;
599     *)
600         _notrun "can't mkfs $FSTYP with geometry"
601         ;;
602     esac
603     _scratch_mkfs
604 }
605
606 _scratch_resvblks()
607 {
608         case $FSTYP in
609         xfs)
610                 xfs_io -x -c "resblks $1" $SCRATCH_MNT
611                 ;;
612         *)
613                 ;;
614         esac
615 }
616
617 _scratch_xfs_db_options()
618 {
619     SCRATCH_OPTIONS=""
620     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
621         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
622     echo $SCRATCH_OPTIONS $* $SCRATCH_DEV
623 }
624
625 _scratch_xfs_logprint()
626 {
627     SCRATCH_OPTIONS=""
628     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
629         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
630     $XFS_LOGPRINT_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV
631 }
632
633 _scratch_xfs_check()
634 {
635     SCRATCH_OPTIONS=""
636     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
637         SCRATCH_OPTIONS="-l $SCRATCH_LOGDEV"
638     [ "$LARGE_SCRATCH_DEV" = yes ] && \
639         SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -t"
640     _xfs_check $SCRATCH_OPTIONS $* $SCRATCH_DEV
641 }
642
643 _scratch_xfs_repair()
644 {
645     SCRATCH_OPTIONS=""
646     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
647         SCRATCH_OPTIONS="-l$SCRATCH_LOGDEV"
648     [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
649         SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -r$SCRATCH_RTDEV"
650     [ "$LARGE_SCRATCH_DEV" = yes ] && SCRATCH_OPTIONS=$SCRATCH_OPTIONS" -t"
651     $XFS_REPAIR_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV
652 }
653
654 _get_pids_by_name()
655 {
656     if [ $# -ne 1 ]
657     then
658         echo "Usage: _get_pids_by_name process-name" 1>&2
659         exit 1
660     fi
661
662     # Algorithm ... all ps(1) variants have a time of the form MM:SS or
663     # HH:MM:SS before the psargs field, use this as the search anchor.
664     #
665     # Matches with $1 (process-name) occur if the first psarg is $1
666     # or ends in /$1 ... the matching uses sed's regular expressions,
667     # so passing a regex into $1 will work.
668
669     ps $PS_ALL_FLAGS \
670     | sed -n \
671         -e 's/$/ /' \
672         -e 's/[         ][      ]*/ /g' \
673         -e 's/^ //' \
674         -e 's/^[^ ]* //' \
675         -e "/[0-9]:[0-9][0-9]  *[^ ]*\/$1 /s/ .*//p" \
676         -e "/[0-9]:[0-9][0-9]  *$1 /s/ .*//p"
677 }
678
679 # fix malloc libs output
680 #
681 _fix_malloc()
682 {
683     # filter out the Electric Fence notice
684     $PERL_PROG -e '
685         while (<>) {
686             if (defined $o && /^\s+Electric Fence/) {
687                 chomp($o);
688                 print "$o";
689                 undef $o;
690                 next;
691             }
692             print $o if (defined $o);
693
694             $o=$_;
695         }
696         print $o if (defined $o);
697     '
698 }
699
700 # check if run as root
701 #
702 _need_to_be_root()
703 {
704     id=`id | $SED_PROG -e 's/(.*//' -e 's/.*=//'`
705     if [ "$id" -ne 0 ]
706     then
707         echo "Arrgh ... you need to be root (not uid=$id) to run this test"
708         exit 1
709     fi
710 }
711
712
713 #
714 # _df_device : get an IRIX style df line for a given device
715 #
716 #       - returns "" if not mounted
717 #       - returns fs type in field two (ala IRIX)
718 #       - joins line together if split by fancy df formatting
719 #       - strips header etc
720 #
721
722 _df_device()
723 {
724     if [ $# -ne 1 ]
725     then
726         echo "Usage: _df_device device" 1>&2
727         exit 1
728     fi
729
730     $DF_PROG 2>/dev/null | $AWK_PROG -v what=$1 '
731         match($1,what) && NF==1 {
732             v=$1
733             getline
734             print v, $0
735             exit
736         }
737         match($1,what) {
738             print
739             exit
740         }
741     '
742 }
743
744 #
745 # _df_dir : get an IRIX style df line for device where a directory resides
746 #
747 #       - returns fs type in field two (ala IRIX)
748 #       - joins line together if split by fancy df formatting
749 #       - strips header etc
750 #
751
752 _df_dir()
753 {
754     if [ $# -ne 1 ]
755     then
756         echo "Usage: _df_dir device" 1>&2
757         exit 1
758     fi
759
760     $DF_PROG $1 2>/dev/null | $AWK_PROG -v what=$1 '
761         NR == 2 && NF==1 {
762             v=$1
763             getline
764             print v, $0;
765             exit 0
766         }
767         NR == 2 {
768             print;
769             exit 0
770         }
771         {}
772     '
773     # otherwise, nada
774 }
775
776 # return percentage used disk space for mounted device
777
778 _used()
779 {
780     if [ $# -ne 1 ]
781     then
782         echo "Usage: _used device" 1>&2
783         exit 1
784     fi
785
786     _df_device $1 | $AWK_PROG '{ sub("%", "") ; print $6 }'
787 }
788
789 # return the FS type of a mounted device
790 #
791 _fs_type()
792 {
793     if [ $# -ne 1 ]
794     then
795         echo "Usage: _fs_type device" 1>&2
796         exit 1
797     fi
798
799     #
800     # The Linux kernel shows NFSv4 filesystems in df output as
801     # filesystem type nfs4, although we mounted it as nfs earlier.
802     # Fix the filesystem type up here so that the callers don't
803     # have to bother with this quirk.
804     #
805     _df_device $1 | $AWK_PROG '{ print $2 }' | sed -e 's/nfs4/nfs/'
806 }
807
808 # return the FS mount options of a mounted device
809 #
810 # should write a version which just parses the output of mount for IRIX
811 # compatibility, but since this isn't used at all, at the moment I'll leave
812 # this for now
813 #
814 _fs_options()
815 {
816     if [ $# -ne 1 ]
817     then
818         echo "Usage: _fs_options device" 1>&2
819         exit 1
820     fi
821
822     $AWK_PROG -v dev=$1 '
823         match($1,dev) { print $4 }
824     ' </proc/mounts
825 }
826
827 # returns device number if a file is a block device
828 #
829 _is_block_dev()
830 {
831     if [ $# -ne 1 ]
832     then
833         echo "Usage: _is_block_dev dev" 1>&2
834         exit 1
835     fi
836
837     _dev=$1
838     if [ -L "${_dev}" ]; then
839         _dev=`readlink -f ${_dev}`
840     fi
841
842     if [ -b "${_dev}" ]; then
843         src/lstat64 ${_dev} | $AWK_PROG '/Device type:/ { print $9 }'
844     fi
845 }
846
847 # Do a command, log it to $seqres.full, optionally test return status
848 # and die if command fails. If called with one argument _do executes the
849 # command, logs it, and returns its exit status. With two arguments _do
850 # first prints the message passed in the first argument, and then "done"
851 # or "fail" depending on the return status of the command passed in the
852 # second argument. If the command fails and the variable _do_die_on_error
853 # is set to "always" or the two argument form is used and _do_die_on_error
854 # is set to "message_only" _do will print an error message to
855 # $seqres.out and exit.
856
857 _do()
858 {
859     if [ $# -eq 1 ]; then
860         _cmd=$1
861     elif [ $# -eq 2 ]; then
862         _note=$1
863         _cmd=$2
864         echo -n "$_note... "
865     else
866         echo "Usage: _do [note] cmd" 1>&2
867         status=1; exit
868     fi
869
870     (eval "echo '---' \"$_cmd\"") >>$seqres.full
871     (eval "$_cmd") >$tmp._out 2>&1; ret=$?
872     cat $tmp._out | _fix_malloc >>$seqres.full
873     if [ $# -eq 2 ]; then
874         if [ $ret -eq 0 ]; then
875             echo "done"
876         else
877             echo "fail"
878         fi
879     fi
880     if [ $ret -ne 0  ] \
881         && [ "$_do_die_on_error" = "always" \
882             -o \( $# -eq 2 -a "$_do_die_on_error" = "message_only" \) ]
883     then
884         [ $# -ne 2 ] && echo
885         eval "echo \"$_cmd\" failed \(returned $ret\): see $seqres.full"
886         status=1; exit
887     fi
888
889     return $ret
890 }
891
892 # bail out, setting up .notrun file
893 #
894 _notrun()
895 {
896     echo "$*" > $seqres.notrun
897     echo "$seq not run: $*"
898     status=0
899     exit
900 }
901
902 # just plain bail out
903 #
904 _fail()
905 {
906     echo "$*" | tee -a $seqres.full
907     echo "(see $seqres.full for details)"
908     status=1
909     exit 1
910 }
911
912 # tests whether $FSTYP is one of the supported filesystems for a test
913 #
914 _supported_fs()
915 {
916     for f
917     do
918         if [ "$f" = "$FSTYP" -o "$f" = "generic" ]
919         then
920             return
921         fi
922     done
923
924     _notrun "not suitable for this filesystem type: $FSTYP"
925 }
926
927
928 # tests whether $FSTYP is one of the supported OSes for a test
929 #
930 _supported_os()
931 {
932     for h
933     do
934         if [ "$h" = "$HOSTOS" ]
935         then
936             return
937         fi
938     done
939
940     _notrun "not suitable for this OS: $HOSTOS"
941 }
942
943 # this test needs a scratch partition - check we're ok & unmount it
944 #
945 _require_scratch()
946 {
947     case "$FSTYP" in
948         nfs*)
949                  _notrun "requires a scratch device"
950                  ;;
951         tmpfs)
952                 if [ -z "$SCRATCH_DEV" -o ! -d "$SCRATCH_MNT" ];
953                 then
954                     _notrun "this test requires a valid \$SCRATCH_MNT and unique $SCRATCH_DEV"
955                 fi
956                 ;;
957         *)
958                  if [ -z "$SCRATCH_DEV" -o "`_is_block_dev $SCRATCH_DEV`" = "" ]
959                  then
960                      _notrun "this test requires a valid \$SCRATCH_DEV"
961                  fi
962                  if [ "`_is_block_dev $SCRATCH_DEV`" = "`_is_block_dev $TEST_DEV`" ]
963                  then
964                      _notrun "this test requires a valid \$SCRATCH_DEV"
965                  fi
966                 if [ ! -d "$SCRATCH_MNT" ]
967                 then
968                      _notrun "this test requires a valid \$SCRATCH_MNT"
969                 fi
970                  ;;
971     esac
972
973     # mounted?
974     if _mount | grep -q $SCRATCH_DEV
975     then
976         # if it's mounted, make sure its on $SCRATCH_MNT
977         if ! _mount | grep $SCRATCH_DEV | grep -q $SCRATCH_MNT
978         then
979             echo "\$SCRATCH_DEV is mounted but not on \$SCRATCH_MNT - aborting"
980             exit 1
981         fi
982         # and then unmount it
983         if ! $UMOUNT_PROG $SCRATCH_DEV
984         then
985             echo "failed to unmount $SCRATCH_DEV"
986             exit 1
987         fi
988     fi
989 }
990
991 # this test needs a logdev
992 #
993 _require_logdev()
994 {
995     [ -z "$SCRATCH_LOGDEV" -o ! -b "$SCRATCH_LOGDEV" ] && \
996         _notrun "This test requires a valid \$SCRATCH_LOGDEV"
997     [ "$USE_EXTERNAL" != yes ] && \
998         _notrun "This test requires USE_EXTERNAL to be enabled"
999
1000     # ensure its not mounted
1001     $UMOUNT_PROG $SCRATCH_LOGDEV 2>/dev/null
1002 }
1003
1004 # this test requires loopback device support
1005 #
1006 _require_loop()
1007 {
1008     if [ "$HOSTOS" != "Linux" ]
1009     then
1010         _notrun "This test requires linux for loopback device support"
1011     fi
1012
1013     modprobe loop >/dev/null 2>&1
1014     if grep loop /proc/devices >/dev/null 2>&1
1015     then
1016         :
1017     else
1018         _notrun "This test requires loopback device support"
1019     fi
1020 }
1021
1022 # this test requires ext2 filesystem support
1023 #
1024 _require_ext2()
1025 {
1026     if [ "$HOSTOS" != "Linux" ]
1027     then
1028         _notrun "This test requires linux for ext2 filesystem support"
1029     fi
1030
1031     modprobe ext2 >/dev/null 2>&1
1032     if grep ext2 /proc/filesystems >/dev/null 2>&1
1033     then
1034         :
1035     else
1036         _notrun "This test requires ext2 filesystem support"
1037     fi
1038 }
1039
1040 # this test requires that (large) loopback device files are not in use
1041 #
1042 _require_no_large_scratch_dev()
1043 {
1044     [ "$LARGE_SCRATCH_DEV" = yes ] && \
1045         _notrun "Large filesystem testing in progress, skipped this test"
1046 }
1047
1048 # this test requires that a realtime subvolume is in use, and
1049 # that the kernel supports realtime as well.
1050 #
1051 _require_realtime()
1052 {
1053     [ "$USE_EXTERNAL" = yes ] || \
1054         _notrun "External volumes not in use, skipped this test"
1055     [ "$SCRATCH_RTDEV" = "" ] && \
1056         _notrun "Realtime device required, skipped this test"
1057 }
1058
1059 # this test requires that a specified command (executable) exists
1060 # $1 - command, $2 - name for error message
1061 #
1062 _require_command()
1063 {
1064     [ -n "$1" ] && _cmd="$1" || _cmd="$2"
1065     [ -n "$1" -a -x "$1" ] || _notrun "$_cmd utility required, skipped this test"
1066 }
1067
1068 # this test requires the device mapper flakey target
1069 #
1070 _require_dm_flakey()
1071 {
1072     _require_command $DMSETUP_PROG
1073
1074     modprobe dm-flakey >/dev/null 2>&1
1075     $DMSETUP_PROG targets | grep flakey >/dev/null 2>&1
1076     if [ $? -eq 0 ]
1077     then
1078         :
1079     else
1080         _notrun "This test requires dm flakey support"
1081     fi
1082 }
1083
1084 # this test requires the projid32bit feature to be available in mkfs.xfs.
1085 #
1086 _require_projid32bit()
1087 {
1088        _scratch_mkfs_xfs_supported -i projid32bit=1 >/dev/null 2>&1 \
1089            || _notrun "mkfs.xfs doesn't have projid32bit feature"
1090 }
1091
1092 _require_projid16bit()
1093 {
1094         _scratch_mkfs_xfs_supported -i projid32bit=0 >/dev/null 2>&1 \
1095            || _notrun "16 bit project IDs not supported on $SCRATCH_DEV"
1096 }
1097
1098 # this test requires the crc feature to be available in mkfs.xfs
1099 #
1100 _require_xfs_mkfs_crc()
1101 {
1102         _scratch_mkfs_xfs_supported -m crc=1 >/dev/null 2>&1 \
1103            || _notrun "mkfs.xfs doesn't have crc feature"
1104 }
1105
1106 # this test requires the xfs kernel support crc feature
1107 #
1108 _require_xfs_crc()
1109 {
1110         _scratch_mkfs_xfs -m crc=1 >/dev/null 2>&1
1111         _scratch_mount >/dev/null 2>&1 \
1112            || _notrun "Kernel doesn't support crc feature"
1113         umount $SCRATCH_MNT
1114 }
1115
1116 # this test requires the finobt feature to be available in mkfs.xfs
1117 #
1118 _require_xfs_mkfs_finobt()
1119 {
1120         _scratch_mkfs_xfs_supported -m crc=1,finobt=1 >/dev/null 2>&1 \
1121            || _notrun "mkfs.xfs doesn't have finobt feature"
1122 }
1123
1124 # this test requires the xfs kernel support finobt feature
1125 #
1126 _require_xfs_finobt()
1127 {
1128         _scratch_mkfs_xfs -m crc=1,finobt=1 >/dev/null 2>&1
1129         _scratch_mount >/dev/null 2>&1 \
1130            || _notrun "Kernel doesn't support finobt feature"
1131         umount $SCRATCH_MNT
1132 }
1133
1134 # this test requires that external log/realtime devices are not in use
1135 #
1136 _require_nonexternal()
1137 {
1138     [ "$USE_EXTERNAL" = yes ] && \
1139         _notrun "External device testing in progress, skipped this test"
1140 }
1141
1142 # this test requires that a (specified) aio-dio executable exists
1143 # $1 - command (optional)
1144 #
1145 _require_aiodio()
1146 {
1147     if [ -z "$1" ]
1148     then
1149         AIO_TEST=src/aio-dio-regress/aiodio_sparse2
1150         [ -x $AIO_TEST ] || _notrun "aio-dio utilities required"
1151     else
1152         AIO_TEST=src/aio-dio-regress/$1
1153         [ -x $AIO_TEST ] || _notrun "$AIO_TEST not built"
1154     fi
1155 }
1156
1157 # run an aio-dio program
1158 # $1 - command
1159 _run_aiodio()
1160 {
1161     if [ -z "$1" ]
1162     then
1163         echo "usage: _run_aiodio command_name" 2>&1
1164         status=1; exit 1
1165     fi
1166
1167     _require_aiodio $1
1168
1169     local testtemp=$TEST_DIR/aio-testfile
1170     rm -f $testtemp
1171     $AIO_TEST $testtemp 2>&1
1172     status=$?
1173     rm -f $testtemp
1174
1175     return $status
1176 }
1177
1178 # indicate whether YP/NIS is active or not
1179 #
1180 _yp_active()
1181 {
1182         local dn
1183         dn=$(domainname 2>/dev/null)
1184         test -n "${dn}" -a "${dn}" != "(none)"
1185         echo $?
1186 }
1187
1188 # cat the password file
1189 #
1190 _cat_passwd()
1191 {
1192         [ $(_yp_active) -eq 0 ] && ypcat passwd
1193         cat /etc/passwd
1194 }
1195
1196 # cat the group file
1197 #
1198 _cat_group()
1199 {
1200         [ $(_yp_active) -eq 0 ] && ypcat group
1201         cat /etc/group
1202 }
1203
1204 # check for the fsgqa user on the machine
1205 #
1206 _require_user()
1207 {
1208     qa_user=fsgqa
1209     _cat_passwd | grep -q $qa_user
1210     [ "$?" == "0" ] || _notrun "$qa_user user not defined."
1211     echo /bin/true | su $qa_user
1212     [ "$?" == "0" ] || _notrun "$qa_user cannot execute commands."
1213 }
1214
1215 # check for the fsgqa group on the machine
1216 #
1217 _require_group()
1218 {
1219     qa_group=fsgqa
1220     _cat_group | grep -q $qa_group
1221     [ "$?" == "0" ] || _notrun "$qa_group user not defined."
1222 }
1223
1224 _filter_user_do()
1225 {
1226         perl -ne "
1227 s,.*Permission\sdenied.*,Permission denied,;
1228 s,.*no\saccess\sto\stty.*,,;
1229 s,.*no\sjob\scontrol\sin\sthis\sshell.*,,;
1230 s,^\s*$,,;
1231         print;"
1232 }
1233
1234 _user_do()
1235 {
1236     if [ "$HOSTOS" == "IRIX" ]
1237         then
1238         echo $1 | /bin/bash "su $qa_user 2>&1" | _filter_user_do
1239     else
1240         echo $1 | su $qa_user 2>&1 | _filter_user_do
1241     fi
1242 }
1243
1244 _require_xfs_io_command()
1245 {
1246         if [ $# -ne 1 ]
1247         then
1248                 echo "Usage: _require_xfs_io_command command" 1>&2
1249                 exit 1
1250         fi
1251         command=$1
1252
1253         testfile=$TEST_DIR/$$.xfs_io
1254         case $command in
1255         "falloc" )
1256                 testio=`$XFS_IO_PROG -F -f -c "falloc 0 1m" $testfile 2>&1`
1257                 ;;
1258         "fpunch" | "fcollapse" | "zero" | "fzero" )
1259                 testio=`$XFS_IO_PROG -F -f -c "pwrite 0 20k" -c "fsync" \
1260                         -c "$command 4k 8k" $testfile 2>&1`
1261                 ;;
1262         "fiemap")
1263                 testio=`$XFS_IO_PROG -F -f -c "pwrite 0 20k" -c "fsync" \
1264                         -c "fiemap -v" $testfile 2>&1`
1265                 ;;
1266         "flink" )
1267                 testio=`$XFS_IO_PROG -T -F -c "flink $testfile" \
1268                         $TEST_DIR 2>&1`
1269                 ;;
1270         *)
1271                 testio=`$XFS_IO_PROG -c "$command help" 2>&1`
1272         esac
1273
1274         rm -f $testfile 2>&1 > /dev/null
1275         echo $testio | grep -q "not found" && \
1276                 _notrun "xfs_io $command support is missing"
1277         echo $testio | grep -q "Operation not supported" && \
1278                 _notrun "xfs_io $command failed (old kernel/wrong fs?)"
1279 }
1280
1281 # Check that a fs has enough free space (in 1024b blocks)
1282 #
1283 _require_fs_space()
1284 {
1285         MNT=$1
1286         BLOCKS=$2       # in units of 1024
1287         let GB=$BLOCKS/1024/1024
1288
1289         FREE_BLOCKS=`df -klP $MNT | grep -v Filesystem | awk '{print $4}'`
1290         [ $FREE_BLOCKS -lt $BLOCKS ] && \
1291                 _notrun "This test requires at least ${GB}GB free on $MNT to run"
1292 }
1293
1294 #
1295 # Check if the filesystem supports sparse files.
1296 #
1297 # Unfortunately there is no better way to do this than a manual black list.
1298 #
1299 _require_sparse_files()
1300 {
1301     case $FSTYP in
1302     hfsplus)
1303         _notrun "Sparse files not supported by this filesystem type: $FSTYP"
1304         ;;
1305     *)
1306         ;;
1307     esac
1308 }
1309
1310 _require_debugfs()
1311 {
1312     #boot_params always present in debugfs
1313     [ -d "$DEBUGFS_MNT/boot_params" ] || _notrun "Debugfs not mounted"
1314 }
1315
1316 _require_fail_make_request()
1317 {
1318     [ -f "$DEBUGFS_MNT/fail_make_request/probability" ] \
1319         || _notrun "$DEBUGFS_MNT/fail_make_request \
1320  not found. Seems that CONFIG_FAIL_MAKE_REQUEST kernel config option not enabled"
1321 }
1322
1323 #
1324 # Check if the file system supports seek_data/hole
1325 #
1326 _require_seek_data_hole()
1327 {
1328     testfile=$TEST_DIR/$$.seek
1329     testseek=`$here/src/seek_sanity_test -t $testfile 2>&1`
1330     rm -f $testfile &>/dev/null
1331     echo $testseek | grep -q "Kernel does not support" && \
1332         _notrun "File system does not support llseek(2) SEEK_DATA/HOLE"
1333 }
1334
1335 # check that a FS on a device is mounted
1336 # if so, return mount point
1337 #
1338 _is_mounted()
1339 {
1340     if [ $# -ne 1 ]
1341     then
1342         echo "Usage: _is_mounted device" 1>&2
1343         exit 1
1344     fi
1345
1346     device=$1
1347
1348     if _mount | grep "$device " | $AWK_PROG -v pattern="type $FSTYP" '
1349         pattern        { print $3 ; exit 0 }
1350         END            { exit 1 }
1351     '
1352     then
1353         echo "_is_mounted: $device is not a mounted $FSTYP FS"
1354         exit 1
1355     fi
1356 }
1357
1358 # remount a FS to a new mode (ro or rw)
1359 #
1360 _remount()
1361 {
1362     if [ $# -ne 2 ]
1363     then
1364         echo "Usage: _remount device ro/rw" 1>&2
1365         exit 1
1366     fi
1367     device=$1
1368     mode=$2
1369
1370     if ! mount -o remount,$mode $device
1371     then
1372         echo "_remount: failed to remount filesystem on $device as $mode"
1373         exit 1
1374     fi
1375 }
1376
1377 # Run the appropriate repair/check on a filesystem
1378 #
1379 # if the filesystem is mounted, it's either remounted ro before being
1380 # checked or it's unmounted and then remounted
1381 #
1382
1383 # If set, we remount ro instead of unmounting for fsck
1384 USE_REMOUNT=0
1385
1386 _umount_or_remount_ro()
1387 {
1388     if [ $# -ne 1 ]
1389     then
1390         echo "Usage: _umount_or_remount_ro <device>" 1>&2
1391         exit 1
1392     fi
1393
1394     device=$1
1395     mountpoint=`_is_mounted $device`
1396
1397     if [ $USE_REMOUNT -eq 0 ]; then
1398         $UMOUNT_PROG $device
1399     else
1400         _remount $device ro
1401     fi
1402     echo "$mountpoint"
1403 }
1404
1405 _mount_or_remount_rw()
1406 {
1407     if [ $# -ne 3 ]
1408     then
1409         echo "Usage: _mount_or_remount_rw <opts> <device> <mountpoint>" 1>&2
1410         exit 1
1411     fi
1412     mount_opts=$1
1413     device=$2
1414     mountpoint=$3
1415
1416     if [ $USE_REMOUNT -eq 0 ]
1417     then
1418         if ! _mount -t $FSTYP $mount_opts $device $mountpoint
1419         then
1420             echo "!!! failed to remount $device on $mountpoint"
1421             return 0 # ok=0
1422         fi
1423     else
1424         _remount $device rw
1425     fi
1426
1427     return 1 # ok=1
1428 }
1429
1430 # Check a generic filesystem in no-op mode; this assumes that the
1431 # underlying fsck program accepts "-n" for a no-op (check-only) run,
1432 # and that it will still return an errno for corruption in this mode.
1433 #
1434 # Filesystems which don't support this will need to define their
1435 # own check routine.
1436 #
1437 _check_generic_filesystem()
1438 {
1439     device=$1
1440
1441     # If type is set, we're mounted
1442     type=`_fs_type $device`
1443     ok=1
1444
1445     if [ "$type" = "$FSTYP" ]
1446     then
1447         # mounted ...
1448         mountpoint=`_umount_or_remount_ro $device`
1449     fi
1450
1451     fsck -t $FSTYP $FSCK_OPTIONS $device >$tmp.fsck 2>&1
1452     if [ $? -ne 0 ]
1453     then
1454         echo "_check_generic_filesystem: filesystem on $device is inconsistent (see $seqres.full)"
1455
1456         echo "_check_generic filesystem: filesystem on $device is inconsistent" >>$seqres.full
1457         echo "*** fsck.$FSTYP output ***"       >>$seqres.full
1458         cat $tmp.fsck                           >>$seqres.full
1459         echo "*** end fsck.$FSTYP output"       >>$seqres.full
1460
1461         ok=0
1462     fi
1463     rm -f $tmp.fsck
1464
1465     if [ $ok -eq 0 ]
1466     then
1467         echo "*** mount output ***"             >>$seqres.full
1468         _mount                                  >>$seqres.full
1469         echo "*** end mount output"             >>$seqres.full
1470     elif [ "$type" = "$FSTYP" ]
1471     then
1472         # was mounted ...
1473         _mount_or_remount_rw "$MOUNT_OPTIONS" $device $mountpoint
1474         ok=$?
1475     fi
1476
1477     if [ $ok -eq 0 ]; then
1478         status=1
1479         exit 1
1480     fi
1481
1482     return 0
1483 }
1484
1485 # run xfs_check and friends on a FS.
1486
1487 _check_xfs_filesystem()
1488 {
1489     if [ $# -ne 3 ]
1490     then
1491         echo "Usage: _check_xfs_filesystem device <logdev>|none <rtdev>|none" 1>&2
1492         exit 1
1493     fi
1494
1495     extra_mount_options=""
1496     device=$1
1497     if [ "$2" != "none" ]; then
1498         extra_log_options="-l$2"
1499         extra_mount_options="-ologdev=$2"
1500     fi
1501
1502     if [ "$3" != "none" ]; then
1503         extra_rt_options="-r$3"
1504         extra_mount_options=$extra_mount_options" -ortdev=$3"
1505     fi
1506     extra_mount_options=$extra_mount_options" $MOUNT_OPTIONS"
1507
1508     [ "$FSTYP" != xfs ] && return 0
1509
1510     type=`_fs_type $device`
1511     ok=1
1512
1513     if [ "$type" = "xfs" ]
1514     then
1515         # mounted ...
1516         mountpoint=`_umount_or_remount_ro $device`
1517     fi
1518
1519     $XFS_LOGPRINT_PROG -t $extra_log_options $device 2>&1 \
1520                 | tee $tmp.logprint | grep -q "<CLEAN>"
1521     if [ $? -ne 0 -a "$HOSTOS" = "Linux" ]
1522     then
1523         echo "_check_xfs_filesystem: filesystem on $device has dirty log (see $seqres.full)"
1524
1525         echo "_check_xfs_filesystem: filesystem on $device has dirty log"   >>$seqres.full
1526         echo "*** xfs_logprint -t output ***"   >>$seqres.full
1527         cat $tmp.logprint                       >>$seqres.full
1528         echo "*** end xfs_logprint output"      >>$seqres.full
1529
1530         ok=0
1531     fi
1532
1533     # xfs_check runs out of memory on large files, so even providing the test
1534     # option (-t) to avoid indexing the free space trees doesn't make it pass on
1535     # large filesystems. Avoid it.
1536     if [ "$LARGE_SCRATCH_DEV" != yes ]; then
1537             _xfs_check $extra_log_options $device 2>&1 |\
1538                  _fix_malloc >$tmp.fs_check
1539     fi
1540     if [ -s $tmp.fs_check ]
1541     then
1542         echo "_check_xfs_filesystem: filesystem on $device is inconsistent (c) (see $seqres.full)"
1543
1544         echo "_check_xfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1545         echo "*** xfs_check output ***"         >>$seqres.full
1546         cat $tmp.fs_check                       >>$seqres.full
1547         echo "*** end xfs_check output"         >>$seqres.full
1548
1549         ok=0
1550     fi
1551
1552     $XFS_REPAIR_PROG -n $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1
1553     if [ $? -ne 0 ]
1554     then
1555         echo "_check_xfs_filesystem: filesystem on $device is inconsistent (r) (see $seqres.full)"
1556
1557         echo "_check_xfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1558         echo "*** xfs_repair -n output ***"     >>$seqres.full
1559         cat $tmp.repair | _fix_malloc           >>$seqres.full
1560         echo "*** end xfs_repair output"        >>$seqres.full
1561
1562         ok=0
1563     fi
1564     rm -f $tmp.fs_check $tmp.logprint $tmp.repair
1565
1566     if [ $ok -eq 0 ]
1567     then
1568         echo "*** mount output ***"             >>$seqres.full
1569         _mount                                  >>$seqres.full
1570         echo "*** end mount output"             >>$seqres.full
1571     elif [ "$type" = "xfs" ]
1572     then
1573         _mount_or_remount_rw "$extra_mount_options" $device $mountpoint
1574     fi
1575
1576     if [ $ok -eq 0 ]; then
1577         status=1
1578         exit 1
1579     fi
1580
1581     return 0
1582 }
1583
1584 # Filter the knowen errors the UDF Verifier reports.
1585 _udf_test_known_error_filter()
1586 {
1587         egrep -v "PVD  60  Error: Interchange Level: 1, Maximum Interchange Level: 0|FSD  28  Error: Interchange Level: 1, Maximum Interchange Level: 1,|PVD  72  Warning: Volume Set Identifier: \"\*IRIX UDF\",|Warning: [0-9]+ unused blocks NOT marked as unallocated."
1588
1589 }
1590
1591 _check_udf_filesystem()
1592 {
1593     [ "$DISABLE_UDF_TEST" == "1" ] && return
1594
1595     if [ $# -ne 1 -a $# -ne 2 ]
1596     then
1597         echo "Usage: _check_udf_filesystem device [last_block]" 1>&2
1598         exit 1
1599     fi
1600
1601     if [ ! -x $here/src/udf_test ]
1602     then
1603         echo "udf_test not installed, please download and build the Philips"
1604         echo "UDF Verification Software from http://www.extra.research.philips.com/udf/."
1605         echo "Then copy the udf_test binary to $here/src/."
1606         echo "If you do not wish to run udf_test then set environment variable DISABLE_UDF_TEST"
1607         echo "to 1."
1608         return
1609     fi
1610
1611     device=$1
1612     if [ $# -eq 2 ];
1613     then
1614         LAST_BLOCK=`expr \( $2 - 1 \)`
1615         OPT_ARG="-lastvalidblock $LAST_BLOCK"
1616     fi
1617
1618     rm -f $seqres.checkfs
1619     sleep 1 # Due to a problem with time stamps in udf_test
1620     $here/src/udf_test $OPT_ARG $device | tee $seqres.checkfs | egrep "Error|Warning" | \
1621         _udf_test_known_error_filter | \
1622         egrep -iv "Error count:.*[0-9]+.*total occurrences:.*[0-9]+|Warning count:.*[0-9]+.*total occurrences:.*[0-9]+" && \
1623         echo "Warning UDF Verifier reported errors see $seqres.checkfs."
1624 }
1625
1626 _check_xfs_test_fs()
1627 {
1628     TEST_LOG="none"
1629     TEST_RT="none"
1630     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \
1631         TEST_LOG="$TEST_LOGDEV"
1632
1633     [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ] && \
1634         TEST_RT="$TEST_RTDEV"
1635
1636     _check_xfs_filesystem $TEST_DEV $TEST_LOG $TEST_RT
1637
1638     # check for ipath consistency
1639     if $XFS_GROWFS_PROG -n $TEST_DIR | grep -q 'inode-paths=1'; then
1640         # errors go to stderr
1641         xfs_check_ipaths $TEST_DIR >/dev/null
1642         xfs_repair_ipaths -n $TEST_DIR >/dev/null
1643     fi
1644 }
1645
1646 _check_btrfs_filesystem()
1647 {
1648     device=$1
1649
1650     # If type is set, we're mounted
1651     type=`_fs_type $device`
1652     ok=1
1653
1654     if [ "$type" = "$FSTYP" ]
1655     then
1656         # mounted ...
1657         mountpoint=`_umount_or_remount_ro $device`
1658     fi
1659
1660     btrfsck $device >$tmp.fsck 2>&1
1661     if [ $? -ne 0 ]
1662     then
1663         echo "_check_btrfs_filesystem: filesystem on $device is inconsistent (see $seqres.full)"
1664
1665         echo "_check_btrfs_filesystem: filesystem on $device is inconsistent" >>$seqres.full
1666         echo "*** fsck.$FSTYP output ***"       >>$seqres.full
1667         cat $tmp.fsck                           >>$seqres.full
1668         echo "*** end fsck.$FSTYP output"       >>$seqres.full
1669
1670         ok=0
1671     fi
1672     rm -f $tmp.fsck
1673
1674     if [ $ok -eq 0 ]
1675     then
1676         echo "*** mount output ***"             >>$seqres.full
1677         _mount                                  >>$seqres.full
1678         echo "*** end mount output"             >>$seqres.full
1679     elif [ "$type" = "$FSTYP" ]
1680     then
1681         # was mounted ...
1682         _mount_or_remount_rw "$MOUNT_OPTIONS" $device $mountpoint
1683         ok=$?
1684     fi
1685
1686     if [ $ok -eq 0 ]; then
1687         status=1
1688         exit 1
1689     fi
1690
1691     return 0
1692 }
1693
1694 _check_test_fs()
1695 {
1696     case $FSTYP in
1697     xfs)
1698         _check_xfs_test_fs
1699         ;;
1700     nfs)
1701         # no way to check consistency for nfs
1702         ;;
1703     udf)
1704         # do nothing for now
1705         ;;
1706     btrfs)
1707         _check_btrfs_filesystem $TEST_DEV
1708         ;;
1709     tmpfs)
1710         # no way to check consistency for tmpfs
1711         ;;
1712     *)
1713         _check_generic_filesystem $TEST_DEV
1714         ;;
1715     esac
1716 }
1717
1718 _check_scratch_fs()
1719 {
1720     device=$SCRATCH_DEV
1721     [ $# -eq 1 ] && device=$1
1722
1723     case $FSTYP in
1724     xfs)
1725         SCRATCH_LOG="none"
1726         SCRATCH_RT="none"
1727         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
1728             SCRATCH_LOG="$SCRATCH_LOGDEV"
1729
1730         [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ] && \
1731             SCRATCH_RT="$SCRATCH_RTDEV"
1732
1733         _check_xfs_filesystem $device $SCRATCH_LOG $SCRATCH_RT
1734         ;;
1735     udf)
1736         _check_udf_filesystem $device $udf_fsize
1737         ;;
1738     nfs*)
1739         # Don't know how to check an NFS filesystem, yet.
1740         ;;
1741     btrfs)
1742         _check_btrfs_filesystem $device
1743         ;;
1744     tmpfs)
1745         # no way to check consistency for tmpfs
1746         ;;
1747     *)
1748         _check_generic_filesystem $device
1749         ;;
1750     esac
1751 }
1752
1753 _full_fstyp_details()
1754 {
1755      [ -z "$FSTYP" ] && FSTYP=xfs
1756      if [ $FSTYP = xfs ]; then
1757         if [ -d /proc/fs/xfs ]; then
1758             if grep -q 'debug 0' /proc/fs/xfs/stat; then
1759                 FSTYP="$FSTYP (non-debug)"
1760             elif grep -q 'debug 1' /proc/fs/xfs/stat; then
1761                 FSTYP="$FSTYP (debug)"
1762             fi
1763         else
1764             if uname -a | grep -qi 'debug'; then
1765                 FSTYP="$FSTYP (debug)"
1766             else
1767                 FSTYP="$FSTYP (non-debug)"
1768             fi
1769         fi
1770      fi
1771      echo $FSTYP
1772 }
1773
1774 _full_platform_details()
1775 {
1776      os=`uname -s`
1777      host=`hostname -s`
1778      kernel=`uname -r`
1779      platform=`uname -m`
1780      echo "$os/$platform $host $kernel"
1781 }
1782
1783 _link_out_file()
1784 {
1785         if [ -z "$1" -o -z "$2" ]; then
1786                 echo Error must pass src and dst.
1787                 exit
1788         fi
1789         rm -f $2
1790         if [ "`uname`" == "IRIX64" ] || [ "`uname`" == "IRIX" ]; then
1791                 ln -s $1.irix $2
1792         elif [ "`uname`" == "Linux" ]; then
1793                 ln -s $1.linux $2
1794         else
1795                 echo Error test $seq does not run on the operating system: `uname`
1796                 exit
1797         fi
1798 }
1799
1800 _die()
1801 {
1802         echo $@
1803         exit 1
1804 }
1805
1806 #takes files, randomdata
1807 _nfiles()
1808 {
1809         f=0
1810         while [ $f -lt $1 ]
1811         do
1812                 file=f$f
1813                 echo > $file
1814                 if [ $size -gt 0 ]; then
1815                     if [ "$2" == "false" ]; then
1816                         dd if=/dev/zero of=$file bs=1024 count=$size 2>&1 | _filter_dd
1817                     else
1818                         dd if=/dev/urandom of=$file bs=1024 count=$size 2>&1 | _filter_dd
1819                     fi
1820                 fi
1821                 let f=$f+1
1822         done
1823 }
1824
1825 # takes dirname, depth, randomdata
1826 _descend()
1827 {
1828         dirname=$1; depth=$2; randomdata=$3
1829         mkdir $dirname  || die "mkdir $dirname failed"
1830         cd $dirname
1831
1832         _nfiles $files $randomdata          # files for this dir and data type
1833
1834         [ $depth -eq 0 ] && return
1835         let deep=$depth-1 # go 1 down
1836
1837         [ $verbose = true ] && echo "descending, depth from leaves = $deep"
1838
1839         d=0
1840         while [ $d -lt $dirs ]
1841         do
1842                 _descend d$d $deep &
1843                 let d=$d+1
1844                 wait
1845         done
1846 }
1847
1848 # Populate a filesystem with inodes for performance experiments
1849 #
1850 # usage: populate [-v] [-n ndirs] [-f nfiles] [-d depth] [-r root] [-s size] [-x]
1851 #
1852 _populate_fs()
1853 {
1854     here=`pwd`
1855     dirs=5          # ndirs in each subdir till leaves
1856     size=0          # sizeof files in K
1857     files=100       # num files in _each_ subdir
1858     depth=2         # depth of tree from root to leaves
1859     verbose=false
1860     root=root       # path of initial root of directory tree
1861     randomdata=false # -x data type urandom or zero
1862
1863     OPTIND=1
1864     while getopts "d:f:n:r:s:v:x" c
1865     do
1866         case $c in
1867         d)      depth=$OPTARG;;
1868         n)      dirs=$OPTARG;;
1869         f)      files=$OPTARG;;
1870         s)      size=$OPTARG;;
1871         v)      verbose=true;;
1872         r)      root=$OPTARG;;
1873         x)      randomdata=true;;
1874         esac
1875     done
1876
1877     _descend $root $depth $randomdata
1878     wait
1879
1880     cd $here
1881
1882     [ $verbose = true ] && echo done
1883 }
1884
1885 # query whether the given file has the given inode flag set
1886 #
1887 _test_inode_flag()
1888 {
1889     flag=$1
1890     file=$2
1891
1892     if which $XFS_IO_PROG >/dev/null; then
1893         if $XFS_IO_PROG -r -c 'lsattr -v' "$file" | grep -q "$flag" ; then
1894             return 0
1895         fi
1896     fi
1897     return 1
1898 }
1899
1900 # query the given files extsize allocator hint in bytes (if any)
1901 #
1902 _test_inode_extsz()
1903 {
1904     file=$1
1905     blocks=""
1906
1907     if which $XFS_IO_PROG >/dev/null; then
1908         blocks=`$XFS_IO_PROG -r -c 'stat' "$file" | \
1909                 awk '/^xattr.extsize =/ { print $3 }'`
1910     fi
1911     [ -z "$blocks" ] && blocks="0"
1912     echo $blocks
1913 }
1914
1915 # scratch_dev_pool should contain the disks pool for the btrfs raid
1916 _require_scratch_dev_pool()
1917 {
1918         local i
1919         local ndevs
1920
1921         if [ -z "$SCRATCH_DEV_POOL" ]; then
1922                 _notrun "this test requires a valid \$SCRATCH_DEV_POOL"
1923         fi
1924
1925         if [ -z "$1" ]; then
1926                 ndevs=2
1927         else
1928                 ndevs=$1
1929         fi
1930
1931         # btrfs test case needs ndevs or more scratch_dev_pool; other FS not sure
1932         # so fail it
1933         case $FSTYP in
1934         btrfs)
1935                 if [ "`echo $SCRATCH_DEV_POOL|wc -w`" -lt $ndevs ]; then
1936                         _notrun "btrfs and this test needs $ndevs or more disks in SCRATCH_DEV_POOL"
1937                 fi
1938         ;;
1939         *)
1940                 _notrun "dev_pool is not supported by fstype \"$FSTYP\""
1941         ;;
1942         esac
1943
1944         for i in $SCRATCH_DEV_POOL; do
1945                 if [ "`_is_block_dev $i`" = "" ]; then
1946                         _notrun "this test requires valid block disk $i"
1947                 fi
1948                 if [ "`_is_block_dev $i`" = "`_is_block_dev $TEST_DEV`" ]; then
1949                         _notrun "$i is part of TEST_DEV, this test requires unique disks"
1950                 fi
1951                 if _mount | grep -q $i; then
1952                         if ! $UMOUNT_PROG $i; then
1953                             echo "failed to unmount $i - aborting"
1954                             exit 1
1955                         fi
1956                 fi
1957                 # to help better debug when something fails, we remove
1958                 # traces of previous btrfs FS on the dev.
1959                 dd if=/dev/zero of=$i bs=4096 count=100 > /dev/null 2>&1
1960         done
1961 }
1962
1963 # We will check if the device is deletable
1964 _require_deletable_scratch_dev_pool()
1965 {
1966         local i
1967         local x
1968         for i in $SCRATCH_DEV_POOL; do
1969                 x=`echo $i | cut -d"/" -f 3`
1970                 if [ ! -f /sys/class/block/${x}/device/delete ]; then
1971                         _notrun "$i is a device which is not deletable"
1972                 fi
1973         done
1974 }
1975
1976 # We check for btrfs and (optionally) features of the btrfs command
1977 _require_btrfs()
1978 {
1979         cmd=$1
1980         _require_command $BTRFS_UTIL_PROG btrfs
1981         if [ -z "$1" ]; then
1982                 return 1;
1983         fi
1984         $BTRFS_UTIL_PROG $cmd --help >/dev/null 2>&1
1985         [ $? -eq 0 ] || _notrun "$BTRFS_UTIL_PROG too old (must support $cmd)"
1986 }
1987
1988 # Check that fio is present, and it is able to execute given jobfile
1989 _require_fio()
1990 {
1991         job=$1
1992
1993         _require_command $FIO_PROG
1994         if [ -z "$1" ]; then
1995                 return 1;
1996         fi
1997
1998         $FIO_PROG --warnings-fatal --showcmd $job >> $seqres.full 2>&1
1999         [ $? -eq 0 ] || _notrun "$FIO_PROG too old, see $seqres.full"
2000 }
2001
2002 # Does freeze work on this fs?
2003 _require_freeze()
2004 {
2005         xfs_freeze -f "$TEST_DIR" >/dev/null 2>&1
2006         result=$? 
2007         xfs_freeze -u "$TEST_DIR" >/dev/null 2>&1
2008         [ $result -eq 0 ] || _notrun "$FSTYP does not support freezing"
2009 }
2010
2011 # arg 1 is dev to remove and is output of the below eg.
2012 # ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
2013 _devmgt_remove()
2014 {
2015         local lun=$1
2016         local disk=$2
2017
2018         echo 1 > /sys/class/scsi_device/${lun}/device/delete || _fail "Remove disk failed"
2019
2020         stat $disk > /dev/null 2>&1
2021         while [ $? -eq 0 ]; do
2022                 sleep 1
2023                 stat $disk > /dev/null 2>&1
2024         done
2025 }
2026
2027 # arg 1 is dev to add and is output of the below eg.
2028 # ls -l /sys/class/block/sdd | rev | cut -d "/" -f 3 | rev
2029 _devmgt_add()
2030 {
2031         local h
2032         local tdl
2033         # arg 1 will be in h:t:d:l format now in the h and "t d l" format
2034         h=`echo ${1} | cut -d":" -f 1`
2035         tdl=`echo ${1} | cut -d":" -f 2-|sed 's/:/ /g'`
2036
2037         echo ${tdl} >  /sys/class/scsi_host/host${h}/scan || _fail "Add disk failed"
2038 }
2039
2040 _require_fstrim()
2041 {
2042         if [ -z "$FSTRIM_PROG" ]; then
2043                 _notrun "This test requires fstrim utility."
2044         fi
2045 }
2046
2047 _test_batched_discard()
2048 {
2049         if [ $# -ne 1 ]; then
2050                 echo "Usage: _test_batched_discard mnt_point" 1>&2
2051                 exit 1
2052         fi
2053         _require_fstrim
2054         $FSTRIM_PROG ${1} &>/dev/null
2055 }
2056
2057 _require_dumpe2fs()
2058 {
2059         if [ -z "$DUMPE2FS_PROG" ]; then
2060                 _notrun "This test requires dumpe2fs utility."
2061         fi
2062 }
2063
2064 _require_ugid_map()
2065 {
2066         if [ ! -e /proc/self/uid_map ]; then
2067                 _notrun "This test requires procfs uid_map support."
2068         fi
2069         if [ ! -e /proc/self/gid_map ]; then
2070                 _notrun "This test requires procfs gid_map support."
2071         fi
2072 }
2073
2074 _require_cp_reflink()
2075 {
2076        cp --help | grep -q reflink || \
2077                _notrun "This test requires a cp with --reflink support."
2078 }
2079
2080 _require_fssum()
2081 {
2082         FSSUM_PROG=$here/src/fssum
2083         [ -x $FSSUM_PROG ] || _notrun "fssum not built"
2084 }
2085
2086 # Given 2 files, verify that they have the same mapping but different
2087 # inodes - i.e. an undisturbed reflink
2088 # Silent if so, make noise if not
2089 _verify_reflink()
2090 {
2091        # not a hard link or symlink?
2092        cmp -s  <(stat -c '%i' $1) <(stat -c '%i' $2) \
2093                && echo "$1 and $2 are not reflinks: same inode number"
2094
2095        # same mapping?
2096        diff -u <($XFS_IO_PROG -c "fiemap" $1 | grep -v $1) \
2097                <($XFS_IO_PROG -c "fiemap" $2 | grep -v $2) \
2098                || echo "$1 and $2 are not reflinks: different extents"
2099 }
2100
2101 _require_relatime()
2102 {
2103         _scratch_mkfs > /dev/null 2>&1
2104         _mount -t $FSTYP -o relatime $SCRATCH_DEV $SCRATCH_MNT || \
2105                 _notrun "relatime not supported by the current kernel"
2106         _scratch_unmount
2107 }
2108
2109 _create_loop_device()
2110 {
2111         file=$1
2112         dev=`losetup -f --show $file` || _fail "Cannot assign $file to a loop device"
2113         echo $dev
2114 }
2115
2116 _destroy_loop_device()
2117 {
2118         dev=$1
2119         losetup -d $dev || _fail "Cannot destroy loop device $dev"
2120 }
2121
2122 _scale_fsstress_args()
2123 {
2124     args=""
2125     while [ $# -gt 0 ]; do
2126         case "$1" in
2127             -n) args="$args $1 $(($2 * $TIME_FACTOR))"; shift ;;
2128             -p) args="$args $1 $(($2 * $LOAD_FACTOR))"; shift ;;
2129             *) args="$args $1" ;;
2130         esac
2131         shift
2132     done
2133     echo $args
2134 }
2135
2136 #
2137 # Return the logical block size if running on a block device,
2138 # else substitute the page size.
2139 #
2140 _min_dio_alignment()
2141 {
2142     dev=$1
2143
2144     if [ -b "$dev" ]; then
2145         blockdev --getss $dev
2146     else
2147         $here/src/feature -s
2148     fi
2149 }
2150
2151 run_check()
2152 {
2153         echo "# $@" >> $seqres.full 2>&1
2154         "$@" >> $seqres.full 2>&1 || _fail "failed: '$@'"
2155 }
2156
2157 _run_btrfs_util_prog()
2158 {
2159         run_check $BTRFS_UTIL_PROG $*
2160 }
2161
2162 _require_btrfs_send_stream_version()
2163 {
2164         $BTRFS_UTIL_PROG send 2>&1 | \
2165                 grep '^[ \t]*\-\-stream\-version <version>' > /dev/null 2>&1
2166         if [ $? -ne 0 ]; then
2167                 _notrun "Missing btrfs-progs send --stream-version command line option, skipped this test"
2168         fi
2169 }
2170
2171 init_rc()
2172 {
2173         if [ "$iam" == new ]
2174         then
2175                 return
2176         fi
2177         # make some further configuration checks here
2178         if [ "$TEST_DEV" = ""  ]
2179         then
2180                 echo "common/rc: Error: \$TEST_DEV is not set"
2181                 exit 1
2182         fi
2183
2184         # if $TEST_DEV is not mounted, mount it now as XFS
2185         if [ -z "`_fs_type $TEST_DEV`" ]
2186         then
2187                 # $TEST_DEV is not mounted
2188                 if ! _test_mount
2189                 then
2190                         echo "common/rc: retrying test device mount with external set"
2191                         [ "$USE_EXTERNAL" != "yes" ] && export USE_EXTERNAL=yes
2192                         if ! _test_mount
2193                         then
2194                                 echo "common/rc: could not mount $TEST_DEV on $TEST_DIR"
2195                                 exit 1
2196                         fi
2197                 fi
2198         fi
2199
2200         if [ "`_fs_type $TEST_DEV`" != "$FSTYP" ]
2201         then
2202                 echo "common/rc: Error: \$TEST_DEV ($TEST_DEV) is not a MOUNTED $FSTYP filesystem"
2203                 $DF_PROG $TEST_DEV
2204                 exit 1
2205         fi
2206         # Figure out if we need to add -F ("foreign", deprecated) option to xfs_io
2207         xfs_io -c stat $TEST_DIR 2>&1 | grep -q "is not on an XFS filesystem" && \
2208         export XFS_IO_PROG="$XFS_IO_PROG -F"
2209 }
2210
2211 # get real device path name by following link
2212 _real_dev()
2213 {
2214         local _dev=$1
2215         if [ -b "$_dev" ] && [ -L "$_dev" ]; then
2216                 _dev=`readlink -f "$_dev"`
2217         fi
2218         echo $_dev
2219 }
2220
2221 # basename of a device
2222 _short_dev()
2223 {
2224         echo `basename $(_real_dev $1)`
2225 }
2226
2227 init_rc
2228
2229 ################################################################################
2230 # make sure this script returns success
2231 /bin/true