From ebe1595206fe5e599b5e2b76ccc8392991c028b5 Mon Sep 17 00:00:00 2001
From: tianzy <tianzy>
Date: Fri, 24 Aug 2007 11:12:50 +0000
Subject: [PATCH] Branch b1_6 fix the bug of "mds_obd_create error creating tmp
 object" b=12223 i=green i=wangdi

---
 lustre/ChangeLog             |  6 +++++
 lustre/include/lustre_log.h  | 16 ++++++++++++
 lustre/mds/mds_fs.c          |  4 +--
 lustre/obdclass/llog_obd.c   |  4 +++
 lustre/quota/quota_context.c |  4 ---
 lustre/quota/quota_ctl.c     | 17 +++++++++++-
 lustre/quota/quota_master.c  | 39 ++++++++++++++--------------
 lustre/tests/sanity-quota.sh | 50 ++++++++++++++++++++++++++++++++++++
 8 files changed, 113 insertions(+), 27 deletions(-)

diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index dba9173db2..75474feeee 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -73,6 +73,12 @@ Bugzilla   : 13362
 Description: Sanity.sh test_65k failed: setstripe should have succeeded
 Details    : execute lfs setstripe on client
 
+Severity   : major
+Bugzilla   : 12223
+Description: mds_obd_create error creating tmp object
+Details    : When the user sets quota on root, llog will be affected and can't 
+             create files and write files.
+
 --------------------------------------------------------------------------------
 
 2007-08-27         Cluster File Systems, Inc. <info@clusterfs.com>
diff --git a/lustre/include/lustre_log.h b/lustre/include/lustre_log.h
index b9b75e3985..565d08dc96 100644
--- a/lustre/include/lustre_log.h
+++ b/lustre/include/lustre_log.h
@@ -218,6 +218,14 @@ struct llog_ctxt {
         void                    *llog_proc_cb;
 };
 
