Whamcloud - gitweb
LU-9166 mdt: Add trailing newlines to proc files
[fs/lustre-release.git] / lustre / tests / sanity.sh
index 3f9cc8e..146525c 100755 (executable)
@@ -1909,6 +1909,9 @@ check_seq_oid()
                local ff_pstripe
                if echo $ff_parent | grep -q 'stripe='; then
                        ff_pstripe=$(echo $ff_parent | sed -e 's/.*stripe=//')
+                       if echo $ff_pstripe | grep -q 'stripe_size='; then
+                               ff_pstripe=$(echo $ff_pstripe | cut -d' ' -f1)
+                       fi
                else
                        #
                        # $LL_DECODE_FILTER_FID does not print "stripe="; look
@@ -1919,6 +1922,15 @@ check_seq_oid()
                                sed -e 's/\]//')
                fi
 
+               if echo $ff_parent | grep -q 'stripe_count='; then
+                       local ff_scnt=$(echo $ff_parent |
+                                       sed -e 's/.*stripe_count=//' |
+                                       cut -d' ' -f1)
+
+                       [ $lmm_count -eq $ff_scnt ] ||
+                               error "FF stripe count $lmm_count != $ff_scnt"
+               fi
+
                 # compare lmm_seq and filter_fid->ff_parent.f_seq
                 [ $ff_pseq = $lmm_seq ] ||
                         error "FF parent SEQ $ff_pseq != $lmm_seq"
@@ -2053,11 +2065,11 @@ test_27D() {
 
        local skip27D
        [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.7.64) ] &&
-               skip27D = "-s 29"
+               skip27D = "-s 29,30,31"
        llapi_layout_test -d$DIR/$tdir -p$POOL -o$OSTCOUNT $skip27D ||
                error "llapi_layout_test failed"
 
-       cleanup_pools || error "cleanup_pools failed"
+       destroy_test_pools || error "destroy test pools failed"
 }
 run_test 27D "validate llapi_layout API"
 
@@ -3644,7 +3656,7 @@ test_42a() {
                error "$BEFOREWRITES < $AFTERWRITES"
        start_writeback
 }
-run_test 42a "ensure that we don't flush on close =============="
+run_test 42a "ensure that we don't flush on close"
 
 test_42b() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
@@ -3805,56 +3817,53 @@ test_43A() { # was test_43
        # give multiop a chance to open
        sleep 1
 
-       $DIR/$tdir/$tfile && error || true
+       $DIR/$tdir/$tfile && error "execute $DIR/$tdir/$tfile succeeded" || true
        kill -USR1 $pid
 }
 run_test 43A "execution of file opened for write should return -ETXTBSY"
 
 test_43a() {
-       [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
-       test_mkdir -p $DIR/$tdir
-       cp -p `which $MULTIOP` $DIR/$tdir/multiop ||
-                       cp -p multiop $DIR/$tdir/multiop
+       test_mkdir $DIR/$tdir
+       cp -p $(which $MULTIOP) $DIR/$tdir/multiop ||
+               cp -p multiop $DIR/$tdir/multiop
        MULTIOP_PROG=$DIR/$tdir/multiop multiop_bg_pause $TMP/$tfile.junk O_c ||
-                       return 1
-        MULTIOP_PID=$!
-        $MULTIOP $DIR/$tdir/multiop Oc && error "expected error, got success"
-        kill -USR1 $MULTIOP_PID || return 2
-        wait $MULTIOP_PID || return 3
-       rm $TMP/$tfile.junk $DIR/$tdir/multiop
+               error "multiop open $TMP/$tfile.junk failed"
+       MULTIOP_PID=$!
+       $MULTIOP $DIR/$tdir/multiop Oc && error "expected error, got success"
+       kill -USR1 $MULTIOP_PID || error "kill -USR1 PID $MULTIOP_PID failed"
+       wait $MULTIOP_PID || error "wait PID $MULTIOP_PID failed"
 }
 run_test 43a "open(RDWR) of file being executed should return -ETXTBSY"
 
 test_43b() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
-       test_mkdir -p $DIR/$tdir
-       cp -p `which $MULTIOP` $DIR/$tdir/multiop ||
-                       cp -p multiop $DIR/$tdir/multiop
+       test_mkdir $DIR/$tdir
+       cp -p $(which $MULTIOP) $DIR/$tdir/multiop ||
+               cp -p multiop $DIR/$tdir/multiop
        MULTIOP_PROG=$DIR/$tdir/multiop multiop_bg_pause $TMP/$tfile.junk O_c ||
-                       return 1
-        MULTIOP_PID=$!
-        $TRUNCATE $DIR/$tdir/multiop 0 && error "expected error, got success"
-        kill -USR1 $MULTIOP_PID || return 2
-        wait $MULTIOP_PID || return 3
-       rm $TMP/$tfile.junk $DIR/$tdir/multiop
+               error "multiop open $TMP/$tfile.junk failed"
+       MULTIOP_PID=$!
+       $TRUNCATE $DIR/$tdir/multiop 0 && error "expected error, got success"
+       kill -USR1 $MULTIOP_PID || error "kill -USR1 PID $MULTIOP_PID failed"
+       wait $MULTIOP_PID || error "wait PID $MULTIOP_PID failed"
 }
 run_test 43b "truncate of file being executed should return -ETXTBSY"
 
 test_43c() {
        local testdir="$DIR/$tdir"
-       test_mkdir -p $DIR/$tdir
+       test_mkdir $testdir
        cp $SHELL $testdir/
-       ( cd $(dirname $SHELL) && md5sum $(basename $SHELL) ) | \
-               ( cd $testdir && md5sum -c)
+       ( cd $(dirname $SHELL) && md5sum $(basename $SHELL) ) |
+               ( cd $testdir && md5sum -c )
 }
