Whamcloud - gitweb
LU-2524 test: Modify tdir to be single directory
[fs/lustre-release.git] / lustre / tests / test-framework.sh
index 0734bf5..332f740 100644 (file)
@@ -5,6 +5,7 @@ trap 'print_summary && touch $TF_FAIL && \
 set -e
 #set -x
 
+export LANG=en_US
 export EJOURNAL=${EJOURNAL:-""}
 export REFORMAT=${REFORMAT:-""}
 export WRITECONF=${WRITECONF:-""}
@@ -178,6 +179,15 @@ init_test_env() {
         fi
     fi
 
+       export RESIZE2FS=$RESIZE2FS
+       if [ -z "$RESIZE2FS" ]; then
+               if which resizefs.ldiskfs >/dev/null 2>&1; then
+                       export RESIZE2FS=resizefs.ldiskfs
+               else
+                       export RESIZE2FS=resize2fs
+               fi
+       fi
+
     export LFSCK_BIN=${LFSCK_BIN:-lfsck}
     export LFSCK_ALWAYS=${LFSCK_ALWAYS:-"no"} # check fs after each test suite
     export FSCK_MAX_ERR=4   # File system errors left uncorrected
@@ -291,13 +301,14 @@ init_test_env() {
     export RLUSTRE=${RLUSTRE:-$LUSTRE}
     export RPWD=${RPWD:-$PWD}
     export I_MOUNTED=${I_MOUNTED:-"no"}
-    if [ ! -f /lib/modules/$(uname -r)/kernel/fs/lustre/mdt.ko -a \
-        ! -f /lib/modules/$(uname -r)/updates/kernel/fs/lustre/mdt.ko -a \
-        ! -f `dirname $0`/../mdt/mdt.ko ]; then
-        export CLIENTMODSONLY=yes
-    fi
+       if [ ! -f /lib/modules/$(uname -r)/kernel/fs/lustre/mdt.ko -a \
+            ! -f /lib/modules/$(uname -r)/updates/kernel/fs/lustre/mdt.ko -a \
+            ! -f /lib/modules/$(uname -r)/extra/kernel/fs/lustre/mdt.ko -a \
+            ! -f $LUSTRE/mdt/mdt.ko ]; then
+           export CLIENTMODSONLY=yes
+       fi
 
-    export SHUTDOWN_ATTEMPTS=${SHUTDOWN_ATTEMPTS:-3}
+       export SHUTDOWN_ATTEMPTS=${SHUTDOWN_ATTEMPTS:-3}
        export OSD_TRACK_DECLARES_LBUG=${OSD_TRACK_DECLARES_LBUG:-"yes"}
 
     # command line
@@ -475,7 +486,6 @@ load_modules_local() {
     load_module ../lnet/lnet/lnet
     LNETLND=${LNETLND:-"socklnd/ksocklnd"}
     load_module ../lnet/klnds/$LNETLND
-    load_module lvfs/lvfs
     load_module obdclass/obdclass
     load_module ptlrpc/ptlrpc
     load_module ptlrpc/gss/ptlrpc_gss
@@ -498,19 +508,15 @@ load_modules_local() {
                        modprobe zfs
                        load_module osd-zfs/osd_zfs
                fi
-               load_module mgs/mgs
-               load_module mdd/mdd
                if [[ $(node_fstypes $HOSTNAME) == *ldiskfs* ]]; then
-                       #
-                       # This block shall be moved up beside osd-zfs as soon
-                       # as osd-ldiskfs stops using mdd symbols.
-                       #
                        grep -q exportfs_decode_fh $SYMLIST ||
                                { modprobe exportfs 2> /dev/null || true; }
-                       load_module ../ldiskfs/ldiskfs/ldiskfs
-                       load_module lvfs/fsfilt_ldiskfs
+                       load_module ../ldiskfs/ldiskfs
                        load_module osd-ldiskfs/osd_ldiskfs
                fi
+               load_module nodemap/nodemap
+               load_module mgs/mgs
+               load_module mdd/mdd
                load_module mdt/mdt
                load_module ost/ost
                load_module lod/lod
@@ -895,6 +901,33 @@ zpool_name() {
 }
 
 #
+# Create ZFS storage pool.
+#
+create_zpool() {
+       local facet=$1
+       local poolname=$2
+       local vdev=$3
+       shift 3
+       local opts=${@:-"-o cachefile=none"}
+
+       do_facet $facet "$ZPOOL list -H $poolname >/dev/null 2>&1 ||
+               $ZPOOL create -f $opts $poolname $vdev"
+}
+
+#
+# Create ZFS file system.
+#
+create_zfs() {
+       local facet=$1
+       local dataset=$2
+       shift 2
+       local opts=${@:-"-o mountpoint=legacy"}
+
+       do_facet $facet "$ZFS list -H $dataset >/dev/null 2>&1 ||
+               $ZFS create $opts $dataset"
+}
+
+#
 # Export ZFS storage pool.
 # Before exporting the pool, all datasets within the pool should be unmounted.
 #
@@ -914,6 +947,22 @@ export_zpool() {
 }
 
 #
+# Destroy ZFS storage pool.
+# Destroy the given pool and free up any devices for other use. This command
+# tries to unmount any active datasets before destroying the pool.
+# -f    Force any active datasets contained within the pool to be unmounted.
+#
+destroy_zpool() {
+       local facet=$1
+       local poolname=${2:-$(zpool_name $facet)}
+
+       if [[ -n "$poolname" ]]; then
+               do_facet $facet "! $ZPOOL list -H $poolname >/dev/null 2>&1 ||
+                       $ZPOOL destroy -f $poolname"
+       fi
+}
+
+#
 # Import ZFS storage pool.
 # Force importing, even if the pool appears to be potentially active.
 #
@@ -1914,6 +1963,7 @@ wait_update () {
        local sleep=1
        local print=10
 
+       PREV_RESULT=$(do_node $node "$TEST")
        while [ true ]; do
                RESULT=$(do_node $node "$TEST")
                if [[ "$RESULT" == "$FINAL" ]]; then
@@ -2068,6 +2118,7 @@ wait_mds_ost_sync () {
        echo "Waiting for orphan cleanup..."
        # MAX value includes time needed for MDS-OST reconnection
        local MAX=$(( TIMEOUT * 2 ))
+       local WAIT_TIMEOUT=${1:-$MAX}
        local WAIT=0
        local new_wait=true
        local list=$(comma_list $(mdts_nodes))
@@ -2080,7 +2131,9 @@ wait_mds_ost_sync () {
                list=$(comma_list $(osts_nodes))
                cmd="$LCTL get_param -n obdfilter.*.mds_sync"
        fi
-       while [ $WAIT -lt $MAX ]; do
+
+       echo "wait $WAIT_TIMEOUT secs maximumly for $list mds-ost sync done."
+       while [ $WAIT -lt $WAIT_TIMEOUT ]; do
                local -a sync=($(do_nodes $list "$cmd"))
                local con=1
                local i
@@ -2096,10 +2149,13 @@ wait_mds_ost_sync () {
                done
                sleep 2 # increase waiting time and cover statfs cache
                [ ${con} -eq 1 ] && return 0
-               echo "Waiting $WAIT secs for $facet mds-ost sync done."
+               echo "Waiting $WAIT secs for $list $i mds-ost sync done."
                WAIT=$((WAIT + 2))
        done
-       echo "$facet recovery not done in $MAX sec. $STATUS"
+
+       # show which nodes are not finished.
+       do_nodes $list "$cmd"
+       echo "$facet recovery node $i not done in $WAIT_TIMEOUT sec. $STATUS"
        return 1
 }
 
@@ -2558,7 +2614,11 @@ facet_host() {
        varname=${facet}_HOST
        if [ -z "${!varname}" ]; then
                if [ "${facet:0:3}" == "ost" ]; then
-                       eval export ${facet}_HOST=${ost_HOST}
+                       local fh=${facet%failover}_HOST
+                       eval export ${facet}_HOST=${!fh}
+                       if [ -z "${!varname}" ]; then
+                               eval export ${facet}_HOST=${ost_HOST}
+                       fi
                elif [ "${facet:0:3}" == "mdt" -o \
                        "${facet:0:3}" == "mds" -o \
                        "${facet:0:3}" == "mgs" ]; then
@@ -2844,9 +2904,10 @@ add() {
        fi
 }
 
+# Device formatted as ost
 ostdevname() {
-    num=$1
-    DEVNAME=OSTDEV$num
+       local num=$1
+       local DEVNAME=OSTDEV$num
 
        local fstype=$(facet_fstype ost$num)
 
@@ -2855,8 +2916,9 @@ ostdevname() {
                        #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
                        eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}};;
                zfs )
-                       #dataset name is independent of vdev device names
-                       eval DEVPTR=${FSNAME}-ost${num}/ost${num};;
+                       #try $OSTZFSDEVn - independent of vdev
+                       DEVNAME=OSTZFSDEV$num
+                       eval DEVPTR=${!DEVNAME:=${FSNAME}-ost${num}/ost${num}};;
                * )
                        error "unknown fstype!";;
        esac
@@ -2864,9 +2926,11 @@ ostdevname() {
     echo -n $DEVPTR
 }
 
+# Physical device location of data
 ostvdevname() {
-       num=$1
-       DEVNAME=OSTDEV$num
+       local num=$1
+       local DEVNAME
+       local VDEVPTR
 
        local fstype=$(facet_fstype ost$num)
 
@@ -2875,7 +2939,9 @@ ostvdevname() {
                        # vdevs are not supported by ldiskfs
                        eval VDEVPTR="";;
                zfs )
-                       #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
+                       #if $OSTDEVn isn't defined, default is $OSTDEVBASE{n}
+                       # Device formated by zfs
+                       DEVNAME=OSTDEV$num
                        eval VDEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}};;
                * )
                        error "unknown fstype!";;
@@ -2884,19 +2950,21 @@ ostvdevname() {
        echo -n $VDEVPTR
 }
 
+# Logical device formated for lustre
 mdsdevname() {
-    num=$1
-    DEVNAME=MDSDEV$num
+       local num=$1
+       local DEVNAME=MDSDEV$num
 
        local fstype=$(facet_fstype mds$num)
 
        case $fstype in
                ldiskfs )
-                       #if $MDSDEVn isn't defined, default is $MDSDEVBASE + num
+                       #if $MDSDEVn isn't defined, default is $MDSDEVBASE{n}
                        eval DEVPTR=${!DEVNAME:=${MDSDEVBASE}${num}};;
                zfs )
-                       #dataset name is independent of vdev device names
-                       eval DEVPTR=${FSNAME}-mdt${num}/mdt${num};;
+                       # try $MDSZFSDEVn - independent of vdev
+                       DEVNAME=MDSZFSDEV$num
+                       eval DEVPTR=${!DEVNAME:=${FSNAME}-mdt${num}/mdt${num}};;
                * )
                        error "unknown fstype!";;
        esac
@@ -2904,10 +2972,10 @@ mdsdevname() {
        echo -n $DEVPTR
 }
 
+# Physical location of data
 mdsvdevname() {
-       num=$1
-       DEVNAME=MDSDEV$num
-
+       local VDEVPTR=""
+       local num=$1
        local fstype=$(facet_fstype mds$num)
 
        case $fstype in
@@ -2915,7 +2983,9 @@ mdsvdevname() {
                        # vdevs are not supported by ldiskfs
                        eval VDEVPTR="";;
                zfs )
-                       #if $MDSDEVn isn't defined, default is $MDSDEVBASE + num
+                       # if $MDSDEVn isn't defined, default is $MDSDEVBASE{n}
+                       # Device formated by ZFS
+                       local DEVNAME=MDSDEV$num
                        eval VDEVPTR=${!DEVNAME:=${MDSDEVBASE}${num}};;
                * )
                        error "unknown fstype!";;
@@ -2938,10 +3008,11 @@ mgsdevname() {
                fi;;
        zfs )
                if [ $(facet_host mgs) = $(facet_host mds1) ] &&
-                  ( [ -z "$MGSDEV" ] || [ $MGSDEV = $(mdsvdevname 1) ] ); then
+                   ( [ -z "$MGSZFSDEV" ] &&
+                       [ -z "$MGSDEV" -o "$MGSDEV" = $(mdsvdevname 1) ] ); then
                        DEVPTR=$(mdsdevname 1)
                else
-                       DEVPTR=${FSNAME}-mgs/mgs
+                       DEVPTR=${MGSZFSDEV:-${FSNAME}-mgs/mgs}
                fi;;
        * )
                error "unknown fstype!";;
@@ -2951,8 +3022,7 @@ mgsdevname() {
 }
 
 mgsvdevname() {
-       local VDEVPTR
-       DEVNAME=MGSDEV
+       local VDEVPTR=""
 
        local fstype=$(facet_fstype mgs)
 
@@ -2962,9 +3032,10 @@ mgsvdevname() {
                ;;
        zfs )
                if [ $(facet_host mgs) = $(facet_host mds1) ] &&
-                  ( [ -z "$MGSDEV" ] || [ $MGSDEV = $(mdsvdevname 1) ] ); then
+                  ( [ -z "$MGSDEV" ] &&
+                      [ -z "$MGSZFSDEV" -o "$MGSZFSDEV" = $(mdsdevname 1) ]); then
                        VDEVPTR=$(mdsvdevname 1)
-               else
+               elif [ -n "$MGSDEV" ]; then
                        VDEVPTR=$MGSDEV
                fi;;
        * )
@@ -2984,6 +3055,84 @@ facet_mntpt () {
     echo -n $mntpt
 }
 
+mount_ldiskfs() {
+       local facet=$1
+       local dev=$(facet_device $facet)
+       local mnt=$(facet_mntpt $facet)
+       local opts
+
+       if ! do_facet $facet test -b $dev; then
+               opts="-o loop"
+       fi
+       do_facet $facet mount -t ldiskfs $opts $dev $mnt
+}
+
+unmount_ldiskfs() {
+       local facet=$1
+       local dev=$(facet_device $facet)
+       local mnt=$(facet_mntpt $facet)
+
+       do_facet $facet umount -d $mnt
+}
+
+var_name() {
+       echo -n "$1" | tr -c '[:alnum:]\n' '_'
+}
+
+mount_zfs() {
+       local facet=$1
+       local ds=$(facet_device $facet)
+       local mnt=$(facet_mntpt $facet)
+       local canmnt
+       local mntpt
+
+       import_zpool $facet
+       canmnt=$(do_facet $facet $ZFS get -H -o value canmount $ds)
+       mntpt=$(do_facet $facet $ZFS get -H -o value mountpoint $ds)
+       do_facet $facet $ZFS set canmount=noauto $ds
+       #
+       # The "legacy" mount method is used here because "zfs unmount $mnt"
+       # calls stat(2) on $mnt/../*, which may include $MOUNT.  If certain
+       # targets are not available at the time, the stat(2) on $MOUNT will
+       # hang.
+       #
+       do_facet $facet $ZFS set mountpoint=legacy $ds
+       do_facet $facet mount -t zfs $ds $mnt
+       eval export mz_$(var_name ${facet}_$ds)_canmount=$canmnt
+       eval export mz_$(var_name ${facet}_$ds)_mountpoint=$mntpt
+}
+
+unmount_zfs() {
+       local facet=$1
+       local ds=$(facet_device $facet)
+       local mnt=$(facet_mntpt $facet)
+       local var_mntpt=mz_$(var_name ${facet}_$ds)_mountpoint
+       local var_canmnt=mz_$(var_name ${facet}_$ds)_canmount
+       local mntpt=${!var_mntpt}
+       local canmnt=${!var_canmnt}
+
+       unset $var_mntpt
+       unset $var_canmnt
+       do_facet $facet umount $mnt
+       do_facet $facet $ZFS set mountpoint=$mntpt $ds
+       do_facet $facet $ZFS set canmount=$canmnt $ds
+       export_zpool $facet
+}
+
+mount_fstype() {
+       local facet=$1
+       local fstype=$(facet_fstype $facet)
+
+       mount_$fstype $facet
+}
+
+unmount_fstype() {
+       local facet=$1
+       local fstype=$(facet_fstype $facet)
+
+       unmount_$fstype $facet
+}
+
 ########
 ## MountConf setup
 
@@ -3663,7 +3812,13 @@ check_and_setup_lustre() {
     fi
 
        if [ $(lower $OSD_TRACK_DECLARES_LBUG) == 'yes' ] ; then
-               local facets="$(get_facets OST),$(get_facets MDS),mgs"
+               local facets=""
+               [ "$(facet_fstype ost1)" = "ldiskfs" ] &&
+                       facets="$(get_facets OST)"
+               [ "$(facet_fstype mds1)" = "ldiskfs" ] &&
+                       facets="$facets,$(get_facets MDS)"
+               [ "$(facet_fstype mgs)" = "ldiskfs" ] &&
+                       facets="$facets,mgs"
                local nodes="$(facets_hosts ${facets})"
                if [ -n "$nodes" ] ; then
                        do_nodes $nodes "$LCTL set_param \
@@ -3759,6 +3914,19 @@ run_e2fsck() {
     return 0
 }
 
+#
+# Run resize2fs on MDT or OST device.
+#
+run_resize2fs() {
+       local facet=$1
+       local device=$2
+       local size=$3
+       shift 3
+       local opts="$@"
+
+       do_facet $facet "$RESIZE2FS $opts $device $size"
+}
+
 # verify a directory is shared among nodes.
 check_shared_dir() {
        local dir=$1
@@ -4104,12 +4272,16 @@ drop_update_reply() {
 
 pause_bulk() {
 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
-    RC=0
-    do_facet ost1 lctl set_param fail_loc=0x214
-    do_facet client "$1" || RC=$?
-    do_facet client "sync"
-    do_facet ost1 lctl set_param fail_loc=0
-    return $RC
+       RC=0
+
+       local timeout=${2:-0}
+       # default is (obd_timeout / 4) if unspecified
+       echo "timeout is $timeout/$2"
+       do_facet ost1 lctl set_param fail_val=$timeout fail_loc=0x80000214
+       do_facet client "$1" || RC=$?
+       do_facet client "sync"
+       do_facet ost1 lctl set_param fail_loc=0
+       return $RC
 }
 
 drop_ldlm_cancel() {
@@ -4151,7 +4323,7 @@ clear_failloc() {
 }
 
 set_nodes_failloc () {
-    do_nodes $(comma_list $1)  lctl set_param fail_loc=$2
+       do_nodes $(comma_list $1)  lctl set_param fail_val=0 fail_loc=$2
 }
 
 cancel_lru_locks() {
@@ -4269,7 +4441,11 @@ error_noexit() {
        if [ -z "$*" ]; then
                echo "error() without useful message, please fix" > $LOGDIR/err
        else
-               echo "$@" > $LOGDIR/err
+               if [[ `echo $TYPE | grep ^IGNORE` ]]; then
+                       echo "$@" > $LOGDIR/ignore
+               else
+                       echo "$@" > $LOGDIR/err
+               fi
        fi
 }
 
@@ -4292,9 +4468,10 @@ error_exit() {
 
 # use only if we are ignoring failures for this test, bugno required.
 # (like ALWAYS_EXCEPT, but run the test and ignore the results.)
-# e.g. error_ignore 5494 "your message"
+# e.g. error_ignore bz5494 "your message" or
+# error_ignore LU-5494 "your message"
 error_ignore() {
-       local TYPE="IGNORE (bz$1)"
+       local TYPE="IGNORE ($1)"
        shift
        error_noexit "$@"
 }
@@ -4506,34 +4683,35 @@ banner() {
 }
 
 #
-# Run a single test function and cleanup after it.  
+# Run a single test function and cleanup after it.
 #
 # This function should be run in a subshell so the test func can
 # exit() without stopping the whole script.
 #
 run_one() {
-    local testnum=$1
-    local message=$2
-    tfile=f.${TESTSUITE}.${testnum}
-    export tdir=d0.${TESTSUITE}/d${base}
-    export TESTNAME=test_$testnum
-    local SAVE_UMASK=`umask`
-    umask 0022
-
-    banner "test $testnum: $message"
-    test_${testnum} || error "test_$testnum failed with $?"
-    cd $SAVE_PWD
-    reset_fail_loc
-    check_grant ${testnum} || error "check_grant $testnum failed with $?"
-    check_catastrophe || error "LBUG/LASSERT detected"
+       local testnum=$1
+       local message=$2
+       export tfile=f${testnum}.${TESTSUITE}
+       export tdir=d${testnum}.${TESTSUITE}
+       export TESTNAME=test_$testnum
+       local SAVE_UMASK=`umask`
+       umask 0022
+
+       banner "test $testnum: $message"
+       test_${testnum} || error "test_$testnum failed with $?"
+       cd $SAVE_PWD
+       reset_fail_loc
+       check_grant ${testnum} || error "check_grant $testnum failed with $?"
+       check_catastrophe || error "LBUG/LASSERT detected"
        if [ "$PARALLEL" != "yes" ]; then
                ps auxww | grep -v grep | grep -q multiop &&
                                        error "multiop still running"
        fi
-    unset TESTNAME
-    unset tdir
-    umask $SAVE_UMASK
-    return 0
+       unset TESTNAME
+       unset tdir
+       unset tfile
+       umask $SAVE_UMASK
+       return 0
 }
 
 #
@@ -4548,6 +4726,7 @@ run_one_logged() {
        local name=${TESTSUITE}.test_${1}.test_log.$(hostname -s).log
        local test_log=$LOGDIR/$name
        rm -rf $LOGDIR/err
+       rm -rf $LOGDIR/ignore
        rm -rf $LOGDIR/skip
        local SAVE_UMASK=`umask`
        umask 0022
@@ -4557,7 +4736,7 @@ run_one_logged() {
        (run_one $1 "$2") 2>&1 | tee -i $test_log
        local RC=${PIPESTATUS[0]}
 
-       [ $RC -ne 0 ] && [ ! -f $LOGDIR/err ] && \
+       [ $RC -ne 0 ] && [ ! -f $LOGDIR/err ] &&
                echo "test_$1 returned $RC" | tee $LOGDIR/err
 
        duration=$((`date +%s` - $BEFORE))
@@ -4565,11 +4744,17 @@ run_one_logged() {
 
        if [[ -f $LOGDIR/err ]]; then
                TEST_ERROR=$(cat $LOGDIR/err)
+       elif [[ -f $LOGDIR/ignore ]]; then
+               TEST_ERROR=$(cat $LOGDIR/ignore)
        elif [[ -f $LOGDIR/skip ]]; then
                TEST_ERROR=$(cat $LOGDIR/skip)
        fi
        log_sub_test_end $TEST_STATUS $duration "$RC" "$TEST_ERROR"
 
+       if [[ "$TEST_STATUS" != "SKIP" ]] && [[ -f $TF_SKIP ]]; then
+               rm -f $TF_SKIP
+       fi
+
        if [ -f $LOGDIR/err ]; then
                $FAIL_ON_ERROR && exit $RC
        fi
@@ -5261,7 +5446,7 @@ get_mds_dir () {
 
 mdsrate_cleanup () {
        if [ -d $4 ]; then
-               mpi_run -np $1 ${MACHINEFILE_OPTION} $2 ${MDSRATE} --unlink \
+               mpi_run ${MACHINEFILE_OPTION} $2 -np $1 ${MDSRATE} --unlink \
                        --nfiles $3 --dir $4 --filefmt $5 $6
                rmdir $4
        fi
@@ -5274,7 +5459,7 @@ delayed_recovery_enabled () {
 
 ########################
 
-convert_facet2label() { 
+convert_facet2label() {
     local facet=$1
 
     if [ x$facet = xost ]; then
@@ -5285,7 +5470,7 @@ convert_facet2label() {
 
     if [ -n ${!varsvc} ]; then
         echo ${!varsvc}
-    else  
+    else
         error "No lablel for $facet!"
     fi
 }
@@ -6051,7 +6236,7 @@ check_write_access() {
        local file
 
        for node in ${list//,/ }; do
-               file=$dir/check_file.$(short_hostname $node)
+               file=$dir/check_file.$(short_nodename $node)
                if [[ ! -f "$file" ]]; then
                        # Logdir not accessible/writable from this node.
                        return 1
@@ -6267,6 +6452,45 @@ min_ost_size () {
     $LCTL get_param -n osc.*.kbytesavail | sort -n | head -n1
 }
 
+#
+# Get the available size (KB) of a given obd target.
+#
+get_obd_size() {
+       local facet=$1
+       local obd=$2
+       local size
+
+       [[ $facet != client ]] || return 0
+
+       size=$(do_facet $facet $LCTL get_param -n *.$obd.kbytesavail | head -n1)
+       echo -n $size
+}
+
+#
+# Get the page size (bytes) on a given facet node.
+#
+get_page_size() {
+       local facet=$1
+       local size
+
+       size=$(do_facet $facet getconf PAGE_SIZE)
+       [[ ${PIPESTATUS[0]} = 0 && -n "$size" ]] || size=4096
+       echo -n $size
+}
+
+#
+# Get the block count of the filesystem.
+#
+get_block_count() {
+       local facet=$1
+       local device=$2
+       local count
+
+       count=$(do_facet $facet "$DUMPE2FS -h $device 2>&1" |
+               awk '/^Block count:/ {print $3}')
+       echo -n $count
+}
+
 # Get the block size of the filesystem.
 get_block_size() {
     local facet=$1
@@ -6488,3 +6712,15 @@ test_mkdir() {
        fi
        return $rc
 }
+
+# find the smallest and not in use file descriptor
+free_fd()
+{
+        local max_fd=$(ulimit -n)
+        local fd=3
+        while [[ $fd -le $max_fd && -e /proc/self/fd/$fd ]]; do
+                ((++fd))
+        done
+        [ $fd -lt $max_fd ] || error "finding free file descriptor failed"
+        echo $fd
+}