Whamcloud - gitweb
LU-3285 test: add Data-on-MDT tests and fixes 20/28020/26
authorMikhail Pershin <mike.pershin@intel.com>
Thu, 21 Aug 2014 10:23:33 +0000 (14:23 +0400)
committerMike Pershin <mike.pershin@intel.com>
Tue, 17 Oct 2017 20:30:02 +0000 (20:30 +0000)
- add test for basic DoM functionality in sanity.sh
- add test to read/write many files with small chunks of data,
  it is used for performance comparision.
- the sanity-dom.sh is added to test Data-on-MDT.
  It contains specific sanity tests and calls sanity.sh and
  sanityn.sh with limited set of test to cover the same cases
  as OSC.
- fixes for DoM code for issues revealed by tests.

Test-Parameters: mdssizegb=20 testlist=sanity-dom,dom-performance
Signed-off-by: Mikhal Pershin <mike.pershin@intel.com>
Change-Id: I17fbbf8e913cc14043703969d01ac65e6828fcc6
Reviewed-on: https://review.whamcloud.com/28020
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
lustre/lov/lov_object.c
lustre/tests/.gitignore
lustre/tests/Makefile.am
lustre/tests/conf-sanity.sh
lustre/tests/dom-performance.sh [new file with mode: 0644]
lustre/tests/sanity-dom.sh [new file with mode: 0644]
lustre/tests/sanity.sh
lustre/tests/sanityn.sh
lustre/tests/smalliomany.c [new file with mode: 0644]