-run_test 43c "md5sum of copy into lustre========================"
+run_test 43c "md5sum of copy into lustre"
 
 test_44A() { # was test_44
        [[ $OSTCOUNT -lt 2 ]] && skip_env "skipping 2-stripe test" && return
        dd if=/dev/zero of=$DIR/f1 bs=4k count=1 seek=1023
        dd if=$DIR/f1 bs=4k count=1 > /dev/null
 }
-run_test 44A "zero length read from a sparse stripe ============="
+run_test 44A "zero length read from a sparse stripe"
 
 test_44a() {
        local nstripe=$($LCTL lov_getconfig $DIR | grep default_stripe_count: |
@@ -4236,6 +4245,35 @@ test_51e() {
 }
 run_test 51e "check file nlink limit"
 
+test_51f() {
+       test_mkdir $DIR/$tdir
+
+       local max=100000
+       local ulimit_old=$(ulimit -n)
+       local spare=20 # number of spare fd's for scripts/libraries, etc.
+       local mdt=$(lfs getstripe -M $DIR/$tdir)
+       local numfree=$(lfs df -i $DIR/$tdir | awk '/MDT:'$mdt'/ { print $4 }')
+
+       echo "MDT$mdt numfree=$numfree, max=$max"
+       [[ $numfree -gt $max ]] && numfree=$max || numfree=$((numfree * 7 / 8))
+       if [ $((numfree + spare)) -gt $ulimit_old ]; then
+               while ! ulimit -n $((numfree + spare)); do
+                       numfree=$((numfree * 3 / 4))
+               done
+               echo "changed ulimit from $ulimit_old to $((numfree + spare))"
+       else
+               echo "left ulimit at $ulimit_old"
+       fi
+
+       createmany -o -k -t 120 $DIR/$tdir/f $numfree ||
+               error "create+open $numfree files in $DIR/$tdir failed"
+       ulimit -n $ulimit_old
+
+       # if createmany exits at 120s there will be fewer than $numfree files
+       unlinkmany $DIR/$tdir/f $numfree || true
+}
+run_test 51f "check many open files limit"
+
 test_52a() {
        [ -f $DIR/$tdir/foo ] && chattr -a $DIR/$tdir/foo
        test_mkdir -p $DIR/$tdir
@@ -4523,6 +4561,30 @@ test_56b() {
 }
 run_test 56b "check $LFS getdirstripe"
 
+test_56c() {
+       local ost_idx=0
+       local ost_name=$(ostname_from_index $ost_idx)
+
+       local old_status=$(ost_dev_status $ost_idx)
+       [[ -z "$old_status" ]] ||
+               { skip_env "OST $ost_name is in $old_status status"; return 0; }
+
+       do_facet ost1 $LCTL set_param -n obdfilter.$ost_name.degraded=1
+       sleep_maxage
+
+       local new_status=$(ost_dev_status $ost_idx)
+       [[ "$new_status" = "D" ]] ||
+               error "OST $ost_name is in status of '$new_status', not 'D'"
+
+       do_facet ost1 $LCTL set_param -n obdfilter.$ost_name.degraded=0
+       sleep_maxage
+
+       new_status=$(ost_dev_status $ost_idx)
+       [[ -z "$new_status" ]] ||
+               error "OST $ost_name is in status of '$new_status', not ''"
+}
+run_test 56c "check 'lfs df' showing device status"
+
 NUMFILES=3
 NUMDIRS=3
 setup_56() {
@@ -5352,7 +5414,23 @@ test_60a() {
        start mgs $(mgsdevname) $MGS_MOUNT_OPTS || error "start mgs failed"
        $pass || error "test failed, see FAILED test_60a messages for specifics"
 }
-run_test 60a "llog_test run from kernel module and test llog_reader =========="
+run_test 60a "llog_test run from kernel module and test llog_reader"
+
+test_60aa() {
+       # test old logid format
+       if [ $(lustre_version_code mgs) -le $(version_code 3.1.53) ]; then
+               do_facet mgs $LCTL dl | grep MGS
+               do_facet mgs "$LCTL --device %MGS llog_print \\\\\\\$$FSNAME-client" ||
+                       error "old llog_print failed"
+       fi
+
+       # test new logid format
+       if [ $(lustre_version_code mgs) -ge $(version_code 2.9.53) ]; then
+               do_facet mgs "$LCTL --device MGS llog_print $FSNAME-client" ||
+                       error "new llog_print failed"
+       fi
+}
+run_test 60aa "llog_print works with FIDs and simple names"
 
 test_60b() { # bug 6411
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
@@ -8923,6 +9001,9 @@ check_mds_dmesg() {
 }
 
 test_129() {
+       [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.5.56) ]] ||
+               { skip "Need MDS version with at least 2.5.56"; return 0; }
+
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
        if [ "$(facet_fstype $SINGLEMDS)" != ldiskfs ]; then
                skip "Only applicable to ldiskfs-based MDTs"
@@ -9344,22 +9425,27 @@ test_131e() {
 run_test 131e "test read hitting hole"
 
 check_stats() {
+       local facet=$1
+       local op=$2
+       local want=${3:-0}
        local res
-       local count
-       case $1 in
-       $SINGLEMDS) res=`do_facet $SINGLEMDS $LCTL get_param mdt.$FSNAME-MDT0000.md_stats | grep "$2"`
+
+       case $facet in
+       mds*) res=$(do_facet $facet \
+                  $LCTL get_param mdt.$FSNAME-MDT0000.md_stats | grep "$op")
                 ;;
-       ost) res=`do_facet ost1 $LCTL get_param obdfilter.$FSNAME-OST0000.stats | grep "$2"`
+       ost*) res=$(do_facet $facet \
+                  $LCTL get_param obdfilter.$FSNAME-OST0000.stats | grep "$op")
                 ;;
-       *) error "Wrong argument $1" ;;
+       *) error "Wrong facet '$facet'" ;;
        esac
        echo $res
