From 75b2f9067d9ead67492593ea76611f7e75c8d56e Mon Sep 17 00:00:00 2001
From: tianzy <tianzy>
Date: Fri, 24 Aug 2007 12:39:50 +0000
Subject: [PATCH] Branch HEAD 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   |  5 +++-
 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(+), 28 deletions(-)

diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index cd2acd2adf..6d7c580512 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -144,6 +144,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-10         Cluster File Systems, Inc. <info@clusterfs.com>
diff --git a/lustre/include/lustre_log.h b/lustre/include/lustre_log.h
index 9f6725fa51..e32a840514 100644
--- a/lustre/include/lustre_log.h
+++ b/lustre/include/lustre_log.h
@@ -217,6 +217,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;
@@ -292,6 +300,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;
 
@@ -309,7 +318,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);
 }
 
@@ -405,6 +417,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;
 
@@ -414,7 +427,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 b1e80ec41c..c62dd112ca 100644
--- a/lustre/mds/mds_fs.c
+++ b/lustre/mds/mds_fs.c
@@ -708,7 +708,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);
 
         if (strncmp(exp->exp_obd->obd_name, MDD_OBD_NAME,
                                    strlen(MDD_OBD_NAME))) {
@@ -800,7 +800,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 f8c875b005..f2cd31219c 100644
--- a/lustre/obdclass/llog_obd.c
+++ b/lustre/obdclass/llog_obd.c
@@ -136,6 +136,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;
 
@@ -145,8 +146,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 595f5e4823..65c727e1d6 100644
--- a/lustre/quota/quota_context.c
+++ b/lustre/quota/quota_context.c
@@ -210,10 +210,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 216f2c2217..f007b68477 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 09184c96e9..73241fe209 100644
--- a/lustre/tests/sanity-quota.sh
+++ b/lustre/tests/sanity-quota.sh
@@ -1050,6 +1050,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