From fa23dd3d7ef2c61e48c51e1a59fee55d28ab3186 Mon Sep 17 00:00:00 2001
From: tianzy <tianzy>
Date: Wed, 13 Feb 2008 11:38:02 +0000
Subject: [PATCH] Branch b1_6 In filter_commitrw_write, lqs is freed between
 lquota_chkquota and lquota_pending_commit which led to
 "quota_pending_commit()) there are too many blocks!" b=14784 i=Johann
 i=andrew.perepechko

---
 lustre/quota/quota_interface.c | 22 ++++++++++++----
 lustre/tests/sanity-quota.sh   | 48 ++++++++++++++++++++++++++++++----
 2 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/lustre/quota/quota_interface.c b/lustre/quota/quota_interface.c
index f86afef13c..795eaae4a5 100644
--- a/lustre/quota/quota_interface.c
+++ b/lustre/quota/quota_interface.c
@@ -404,7 +404,10 @@ static int quota_check_common(struct obd_device *obd, unsigned int uid,
                 }
 
                 spin_unlock(&lqs->lqs_lock);
-                lqs_putref(lqs);
+                /* When cycle is zero, lqs_*_pending will be changed. We will
+                 * putref lqs in quota_pending_commit instead of here b=14784 */
+                if (cycle)
+                        lqs_putref(lqs);
         }
 
         if (rc2[0] == QUOTA_RET_ACQUOTA || rc2[1] == QUOTA_RET_ACQUOTA)
@@ -499,27 +502,36 @@ static int quota_pending_commit(struct obd_device *obd, unsigned int uid,
 
                 quota_search_lqs(&qdata[i], NULL, qctxt, &lqs);
                 if (lqs) {
+                        int flag = 0;
                         spin_lock(&lqs->lqs_lock);
                         CDEBUG(D_QUOTA, "pending: %lu, count: %d.\n",
                                isblk ? lqs->lqs_bwrite_pending :
                                lqs->lqs_iwrite_pending, count);
 
                         if (isblk) {
-                                if (lqs->lqs_bwrite_pending >= count)
+                                if (lqs->lqs_bwrite_pending >= count) {
                                         lqs->lqs_bwrite_pending -= count;
-                                else
+                                        flag = 1;
+                                } else {
                                         CDEBUG(D_ERROR,
                                                "there are too many blocks!\n");
+                                }
                         } else {
-                                if (lqs->lqs_iwrite_pending >= count)
+                                if (lqs->lqs_iwrite_pending >= count) {
                                         lqs->lqs_iwrite_pending -= count;
-                                else
+                                        flag = 1;
+                                } else {
                                         CDEBUG(D_ERROR,
                                                "there are too many files!\n");
+                                }
                         }
 
                         spin_unlock(&lqs->lqs_lock);
                         lqs_putref(lqs);
+                        /* When lqs_*_pening is changed back, we'll putref lqs
+                         * here b=14784 */
+                        if (flag)
+                                lqs_putref(lqs);
                 }
         }
 
diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh
index 32f2e97a35..0fe1d48a3a 100644
--- a/lustre/tests/sanity-quota.sh
+++ b/lustre/tests/sanity-quota.sh
@@ -165,6 +165,8 @@ test_1_sub() {
 	chmod 0777 $DIR/$tdir
         TESTFILE="$DIR/$tdir/$tfile-0"
 
+	wait_delete_completed
+
         # test for user
         log "  User quota (limit: $LIMIT kbytes)"
         $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR
@@ -251,6 +253,8 @@ test_2_sub() {
 	chmod 0777 $DIR/$tdir
         TESTFILE="$DIR/$tdir/$tfile-0"
 
+	wait_delete_completed
+
         # test for user
         log "  User quota (limit: $LIMIT files)"
         $LFS setquota -u $TSTUSR 0 0 0 $LIMIT $DIR
@@ -330,6 +334,8 @@ test_block_soft() {
 	TIMER=$(($2 * 3 / 2))
 	OFFSET=0
 
+	wait_delete_completed
+
 	echo "    Write to exceed soft limit"
 	RUNDD="$RUNAS dd if=/dev/zero of=$TESTFILE bs=$BLK_SZ"
 	$RUNDD count=$((BUNIT_SZ+1)) || \
@@ -383,6 +389,7 @@ test_block_soft() {
 
 	# cleanup
 	rm -f $TESTFILE
+	sync; sleep 3; sync;
 }
 
 # block soft limit (start timer, timer goes off, stop timer)
@@ -424,6 +431,8 @@ test_file_soft() {
 	LIMIT=$2
 	TIMER=$(($3 * 3 / 2))
 
+	wait_delete_completed
+
 	echo "    Create files to exceed soft limit"
 	$RUNAS createmany -m ${TESTFILE}_ $((LIMIT + 1)) || \
 		error "create failure, but expect success"
@@ -464,6 +473,7 @@ test_file_soft() {
 
 	# cleanup
 	rm -f ${TESTFILE}_xxx
+	sync; sleep 3; sync;
 }
 
 # file soft limit (start timer, timer goes off, stop timer)
@@ -505,6 +515,8 @@ test_4a() {
         GR_STR5="5c"
         GR_STR6="1111111111111111"
 
+	wait_delete_completed
+
         # test of valid grace strings handling
         echo "  Valid grace strings test"
         $LFS setquota -t -u $GR_STR1 $GR_STR2 $DIR
@@ -528,6 +540,8 @@ test_5() {
 	BLIMIT=$(( $BUNIT_SZ * $((OSTCOUNT + 1)) * 10)) # 10 bunits on each server
 	ILIMIT=$(( $IUNIT_SZ * 10 )) # 10 iunits on mds
 
+	wait_delete_completed
+
 	echo "  Set quota limit (0 $BLIMIT 0 $ILIMIT) for $TSTUSR.$TSTUSR"
 	$LFS setquota -u $TSTUSR 0 $BLIMIT 0 $ILIMIT $DIR
 	$LFS setquota -g $TSTUSR 0 $BLIMIT 0 $ILIMIT $DIR
@@ -547,6 +561,7 @@ test_5() {
 
 	# cleanup
 	unlinkmany $DIR/$tdir/$tfile-0_ $((ILIMIT + 1))
+	sync; sleep 3; sync;
 
 	$LFS setquota -u $TSTUSR 0 0 0 0 $DIR
 	$LFS setquota -g $TSTUSR 0 0 0 0 $DIR
@@ -560,6 +575,8 @@ test_6() {
 		return 0;
 	fi
 
+	wait_delete_completed
+
 	chmod 0777 $DIR/$tdir
 
 	LIMIT=$((BUNIT_SZ * (OSTCOUNT + 1) * 5)) # 5 bunits per server
@@ -610,6 +627,8 @@ test_6() {
 
 	# cleanup
 	rm -f $FILEA
+	sync; sleep 3; sync;
+
 	$LFS setquota -u $TSTUSR 0 0 0 0 $DIR
 	$LFS setquota -g $TSTUSR 0 0 0 0 $DIR
 	return 0
@@ -622,6 +641,8 @@ test_7()
 	chmod 0777 $DIR/$tdir
 	remote_mds && skip "remote mds" && return 0
 
+	wait_delete_completed
+
 	LIMIT=$(( $BUNIT_SZ * $(($OSTCOUNT + 1)) ))
 	TESTFILE="$DIR/$tdir/$tfile-0"
 
@@ -674,6 +695,8 @@ test_8() {
 
 	[ ! -d $DBENCH_LIB ] && skip "dbench not installed" && return 0
 
+	wait_delete_completed
+
 	echo "  Set enough high limit for user: $TSTUSR"
 	$LFS setquota -u $TSTUSR 0 $BLK_LIMIT 0 $FILE_LIMIT $DIR
 	echo "  Set enough high limit for group: $TSTUSR"
@@ -692,6 +715,8 @@ test_8() {
 	RC=$?
 
 	rm -f client.txt
+	sync; sleep 3; sync;
+
 	cd $SAVE_PWD
 	return $RC
 }
@@ -720,6 +745,8 @@ check_whether_skip () {
 test_9() {
 	check_whether_skip && return 0
 
+	wait_delete_completed
+
  	set_blk_tunesz 512
  	set_blk_unitsz 1024
 
@@ -761,8 +788,6 @@ test_9() {
 	set_blk_unitsz $((128 * 1024))
 	set_blk_tunesz $((128 * 1024 / 2))
 
-	wait_delete_completed
-
         return $RC
 }
 run_test 9 "run for fixing bug10707(64bit) ==========="
@@ -772,7 +797,7 @@ test_10() {
 	chmod 0777 $DIR/$tdir
 	check_whether_skip && return 0
 
-	sync; sleep 10; sync;
+	wait_delete_completed
 
  	set_blk_tunesz 512
  	set_blk_unitsz 1024
@@ -820,13 +845,13 @@ test_10() {
 	set_blk_unitsz $((128 * 1024))
 	set_blk_tunesz $((128 * 1024 / 2))
 
-	wait_delete_completed
-
 	return $RC
 }
 run_test 10 "run for fixing bug10707(32bit) ==========="
 
 test_11() {
+       wait_delete_completed
+
        #prepare the test
        block_limit=`(echo 0; df -t lustre -P | awk '{print $(NF - 4)}') | tail -n 1`
        echo $block_limit
@@ -903,6 +928,8 @@ test_12() {
 	TESTFILE="$DIR/$tdir/$tfile-0"
 	TESTFILE2="$DIR2/$tdir/$tfile-1"
 
+	wait_delete_completed
+
 	echo "   User quota (limit: $LIMIT kbytes)"
 	$LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR
 
@@ -1012,6 +1039,7 @@ test_13() {
 		error "files too small $fz + $fz2 < $((BUNIT_SZ * BLK_SZ * 10))"
 
 	rm -f $TESTFILE $TESTFILE.2
+	sync; sleep 3; sync;
 
 	$LFS setquota -u $TSTUSR 0 0 0 0 $DIR		# clear user limit
 }
@@ -1070,6 +1098,7 @@ test_14(){ # b=12223 -- setting quota on root
 	# clean
 	unlinkmany ${TESTFILE} 15
 	rm -f $TESTFILE
+	sync; sleep 3; sync;
 }
 run_test 14 "test setting quota on root ==="
 
@@ -1085,6 +1114,8 @@ test_14a(){
         # 3. start quota in old mode and put some entries
         # 4. restart quota in new mode forcing conversion and check the entries
 
+        wait_delete_completed
+
         MISSING_USERS=""
         for i in `seq 1 30`; do
                 check_runas_id_ret quota15_$i "runas -u quota15_$i"
@@ -1124,6 +1155,8 @@ test_15(){
         LIMIT=$((24 * 1024 * 1024 * 1024 * 1024)) # 24 TB
         PATTERN="`echo $DIR | sed 's/\//\\\\\//g'`"
 
+	wait_delete_completed
+
         # test for user
         $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR || error "failed setting user quota limit $LIMIT"
         TOTAL_LIMIT="`$LFS quota -u $TSTUSR $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $4 }'`"
@@ -1151,6 +1184,8 @@ test_16_tub() {
 	LIMIT=$(( $BUNIT_SZ * $(($OSTCOUNT + 1)) * 4))
 	TESTFILE="$DIR/$tdir/$tfile"
 
+	wait_delete_completed
+
 	echo "  User quota (limit: $LIMIT kbytes)"
 	if [ $1 == "u" ]; then
 	    $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR
@@ -1181,6 +1216,7 @@ test_16_tub() {
 	fi
 
 	rm -f $TESTFILE
+	sync; sleep 3; sync;
 	$LFS setquota -$1 $TSTUSR 0 0 0 0 $DIR
 }
 
@@ -1208,6 +1244,8 @@ test_17() {
 	set_blk_tunesz 512
 	set_blk_unitsz 1024
 
+	wait_delete_completed
+
         #define OBD_FAIL_QUOTA_RET_QDATA | OBD_FAIL_ONCE
 	lustre_fail ost 0x80000A02
 
-- 
GitLab