-       [ -z "$res" ] && error "The counter for $2 on $1 was not incremented"
+       [ "$res" ] || error "The counter for $op on $facet was not incremented"
        # if the argument $3 is zero, it means any stat increment is ok.
-       if [[ $3 -gt 0 ]]; then
-               count=$(echo $res | awk '{ print $2 }')
-               [[ $count -ne $3 ]] &&
-                       error "The $2 counter on $1 is wrong - expected $3"
+       if [[ $want -gt 0 ]]; then
+               local count=$(echo $res | awk '{ print $2 }')
+               [[ $count -ne $want ]] &&
+                       error "The $op counter on $facet is $count, not $want"
        fi
 }
 
@@ -9459,17 +9545,17 @@ test_133c() {
        dd if=/dev/zero of=${testdir}/${tfile} conv=notrunc bs=512k count=1 || error "dd failed"
        sync
        cancel_lru_locks osc
-       check_stats ost "write" 1
+       check_stats ost1 "write" 1
 
        dd if=${testdir}/${tfile} of=/dev/null bs=1k count=1 || error "dd failed"
-       check_stats ost "read" 1
+       check_stats ost1 "read" 1
 
        > ${testdir}/${tfile} || error "truncate failed"
-       check_stats ost "punch" 1
+       check_stats ost1 "punch" 1
 
        rm -f ${testdir}/${tfile} || error "file remove failed"
        wait_delete_completed
-       check_stats ost "destroy" 1
+       check_stats ost1 "destroy" 1
 
        rm -rf $DIR/${tdir}
 }