index 216221a..ac0493e 100644 (file)
@@ -449,8 +449,16 @@ static int lov_attr_get_dom(const struct lu_env *env, struct lov_object *lov,
                return OST_LVB_GET_ERR(loi->loi_lvb.lvb_blocks);
 
        cl_lvb2attr(attr, &loi->loi_lvb);
-       attr->cat_kms = attr->cat_size > loi->loi_kms ? attr->cat_size :
-                                                       loi->loi_kms;
+
+       /* DoM component size can be bigger than stripe size after
+        * client's setattr RPC, so do not count anything beyound
+        * component end. Alternatively, check that limit on server
+        * and do not allow size overflow there. */
+       if (attr->cat_size > lle->lle_extent.e_end)
+               attr->cat_size = lle->lle_extent.e_end;
+
+       attr->cat_kms = attr->cat_size;
+
        dom->lo_dom_r0.lo_attr_valid = 1;
        *lov_attr = attr;
 
@@ -530,7 +538,6 @@ static int lov_init_dom(const struct lu_env *env, struct lov_device *dev,
        struct cl_device *mdcdev;
        struct lov_oinfo *loi = NULL;
        struct cl_object_conf *sconf = &lti->lti_stripe_conf;
-       struct inode *inode = conf->coc_inode;
 
        int rc;
        __u32 idx = 0;
@@ -563,15 +570,6 @@ static int lov_init_dom(const struct lu_env *env, struct lov_device *dev,
                RETURN(-ENOMEM);
 
        fid_to_ostid(lu_object_fid(lov2lu(lov)), &loi->loi_oi);
-       /* Initialize lvb structure */
-       loi->loi_lvb.lvb_mtime = LTIME_S(inode->i_mtime);
-       loi->loi_lvb.lvb_atime = LTIME_S(inode->i_atime);
-       loi->loi_lvb.lvb_ctime = LTIME_S(inode->i_ctime);
-       loi->loi_lvb.lvb_blocks = inode->i_blocks;
-       loi->loi_lvb.lvb_size = i_size_read(inode);
-       if (loi->loi_lvb.lvb_size > lsme->lsme_stripe_size)
-               loi->loi_lvb.lvb_size = lsme->lsme_stripe_size;
-       loi_kms_set(loi, loi->loi_lvb.lvb_size);
 
        sconf->u.coc_oinfo = loi;
 again:
@@ -879,6 +877,11 @@ static int lov_attr_get_composite(const struct lu_env *env,
                if (lov_attr == NULL)
                        continue;
 
+               CDEBUG(D_INODE, "COMP ID #%i: s=%llu m=%llu a=%llu c=%llu "
+                      "b=%llu\n", index - 1, lov_attr->cat_size,
+                      lov_attr->cat_mtime, lov_attr->cat_atime,
+                      lov_attr->cat_ctime, lov_attr->cat_blocks);
+
                /* merge results */
                attr->cat_blocks += lov_attr->cat_blocks;
                if (attr->cat_size < lov_attr->cat_size)
index 2bce603..eb86343 100644 (file)
@@ -69,6 +69,7 @@
 /setuid
 /sleeptest
 /small_write
+/smalliomany
 /stat
 /statmany
 /statone
index 33598d2..68dabfb 100644 (file)
@@ -39,6 +39,7 @@ noinst_SCRIPTS += posix.sh sanity-scrub.sh scrub-performance.sh ha.sh
 noinst_SCRIPTS += sanity-lfsck.sh lfsck-performance.sh
 noinst_SCRIPTS += resolveip
 noinst_SCRIPTS += sanity-hsm.sh sanity-lsnapshot.sh sanity-pfl.sh
+noinst_SCRIPTS += sanity-dom.sh dom-performance.sh
 nobase_noinst_SCRIPTS = cfg/local.sh
 nobase_noinst_SCRIPTS += test-groups/regression test-groups/regression-mpi
 nobase_noinst_SCRIPTS += acl/make-tree acl/run cfg/ncli.sh
@@ -68,7 +69,7 @@ noinst_PROGRAMS = openunlink truncate directio writeme mlink utime
 noinst_PROGRAMS += tchmod fsx test_brw sendfile
 noinst_PROGRAMS += createmany chownmany statmany multifstat createtest
 noinst_PROGRAMS += opendirunlink opendevunlink unlinkmany checkstat
-noinst_PROGRAMS += statone runas openfile rmdirmany
+noinst_PROGRAMS += statone runas openfile rmdirmany smalliomany
 noinst_PROGRAMS += small_write multiop ll_sparseness_verify
 noinst_PROGRAMS += ll_sparseness_write mrename ll_dirstripe_verify mkdirmany
 noinst_PROGRAMS += openfilleddirunlink rename_many memhog
index 7fd8581..a678edc 100644 (file)
@@ -1687,6 +1687,7 @@ t32_test() {
        local tarball=$1
        local writeconf=$2
        local dne_upgrade=${dne_upgrade:-"no"}
+       local dom_upgrade=${dom_upgrade:-"no"}
        local ff_convert=${ff_convert:-"no"}
        local shall_cleanup_mdt=false
        local shall_cleanup_mdt1=false
@@ -2023,11 +2024,6 @@ t32_test() {
                shall_cleanup_lustre=true
                $r $LCTL set_param debug="$PTLDEBUG"
 
-               t32_verify_quota $node $fsname $tmp/mnt/lustre || {
-                       error_noexit "verify quota failed"
-                       return 1
-               }
-
                if $r test -f $tmp/list; then
                        #
                        # There is not a Test Framework API to copy files to or
@@ -2079,6 +2075,43 @@ t32_test() {
                        echo "list verification skipped"
                fi
 
+               if [ "$dom_upgrade" != "no" ]; then
+                       echo "Check DoM file can be created"
+                       $SETSTRIPE -E 1M -L mdt -E EOF $tmp/mnt/lustre/dom || {
+                               error_noexit "Verify DoM creation"
+                               return 1
+                       }
+                       [ $($GETSTRIPE -L $tmp/mnt/lustre/dom) == 100 ] || {
+                               error_noexit "Verify a DoM file"
+                               return 1
+                       }
+                       dd if=/dev/urandom of=$tmp/mnt/lustre/dom bs=4096 \
+                               count=1 conv=fsync || {
+                               error_noexit "Cannot write to DoM file"
+                               return 1
+                       }
+                       [ $(stat -c%s $tmp/mnt/lustre/dom) == 4096 ] || {
+                               error_noexit "DoM: bad size after write"
+                               return 1
+                       }
+                       rm $tmp/mnt/lustre/dom
+
+                       $r $LCTL get_param -n lod.*MDT0000*.dom_stripesize || {
+                               error_noexit "Getting \"dom_stripesize\""
+                               return 1
+                       }
+                       $r $LCTL conf_param \
+                               $fsname-MDT0000.lod.dom_stripesize=0 || {
+                               error_noexit "Changing \"dom_stripesize\""
+                               return 1
+                       }
+                       wait_update $(facet_host mds) "$LCTL get_param \
+                               -n lod.*MDT0000*.dom_stripesize" 0 || {
+                               error_noexit "Verifying \"dom_stripesize\""
+                               return 1
+                       }
+               fi
+
                if [ "$dne_upgrade" != "no" ]; then
                        $LFS mkdir -i 1 -c2 $tmp/mnt/lustre/striped_dir || {
                                error_noexit "set striped dir failed"
@@ -2383,6 +2416,21 @@ test_32d() {
 }
 run_test 32d "convert ff test"
 
+test_32e() {
+       local tarballs
+       local tarball
+       local rc=0
+
+       t32_check
+       for tarball in $tarballs; do
+               echo $tarball | grep "2_9" || continue
+               #load_modules
+               dom_upgrade=yes t32_test $tarball writeconf || let "rc += $?"
+       done
+       return $rc
+}
+run_test 32e "dom upgrade test"
+
 test_33a() { # bug 12333, was test_33
        local FSNAME2=test-123
        local MDSDEV=$(mdsdevname ${SINGLEMDS//mds/})
diff --git a/lustre/tests/dom-performance.sh b/lustre/tests/dom-performance.sh
new file mode 100644 (file)
index 0000000..a75e849
--- /dev/null
@@ -0,0 +1,324 @@
+#!/bin/bash
+#
+# Run select tests by setting ONLY, or as arguments to the script.
+# Skip specific tests by setting EXCEPT.
+#
+
+set -e
+
+ONLY=${ONLY:-"$*"}
+ALWAYS_EXCEPT=""
+[ "$SLOW" = "no" ] && EXCEPT_SLOW=""
+# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
+
+LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
+
+. $LUSTRE/tests/test-framework.sh
+CLEANUP=${CLEANUP:-:}
+SETUP=${SETUP:-:}
+init_test_env $@
+. ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
+init_logging
+
+FAIL_ON_ERROR=false
+
+check_and_setup_lustre
+
+# $RUNAS_ID may get set incorrectly somewhere else
+if [[ $UID -eq 0 && $RUNAS_ID -eq 0 ]]; then
+       skip_env "\$RUNAS_ID set to 0, but \$UID is also 0!" && exit
+fi
+check_runas_id $RUNAS_ID $RUNAS_GID $RUNAS
+
+build_test_filter
+
+DOM="yes"
+DOM_SIZE=${DOM_SIZE:-"1M"}
+OSC="mdc"
+
+rm -rf $DIR/*
+
+NORM=$DIR/norm
+DOM=$DIR/dom
+STATS=${STATS:-"yes"}
+
+# 1 stripe for normal files
+mkdir -p $NORM
+lfs setstripe -c 1 $NORM
+
+if [ "x$DNE" == "xyes" ] ; then
+       lfs setdirstripe -i 0 -c 2 $DOM
+else
+       mkdir -p $DOM
+fi
+
+lfs setstripe -E ${DOM_SIZE} -L mdt -E EOF $DOM
+
+# total number of files
+FNUM=16384
+# number of threads
+NUM=4
+
+clear_stats() {
+       local cli=$1
+
+       $LCTL set_param -n ${cli}.*.${cli}_stats=0
+       $LCTL set_param -n ${cli}.*.rpc_stats=0
+       $LCTL set_param -n ${cli}.*.stats=0
+       $LCTL set_param -n llite.*.read_ahead_stats=0
+       $LCTL set_param -n llite.*.unstable_stats=0
+}
+
+collect_stats() {
+       local cli=$1
+
+       sync;sync
+
+       if [ "x$STATS" != "xyes" ] ; then
+               return 0
+       fi
+
+       $LCTL get_param ${cli}.*.${cli}_stats
+       $LCTL get_param ${cli}.*.rpc_stats
+       # for OSC get both OSC and MDC stats
+       if [ $cli == "osc" ] ; then
+               $LCTL get_param mdc.*.stats
+       fi
+       $LCTL get_param ${cli}.*.stats
+       $LCTL get_param ${cli}.*.unstable_stats
+       $LCTL get_param ${cli}.*.${cli}_cached_mb
+       $LCTL get_param llite.*.read_ahead_stats
+}
+
+setup_test() {
+       local cli=$1
+
+       cancel_lru_locks $cli
+       ### drop all debug
+       $LCTL set_param -n debug=0
+       clear_stats $cli
+}
+
+run_cmd() {
+       local cmd=$1
+
+       setup_test $OSC
+       if ! grep -qw "$MOUNT" /proc/mounts ; then
+               echo "!!!!! Lustre is not mounted !!!!!, aborting"
+               return 0
+       fi
+
+       echo "##### $cmd #####"
+       echo "##### $(date +'%F %H:%M:%S'): START"
+       eval $cmd
+       echo "##### $(date +'%F %H:%M:%S'): GETSTATS"
+       collect_stats $OSC
+       echo "##### $(date +'%F %H:%M:%S'): STOP"
+       remount_client $DIR
+
+}
+
+run_MDtest() {
+       if ! which mdtest > /dev/null 2>&1 ; then
+               echo "Mdtest is not installed, skipping"
+               return 0
+       fi
+
+       local mdtest=$(which mdtest)
+
+       local TDIR=${1:-$MOUNT}
+       local th_num=$((FNUM * 2 / NUM))
+
+       for bsize in 4096 ; do
+               run_cmd "mpirun -np $NUM $mdtest \
+                        -i 3 -I $th_num -F -z 1 -b 1 -L -u -w $bsize -d $TDIR"
+       done
+       rm -rf $TDIR/*
+       return 0
+}
+
+run_smalliomany() {
+       if [ ! -f createmany ] ; then
+               echo "Createmany is not installed, skipping"
+               return 0
+       fi
+
+       if [ ! -f smalliomany ] ; then
+               echo "Smalliomany is not installed, skipping"
+               return 0
+       fi
+
+       local TDIR=${1:-$DIR}
+       local count=$FNUM
+
+       local MIN=$((count * 16))
+       [ $MDSSIZE -le $MIN ] && count=$((MDSSIZE / 16))
+
+       run_cmd "./createmany -o $TDIR/file- $count | grep 'total'"
+
+       if [ -f statmany ]; then
+               run_cmd "./statmany -s $TDIR/file- $count $((count * 5)) | \
+                       grep 'total'"
+       fi
+
+       for opc in w a r ; do
+               run_cmd "./smalliomany -${opc} $TDIR/file- $count 300 | \
+                       grep 'total'"
+       done
+
+       run_cmd "./unlinkmany $TDIR/file- $count | grep 'total'"
+       return 0
+}
+
+run_IOR() {
+       if ! which IOR > /dev/null 2>&1 ; then
+               echo "IOR is not installed, skipping"
+               return 0
+       fi
+
+       local IOR=$(which IOR)
+       local iter=$((FNUM / NUM))
+
+       if [ "x$DIO" == "xyes" ] ; then
+               direct="-B"
+       else
+               direct=""
+       fi
+
+       local TDIR=${1:-$MOUNT}
+
+       for bsize in 4 ; do
+               segments=$((128 / bsize))
+
+               run_cmd "mpirun -np $NUM $IOR \
+                       -a POSIX -b ${bsize}K -t ${bsize}K -o $TDIR/ -k \
+                       -s $segments -w -r -i $iter -F -E -z -m -Z $direct"
+               # check READ performance only (no cache)
+               run_cmd "mpirun -np $NUM $IOR \
+                       -a POSIX -b ${bsize}K -t ${bsize}K -o $TDIR/ -X 42\
+                       -s $segments -r -i $iter -F -E -z -m -Z $direct"
+       done
+       rm -rf $TDIR/*
+       return 0
+}
+
+run_dbench() {
+       if ! which dbench > /dev/null 2>&1 ; then
+               echo "Dbench is not installed, skipping"
+               return 0
+       fi
+
+       if [ "x$DNE" == "xyes" ] ; then
+               echo "dbench uses subdirs, skipping for DNE setup"
+               return 0
+       fi
+
+       local TDIR=${1:-$MOUNT}
+
+       run_cmd "dbench -D $TDIR $NUM | egrep -v 'warmup|execute'"
+       rm -rf $TDIR/*
+       return 0
+}
+
+run_smallfile() {
+       if ! which unzip > /dev/null 2>&1 ; then
+               echo "No unzip is installed, skipping"
+               return 0;
+       fi
+
+       if [ "x$DIO" == "xyes" ] ; then
+               echo "smallfile has no DIRECT IO mode, skipping"
+               return 0
+       fi
+
+       if [ "x$DNE" == "xyes" ] ; then
+               echo "smallfile uses subdirs, skipping for DNE setup"
+               return 0
+       fi
+
+       local host_set=$(hostname)
+
+       ### since smallfile is not installed system wide, get it right now
+       [ -f master.zip ] || \
+               wget https://github.com/bengland2/smallfile/archive/master.zip
+       unzip -uo master.zip
+       cd ./smallfile-master
+
+       if ! ls ./smallfile_cli.py > /dev/null 2>&1 ; then
+               echo "No smallfile test found, skipping"
+               cd ..
+               return 0
+       fi
+
+       local TDIR=${1:-$MOUNT}
+       local thrds=$NUM
+       local fsize=64 # in Kbytes
+       local total=$FNUM # files in test
+       local fnum=$((total / NUM))
+
+       SYNC_DIR=${MOUNT}/sync
+       mkdir -p $SYNC_DIR
+
+       SMF="./smallfile_cli.py --pause 10 --host-set $host_set \
+            --response-times Y --threads $thrds --file-size $fsize \
+            --files $fnum --top $TDIR --network-sync-dir $SYNC_DIR \
+            --file-size-distribution exponential"
+
+       run_cmd "$SMF --operation create"
+
+       for oper in read append overwrite ; do
+               for bsize in 8 ; do
+                       run_cmd "$SMF --record-size $bsize --operation $oper"
+               done
+       done
+       run_cmd "$SMF --operation delete"
+
+       rm -rf $TDIR/*
+       cd ..
+       return 0
+}
+
+test_smallio() {
+       OSC="mdc"
+       run_smalliomany $DOM
+       OSC="osc"
+       run_smalliomany $NORM
+}
+run_test smallio "Performance comparision: smallio"
+
+test_mdtest() {
+       OSC="mdc"
+       run_MDtest $DOM
+       OSC="osc"
+       run_MDtest $NORM
+}
+run_test mdtest "Performance comparision: mdtest"
+
+test_IOR() {
+       OSC="mdc"
+       run_IOR $DOM
+       OSC="osc"
+       run_IOR $NORM
+}
+run_test IOR "Performance comparision: IOR"
+
+test_dbench() {
+       OSC="mdc"
+       run_dbench $DOM
+       OSC="osc"
+       run_dbench $NORM
+}
+run_test dbench "Performance comparision: dbench"
+
+test_smf() {
+       OSC="mdc"
+       run_smallfile $DOM
+       OSC="osc"
+       run_smallfile $NORM
+
+}
+run_test smf "Performance comparision: smallfile"
+
+complete $SECONDS
+check_and_cleanup_lustre
+exit_status
diff --git a/lustre/tests/sanity-dom.sh b/lustre/tests/sanity-dom.sh
new file mode 100644 (file)
index 0000000..7c47479
--- /dev/null
@@ -0,0 +1,125 @@
+#!/bin/bash
+#
+# Run select tests by setting ONLY, or as arguments to the script.
+# Skip specific tests by setting EXCEPT.
+#
+
+set -e
+
+ONLY=${ONLY:-"$*"}
+ALWAYS_EXCEPT="$SANITY_DOM_EXCEPT"
+[ "$SLOW" = "no" ] && EXCEPT_SLOW=""
+# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
+
+LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
+
+. $LUSTRE/tests/test-framework.sh
+CLEANUP=${CLEANUP:-:}
+SETUP=${SETUP:-:}
+init_test_env $@
+. ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
+init_logging
+
+MULTIOP=${MULTIOP:-multiop}
+OPENFILE=${OPENFILE:-openfile}
+MOUNT_2=${MOUNT_2:-"yes"}
+FAIL_ON_ERROR=false
+
+check_and_setup_lustre
+
+# $RUNAS_ID may get set incorrectly somewhere else
+if [[ $UID -eq 0 && $RUNAS_ID -eq 0 ]]; then
+       skip_env "\$RUNAS_ID set to 0, but \$UID is also 0!" && exit
+fi
+check_runas_id $RUNAS_ID $RUNAS_GID $RUNAS
+
+build_test_filter
+
+DOM="yes"
+DOM_SIZE=${DOM_SIZE:-"$((1024*1024))"}
+OSC="mdc"
+
+lfs setstripe -E $DOM_SIZE -L mdt -E EOF $DIR1
+
+mkdir -p $MOUNT2
+mount_client $MOUNT2
+
+lctl set_param debug=0xffffffff 2> /dev/null
+
+test_1() {
+       dd if=/dev/zero of=$DIR1/$tfile bs=7k count=1 || error "write 1"
+       $TRUNCATE $DIR2/$tfile 1000 || error "truncate"
+       dd if=/dev/zero of=$DIR1/$tfile bs=3k count=1 seek=1 || error "write 2"
+       $CHECKSTAT -t file -s 6144 $DIR2/$tfile || error "stat"
+       rm $DIR1/$tfile
+}
+run_test 1 "write a file on one mount, truncate on the other, write again"
+
+test_2() {
+       SZ1=234852
+       dd if=/dev/zero of=$DIR/$tfile bs=1M count=1 seek=4 || return 1
+       dd if=/dev/zero bs=$SZ1 count=1 >> $DIR/$tfile || return 2
+       dd if=$DIR/$tfile of=$DIR/${tfile}_left bs=1M skip=5 || return 3
+       $CHECKSTAT -t file -s $SZ1 $DIR/${tfile}_left ||
+               error "Error reading at the end of the file $tfile"
+}
+run_test 2 "Write with a seek, append, read from a single mountpoint"
+
+test_3() {
+       # Write on one node to the DoM stripe and then truncate to over DoM size
+       dd if=/dev/zero of=$DIR1/$tfile bs=$((DOM_SIZE-100)) count=1 ||
+               return 1
+       truncate $DIR1/$tfile $((DOM_SIZE+700)) || return 2
+       # read on the second node inside DoM stripe to take a lock data from
+       # the first client
+       dd if=$DIR2/$tfile of=/dev/null bs=4096 count=1 seek=1 || return 3
+       $CHECKSTAT -t file -s $((DOM_SIZE+700)) $DIR2/$tfile ||
+               error "Wrong size after first truncate $tfile on first node"
+       # now do local truncate over DoM size and check size is correct
+       truncate $DIR2/$tfile $((DOM_SIZE+500)) || return 4
+       $CHECKSTAT -t file -s $((DOM_SIZE+500)) $DIR2/$tfile ||
+               error "Wrong size after second truncate on the same node"
+       $CHECKSTAT -t file -s $((DOM_SIZE+500)) $DIR1/$tfile ||
+               error "Wrong size after second truncate on other node"
+}
+run_test 3 "Truncate over DoM size on different nodes"
+
+# TODO: tests below are from sanityn but their adapted version should be
+# put here: 31 32 34 71 75
+
+test_sn16() {
+       local file1=$DIR1/$tfile
+       local file2=$DIR2/$tfile
+
+       touch $file1
+       fsx -c 50 -p 1 -N 1000 -l $(($DOM_SIZE*2)) -S 0 -d -d $file1 $file2
+}
+run_test sn16 "$FSXNUM iterations of dual-mount fsx"
+
+test_sanity()
+{
+       local SAVE_ONLY=$ONLY
+
+       [ ! -f sanity.sh ] && skip_env "No sanity.sh skipping" && return
+       # XXX: to fix 45
+       ONLY="36 39 40 41 42 43 46 56r 101e 119a 131 150 155a 155b 155c \
+               155d 207 241 251" OSC="mdc" DOM="yes" sh sanity.sh
+       ONLY=$SAVE_ONLY
+}
+run_test sanity "Run sanity with Data-on-MDT files"
+
+test_sanityn()
+{
+       local SAVE_ONLY=$ONLY
+
+       [ ! -f sanity.sh ] && skip_env "No sanity.sh skipping" && return
+       # XXX: to fix 60
+       ONLY="1 2 4 5 6 7 8 9 10 11 12 14 17 19 20 23 27 39 51a 51c 51d" \
+               OSC="mdc" DOM="yes" sh sanityn.sh
+       ONLY=$SAVE_ONLY
+}
+run_test sanityn "Run sanityn with Data-on-MDT files"
+
+complete $SECONDS
+check_and_cleanup_lustre
+exit_status
index 628cf5b..f3ce898 100755 (executable)
@@ -40,6 +40,7 @@ SRCDIR=$(cd $(dirname $0); echo $PWD)
 export PATH=$PATH:/sbin
 
 TMP=${TMP:-/tmp}
+OSC=${OSC:-"osc"}
 
 CC=${CC:-cc}
 CHECKSTAT=${CHECKSTAT:-"checkstat -v"}
@@ -3587,7 +3588,7 @@ test_41() {
 run_test 41 "test small file write + fstat ====================="
 
 count_ost_writes() {
-       lctl get_param -n osc.*.stats |
+       lctl get_param -n ${OSC}.*.stats |
                awk -vwrites=0 '/ost_write/ { writes += $2 } \
                        END { printf("%0.0f", writes) }'
 }
@@ -3647,7 +3648,7 @@ setup_test42() {
 test_42a() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
        setup_test42
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
        stop_writeback
        sync; sleep 1; sync # just to be safe
        BEFOREWRITES=`count_ost_writes`
@@ -3663,7 +3664,7 @@ run_test 42a "ensure that we don't flush on close"
 test_42b() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
        setup_test42
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
        stop_writeback
        sync
        dd if=/dev/zero of=$DIR/f42b bs=1024 count=100
@@ -3699,21 +3700,21 @@ run_test 42b "test destroy of file with cached dirty data ======"
 # start the file with a full-file pw lock to match against
 # until the truncate.
 trunc_test() {
-        test=$1
-        file=$DIR/$test
-        offset=$2
-       cancel_lru_locks osc
+       test=$1
+       file=$DIR/$test
+       offset=$2
+       cancel_lru_locks $OSC
        stop_writeback
        # prime the file with 0,EOF PW to match
        touch $file
         $TRUNCATE $file 0
         sync; sync
        # now the real test..
-        dd if=/dev/zero of=$file bs=1024 count=100
-        BEFOREWRITES=`count_ost_writes`
-        $TRUNCATE $file $offset
-        cancel_lru_locks osc
-        AFTERWRITES=`count_ost_writes`
+       dd if=/dev/zero of=$file bs=1024 count=100
+       BEFOREWRITES=`count_ost_writes`
+       $TRUNCATE $file $offset
+       cancel_lru_locks $OSC
+       AFTERWRITES=`count_ost_writes`
        start_writeback
 }
 
@@ -3912,7 +3913,7 @@ run_test 44a "test sparse pwrite ==============================="
 
 dirty_osc_total() {
        tot=0
-       for d in `lctl get_param -n osc.*.cur_dirty_bytes`; do
+       for d in `lctl get_param -n ${OSC}.*.cur_dirty_bytes`; do
                tot=$(($tot + $d))
        done
        echo $tot
@@ -6784,7 +6785,7 @@ test_101e() {
        done
 
        echo "Cancel LRU locks on lustre client to flush the client cache"
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
 
        echo "Reset readahead stats"
        $LCTL set_param -n llite.*.read_ahead_stats 0
@@ -10078,31 +10079,31 @@ test_150() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
        local TF="$TMP/$tfile"
 
-        dd if=/dev/urandom of=$TF bs=6096 count=1 || error "dd failed"
-        cp $TF $DIR/$tfile
-        cancel_lru_locks osc
-        cmp $TF $DIR/$tfile || error "$TMP/$tfile $DIR/$tfile differ"
-        remount_client $MOUNT
-        df -P $MOUNT
-        cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (remount)"
+       dd if=/dev/urandom of=$TF bs=6096 count=1 || error "dd failed"
+       cp $TF $DIR/$tfile
+       cancel_lru_locks $OSC
+       cmp $TF $DIR/$tfile || error "$TMP/$tfile $DIR/$tfile differ"
+       remount_client $MOUNT
+       df -P $MOUNT
+       cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (remount)"
 
-        $TRUNCATE $TF 6000
-        $TRUNCATE $DIR/$tfile 6000
-        cancel_lru_locks osc
-        cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (truncate1)"
+       $TRUNCATE $TF 6000
+       $TRUNCATE $DIR/$tfile 6000
+       cancel_lru_locks $OSC
+       cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (truncate1)"
 
-        echo "12345" >>$TF
-        echo "12345" >>$DIR/$tfile
-        cancel_lru_locks osc
-        cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (append1)"
+       echo "12345" >>$TF
+       echo "12345" >>$DIR/$tfile
+       cancel_lru_locks $OSC
+       cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (append1)"
 
-        echo "12345" >>$TF
-        echo "12345" >>$DIR/$tfile
-        cancel_lru_locks osc
-        cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (append2)"
+       echo "12345" >>$TF
+       echo "12345" >>$DIR/$tfile
+       cancel_lru_locks $OSC
+       cmp $TF $DIR/$tfile || error "$TF $DIR/$tfile differ (append2)"
 
-        rm -f $TF
-        true
+       rm -f $TF
+       true
 }
 run_test 150 "truncate/append tests"
 
@@ -10650,7 +10651,7 @@ test_155_small_load() {
     dd if=/dev/urandom of=$temp bs=6096 count=1 || \
         error "dd of=$temp bs=6096 count=1 failed"
     cp $temp $file
-    cancel_lru_locks osc
+    cancel_lru_locks $OSC
     cmp $temp $file || error "$temp $file differ"
 
     $TRUNCATE $temp 6000
@@ -14026,7 +14027,7 @@ run_test 240 "race between ldlm enqueue and the connection RPC (no ASSERT)"
 test_241_bio() {
        for LOOP in $(seq $1); do
                dd if=$DIR/$tfile of=/dev/null bs=40960 count=1 2>/dev/null
-               cancel_lru_locks osc || true
+               cancel_lru_locks $OSC || true
        done
 }
 
@@ -14040,7 +14041,7 @@ test_241_dio() {
 test_241a() { # was test_241
        dd if=/dev/zero of=$DIR/$tfile count=1 bs=40960
        ls -la $DIR/$tfile
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
        test_241_bio 1000 &
        PID=$!
        test_241_dio 1000
@@ -14996,6 +14997,283 @@ test_260() {
 }
 run_test 260 "Check mdc_close fail"
 
+### Data-on-MDT sanity tests ###
+test_270a() {
+       # create DoM file
+       local dom=$DIR/$tdir/dom_file
+       local tmp=$DIR/$tdir/tmp_file
+
+       mkdir -p $DIR/$tdir
+
+       # basic checks for DoM component creation
+       $SETSTRIPE -E 1024K -E 1024K -L mdt $dom 2>/dev/null &&
+               error "Can set MDT layout to non-first entry"
+
+       $SETSTRIPE -E 1024K -L mdt -E 1024K -L mdt $dom 2>/dev/null &&
+               error "Can define multiple entries as MDT layout"
+
+       $SETSTRIPE -E 1M -L mdt $dom ||
+               error "Can't create DoM layout"
+
+       [ $($GETSTRIPE -L $dom) == 100 ] || error "bad pattern"
+       [ $($GETSTRIPE -c $dom) == 0 ] || error "bad stripe count"
+       [ $($GETSTRIPE -S $dom) == 1048576 ] || error "bad stripe size"
+
+       local mdtidx=$($GETSTRIPE -M $dom)
+       local mdtname=MDT$(printf %04x $mdtidx)
+       local facet=mds$((mdtidx + 1))
+       local space_check=1
+
+       # Skip free space checks with ZFS
+       if [ "$(facet_fstype $facet)" == "zfs" ]; then
+               space_check=0
+       fi
+
+       # write
+       sync
+       local mdtfree1=$(do_facet $facet \
+               lctl get_param -n osd*.*$mdtname.kbytesfree)
+       dd if=/dev/urandom of=$tmp bs=1024 count=100
+       # check also direct IO along write
+       dd if=$tmp of=$dom bs=102400 count=1 oflag=direct
+       sync
+       cmp $tmp $dom || error "file data is different"
+       [ $(stat -c%s $dom) == 102400 ] || error "bad size after write"
+       if [ $space_check == 1 ]; then
+               local mdtfree2=$(do_facet $facet \
+                               lctl get_param -n osd*.*$mdtname.kbytesfree)
+               [ $(($mdtfree1 - $mdtfree2)) -ge 102 ] ||
+                       error "MDT free space is wrong after write"
+       fi
+
+       # truncate
+       $TRUNCATE $dom 10000
+       [ $(stat -c%s $dom) == 10000 ] || error "bad size after truncate"
+       if [ $space_check == 1 ]; then
+               mdtfree1=$(do_facet $facet \
+                               lctl get_param -n osd*.*$mdtname.kbytesfree)
+               [ $(($mdtfree1 - $mdtfree2)) -ge 92 ] ||
+                       error "MDT free space is wrong after truncate"
+       fi
+
+       # append
+       cat $tmp >> $dom
+       sync
+       [ $(stat -c%s $dom) == 112400 ] || error "bad size after append"
+       if [ $space_check == 1 ]; then
+               mdtfree2=$(do_facet $facet \
+                               lctl get_param -n osd*.*$mdtname.kbytesfree)
+               [ $(($mdtfree1 - $mdtfree2)) -ge 102 ] ||
+                       error "MDT free space is wrong after append"
+       fi
+
+       # delete
+       rm $dom
+       if [ $space_check == 1 ]; then
+               mdtfree1=$(do_facet $facet \
+                               lctl get_param -n osd*.*$mdtname.kbytesfree)
+               [ $(($mdtfree1 - $mdtfree2)) -ge 112 ] ||
+                       error "MDT free space is wrong after removal"
+       fi
+
+       # combined striping
+       $SETSTRIPE -E 1024K -L mdt -E EOF $dom ||
+               error "Can't create DoM + OST striping"
+
+       dd if=/dev/urandom of=$tmp bs=1024 count=2000
+       # check also direct IO along write
+       dd if=$tmp of=$dom bs=102400 count=20 oflag=direct
+       sync
+       cmp $tmp $dom || error "file data is different"
+       [ $(stat -c%s $dom) == 2048000 ] || error "bad size after write"
+       rm $dom
+       rm $tmp
+
+       return 0
+}
+run_test 270a "DoM: basic functionality tests"
+
+test_270b() {
+       local dom=$DIR/$tdir/dom_file
+       local max_size=1048576
+
+       mkdir -p $DIR/$tdir
+       $SETSTRIPE -E $max_size -L mdt $dom
+
+       # truncate over the limit
+       $TRUNCATE $dom $(($max_size + 1)) &&
+               error "successful truncate over the maximum size"
+       # write over the limit
+       dd if=/dev/zero of=$dom bs=$max_size seek=1 count=1 &&
+               error "successful write over the maximum size"
+       # append over the limit
+       dd if=/dev/zero of=$dom bs=$(($max_size - 3)) count=1
+       echo "12345" >> $dom && error "successful append over the maximum size"
+       rm $dom
+
+       return 0
+}
+run_test 270b "DoM: maximum size overflow checks for DoM-only file"
+
+test_270c() {
+       mkdir -p $DIR/$tdir
+       $SETSTRIPE -E 1024K -L mdt $DIR/$tdir
+
+       # check files inherit DoM EA
+       touch $DIR/$tdir/first
+       [ $($GETSTRIPE -L $DIR/$tdir/first) == 100 ] ||
+               error "bad pattern"
+       [ $($GETSTRIPE -c $DIR/$tdir/first) == 0 ] ||
+               error "bad stripe count"
+       [ $($GETSTRIPE -S $DIR/$tdir/first) == 1048576 ] ||
+               error "bad stripe size"
+
+       # check directory inherits DoM EA and uses it as default
+       mkdir $DIR/$tdir/subdir
+       touch $DIR/$tdir/subdir/second
+       [ $($GETSTRIPE -L $DIR/$tdir/subdir/second) == 100 ] ||
+               error "bad pattern in sub-directory"
+       [ $($GETSTRIPE -c $DIR/$tdir/subdir/second) == 0 ] ||
+               error "bad stripe count in sub-directory"
+       [ $($GETSTRIPE -S $DIR/$tdir/subdir/second) == 1048576 ] ||
+               error "bad stripe size in sub-directory"
+       return 0
+}
+run_test 270c "DoM: DoM EA inheritance tests"
+
+test_270d() {
+       mkdir -p $DIR/$tdir
+       $SETSTRIPE -E 1024K -L mdt $DIR/$tdir
+
+       # inherit default DoM striping
+       mkdir $DIR/$tdir/subdir
+       touch $DIR/$tdir/subdir/f1
+
+       # change default directory striping
+       $SETSTRIPE -c 1 $DIR/$tdir/subdir
+       touch $DIR/$tdir/subdir/f2
+       [ $($GETSTRIPE -c $DIR/$tdir/subdir/f2) == 1 ] ||
+               error "wrong default striping in file 2"
+       [ $($GETSTRIPE -L $DIR/$tdir/subdir/f2) == 1 ] ||
+               error "bad pattern in file 2"
+       return 0
+}
+run_test 270d "DoM: change striping from DoM to RAID0"
+
+test_270e() {
+       mkdir -p $DIR/$tdir/dom
+       mkdir -p $DIR/$tdir/norm
+       DOMFILES=20
+       NORMFILES=10
+       $SETSTRIPE -E 1M -L mdt $DIR/$tdir/dom
+       $SETSTRIPE -i 0 -S 2M $DIR/$tdir/norm
+
+       createmany -o $DIR/$tdir/dom/dom- $DOMFILES
+       createmany -o $DIR/$tdir/norm/norm- $NORMFILES
+
+       # find DoM files by layout
+       NUM=$($LFIND -L mdt -type f $DIR/$tdir 2>/dev/null | wc -l)
+       [ $NUM -eq  $DOMFILES ] ||
+               error "lfs find -L: found $NUM, expected $DOMFILES"
+       echo "Test 1: lfs find 20 DOM files by layout: OK"
+
+       # there should be 1 dir with default DOM striping
+       NUM=$($LFIND -L mdt -type d $DIR/$tdir 2>/dev/null | wc -l)
+       [ $NUM -eq  1 ] ||
+               error "lfs find -L: found $NUM, expected 1 dir"
+       echo "Test 2: lfs find 1 DOM dir by layout: OK"
+
+       # find DoM files by stripe size
+       NUM=$($LFIND -S -1200K -type f $DIR/$tdir 2>/dev/null | wc -l)
+       [ $NUM -eq  $DOMFILES ] ||
+               error "lfs find -S: found $NUM, expected $DOMFILES"
+       echo "Test 4: lfs find 20 DOM files by stripe size: OK"
+
+       # find files by stripe offset except DoM files
+       NUM=$($LFIND -i 0 -type f $DIR/$tdir 2>/dev/null | wc -l)
+       [ $NUM -eq  $NORMFILES ] ||
+               error "lfs find -i: found $NUM, expected $NORMFILES"
+       echo "Test 5: lfs find no DOM files by stripe index: OK"
+       return 0
+}
+run_test 270e "DoM: lfs find with DoM files test"
+
+test_270f() {
+       local mdtname=${FSNAME}-MDT0000-mdtlov
+       local dom=$DIR/$tdir/dom_file
+       local dom_limit_saved=$(do_facet mds1 $LCTL get_param -n \
+                                               lod.$mdtname.dom_stripesize)
+       local dom_limit=131072
+
+       do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=$dom_limit
+       local dom_current=$(do_facet mds1 $LCTL get_param -n \
+                                               lod.$mdtname.dom_stripesize)
+       [ ${dom_limit} -eq ${dom_current} ] ||
+               error "Cannot change per-MDT DoM stripe limit to $dom_limit"
+
+       $LFS mkdir -i 0 -c 1 $DIR/$tdir
+       $SETSTRIPE -d $DIR/$tdir
+       $SETSTRIPE -E $dom_limit -L mdt $DIR/$tdir ||
+               error "Can't set directory default striping"
+
+       # exceed maximum stripe size
+       $SETSTRIPE -E $(($dom_limit * 2)) -L mdt $dom &&
+               error "Able to create DoM component size more than LOD limit"
+
+       do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=0
+       dom_current=$(do_facet mds1 $LCTL get_param -n \
+                                               lod.$mdtname.dom_stripesize)
+       [ 0 -eq ${dom_current} ] ||
+               error "Can't set zero DoM stripe limit"
+
+       # too low values to be aligned with smallest stripe size 64K
+       do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=30000
+       dom_current=$(do_facet mds1 $LCTL get_param -n \
+                                               lod.$mdtname.dom_stripesize)
+       [ 30000 -eq ${dom_current} ] &&
+               error "Can set too small DoM stripe limit"
+
+       do_facet mds1 $LCTL set_param -n lod.$mdtname.dom_stripesize=2147483648
+       dom_current=$(do_facet mds1 $LCTL get_param -n \
+                                               lod.$mdtname.dom_stripesize)
+       echo $dom_current
+       [ 2147483648 -eq ${dom_current} ] &&
+               error "Can set too large DoM stripe limit"
+
+       do_facet mds1 $LCTL set_param -n \
+                               lod.$mdtname.dom_stripesize=$((dom_limit * 2))
+       $SETSTRIPE -E $((dom_limit * 2)) -L mdt $dom ||
+               error "Can't create DoM component size after limit change"
+       do_facet mds1 $LCTL set_param -n \
+                               lod.$mdtname.dom_stripesize=$((dom_limit / 2))
+       $SETSTRIPE -E $dom_limit -L mdt ${dom}_big &&
+               error "Can create big DoM component after limit decrease"
+       touch ${dom}_def ||
+               error "Can't create file with old default layout"
+
+       do_facet mds1 $LCTL set_param -n lod.*.dom_stripesize=$dom_limit_saved
+       return 0
+}
+run_test 270f "DoM: maximum DoM stripe size checks"
+
+test_271a() {
+       local dom=$DIR/$tdir/dom
+
+       mkdir -p $DIR/$tdir
+
+       $SETSTRIPE -E 1024K -L mdt $dom
+
+       lctl set_param -n mdc.*.stats=clear
+       dd if=/dev/zero of=$dom bs=4096 count=1 || return 1
+       cat $dom > /dev/null
+       local reads=$(lctl get_param -n mdc.*.stats | \
+               awk '/ost_read/ {print $2}')
+       [ -z $reads ] || error "Unexpected $reads READ RPCs"
+       ls $dom
+       rm -f $dom
+}
+run_test 271a "DoM: data is cached for read after write"
+
 cleanup_test_300() {
        trap 0
        umask $SAVE_UMASK
index c20f7f7..e7ce1d7 100755 (executable)
@@ -48,6 +48,8 @@ TRACE=${TRACE:-""}
 
 check_and_setup_lustre
 
+OSC=${OSC:-"osc"}
+
 assert_DIR
 rm -rf $DIR1/[df][0-9]* $DIR1/lnk $DIR/[df].${TESTSUITE}*
 
@@ -432,6 +434,8 @@ run_test 18 "mmap sanity check ================================="
 test_19() { # bug3811
        local node=$(facet_active_host ost1)
 
+       [ "x$DOM" = "xyes" ] && node=$(facet_active_host $SINGLEMDS)
+
        # check whether obdfilter is cache capable at all
        if ! get_osd_param $node '' read_cache_enable >/dev/null; then
                echo "not cache-capable obdfilter"
@@ -446,7 +450,7 @@ test_19() { # bug3811
        cp $TMP/$tfile $DIR1/$tfile
        for i in `seq 1 20`; do
                [ $((i % 5)) -eq 0 ] && log "$testname loop $i"
-               cancel_lru_locks osc > /dev/null
+               cancel_lru_locks $OSC > /dev/null
                cksum $DIR1/$tfile | cut -d" " -f 1,2 > $TMP/sum1 & \
                cksum $DIR2/$tfile | cut -d" " -f 1,2 > $TMP/sum2
                wait
@@ -462,12 +466,12 @@ run_test 19 "test concurrent uncached read races ==============="
 
 test_20() {
        test_mkdir $DIR1/d20
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
        CNT=$((`lctl get_param -n llite.*.dump_page_cache | wc -l`))
        $MULTIOP $DIR1/f20 Ow8190c
        $MULTIOP $DIR2/f20 Oz8194w8190c
        $MULTIOP $DIR1/f20 Oz0r8190c
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
        CNTD=$((`lctl get_param -n llite.*.dump_page_cache | wc -l` - $CNT))
        [ $CNTD -gt 0 ] && \
            error $CNTD" page left in cache after lock cancel" || true
@@ -498,7 +502,7 @@ test_23() { # Bug 5972
        echo "atime should be updated while another read" > $DIR1/$tfile
 
        # clear the lock(mode: LCK_PW) gotten from creating operation
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
        time1=$(date +%s)
        echo "now is $time1"
        sleep $((at_diff + 1))
@@ -530,9 +534,9 @@ test_24a() {
 
        OSC=`lctl dl | awk '/-osc-|OSC.*MNT/ {print $4}' | head -n 1`
 #      OSC=`lctl dl | awk '/-osc-/ {print $4}' | head -n 1`
-       lctl --device %$OSC deactivate
+       lctl --device %osc deactivate
        lfs df -i || error "lfs df -i with deactivated OSC failed"
-       lctl --device %$OSC activate
+       lctl --device %osc activate
        lfs df || error "lfs df with reactivated OSC failed"
 }
 run_test 24a "lfs df [-ih] [path] test ========================="
@@ -622,7 +626,7 @@ test_26b() {
 run_test 26b "sync mtime between ost and mds"
 
 test_27() {
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
        lctl clear
        dd if=/dev/zero of=$DIR2/$tfile bs=$((4096+4))k conv=notrunc count=4 seek=3 &
        DD2_PID=$!
@@ -741,38 +745,39 @@ run_test 31b "voluntary OST cancel / blocking ast race=============="
 
 # enable/disable lockless truncate feature, depending on the arg 0/1
 enable_lockless_truncate() {
-        lctl set_param -n osc.*.lockless_truncate $1
+       lctl set_param -n $OSC.*.lockless_truncate $1
 }
 
 test_32a() { # bug 11270
        local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
-       save_lustre_params client "osc.*.lockless_truncate" > $p
-       cancel_lru_locks osc
+
+       save_lustre_params client "$OSC.*.lockless_truncate" > $p
+       cancel_lru_locks $OSC
        enable_lockless_truncate 1
        rm -f $DIR1/$tfile
        lfs setstripe -c -1 $DIR1/$tfile
        dd if=/dev/zero of=$DIR1/$tfile count=$OSTCOUNT bs=$STRIPE_BYTES > \
                /dev/null 2>&1
-       clear_stats osc.*.osc_stats
+       clear_stats $OSC.*.${OSC}_stats
 
        log "checking cached lockless truncate"
        $TRUNCATE $DIR1/$tfile 8000000
        $CHECKSTAT -s 8000000 $DIR2/$tfile || error "wrong file size"
-       [ $(calc_stats osc.*.osc_stats lockless_truncate) -ne 0 ] ||
+       [ $(calc_stats $OSC.*.${OSC}_stats lockless_truncate) -ne 0 ] ||
                error "cached truncate isn't lockless"
 
        log "checking not cached lockless truncate"
        $TRUNCATE $DIR2/$tfile 5000000
        $CHECKSTAT -s 5000000 $DIR1/$tfile || error "wrong file size"
-       [ $(calc_stats osc.*.osc_stats lockless_truncate) -ne 0 ] ||
+       [ $(calc_stats $OSC.*.${OSC}_stats lockless_truncate) -ne 0 ] ||
                error "not cached truncate isn't lockless"
 
        log "disabled lockless truncate"
        enable_lockless_truncate 0
-       clear_stats osc.*.osc_stats
+       clear_stats $OSC.*.${OSC}_stats
        $TRUNCATE $DIR2/$tfile 3000000
        $CHECKSTAT -s 3000000 $DIR1/$tfile || error "wrong file size"
-       [ $(calc_stats osc.*.osc_stats lockless_truncate) -eq 0 ] ||
+       [ $(calc_stats $OSC.*.${OSC}_stats lockless_truncate) -eq 0 ] ||
                error "lockless truncate disabling failed"
        rm $DIR1/$tfile
        # restore lockless_truncate default values
@@ -795,21 +800,21 @@ test_32b() { # bug 11270
                "ldlm.namespaces.filter-*.contended_locks" >> $p
        save_lustre_params $facets \
                "ldlm.namespaces.filter-*.contention_seconds" >> $p
-       clear_stats osc.*.osc_stats
+       clear_stats $OSC.*.${OSC}_stats
 
        # agressive lockless i/o settings
        do_nodes $(comma_list $(osts_nodes)) \
                "lctl set_param -n ldlm.namespaces.*.max_nolock_bytes=2000000 \
                        ldlm.namespaces.filter-*.contended_locks=0 \
                        ldlm.namespaces.filter-*.contention_seconds=60"
-       lctl set_param -n osc.*.contention_seconds=60
+       lctl set_param -n $OSC.*.contention_seconds=60
        for i in {1..5}; do
                dd if=/dev/zero of=$DIR1/$tfile bs=4k count=1 conv=notrunc > \
                        /dev/null 2>&1
                dd if=/dev/zero of=$DIR2/$tfile bs=4k count=1 conv=notrunc > \
                        /dev/null 2>&1
        done
-       [ $(calc_stats osc.*.osc_stats lockless_write_bytes) -ne 0 ] ||
+       [ $(calc_stats $OSC.*.${OSC}_stats lockless_write_bytes) -ne 0 ] ||
                error "lockless i/o was not triggered"
        # disable lockless i/o (it is disabled by default)
        do_nodes $(comma_list $(osts_nodes)) \
@@ -818,15 +823,15 @@ test_32b() { # bug 11270
                        ldlm.namespaces.filter-*.contention_seconds=0"
        # set contention_seconds to 0 at client too, otherwise Lustre still
        # remembers lock contention
-       lctl set_param -n osc.*.contention_seconds=0
-       clear_stats osc.*.osc_stats
+       lctl set_param -n $OSC.*.contention_seconds=0
+       clear_stats $OSC.*.${OSC}_stats
        for i in {1..1}; do
                dd if=/dev/zero of=$DIR1/$tfile bs=4k count=1 conv=notrunc > \
                        /dev/null 2>&1
                dd if=/dev/zero of=$DIR2/$tfile bs=4k count=1 conv=notrunc > \
                        /dev/null 2>&1
        done
-       [ $(calc_stats osc.*.osc_stats lockless_write_bytes) -eq 0 ] ||
+       [ $(calc_stats $OSC.*.${OSC}_stats lockless_write_bytes) -eq 0 ] ||
                error "lockless i/o works when disabled"
        rm -f $DIR1/$tfile
        restore_lustre_params <$p
@@ -1380,7 +1385,7 @@ test_39d() { # LU-7310
 
        $LCTL set_param fail_loc=0
 
-       cancel_lru_locks osc
+       cancel_lru_locks $OSC
 
        local mtime2=$(stat -c %Y $DIR2/$tfile)
        [ "$mtime2" -ge "$d1" ] && [ "$mtime2" -le "$d2" ] ||
diff --git a/lustre/tests/smalliomany.c b/lustre/tests/smalliomany.c
new file mode 100644 (file)
index 0000000..b2c666d
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+static void usage(char *prog)
+{
+       printf("usage: %s {-w|-a|-r} filenamefmt count seconds\n"
+              "-w : write mode\n"
+              "-a : append\n"
+              "-r : read mode\n", prog);
+       exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+       int do_read = 0, do_append = 0;
+       char *base, *endp;
+       long int start, last;
+       long end = ~0UL >> 1, count = ~0UL >> 1;
+       int c, i, fd, rc = 0, len, mode = 0;
+       long nbytes = 0;
+       char buf[4096];
+
+       while ((c = getopt(argc, argv, "war")) != -1) {
+               switch (c) {
+               case 'w':
+                       mode = O_RDWR;
+                       break;
+               case 'a':
+                       do_append = 1;
+                       mode = O_RDWR | O_APPEND;
+                       break;
+               case 'r':
+                       do_read = 1;
+                       mode = O_RDONLY;
+                       break;
+               case '?':
+                       printf("Unknown option '%c'\n", optopt);
+                       usage(argv[0]);
+               }
+       }
+
+       if (optind + 3 != argc) {
+               fprintf(stderr,
+                       "missing filenamebase, total_files, or seconds\n");
+               usage(argv[0]);
+       }
+
+       base = argv[optind];
+       if (strlen(base) > 4080) {
+               fprintf(stderr, "filenamebase too long\n");
+               exit(1);
+       }
+
+       count = strtoul(argv[optind + 1], NULL, 0);
+
+       end = strtoul(argv[optind + 2], &endp, 0);
+       if (end <= 0 && *endp != '\0') {
+               fprintf(stderr, "%s: error: bad number of seconds '%s'\n",
+                       argv[0], argv[optind + 2]);
+               exit(2);
+       }
+
+       srand(42);
+
+       start = last = time(0);
+       end += start;
+
+       for (i = 0; i < count && time(0) < end; i++) {
+               char filename[4096];
+
+               snprintf(filename, sizeof(filename), "%s%d", base, i);
+
+               fd = open(filename, mode, 0666);
+               if (fd < 0) {
+                       fprintf(stderr, "fail to open %s\n", filename);
+                       rc = errno;
+                       break;
+               }
+
+               len = random() % 4096;
+
+               if (do_read == 0) {
+                       c = write(fd, buf, len);
+                       if (c != len) {
+                               fprintf(stderr, "fail to write %s, len %d,"
+                                       " written %d\n", filename, len, c);
+                               rc = errno;
+                               break;
+                       }
+               } else {
+                       c = read(fd, buf, len);
+               }
+               nbytes += c;
+
+               if (close(fd) < 0) {
+                       fprintf(stderr, "can't close %s\n", filename);
+                       rc = errno;
+                       break;
+               }
+
+               if (i && (i % 10000) == 0) {
+                       printf(" - %ld bytes (time %ld total %ld last %ld)"
+                              "\n", nbytes, time(0), time(0) - start,
+                              time(0) - last);
+                       last = time(0);
+               }
+       }
+       printf("total: %s %ld bytes in %ld seconds: %.2f bytes/second\n",
+              do_read ? "read" : do_append ? "append" : "write", nbytes,
+              time(0) - start, ((double)nbytes / (time(0) - start)));
+
+       return rc;
+}