+#ifndef __KERNEL__
+
+#define cap_raise(c, flag) do {} while(0)
+
+#define CAP_SYS_RESOURCE 24
+
+#endif   /* !__KERNEL__ */
+
 static inline void llog_gen_init(struct llog_ctxt *ctxt)
 {
         struct obd_device *obd = ctxt->loc_exp->exp_obd;
@@ -321,6 +329,7 @@ static inline int llog_write_rec(struct llog_handle *handle,
                                  int numcookies, void *buf, int idx)
 {
         struct llog_operations *lop;
+        __u32 cap;
         int rc, buflen;
         ENTRY;
 
@@ -337,7 +346,10 @@ static inline int llog_write_rec(struct llog_handle *handle,
                 buflen = rec->lrh_len;
         LASSERT(size_round(buflen) == buflen);
 
+        cap = current->cap_effective;             
+        cap_raise(current->cap_effective, CAP_SYS_RESOURCE); 
         rc = lop->lop_write_rec(handle, rec, logcookies, numcookies, buf, idx);
+        current->cap_effective = cap; 
         RETURN(rc);
 }
 
@@ -433,6 +445,7 @@ static inline int llog_create(struct llog_ctxt *ctxt, struct llog_handle **res,
                               struct llog_logid *logid, char *name)
 {
         struct llog_operations *lop;
+        __u32 cap;
         int rc;
         ENTRY;
 
@@ -442,7 +455,10 @@ static inline int llog_create(struct llog_ctxt *ctxt, struct llog_handle **res,
         if (lop->lop_create == NULL)
                 RETURN(-EOPNOTSUPP);
 
+        cap = current->cap_effective;             
+        cap_raise(current->cap_effective, CAP_SYS_RESOURCE);
         rc = lop->lop_create(ctxt, res, logid, name);
+        current->cap_effective = cap; 
         RETURN(rc);
 }
 
diff --git a/lustre/mds/mds_fs.c b/lustre/mds/mds_fs.c
index f252c4986f..70fb74285a 100644
--- a/lustre/mds/mds_fs.c
+++ b/lustre/mds/mds_fs.c
@@ -706,7 +706,7 @@ int mds_obd_create(struct obd_export *exp, struct obdo *oa,
         ENTRY;
 
         /* the owner of object file should always be root */
-        ucred.luc_cap = current->cap_effective | CAP_SYS_RESOURCE;
+        cap_raise(ucred.luc_cap, CAP_SYS_RESOURCE);
 
         push_ctxt(&saved, &exp->exp_obd->obd_lvfs_ctxt, &ucred);
 
@@ -792,7 +792,7 @@ int mds_obd_destroy(struct obd_export *exp, struct obdo *oa,
         int err, namelen, rc = 0;
         ENTRY;
 
-        ucred.luc_cap = current->cap_effective | CAP_SYS_RESOURCE;
+        cap_raise(ucred.luc_cap, CAP_SYS_RESOURCE);
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, &ucred);
 
         namelen = ll_fid2str(fidname, oa->o_id, oa->o_generation);
diff --git a/lustre/obdclass/llog_obd.c b/lustre/obdclass/llog_obd.c
index 46fdca0bba..382b1f1e15 100644
--- a/lustre/obdclass/llog_obd.c
+++ b/lustre/obdclass/llog_obd.c
@@ -176,6 +176,7 @@ int llog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
                 struct lov_stripe_md *lsm, struct llog_cookie *logcookies,
                 int numcookies)
 {
+        __u32 cap;
         int rc;
         ENTRY;
 
@@ -185,7 +186,10 @@ int llog_add(struct llog_ctxt *ctxt, struct llog_rec_hdr *rec,
         }
         
         CTXT_CHECK_OP(ctxt, add, -EOPNOTSUPP);
+        cap = current->cap_effective;             
+        cap_raise(current->cap_effective, CAP_SYS_RESOURCE);
         rc = CTXTP(ctxt, add)(ctxt, rec, lsm, logcookies, numcookies);
+        current->cap_effective = cap; 
         RETURN(rc);
 }
 EXPORT_SYMBOL(llog_add);
diff --git a/lustre/quota/quota_context.c b/lustre/quota/quota_context.c
index 08ef0c51e1..2f0cb2ebf2 100644
--- a/lustre/quota/quota_context.c
+++ b/lustre/quota/quota_context.c
@@ -158,10 +158,6 @@ check_cur_qunit(struct obd_device *obd,
         if (!sb_any_quota_enabled(sb))
                 RETURN(0);
 
-        /* ignore root user */
-        if (qdata->qd_id == 0 && qdata_type == USRQUOTA)
-                RETURN(0);
-
         OBD_ALLOC_PTR(qctl);
         if (qctl == NULL)
                 RETURN(-ENOMEM);
diff --git a/lustre/quota/quota_ctl.c b/lustre/quota/quota_ctl.c
index c056048c71..4f50f7d30e 100644
--- a/lustre/quota/quota_ctl.c
+++ b/lustre/quota/quota_ctl.c
@@ -128,6 +128,20 @@ int filter_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl)
                         atomic_inc(&obt->obt_quotachecking);
                 }
                 break;
+        case Q_SETQUOTA:
+                qctxt_wait_pending_dqacq(&obd->u.obt.obt_qctxt, 
+                                         oqctl->qc_id, oqctl->qc_type, 1);
+
+                push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+                rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
+
+                if (!rc) {
+                        oqctl->qc_cmd = Q_SYNC;
+                        fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);
+                        oqctl->qc_cmd = Q_SETQUOTA;
+                }
+                pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+                break;
         case Q_INITQUOTA:
                 {
                 unsigned int uid = 0, gid = 0;
@@ -234,7 +248,8 @@ int lov_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl)
         ENTRY;
 
         if (oqctl->qc_cmd != Q_QUOTAON && oqctl->qc_cmd != Q_QUOTAOFF &&
-            oqctl->qc_cmd != Q_GETOQUOTA && oqctl->qc_cmd != Q_INITQUOTA) {
+            oqctl->qc_cmd != Q_GETOQUOTA && oqctl->qc_cmd != Q_INITQUOTA &&
+            oqctl->qc_cmd != Q_SETQUOTA) {
                 CERROR("bad quota opc %x for lov obd", oqctl->qc_cmd);
                 RETURN(-EFAULT);
         }
diff --git a/lustre/quota/quota_master.c b/lustre/quota/quota_master.c
index 615c73cc69..a321faa60d 100644
--- a/lustre/quota/quota_master.c
+++ b/lustre/quota/quota_master.c
@@ -214,9 +214,6 @@ int dqacq_handler(struct obd_device *obd, struct qunit_data *qdata, int opc)
 
         OBD_FAIL_RETURN(OBD_FAIL_OBD_DQACQ, -EIO);
 
-        /* slaves never acquires qunit for user root */
-        LASSERT(qdata->qd_id || qdata_type);
-
         dquot = lustre_dqget(obd, info, qdata->qd_id, qdata_type);
         if (IS_ERR(dquot))
                 RETURN(PTR_ERR(dquot));
@@ -651,31 +648,32 @@ static int mds_init_slave_ilimits(struct obd_device *obd,
         /* XXX: for file limits only adjust local now */
         unsigned int uid = 0, gid = 0;
         struct obd_quotactl *ioqc = NULL;
+        int flag;
         int rc;
         ENTRY;
 
         /* if we are going to set zero limit, needn't init slaves */
-        if (!oqctl->qc_dqblk.dqb_ihardlimit && !oqctl->qc_dqblk.dqb_isoftlimit)
+        if (!oqctl->qc_dqblk.dqb_ihardlimit && !oqctl->qc_dqblk.dqb_isoftlimit &&
+            set)
                 RETURN(0);
-        
-        if (!set)
-                goto acquire;
 
         OBD_ALLOC_PTR(ioqc);
         if (!ioqc)
                 RETURN(-ENOMEM);
-
-        ioqc->qc_cmd = Q_INITQUOTA;
+        
+        flag = oqctl->qc_dqblk.dqb_ihardlimit || 
+               oqctl->qc_dqblk.dqb_isoftlimit || set;
+        ioqc->qc_cmd = flag ? Q_INITQUOTA : Q_SETQUOTA;
         ioqc->qc_id = oqctl->qc_id;
         ioqc->qc_type = oqctl->qc_type;
         ioqc->qc_dqblk.dqb_valid = QIF_ILIMITS;
-        ioqc->qc_dqblk.dqb_ihardlimit = MIN_QLIMIT;
+        ioqc->qc_dqblk.dqb_ihardlimit = flag ? MIN_QLIMIT : 0;
 
         /* set local limit to MIN_QLIMIT */
         rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, ioqc);
         if (rc)
                 GOTO(out, rc);
-acquire:
+
         /* trigger local qunit pre-acquire */
         if (oqctl->qc_type == USRQUOTA)
                 uid = oqctl->qc_id;
@@ -701,29 +699,30 @@ static int mds_init_slave_blimits(struct obd_device *obd,
         struct mds_obd *mds = &obd->u.mds;
         struct obd_quotactl *ioqc;
         unsigned int uid = 0, gid = 0;
+        int flag;
         int rc;
         ENTRY;
 
         /* if we are going to set zero limit, needn't init slaves */
-        if (!oqctl->qc_dqblk.dqb_bhardlimit && !oqctl->qc_dqblk.dqb_bsoftlimit)
+        if (!oqctl->qc_dqblk.dqb_bhardlimit && !oqctl->qc_dqblk.dqb_bsoftlimit &&
+            set)
                 RETURN(0);
 
         OBD_ALLOC_PTR(ioqc);
         if (!ioqc)
                 RETURN(-ENOMEM);
 
-        ioqc->qc_cmd = Q_INITQUOTA;
+        flag = oqctl->qc_dqblk.dqb_bhardlimit || 
+               oqctl->qc_dqblk.dqb_bsoftlimit || set;
+        ioqc->qc_cmd = flag ? Q_INITQUOTA : Q_SETQUOTA;
         ioqc->qc_id = oqctl->qc_id;
         ioqc->qc_type = oqctl->qc_type;
         ioqc->qc_dqblk.dqb_valid = QIF_BLIMITS;
-        ioqc->qc_dqblk.dqb_bhardlimit = set ? MIN_QLIMIT : 0;
+        ioqc->qc_dqblk.dqb_bhardlimit = flag ? MIN_QLIMIT : 0;
 
-        /* set local limit to MIN_QLIMIT */
-        if (set) {
-                rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, ioqc);
-                if (rc)
-                        GOTO(out, rc);
-        }
+        rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, ioqc);
+        if (rc)
+                GOTO(out, rc);
 
         /* trigger local qunit pre-acquire */
         if (oqctl->qc_type == USRQUOTA)
diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh
index 1805bb2d36..5698aea06d 100644
--- a/lustre/tests/sanity-quota.sh
+++ b/lustre/tests/sanity-quota.sh
@@ -1060,6 +1060,56 @@ test_13() {
 }
 run_test 13 "test multiple clients write block quota ==="
 
+check_if_quota_zero(){
+        line=`$LFS quota -$1 $2 $MOUNT | wc -l`
+	for i in `seq 3 $line`; do
+	    for j in 3 4 6 7; do
+		tmp=`$LFS quota -$1 $2 $MOUNT | sed -n ${i}p | 
+                     awk  '{print $'"$j"'}'`
+		[ -n "$tmp" ] && [ $tmp -ne 0 ] && $LFS quota -$1 $2 $MOUNT && \
+		    error "quota on $1 isn't clean"
+	    done
+	done
+	echo "pass check_if_quota_zero"
+}
+
+# test setting quota on root, b=12223
+test_13(){
+        TESTFILE="$TSTDIR/quota_tst13"
+
+	# reboot the lustre
+	cd $T_PWD; sh llmountcleanup.sh || error "llmountcleanup failed"
+	sh llmount.sh 
+	pre_test
+	setup
+	run_test 0 "reboot lustre"
+
+	# out of root's file and block quota
+        $LFS setquota -u root 10 10 10 10 $MOUNT
+	createmany -m ${TESTFILE} 20 || \
+	    error "unexpected: user(root) create files failly!"
+	dd if=/dev/zero of=$TESTFILE bs=4k count=4096 || \
+	    error "unexpected: user(root) write files failly!"
+	chmod 666 $TESTFILE
+	$RUNAS dd if=/dev/zero of=${TESTFILE} seek=4096 bs=4k count=4096 && \
+	    error "unexpected: user(quota_usr) write a file successfully!"	
+
+	# trigger the llog
+	chmod 777 $MOUNT
+	for i in `seq 1 10`; do $RUNAS touch ${TESTFILE}a_$i; done 
+	for i in `seq 1 10`; do $RUNAS rm -f ${TESTFILE}a_$i; done 
+
+	# do the check
+	dmesg | tail | grep "\-122" |grep llog_obd_origin_add && error "test_13 failed."
+	$LFS setquota -u root 0 0 0 0 $MOUNT
+	check_if_quota_zero u root
+
+	# clean 
+	unlinkmany ${TESTFILE} 15
+	rm -f $TESTFILE
+}
+run_test 13 "test setting quota on root ==="
+
 # turn off quota
 test_99()
 {
-- 
GitLab