@@ -9646,17 +9732,15 @@ test_133e() {
 }
 run_test 133e "Verifying OST {read,write}_bytes nid stats ================="
 
-proc_dirs=""
-for dir in /proc/fs/lustre/ /proc/sys/lnet/ /proc/sys/lustre/ \
-          /sys/fs/lustre/ /sys/fs/lnet/ /sys/kernel/debug/lnet/ \
-          /sys/kernel/debug/lustre/; do
-       [[ -d $dir ]] && proc_dirs+=" $dir"
-done
+proc_regexp="/{proc,sys}/{fs,sys,kernel/debug}/{lustre,lnet}/"
 
 test_133f() {
        remote_mds_nodsh && skip "remote MDS with nodsh" && return
        remote_ost_nodsh && skip "remote OST with nodsh" && return
        # First without trusting modes.
+       local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
+       echo "proc_dirs='$proc_dirs'"
+       [ -n "$proc_dirs" ] || error "no proc_dirs on $HOSTNAME"
        find $proc_dirs -exec cat '{}' \; &> /dev/null
 
        # Second verifying readability.
@@ -9665,12 +9749,16 @@ test_133f() {
        # eventually, this can also be replaced with "lctl get_param -R",
        # but not until that option is always available on the server
        local facet
-       for facet in $SINGLEMDS ost1; do
-               do_facet $facet find $proc_dirs \
+       for facet in mds1 ost1; do
+               local facet_proc_dirs=$(do_facet $facet \
+                                       \\\ls -d $proc_regexp 2>/dev/null)
+               echo "${facet}_proc_dirs='$facet_proc_dirs'"
+               [ -z "$facet_proc_dirs" ] && error "no proc_dirs on $facet"
+               do_facet $facet find $facet_proc_dirs \
                        ! -name req_history \
                        -exec cat '{}' \\\; &> /dev/null
 
-               do_facet $facet find $proc_dirs \
+               do_facet $facet find $facet_proc_dirs \
                        ! -name req_history \
                        -type f \
                        -exec cat '{}' \\\; &> /dev/null ||
@@ -9683,6 +9771,9 @@ test_133g() {
        remote_mds_nodsh && skip "remote MDS with nodsh" && return
        remote_ost_nodsh && skip "remote OST with nodsh" && return
        # Second verifying writability.
+       local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
+       echo "proc_dirs='$proc_dirs'"
+       [ -n "$proc_dirs" ] || error "no proc_dirs on $HOSTNAME"
        find $proc_dirs \
                -type f \
                -not -name force_lbug \
@@ -9690,21 +9781,20 @@ test_133g() {
                -exec badarea_io '{}' \; &> /dev/null ||
                error "find $proc_dirs failed"
 
-       [ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.5.54) ] &&
-               skip "Too old lustre on MDS" && return
-
-       [ $(lustre_version_code ost1) -le $(version_code 2.5.54) ] &&
-               skip "Too old lustre on ost1" && return
-
        local facet
-       for facet in $SINGLEMDS ost1; do
-               do_facet $facet find $proc_dirs \
+       for facet in mds1 ost1; do
+               [ $(lustre_version_code $facet) -le $(version_code 2.5.54) ] &&
+                       skip "Too old lustre on $facet" && continue
+               local facet_proc_dirs=$(do_facet $facet \
+                                       \\\ls -d $proc_regexp 2> /dev/null)
+               echo "${facet}_proc_dirs='$facet_proc_dirs'"
+               [ -z "$facet_proc_dirs" ] && error "no proc_dirs on $facet"
+               do_facet $facet find $facet_proc_dirs \
                        -type f \
                        -not -name force_lbug \
                        -not -name changelog_mask \
                        -exec badarea_io '{}' \\\; &> /dev/null ||
-               error "$facet find $proc_dirs failed"
-
+                               error "$facet find $facet_proc_dirs failed"
        done
 
        # remount the FS in case writes/reads /proc break the FS
@@ -9714,6 +9804,34 @@ test_133g() {
 }
 run_test 133g "Check for Oopses on bad io area writes/reads in /proc"
 
+test_133h() {
+       remote_mds_nodsh && skip "remote MDS with nodsh" && return
+       remote_ost_nodsh && skip "remote OST with nodsh" && return
+       [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.9.54) ]] &&
+               skip "Need MDS version at least 2.9.54" && return
+
+       local facet
+       for facet in client mds1 ost1; do
+               local facet_proc_dirs=$(do_facet $facet \
+                                       \\\ls -d $proc_regexp 2> /dev/null)
+               [ -z "$facet_proc_dirs" ] && error "no proc_dirs on $facet"
+               echo "${facet}_proc_dirs='$facet_proc_dirs'"
+               # Get the list of files that are missing the terminating newline
+               local missing=($(do_facet $facet \
+                       find ${facet_proc_dirs} -type f \|              \
+                               while read F\; do                       \
+                                       awk -v FS='\v' -v RS='\v\v'     \
+                                       "'END { if(NR>0 &&              \
+                                       \\\$NF !~ /.*\\\n\$/)           \
+                                               print FILENAME}'"       \
+                                       '\$F'\;                         \
+                               done 2>/dev/null))
+               [ ${#missing[*]} -eq 0 ] ||
+                       error "files do not end with newline: ${missing[*]}"
+       done
+}
+run_test 133h "Proc files should end with newlines"
+
 test_134a() {
        remote_mds_nodsh && skip "remote MDS with nodsh" && return
        [[ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.7.54) ]] &&
@@ -11152,6 +11270,55 @@ test_161c() {
 }
 run_test 161c "check CL_RENME[UNLINK] changelog record flags"
 
+test_161d() {
+       local user
+       local pid
+       local fid
+
+       # cleanup previous run
+       rm -rf $DIR/$tdir/$tfile
+
+       user=$(do_facet $SINGLEMDS $LCTL --device $MDT0 \
+               changelog_register -n)
+       [[ $? -eq 0 ]] || error "changelog_register failed"
+
+       # work in a standalone dir to avoid locking on $DIR/$MOUNT to
+       # interfer with $MOUNT/.lustre/fid/ access
+       mkdir $DIR/$tdir
+       [[ $? -eq 0 ]] || error "mkdir failed"
+
+       #define OBD_FAIL_LLITE_CREATE_NODE_PAUSE 0x140c | OBD_FAIL_ONCE
+       $LCTL set_param fail_loc=0x8000140c
+       # 5s pause
+       $LCTL set_param fail_val=5
+
+       # create file
+       echo foofoo > $DIR/$tdir/$tfile &
+       pid=$!
+
+       # wait for create to be delayed
+       sleep 2
+
+       ps -p $pid
+       [[ $? -eq 0 ]] || error "create should be blocked"
+
+       local tempfile=$(mktemp)
+       fid=$(changelog_extract_field $MDT0 "CREAT" "$tfile" "t=")
+       cat $MOUNT/.lustre/fid/$fid 2>/dev/null >$tempfile || error "cat failed"
+       # some delay may occur during ChangeLog publishing and file read just
+       # above, that could allow file write to happen finally
+       [[ -s $tempfile ]] && echo "file should be empty"
+
+       $LCTL set_param fail_loc=0
+
+       wait $pid
+       [[ $? -eq 0 ]] || error "create failed"
+
+       $LFS changelog_clear $MDT0 $user 0
+       do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_deregister $user
+}
+run_test 161d "create with concurrent .lustre/fid access"
+
 check_path() {
     local expected=$1
     shift
@@ -11878,7 +12045,7 @@ test_200() {
                break
        done
 
-       cleanup_pools
+       destroy_test_pools
        return $rc
 }
 run_test 200 "OST pools"
@@ -12078,6 +12245,9 @@ cleanup_205() {
 }
 
 test_205() { # Job stats
+       [[ $(lustre_version_code $SINGLEMDS) -ge $(version_code 2.7.1) ]] ||
+               { skip "Need MDS version with at least 2.7.1"; return 0; }
+
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
        remote_mgs_nodsh && skip "remote MGS with nodsh" && return
        remote_mds_nodsh && skip "remote MDS with nodsh" && return
@@ -14587,7 +14757,11 @@ test_striped_dir() {
                error "getdirstripe failed"
        stripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir)
        if [ "$stripe_count" != "2" ]; then
-               error "stripe_count is $stripe_count, expect 2"
+               error "1:stripe_count is $stripe_count, expect 2"
+       fi
+       stripe_count=$($LFS getdirstripe -T $DIR/$tdir/striped_dir)
+       if [ "$stripe_count" != "2" ]; then
+               error "2:stripe_count is $stripe_count, expect 2"
        fi
 
        stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir)
@@ -14753,13 +14927,13 @@ test_300e() {
        mkdir $DIR/$tdir/striped_dir/dir_c
 
        $LFS setdirstripe -i 0 -c 2 -t all_char $DIR/$tdir/striped_dir/stp_a ||
-               error "set striped dir under striped dir error"
+               error "set striped adir under striped dir error"
 
-       $LFS setdirstripe -i 0 -c 2 -t all_char $DIR/$tdir/striped_dir/stp_b ||
-               error "set striped dir under striped dir error"
+       $LFS setdirstripe -i 0 -c 2 -H all_char $DIR/$tdir/striped_dir/stp_b ||
+               error "set striped bdir under striped dir error"
 
        $LFS setdirstripe -i 0 -c 2 -t all_char $DIR/$tdir/striped_dir/stp_c ||
-               error "set striped dir under striped dir error"
+               error "set striped cdir under striped dir error"
 
        mrename $DIR/$tdir/striped_dir/dir_a $DIR/$tdir/striped_dir/dir_b ||
                error "rename dir under striped dir fails"
@@ -14963,11 +15137,23 @@ test_300i() {
        createmany -o $DIR/$tdir/striped_dir/f- 10 ||
                error "create files under striped dir failed"
 
+       $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/hashdir ||
+               error "set striped hashdir error"
+
+       $LFS setdirstripe -i0 -c$MDSCOUNT -H all_char $DIR/$tdir/hashdir/d0 ||
+               error "create dir0 under hash dir failed"
+       $LFS setdirstripe -i0 -c$MDSCOUNT -H fnv_1a_64 $DIR/$tdir/hashdir/d1 ||
+               error "create dir1 under hash dir failed"
+
        # unfortunately, we need to umount to clear dir layout cache for now
        # once we fully implement dir layout, we can drop this
        umount_client $MOUNT || error "umount failed"
        mount_client $MOUNT || error "mount failed"
 
+       $LFS find -H fnv_1a_64 $DIR/$tdir/hashdir
+       local dircnt=$($LFS find -H fnv_1a_64 $DIR/$tdir/hashdir | wc -l)
+       [ $dircnt -eq 1 ] || error "lfs find striped dir got:$dircnt,except:1"
+
        #set the stripe to be unknown hash type
        #define OBD_FAIL_UNKNOWN_LMV_STRIPE     0x1901
        $LCTL set_param fail_loc=0x1901
@@ -15599,6 +15785,9 @@ test_401a() { #LU-7437
        #count the number of parameters by "list_param -R"
        local params=$($LCTL list_param -R '*' 2>/dev/null | wc -l)
        #count the number of parameters by listing proc files
+       local proc_dirs=$(eval \ls -d $proc_regexp 2>/dev/null)
+       echo "proc_dirs='$proc_dirs'"
+       [ -n "$proc_dirs" ] || error "no proc_dirs on $HOSTNAME"
        local procs=$(find -L $proc_dirs -mindepth 1 -printf '%P\n' 2>/dev/null|
                      sort -u | wc -l)
 
@@ -15923,6 +16112,256 @@ test_409()
 }
 run_test 409 "Large amount of cross-MDTs hard links on the same file"
 
+prep_801() {
+       start_full_debug_logging
+       # cleanup unused barrier locks before test
+       do_facet mgs $LCTL barrier_rescan $FSNAME ||
+               error "Fail to prep barrier test env"
+}
+
+post_801() {
+       stop_full_debug_logging
+}
+
+test_801a() {
+       prep_801
+
+       #define OBD_FAIL_BARRIER_DELAY          0x2202
+       do_facet mgs $LCTL set_param fail_val=3 fail_loc=0x2202
+       do_facet mgs $LCTL barrier_freeze $FSNAME 10 &
+
+       sleep 1
+       local b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                              awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'freezing_p1'" ] ||
+               error "(1) unexpected barrier status $b_status"
+
+       do_facet mgs $LCTL set_param fail_val=0 fail_loc=0
+       wait
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'frozen'" ] ||
+               error "(2) unexpected barrier status $b_status"
+
+       local expired=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                       awk '/will be expired/ { print $7 }')
+       echo "sleep $((expired + 3)) seconds, then the barrier will be expired"
+       sleep $((expired + 3))
+
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'expired'" ] ||
+               error "(3) unexpected barrier status $b_status"
+
+       do_facet mgs $LCTL barrier_freeze $FSNAME 10 ||
+               error "(4) fail to freeze barrier"
+
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'frozen'" ] ||
+               error "(5) unexpected barrier status $b_status"
+
+       #define OBD_FAIL_BARRIER_DELAY          0x2202
+       do_facet mgs $LCTL set_param fail_val=3 fail_loc=0x2202
+       do_facet mgs $LCTL barrier_thaw $FSNAME &
+
+       sleep 1
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'thawing'" ] ||
+               error "(6) unexpected barrier status $b_status"
+
+       do_facet mgs $LCTL set_param fail_val=0 fail_loc=0
+       wait
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'thawed'" ] ||
+               error "(7) unexpected barrier status $b_status"
+
+       #define OBD_FAIL_BARRIER_FAILURE        0x2203
+       do_facet $SINGLEMDS $LCTL set_param fail_loc=0x2203
+       do_facet mgs $LCTL barrier_freeze $FSNAME
+
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                              awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'failed'" ] ||
+               error "(8) unexpected barrier status $b_status"
+
+       do_facet $SINGLEMDS $LCTL set_param fail_loc=0
+       do_facet mgs $LCTL barrier_thaw $FSNAME
+
+       post_801
+}
+run_test 801a "write barrier user interfaces and stat machine"
+
+test_801b() {
+       prep_801
+
+       mkdir $DIR/$tdir || error "(1) fail to mkdir"
+       createmany -d $DIR/$tdir/d 6 || "(2) fail to mkdir"
+       touch $DIR/$tdir/d2/f10 || error "(3) fail to touch"
+       touch $DIR/$tdir/d3/f11 || error "(4) fail to touch"
+       touch $DIR/$tdir/d4/f12 || error "(5) fail to touch"
+
+       cancel_lru_locks mdc
+
+       # 180 seconds should be long enough
+       do_facet mgs $LCTL barrier_freeze $FSNAME 180
+
+       local b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                              awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'frozen'" ] ||
+               error "(6) unexpected barrier status $b_status"
+
+       mkdir $DIR/$tdir/d0/d10 &
+       mkdir_pid=$!
+
+       touch $DIR/$tdir/d1/f13 &
+       touch_pid=$!
+
+       ln $DIR/$tdir/d2/f10 $DIR/$tdir/d2/f14 &
+       ln_pid=$!
+
+       mv $DIR/$tdir/d3/f11 $DIR/$tdir/d3/f15 &
+       mv_pid=$!
+
+       rm -f $DIR/$tdir/d4/f12 &
+       rm_pid=$!
+
+       stat $DIR/$tdir/d5 || error "(7) stat should succeed"
+
+       # To guarantee taht the 'stat' is not blocked
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'frozen'" ] ||
+               error "(8) unexpected barrier status $b_status"
+
+       # let above commands to run at background
+       sleep 5
+
+       ps -p $mkdir_pid || error "(9) mkdir should be blocked"
+       ps -p $touch_pid || error "(10) touch should be blocked"
+       ps -p $ln_pid || error "(11) link should be blocked"
+       ps -p $mv_pid || error "(12) rename should be blocked"
+       ps -p $rm_pid || error "(13) unlink should be blocked"
+
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'frozen'" ] ||
+               error "(14) unexpected barrier status $b_status"
+
+       do_facet mgs $LCTL barrier_thaw $FSNAME
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'thawed'" ] ||
+               error "(15) unexpected barrier status $b_status"
+
+       wait $mkdir_pid || error "(16) mkdir should succeed"
+       wait $touch_pid || error "(17) touch should succeed"
+       wait $ln_pid || error "(18) link should succeed"
+       wait $mv_pid || error "(19) rename should succeed"
+       wait $rm_pid || error "(20) unlink should succeed"
+
+       post_801
+}
+run_test 801b "modification will be blocked by write barrier"
+
+test_801c() {
+       [[ $MDSCOUNT -lt 2 ]] && skip "needs >= 2 MDTs" && return
+
+       prep_801
+
+       stop mds2 || error "(1) Fail to stop mds2"
+
+       do_facet mgs $LCTL barrier_freeze $FSNAME 30
+
+       local b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                              awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'expired'" -o "$b_status" = "'failed'" ] || {
+               do_facet mgs $LCTL barrier_thaw $FSNAME
+               error "(2) unexpected barrier status $b_status"
+       }
+
+       do_facet mgs $LCTL barrier_rescan $FSNAME ||
+               error "(3) Fail to rescan barrier bitmap"
+
+       do_facet mgs $LCTL barrier_freeze $FSNAME 10
+
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'frozen'" ] ||
+               error "(4) unexpected barrier status $b_status"
+
+       do_facet mgs $LCTL barrier_thaw $FSNAME
+       b_status=$(do_facet mgs $LCTL barrier_stat $FSNAME |
+                        awk '/The barrier for/ { print $7 }')
+       [ "$b_status" = "'thawed'" ] ||
+               error "(5) unexpected barrier status $b_status"
+
+       local devname=$(mdsdevname 2)
+
+       start mds2 $devname $MDS_MOUNT_OPTS || error "(6) Fail to start mds2"
+
+       do_facet mgs $LCTL barrier_rescan $FSNAME ||
+               error "(7) Fail to rescan barrier bitmap"
+
+       post_801
+}
+run_test 801c "rescan barrier bitmap"
+
+saved_MGS_MOUNT_OPTS=$MGS_MOUNT_OPTS
+saved_MDS_MOUNT_OPTS=$MDS_MOUNT_OPTS
+saved_OST_MOUNT_OPTS=$OST_MOUNT_OPTS
+
+cleanup_802() {
+       trap 0
+
+       stopall
+       MGS_MOUNT_OPTS=$saved_MGS_MOUNT_OPTS
+       MDS_MOUNT_OPTS=$saved_MDS_MOUNT_OPTS
+       OST_MOUNT_OPTS=$saved_OST_MOUNT_OPTS
+       setupall
+}
+
+test_802() {
+       mkdir $DIR/$tdir || error "(1) fail to mkdir"
+
+       cp $LUSTRE/tests/test-framework.sh $DIR/$tdir/ ||
+               error "(2) Fail to copy"
+
+       trap cleanup_802 EXIT
+
+       # sync by force before remount as readonly
+       sync; sync_all_data; sleep 3; sync_all_data
+
+       stopall
+
+       MGS_MOUNT_OPTS=$(csa_add "$MGS_MOUNT_OPTS" -o rdonly_dev)
+       MDS_MOUNT_OPTS=$(csa_add "$MDS_MOUNT_OPTS" -o rdonly_dev)
+       OST_MOUNT_OPTS=$(csa_add "$OST_MOUNT_OPTS" -o rdonly_dev)
+
+       echo "Mount the server as read only"
+       setupall server_only || error "(3) Fail to start servers"
+
+       echo "Mount client without ro should fail"
+       mount_client $MOUNT &&
+               error "(4) Mount client without 'ro' should fail"
+
+       echo "Mount client with ro should succeed"
+       mount_client $MOUNT ro ||
+               error "(5) Mount client with 'ro' should succeed"
+
+       echo "Modify should be refused"
+       touch $DIR/$tdir/guard && error "(6) Touch should fail under ro mode"
+
+       echo "Read should be allowed"
+       diff $LUSTRE/tests/test-framework.sh $DIR/$tdir/test-framework.sh ||
+               error "(7) Read should succeed under ro mode"
+
+       cleanup_802
+}
+run_test 802 "simulate readonly device"
+
 #
 # tests that do cleanup/setup should be run at the end
 #