From 5d9f2fa74a6816875b4d0a837590bb706e991850 Mon Sep 17 00:00:00 2001
From: tianzy <tianzy>
Date: Wed, 8 Oct 2008 10:24:18 +0000
Subject: [PATCH] Branch b1_6 Fix writing over quota too much. Add a proc entry
 so that sync writes can be triggered earlier, which improve accuracy of
 quota. b=16642 i=johann i=panda

---
 lustre/include/lprocfs_status.h |  4 ++++
 lustre/include/lustre_quota.h   |  3 +++
 lustre/quota/lproc_quota.c      | 32 ++++++++++++++++++++++++++++
 lustre/quota/quota_context.c    |  1 +
 lustre/quota/quota_interface.c  | 37 ++++++++++++++++++++++++++++-----
 5 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h
index 4fefd59ac4..8c50f59fb6 100644
--- a/lustre/include/lprocfs_status.h
+++ b/lustre/include/lprocfs_status.h
@@ -609,6 +609,10 @@ extern int lprocfs_quota_rd_switch_seconds(char *page, char **start, off_t off,
                                            int count, int *eof, void *data);
 extern int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer,
                                            unsigned long count, void *data);
+extern int lprocfs_quota_rd_sync_blk(char *page, char **start, off_t off,
+                                     int count, int *eof, void *data);
+extern int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
+                                     unsigned long count, void *data);
 extern int lprocfs_quota_rd_switch_qs(char *page, char **start, off_t off,
                                       int count, int *eof, void *data);
 extern int lprocfs_quota_wr_switch_qs(struct file *file, const char *buffer,
diff --git a/lustre/include/lustre_quota.h b/lustre/include/lustre_quota.h
index ee1d0a13ec..b8f24c17f9 100644
--- a/lustre/include/lustre_quota.h
+++ b/lustre/include/lustre_quota.h
@@ -264,6 +264,9 @@ struct lustre_quota_ctxt {
                                              * adjusting qunit size. How many
                                              * seconds must be waited between
                                              * enlarging and shinking qunit */
+        int           lqc_sync_blk;         /* when blk qunit reaches this value,
+                                             * later write reqs from client
+                                             * should be sync b=16642 */
         spinlock_t    lqc_lock;         /* guard lqc_imp_valid now */
         cfs_waitq_t   lqc_wait_for_qmaster; /* when mds isn't connected, threads
                                              * on osts who send the quota reqs
diff --git a/lustre/quota/lproc_quota.c b/lustre/quota/lproc_quota.c
index 922f2d48cd..3cb42aa29a 100644
--- a/lustre/quota/lproc_quota.c
+++ b/lustre/quota/lproc_quota.c
@@ -448,6 +448,36 @@ int lprocfs_quota_wr_switch_seconds(struct file *file, const char *buffer,
 }
 EXPORT_SYMBOL(lprocfs_quota_wr_switch_seconds);
 
+int lprocfs_quota_rd_sync_blk(char *page, char **start, off_t off,
+                              int count, int *eof, void *data)
+{
+        struct obd_device *obd = (struct obd_device *)data;
+        LASSERT(obd != NULL);
+
+        return snprintf(page, count, "%d\n",
+                        obd->u.obt.obt_qctxt.lqc_sync_blk);
+}
+EXPORT_SYMBOL(lprocfs_quota_rd_sync_blk);
+
+int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
+                              unsigned long count, void *data)
+{
+        struct obd_device *obd = (struct obd_device *)data;
+        int val, rc;
+        LASSERT(obd != NULL);
+
+        rc = lprocfs_write_helper(buffer, count, &val);
+        if (rc)
+                return rc;
+
+        if (val < 0)
+                return -EINVAL;
+
+        obd->u.obt.obt_qctxt.lqc_sync_blk = val;
+        return count;
+}
+EXPORT_SYMBOL(lprocfs_quota_wr_sync_blk);
+
 int lprocfs_quota_rd_switch_qs(char *page, char **start, off_t off,
                                int count, int *eof, void *data)
 {
@@ -618,6 +648,8 @@ struct lprocfs_vars lprocfs_quota_common_vars[] = {
                             lprocfs_quota_wr_type, 0},
         { "quota_switch_seconds",  lprocfs_quota_rd_switch_seconds,
                                    lprocfs_quota_wr_switch_seconds, 0 },
+        { "quota_sync_blk", lprocfs_quota_rd_sync_blk,
+                            lprocfs_quota_wr_sync_blk, 0},
 };
 
 struct lprocfs_vars lprocfs_quota_master_vars[] = {
diff --git a/lustre/quota/quota_context.c b/lustre/quota/quota_context.c
index 0e9eb8082b..bd22456e33 100644
--- a/lustre/quota/quota_context.c
+++ b/lustre/quota/quota_context.c
@@ -1143,6 +1143,7 @@ qctxt_init(struct obd_device *obd, dqacq_handler_t handler)
         qctxt->lqc_itune_sz = default_iunit_sz * default_itune_ratio / 100;
         qctxt->lqc_switch_seconds = 300; /* enlarging will wait 5 minutes
                                           * after the last shrinking */
+        qctxt->lqc_sync_blk = 0;
         spin_unlock(&qctxt->lqc_lock);
 
         qctxt->lqc_lqs_hash = lustre_hash_init("LQS_HASH", 128, 128,
diff --git a/lustre/quota/quota_interface.c b/lustre/quota/quota_interface.c
index 6bbb8bc21a..bb7f297c80 100644
--- a/lustre/quota/quota_interface.c
+++ b/lustre/quota/quota_interface.c
@@ -169,6 +169,7 @@ static int filter_quota_enforce(struct obd_device *obd, unsigned int ignore)
 static int filter_quota_getflag(struct obd_device *obd, struct obdo *oa)
 {
         struct obd_device_target *obt = &obd->u.obt;
+        struct lustre_quota_ctxt *qctxt = &obt->obt_qctxt;
         int err, cnt, rc = 0;
         struct obd_quotactl *oqctl;
         ENTRY;
@@ -176,15 +177,42 @@ static int filter_quota_getflag(struct obd_device *obd, struct obdo *oa)
         if (!sb_any_quota_enabled(obt->obt_sb))
                 RETURN(0);
 
-        oa->o_flags &= ~(OBD_FL_NO_USRQUOTA | OBD_FL_NO_GRPQUOTA);
-
         OBD_ALLOC_PTR(oqctl);
         if (!oqctl) {
                 CERROR("Not enough memory!");
                 RETURN(-ENOMEM);
         }
 
+        /* set over quota flags for a uid/gid */
+        oa->o_valid |= OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA;
+        oa->o_flags &= ~(OBD_FL_NO_USRQUOTA | OBD_FL_NO_GRPQUOTA);
+
         for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+                struct quota_adjust_qunit oqaq_tmp;
+                struct lustre_qunit_size *lqs = NULL;
+
+                oqaq_tmp.qaq_flags = cnt;
+                oqaq_tmp.qaq_id = (cnt == USRQUOTA) ? oa->o_uid : oa->o_gid;
+
+                quota_search_lqs(NULL, &oqaq_tmp, qctxt, &lqs);
+                if (lqs) {
+                        spin_lock(&lqs->lqs_lock);
+                        if (lqs->lqs_bunit_sz <= qctxt->lqc_sync_blk) {
+                                oa->o_flags |= (cnt == USRQUOTA) ?
+                                        OBD_FL_NO_USRQUOTA : OBD_FL_NO_GRPQUOTA;
+                                CDEBUG(D_QUOTA, "set sync flag: bunit(%lu), "
+                                       "sync_blk(%d)\n", lqs->lqs_bunit_sz,
+                                       qctxt->lqc_sync_blk);
+                                spin_unlock(&lqs->lqs_lock);
+                                /* this is for quota_search_lqs */
+                                lqs_putref(lqs);
+                                continue;
+                        }
+                        spin_unlock(&lqs->lqs_lock);
+                        /* this is for quota_search_lqs */
+                        lqs_putref(lqs);
+                }
+
                 memset(oqctl, 0, sizeof(*oqctl));
 
                 oqctl->qc_cmd = Q_GETQUOTA;
@@ -194,12 +222,11 @@ static int filter_quota_getflag(struct obd_device *obd, struct obdo *oa)
                 if (err) {
                         if (!rc)
                                 rc = err;
+                        oa->o_valid &= ~((cnt == USRQUOTA) ? OBD_MD_FLUSRQUOTA :
+                                                             OBD_MD_FLGRPQUOTA);
                         continue;
                 }
 
-                /* set over quota flags for a uid/gid */
-                oa->o_valid |= (cnt == USRQUOTA) ?
-                               OBD_MD_FLUSRQUOTA : OBD_MD_FLGRPQUOTA;
                 if (oqctl->qc_dqblk.dqb_bhardlimit &&
                    (toqb(oqctl->qc_dqblk.dqb_curspace) >=
                     oqctl->qc_dqblk.dqb_bhardlimit))
-- 
GitLab