Whamcloud - gitweb
LU-9516 tests: fix sanity test_24v
[fs/lustre-release.git] / lustre / tests / sanity.sh
index 0a81f05..feff64f 100755 (executable)
@@ -1184,12 +1184,15 @@ test_24u() { # bug12192
 run_test 24u "create stripe file"
 
 simple_cleanup_common() {
+       local createmany=$1
        local rc=0
-       trap 0
-       [ -z "$DIR" ] || [ -z "$tdir" ] && return 0
+
+       [[ -z "$DIR" || -z "$tdir" || ! -d "$DIR/$tdir" ]] && return 0
 
        local start=$SECONDS
-       rm -rf $DIR/$tdir
+
+       [[ -n "$createmany" ]] && unlinkmany $DIR/$tdir/$tfile $createmany
+       rm -rf $DIR/$tdir || error "cleanup $DIR/$tdir failed"
        rc=$?
        wait_delete_completed
        echo "cleanup time $((SECONDS - start))"
@@ -1213,10 +1216,10 @@ test_24v() {
        test_mkdir "$(dirname $fname)"
        # assume MDT0000 has the fewest inodes
        local stripes=$($LFS getdirstripe -c $(dirname $fname))
-       local free_inodes=$(($(mdt_free_inodes 0) * stripes))
+       local free_inodes=$(($(mdt_free_inodes 0) * ${stripes/#0/1}))
        [[ $free_inodes -lt $nrfiles ]] && nrfiles=$free_inodes
 
-       trap simple_cleanup_common EXIT
+       stack_trap "simple_cleanup_common $nrfiles"
 
        createmany -m "$fname" $nrfiles
 
@@ -1245,12 +1248,10 @@ test_24v() {
        local rpc_pages=$(max_pages_per_rpc $mdt_idx)
        local rpc_max=$((nrfiles / (page_entries * rpc_pages) + stripes))
        local mds_readpage=$(calc_stats mdc.*.stats mds_readpage)
-       echo "readpages: $mds_readpage rpc_max: $rpc_max"
-       (( $mds_readpage < $rpc_max - 2 || $mds_readpage > $rpc_max + 1)) &&
+       echo "readpages: $mds_readpage rpc_max: $rpc_max-2/+1"
+       (( $mds_readpage >= $rpc_max - 2 && $mds_readpage <= $rpc_max + 1)) ||
                error "large readdir doesn't take effect: " \
                      "$mds_readpage should be about $rpc_max"
-
-       simple_cleanup_common
 }
 run_test 24v "list large directory (test hash collision, b=17560)"
 
@@ -1359,19 +1360,15 @@ run_test 24z "cross-MDT rename is done as cp"
 test_24A() { # LU-3182
        local NFILES=5000
 
-       rm -rf $DIR/$tdir
        test_mkdir $DIR/$tdir
-       trap simple_cleanup_common EXIT
+       stack_trap "simple_cleanup_common $NFILES"
        createmany -m $DIR/$tdir/$tfile $NFILES
        local t=$(ls $DIR/$tdir | wc -l)
        local u=$(ls $DIR/$tdir | sort -u | wc -l)
        local v=$(ls -ai $DIR/$tdir | sort -u | wc -l)
-       if [ $t -ne $NFILES ] || [ $u -ne $NFILES ] ||
-          [ $v -ne $((NFILES + 2)) ] ; then
-               error "Expected $NFILES files, got $t ($u unique $v .&..)"
-       fi
 
-       simple_cleanup_common || error "Can not delete directories"
+       (( $t == $NFILES && $u == $NFILES && $v == NFILES + 2 )) ||
+               error "Expected $NFILES files, got $t ($u unique $v .&..)"
 }
 run_test 24A "readdir() returns correct number of entries."
 
@@ -1816,7 +1813,7 @@ test_27m() {
        if [[ $ORIGFREE -gt $MAXFREE ]]; then
                skip "$ORIGFREE > $MAXFREE skipping out-of-space test on OST0"
        fi
-       trap simple_cleanup_common EXIT
+       stack_trap simple_cleanup_common
        test_mkdir $DIR/$tdir
        $LFS setstripe -i 0 -c 1 $DIR/$tdir/$tfile.1
        dd if=/dev/zero of=$DIR/$tdir/$tfile.1 bs=1024 count=$MAXFREE &&
@@ -1835,8 +1832,7 @@ test_27m() {
        touch $DIR/$tdir/$tfile.$i
        [ $($LFS getstripe $DIR/$tdir/$tfile.$i | grep -A 10 obdidx |
            awk '{print $1}'| grep -w "0") ] &&
-               error "OST0 was full but new created file still use it"
-       simple_cleanup_common
+               error "OST0 was full but new created file still use it" || true
 }
 run_test 27m "create file while OST0 was full"
 
@@ -1860,52 +1856,6 @@ reset_enospc() {
        wait_update_facet $SINGLEMDS "$get_prealloc" "" $delay
 }
 
-__exhaust_precreations() {
-       local OSTIDX=$1
-       local FAILLOC=$2
-       local FAILIDX=${3:-$OSTIDX}
-       local ofacet=ost$((OSTIDX + 1))
-
-       mkdir_on_mdt0 $DIR/$tdir
-       local mdtidx=$($LFS getstripe -m $DIR/$tdir)
-       local mfacet=mds$((mdtidx + 1))
-       echo OSTIDX=$OSTIDX MDTIDX=$mdtidx
-
-       local OST=$(ostname_from_index $OSTIDX)
-
-       # on the mdt's osc
-       local mdtosc_proc1=$(get_mdtosc_proc_path $mfacet $OST)
-       local last_id=$(do_facet $mfacet lctl get_param -n \
-                       osp.$mdtosc_proc1.prealloc_last_id)
-       local next_id=$(do_facet $mfacet lctl get_param -n \
-                       osp.$mdtosc_proc1.prealloc_next_id)
-
-       local mdtosc_proc2=$(get_mdtosc_proc_path $mfacet)
-       do_facet $mfacet lctl get_param osp.$mdtosc_proc2.prealloc*
-
-       test_mkdir -p $DIR/$tdir/${OST}
-       $LFS setstripe -i $OSTIDX -c 1 $DIR/$tdir/${OST}
-#define OBD_FAIL_OST_ENOSPC              0x215
-       do_facet $ofacet lctl set_param fail_val=$FAILIDX fail_loc=0x215
-       echo "Creating to objid $last_id on ost $OST..."
-       createmany -o $DIR/$tdir/${OST}/f $next_id $((last_id - next_id + 2))
-       do_facet $mfacet lctl get_param osp.$mdtosc_proc2.prealloc*
-       do_facet $ofacet lctl set_param fail_loc=$FAILLOC
-}
-
-exhaust_precreations() {
-       __exhaust_precreations $1 $2 $3
-       sleep_maxage
-}
-
-exhaust_all_precreations() {
-       local i
-       for (( i=0; i < OSTCOUNT; i++ )) ; do
-               __exhaust_precreations $i $1 -1
-       done
-       sleep_maxage
-}
-
 test_27n() {
        [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
        [ $PARALLEL == "yes" ] && skip "skip parallel run"
@@ -2084,15 +2034,13 @@ test_27u() { # bug 4900
 #define OBD_FAIL_MDS_OSC_PRECREATE      0x139
        do_nodes $list $LCTL set_param fail_loc=0x139
        test_mkdir -p $DIR/$tdir
-       trap simple_cleanup_common EXIT
-       createmany -o $DIR/$tdir/t- 1000
+       stack_trap "simple_cleanup_common 1000"
+       createmany -o $DIR/$tdir/$tfile 1000
        do_nodes $list $LCTL set_param fail_loc=0
 
        TLOG=$TMP/$tfile.getstripe
        $LFS getstripe $DIR/$tdir > $TLOG
        OBJS=$(awk -vobj=0 '($1 == 0) { obj += 1 } END { print obj; }' $TLOG)
-       unlinkmany $DIR/$tdir/t- 1000
-       trap 0
        [[ $OBJS -gt 0 ]] &&
                error "$OBJS objects created on OST-0. See $TLOG" ||
                rm -f $TLOG
@@ -3395,6 +3343,36 @@ test_27Q() {
 }
 run_test 27Q "llapi_file_get_stripe() works on symlinks"
 
+test_27R() {
+       (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
+               skip "need MDS 2.14.55 or later"
+       (( $OSTCOUNT >= 2 )) || skip_env "needs at least 2 OSTs"
+
+       local testdir="$DIR/$tdir"
+       test_mkdir -p $testdir
+       stack_trap "rm -rf $testdir"
+       $LFS setstripe -c -1 $testdir || error "setstripe failed"
+
+       local f1="$testdir/f1"
+       touch $f1 || error "failed to touch $f1"
+       local count=$($LFS getstripe -c $f1)
+       (( $count == $OSTCOUNT )) || error "wrong stripe count"
+
+       do_facet $SINGLEMDS $LCTL set_param lod.*.max_stripecount=-1
+       (( $? == 34 )) || error "setting max_stripecount to -1 should fail and return ERANGE"
+
+       local maxcount=$(($OSTCOUNT - 1))
+       local mdts=$(comma_list $(mdts_nodes))
+       do_nodes $mdts $LCTL set_param lod.*.max_stripecount=$maxcount
+       stack_trap "do_nodes $mdts $LCTL set_param lod.*.max_stripecount=0"
+
+       local f2="$testdir/f2"
+       touch $f2 || error "failed to touch $f2"
+       local count=$($LFS getstripe -c $f2)
+       (( $count == $maxcount )) || error "wrong stripe count"
+}
+run_test 27R "test max_stripecount limitation when stripe count is set to -1"
+
 # createtest also checks that device nodes are created and
 # then visible correctly (#2091)
 test_28() { # bug 2091
@@ -3406,6 +3384,11 @@ run_test 28 "create/mknod/mkdir with bad file types ============"
 test_29() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run"
 
+       [ $MDS1_VERSION -ge $(version_code 2.14.51) ] && {
+               disable_opencache
+               stack_trap "restore_opencache"
+       }
+
        sync; sleep 1; sync # flush out any dirty pages from previous tests
        cancel_lru_locks
        test_mkdir $DIR/d29
@@ -11873,7 +11856,7 @@ test_116a() { # was previously test_116()
 
        [ $MINV -eq 0 ] && skip "no free space in OST$MINI, skip"
        [ $MINV -gt 10000000 ] && skip "too much free space in OST$MINI, skip"
-       trap simple_cleanup_common EXIT
+       stack_trap simple_cleanup_common
 
        # Check if we need to generate uneven OSTs
        test_mkdir -p $DIR/$tdir/OST${MINI}
@@ -11918,8 +11901,6 @@ test_116a() { # was previously test_116()
        if [ $DIFF2 -gt $threshold ]; then
                echo "ok"
        else
-               echo "failed - QOS mode won't be used"
-               simple_cleanup_common
                skip "QOS imbalance criteria not met"
        fi
 
@@ -11977,7 +11958,6 @@ test_116a() { # was previously test_116()
        fi
        [[ $MAXC -gt $MINC ]] ||
                error_ignore LU-9 "stripe QOS didn't balance free space"
-       simple_cleanup_common
 }
 run_test 116a "stripe QOS: free space balance ==================="
 
@@ -16066,14 +16046,11 @@ run_test 160f "changelog garbage collect (timestamped users)"
 
 test_160g() {
        remote_mds_nodsh && skip "remote MDS with nodsh"
-       [[ $MDS1_VERSION -ge $(version_code 2.10.56) ]] ||
-               skip "Need MDS version at least 2.10.56"
+       [[ $MDS1_VERSION -ge $(version_code 2.14.55) ]] ||
+               skip "Need MDS version at least 2.14.55"
 
        local mdts=$(comma_list $(mdts_nodes))
 
-       #define OBD_FAIL_TIME_IN_CHLOG_USER     0x1314
-       do_nodes $mdts $LCTL set_param fail_loc=0x1314
-
        # Create a user
        changelog_register || error "first changelog_register failed"
        changelog_register || error "second changelog_register failed"
@@ -16098,10 +16075,9 @@ test_160g() {
        (( $nbcl > 0 )) || error "no changelogs found"
 
        # reduce the max_idle_indexes value to make sure we exceed it
-       for param in "changelog_max_idle_indexes=1" \
+       for param in "changelog_max_idle_indexes=2" \
                     "changelog_gc=1" \
-                    "changelog_min_gc_interval=2" \
-                    "changelog_min_free_cat_entries=3"; do
+                    "changelog_min_gc_interval=2"; do
                local MDT0=$(facet_svc $SINGLEMDS)
                local var="${param%=*}"
                local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
@@ -16111,10 +16087,6 @@ test_160g() {
                        error "unable to set mdd.*.$param"
        done
 
-       # simulate changelog catalog almost full
-       #define OBD_FAIL_CAT_FREE_RECORDS       0x1313
-       do_nodes $mdts "$LCTL set_param fail_loc=0x1313 fail_val=3"
-
        local start=$SECONDS
        for i in $(seq $MDSCOUNT); do
                cl_users=(${CL_USERS[mds$i]})
@@ -16122,38 +16094,37 @@ test_160g() {
                cl_user2[mds$i]="${cl_users[1]}"
 
                [ -n "${cl_user1[mds$i]}" ] ||
-                       error "mds$i: no user registered"
+                       error "mds$i: user1 is not registered"
                [ -n "${cl_user2[mds$i]}" ] ||
                        error "mds$i: only ${cl_user1[mds$i]} is registered"
 
                user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
                [ -n "$user_rec1" ] ||
-                       error "mds$i: User ${cl_user1[mds$i]} not registered"
+                       error "mds$i: user1 ${cl_user1[mds$i]} not found"
                __changelog_clear mds$i ${cl_user1[mds$i]} +2
                user_rec2=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
                [ -n "$user_rec2" ] ||
-                       error "mds$i: User ${cl_user1[mds$i]} not registered"
-               echo "mds$i: verifying user ${cl_user1[mds$i]} clear: " \
+                       error "mds$i: user1 ${cl_user1[mds$i]} not found (2)"
+               echo "mds$i: verifying user1 ${cl_user1[mds$i]} clear: " \
                     "$user_rec1 + 2 == $user_rec2"
                [ $((user_rec1 + 2)) == $user_rec2 ] ||
-                       error "mds$i: user ${cl_user1[mds$i]} index expected " \
-                             "$user_rec1 + 2, but is $user_rec2"
+                       error "mds$i: user1 ${cl_user1[mds$i]} index " \
+                             "expected $user_rec1 + 2, but is $user_rec2"
                user_rec2=$(changelog_user_rec mds$i ${cl_user2[mds$i]})
                [ -n "$user_rec2" ] ||
-                       error "mds$i: User ${cl_user2[mds$i]} not registered"
+                       error "mds$i: user2 ${cl_user2[mds$i]} not found"
                [ $user_rec1 == $user_rec2 ] ||
-                       error "mds$i: user ${cl_user2[mds$i]} index expected " \
-                             "$user_rec1, but is $user_rec2"
+                       error "mds$i: user2 ${cl_user2[mds$i]} index " \
+                             "expected $user_rec1, but is $user_rec2"
        done
 
        # ensure we are past the previous changelog_min_gc_interval set above
        local sleep2=$((start + 2 - SECONDS))
        (( sleep2 > 0 )) && echo "sleep $sleep2 for interval" && sleep $sleep2
-
        # Generate one more changelog to trigger GC at fail_loc for cl_user2.
        # cl_user1 should be OK because it recently processed records.
        for ((i = 0; i < MDSCOUNT; i++)); do
-               $LFS mkdir -i $i $DIR/$tdir/d$i.3 $DIR/$tdir/d$i.4 ||
+               $LFS mkdir -i $i $DIR/$tdir/d$i.3 ||
                        error "create $DIR/$tdir/d$i.3 failed"
        done
 
@@ -16167,15 +16138,15 @@ test_160g() {
        for (( i = 1; i <= MDSCOUNT; i++ )); do
                # check cl_user1 still registered
                changelog_users mds$i | grep -q "${cl_user1[mds$i]}" ||
-                       error "mds$i: User ${cl_user1[mds$i]} not registered"
+                       error "mds$i: user1 ${cl_user1[mds$i]} not found (3)"
                # check cl_user2 unregistered
                changelog_users mds$i | grep -q "${cl_user2[mds$i]}" &&
-                       error "mds$i: User ${cl_user2[mds$i]} still registered"
+                       error "mds$i: user2 ${cl_user2[mds$i]} is registered"
 
                # check changelogs are present and starting at $user_rec1 + 1
                user_rec1=$(changelog_user_rec mds$i ${cl_user1[mds$i]})
                [ -n "$user_rec1" ] ||
-                       error "mds$i: User ${cl_user1[mds$i]} not registered"
+                       error "mds$i: user1 ${cl_user1[mds$i]} not found (4)"
                first_rec=$($LFS changelog $(facet_svc mds$i) |
                            awk '{ print $1; exit; }')
 
@@ -16184,7 +16155,7 @@ test_160g() {
                        error "mds$i: rec $first_rec != $user_rec1 + 1"
        done
 }
-run_test 160g "changelog garbage collect (old users)"
+run_test 160g "changelog garbage collect on idle records"
 
 test_160h() {
        remote_mds_nodsh && skip "remote MDS with nodsh" && return
@@ -16760,6 +16731,89 @@ test_160q() {
 }
 run_test 160q "changelog effective mask is DEFMASK if not set"
 
+test_160s() {
+       remote_mds_nodsh && skip "remote MDS with nodsh"
+       (( $MDS1_VERSION >= $(version_code 2.14.55) )) ||
+               skip "Need MDS version at least 2.14.55"
+
+       local mdts=$(comma_list $(mdts_nodes))
+
+       #define OBD_FAIL_TIME_IN_CHLOG_USER     0x1314
+       do_nodes $mdts $LCTL set_param fail_loc=0x1314 \
+                                      fail_val=$((24 * 3600 * 10))
+
+       # Create a user which is 10 days old
+       changelog_register || error "first changelog_register failed"
+       local cl_users
+       declare -A cl_user1
+       local i
+
+       # generate some changelog records to accumulate on each MDT
+       # use all_char because created files should be evenly distributed
+       test_mkdir -c $MDSCOUNT -H all_char $DIR/$tdir ||
+               error "test_mkdir $tdir failed"
+       for ((i = 0; i < MDSCOUNT; i++)); do
+               $LFS mkdir -i $i $DIR/$tdir/d$i.1 $DIR/$tdir/d$i.2 ||
+                       error "create $DIR/$tdir/d$i.1 failed"
+       done
+
+       # check changelogs have been generated
+       local nbcl=$(changelog_dump | wc -l)
+       (( nbcl > 0 )) || error "no changelogs found"
+
+       # reduce the max_idle_indexes value to make sure we exceed it
+       for param in "changelog_max_idle_indexes=2097446912" \
+                    "changelog_max_idle_time=2592000" \
+                    "changelog_gc=1" \
+                    "changelog_min_gc_interval=2"; do
+               local MDT0=$(facet_svc $SINGLEMDS)
+               local var="${param%=*}"
+               local old=$(do_facet mds1 "$LCTL get_param -n mdd.$MDT0.$var")
+
+               stack_trap "do_nodes $mdts $LCTL set_param mdd.*.$var=$old" EXIT
+               do_nodes $mdts $LCTL set_param mdd.*.$param ||
+                       error "unable to set mdd.*.$param"
+       done
+
+       local start=$SECONDS
+       for i in $(seq $MDSCOUNT); do
+               cl_users=(${CL_USERS[mds$i]})
+               cl_user1[mds$i]="${cl_users[0]}"
+
+               [[ -n "${cl_user1[mds$i]}" ]] ||
+                       error "mds$i: no user registered"
+       done
+
+       #define OBD_FAIL_MDS_CHANGELOG_IDX_PUMP   0x16d
+       do_nodes $mdts $LCTL set_param fail_loc=0x16d fail_val=500000000
+
+       # ensure we are past the previous changelog_min_gc_interval set above
+       local sleep2=$((start + 2 - SECONDS))
+       (( sleep2 > 0 )) && echo "sleep $sleep2 for interval" && sleep $sleep2
+
+       # Generate one more changelog to trigger GC
+       for ((i = 0; i < MDSCOUNT; i++)); do
+               $LFS mkdir -i $i $DIR/$tdir/d$i.3 $DIR/$tdir/d$i.4 ||
+                       error "create $DIR/$tdir/d$i.3 failed"
+       done
+
+       # ensure gc thread is done
+       for node in $(mdts_nodes); do
+               wait_update $node "pgrep chlg_gc_thread" "" 20 ||
+                       error "$node: GC-thread not done"
+       done
+
+       do_nodes $mdts $LCTL set_param fail_loc=0
+
+       for (( i = 1; i <= MDSCOUNT; i++ )); do
+               # check cl_user1 is purged
+               changelog_users mds$i | grep -q "${cl_user1[mds$i]}" &&
+                       error "mds$i: User ${cl_user1[mds$i]} is registered"
+       done
+       return 0
+}
+run_test 160s "changelog garbage collect on idle records * time"
+
 test_161a() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run"
 
@@ -20331,6 +20385,24 @@ test_230v()
 }
 run_test 230v "subdir migrated to the MDT where its parent is located"
 
+test_230w() {
+       (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+       (( MDS1_VERSION >= $(version_code 2.14.53) )) ||
+               skip "Need MDS version at least 2.14.53"
+
+       mkdir -p $DIR/$tdir/sub || error "mkdir failed"
+
+       $LFS migrate -m 1 -c $MDSCOUNT -d $DIR/$tdir ||
+               error "migrate failed"
+
+       (( $($LFS getdirstripe -c $DIR/$tdir) == MDSCOUNT )) ||
+               error "$tdir stripe count mismatch"
+
+       (( $($LFS getdirstripe -c $DIR/$tdir/sub) == 0 )) ||
+               error "$tdir/sub is striped"
+}
+run_test 230w "non-recursive mode dir migration"
+
 test_231a()
 {
        # For simplicity this test assumes that max_pages_per_rpc
@@ -27501,15 +27573,24 @@ test_817() {
 run_test 817 "nfsd won't cache write lock for exec file"
 
 test_818() {
-       mkdir $DIR/$tdir
-       $LFS setstripe -c1 -i0 $DIR/$tfile
-       $LFS setstripe -c1 -i1 $DIR/$tfile
+       test_mkdir -i0 -c1 $DIR/$tdir
+       $LFS setstripe -c1 -i0 $DIR/$tdir/$tfile
+       $LFS setstripe -c1 -i1 $DIR/$tdir/$tfile
        stop $SINGLEMDS
+
+       # restore osp-syn threads
+       stack_trap "fail $SINGLEMDS"
+
        #define OBD_FAIL_OSP_CANT_PROCESS_LLOG          0x2105
        do_facet $SINGLEMDS lctl set_param fail_loc=0x80002105
        start $SINGLEMDS $(mdsdevname ${SINGLEMDS//mds/}) $MDS_MOUNT_OPTS ||
                error "start $SINGLEMDS failed"
        rm -rf $DIR/$tdir
+
+       local testid=$(echo $TESTNAME | tr '_' ' ')
+
+       do_facet mds1 dmesg | tac | sed "/$testid/,$ d" |
+               grep "run LFSCK" || error "run LFSCK is not suggested"
 }
 run_test 818 "unlink with failed llog"
 
@@ -27637,6 +27718,48 @@ test_823() {
 }
 run_test 823 "Setting create_count > OST_MAX_PRECREATE is lowered to maximum"
 
+test_831() {
+       local sync_changes=$(do_facet $SINGLEMDS \
+               $LCTL get_param -n osp.$FSNAME-OST0000-osc-MDT0000.sync_changes)
+
+       [ "$sync_changes" -gt 100 ] &&
+               skip "Sync changes $sync_changes > 100 already"
+
+       local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
+
+       $LFS mkdir -i 0 $DIR/$tdir
+       $LFS setstripe -c 1 -i 0 $DIR/$tdir
+
+       save_lustre_params mds1 \
+               "osp.$FSNAME-OST*-osc-MDT0000.max_sync_changes" > $p
+       save_lustre_params mds1 \
+               "osp.$FSNAME-OST*-osc-MDT0000.max_rpcs_in_progress" >> $p
+
+       do_facet mds1 "$LCTL set_param -n \
+               osp.$FSNAME-OST*-osc-MDT0000.max_sync_changes=100 \
+               osp.$FSNAME-OST*-osc-MDT0000.max_rpcs_in_progress=128"
+       stack_trap "restore_lustre_params < $p" EXIT
+
+       createmany -o $DIR/$tdir/f- 1000
+       unlinkmany $DIR/$tdir/f- 1000 &
+       local UNLINK_PID=$!
+
+       while sleep 1; do
+               sync_changes=$(do_facet mds1 \
+               $LCTL get_param -n osp.$FSNAME-OST0000-osc-MDT0000.sync_changes)
+               # the check in the code is racy, fail the test
+               # if the value above the limit by 10.
+               [ $sync_changes -gt 110 ] && {
+                       kill -2 $UNLINK_PID
+                       wait
+                       error "osp changes throttling failed, $sync_changes>110"
+               }
+               kill -0 $UNLINK_PID 2> /dev/null || break
+       done
+       wait
+}
+run_test 831 "throttling unlink/setattr queuing on OSP"
+
 #
 # tests that do cleanup/setup should be run at the end
 #