Whamcloud - gitweb
LU-7795 quota: tuneable soft least qunit 96/18896/9
authorNiu Yawei <yawei.niu@intel.com>
Mon, 14 Mar 2016 07:01:09 +0000 (03:01 -0400)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 27 May 2016 00:57:41 +0000 (00:57 +0000)
Introduce a tuneable least qunit for soft block quota, which is
used when soft limit is exceeded to retain an acceptable write
performance.

Remove the stale declarations of quota proc function.

Signed-off-by: Niu Yawei <yawei.niu@intel.com>
Change-Id: I172d1d08494418a6f7bc261f022c587da34b784d
Reviewed-on: http://review.whamcloud.com/18896
Tested-by: Jenkins
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Wang Shilong <wshilong@ddn.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/lprocfs_status.h
lustre/quota/qmt_entry.c
lustre/quota/qmt_internal.h
lustre/quota/qmt_pool.c

index f103aae..4b1ed5f 100644 (file)
@@ -859,65 +859,6 @@ int lprocfs_wr_root_squash(const char __user *buffer, unsigned long count,
 int lprocfs_wr_nosquash_nids(const char __user *buffer, unsigned long count,
                             struct root_squash_info *squash, char *name);
 
 int lprocfs_wr_nosquash_nids(const char __user *buffer, unsigned long count,
                             struct root_squash_info *squash, char *name);
 
-/* all quota proc functions */
-extern int lprocfs_quota_rd_bunit(char *page, char **start,
-                                  off_t off, int count,
-                                  int *eof, void *data);
-extern int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
-                                  unsigned long count, void *data);
-extern int lprocfs_quota_rd_btune(char *page, char **start,
-                                  off_t off, int count,
-                                  int *eof, void *data);
-extern int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
-                                  unsigned long count, void *data);
-extern int lprocfs_quota_rd_iunit(char *page, char **start,
-                                  off_t off, int count,
-                                  int *eof, void *data);
-extern int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
-                                  unsigned long count, void *data);
-extern int lprocfs_quota_rd_itune(char *page, char **start,
-                                  off_t off, int count,
-                                  int *eof, void *data);
-extern int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
-                                  unsigned long count, void *data);
-extern int lprocfs_quota_rd_type(char *page, char **start, off_t off, int count,
-                                 int *eof, void *data);
-extern int lprocfs_quota_wr_type(struct file *file, const char *buffer,
-                                 unsigned long count, void *data);
-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,
-                                      unsigned long count, void *data);
-extern int lprocfs_quota_rd_boundary_factor(char *page, char **start, off_t off,
-                                            int count, int *eof, void *data);
-extern int lprocfs_quota_wr_boundary_factor(struct file *file,
-                                            const char *buffer,
-                                            unsigned long count, void *data);
-extern int lprocfs_quota_rd_least_bunit(char *page, char **start, off_t off,
-                                        int count, int *eof, void *data);
-extern int lprocfs_quota_wr_least_bunit(struct file *file,
-                                        const char *buffer,
-                                        unsigned long count, void *data);
-extern int lprocfs_quota_rd_least_iunit(char *page, char **start, off_t off,
-                                        int count, int *eof, void *data);
-extern int lprocfs_quota_wr_least_iunit(struct file *file,
-                                        const char *buffer,
-                                        unsigned long count, void *data);
-extern int lprocfs_quota_rd_qs_factor(char *page, char **start, off_t off,
-                                      int count, int *eof, void *data);
-extern int lprocfs_quota_wr_qs_factor(struct file *file,
-                                      const char *buffer,
-                                      unsigned long count, void *data);
 #else /* !CONFIG_PROC_FS */
 
 #define proc_lustre_root NULL
 #else /* !CONFIG_PROC_FS */
 
 #define proc_lustre_root NULL
index 8997dec..d7a48f9 100644 (file)
@@ -425,7 +425,7 @@ void qmt_adjust_edquot(struct lquota_entry *lqe, __u64 now)
 
                /* See comment in qmt_adjust_qunit(). LU-4139 */
                if (qmt_hard_exhausted(lqe) ||
 
                /* See comment in qmt_adjust_qunit(). LU-4139 */
                if (qmt_hard_exhausted(lqe) ||
-                   pool->qpi_key >> 16 == LQUOTA_RES_MD) {
+                   pool->qpi_key >> 16 != LQUOTA_RES_DT) {
                        /* we haven't reached the minimal qunit yet so there is
                         * still hope that the rebalancing process might free
                         * up some quota space */
                        /* we haven't reached the minimal qunit yet so there is
                         * still hope that the rebalancing process might free
                         * up some quota space */
@@ -443,9 +443,7 @@ void qmt_adjust_edquot(struct lquota_entry *lqe, __u64 now)
                                               lqe->lqe_revoke_time))
                                RETURN_EXIT;
                } else {
                                               lqe->lqe_revoke_time))
                                RETURN_EXIT;
                } else {
-                       /* When exceeding softlimit, block qunit will be shrunk
-                        * to (4 * least_qunit) finally. */
-                       if (lqe->lqe_qunit > (pool->qpi_least_qunit << 2))
+                       if (lqe->lqe_qunit > pool->qpi_soft_least_qunit)
                                RETURN_EXIT;
                }
 
                                RETURN_EXIT;
                }
 
@@ -487,12 +485,11 @@ static __u64 qmt_calc_softlimit(struct lquota_entry *lqe, bool *oversoft)
        LASSERT(lqe->lqe_softlimit != 0);
        *oversoft = false;
        /* No need to do special tweaking for inode limit */
        LASSERT(lqe->lqe_softlimit != 0);
        *oversoft = false;
        /* No need to do special tweaking for inode limit */
-       if (pool->qpi_key >> 16 == LQUOTA_RES_MD)
+       if (pool->qpi_key >> 16 != LQUOTA_RES_DT)
                return lqe->lqe_softlimit;
 
                return lqe->lqe_softlimit;
 
-       /* Added (least_qunit * 4) as margin */
        if (lqe->lqe_granted <= lqe->lqe_softlimit +
        if (lqe->lqe_granted <= lqe->lqe_softlimit +
-                               (pool->qpi_least_qunit << 2)) {
+                               pool->qpi_soft_least_qunit) {
                return lqe->lqe_softlimit;
        } else if (lqe->lqe_hardlimit != 0) {
                *oversoft = true;
                return lqe->lqe_softlimit;
        } else if (lqe->lqe_hardlimit != 0) {
                *oversoft = true;
@@ -531,7 +528,7 @@ __u64 qmt_alloc_expand(struct lquota_entry *lqe, __u64 granted, __u64 spare)
                remaining = qmt_calc_softlimit(lqe, &oversoft);
                if (remaining == 0)
                        remaining = lqe->lqe_granted +
                remaining = qmt_calc_softlimit(lqe, &oversoft);
                if (remaining == 0)
                        remaining = lqe->lqe_granted +
-                                   (pool->qpi_least_qunit << 2);
+                                   pool->qpi_soft_least_qunit;
        } else {
                remaining = lqe->lqe_hardlimit;
        }
        } else {
                remaining = lqe->lqe_hardlimit;
        }
@@ -600,10 +597,10 @@ void qmt_adjust_qunit(const struct lu_env *env, struct lquota_entry *lqe)
                bool oversoft;
                /* As a compromise of write performance and the grace time
                 * accuracy, the block qunit size will be shrunk to
                bool oversoft;
                /* As a compromise of write performance and the grace time
                 * accuracy, the block qunit size will be shrunk to
-                * (4 * least_qunit) when over softlimit. LU-4139. */
+                * qpi_soft_least_qunit when over softlimit. LU-4139. */
                limit = qmt_calc_softlimit(lqe, &oversoft);
                if (oversoft)
                limit = qmt_calc_softlimit(lqe, &oversoft);
                if (oversoft)
-                       qunit2 = pool->qpi_least_qunit << 2;
+                       qunit2 = pool->qpi_soft_least_qunit;
                if (limit == 0)
                        GOTO(done, qunit = qunit2);
        } else if (lqe->lqe_hardlimit != 0) {
                if (limit == 0)
                        GOTO(done, qunit = qunit2);
        } else if (lqe->lqe_hardlimit != 0) {
index e21c78f..7f02256 100644 (file)
@@ -139,6 +139,22 @@ struct qmt_pool_info {
        /* Global quota parameters which apply to all quota type */
        /* the least value of qunit */
        unsigned long            qpi_least_qunit;
        /* Global quota parameters which apply to all quota type */
        /* the least value of qunit */
        unsigned long            qpi_least_qunit;
+
+       /* Least value of qunit when soft limit is exceeded.
+        *
+        * When soft limit is exceeded, qunit will be shrinked to least_qunit
+        * (1M for block limit), that results in significant write performance
+        * drop since the client will turn to sync write from now on.
+        *
+        * To retain the write performance in an acceptable level, we choose
+        * to sacrifice grace time accuracy a bit and use a larger least_qunit
+        * when soft limit is exceeded. It's (qpi_least_qunit * 4) by default,
+        * and user may enlarge it via procfs to get even better performance
+        * (with the cost of losing more grace time accuracy).
+        *
+        * See qmt_calc_softlimit().
+        */
+       unsigned long            qpi_soft_least_qunit;
 };
 
 /*
 };
 
 /*
index 78e1acb..47f5b12 100644 (file)
@@ -171,9 +171,52 @@ static int qpi_state_seq_show(struct seq_file *m, void *data)
 }
 LPROC_SEQ_FOPS_RO(qpi_state);
 
 }
 LPROC_SEQ_FOPS_RO(qpi_state);
 
+static int qpi_soft_least_qunit_seq_show(struct seq_file *m, void *data)
+{
+       struct qmt_pool_info    *pool = m->private;
+       LASSERT(pool != NULL);
+
+       return seq_printf(m, "%lu\n", pool->qpi_soft_least_qunit);
+}
+
+static ssize_t
+qpi_soft_least_qunit_seq_write(struct file *file, const char __user *buffer,
+                              size_t count, loff_t *off)
+{
+       struct qmt_pool_info    *pool;
+       int     qunit, rc;
+       s64     least_qunit;
+
+       pool = ((struct seq_file *)file->private_data)->private;
+       LASSERT(pool != NULL);
+
+       /* Not tuneable for inode limit */
+       if (pool->qpi_key >> 16 != LQUOTA_RES_DT)
+               return -EINVAL;
+
+       rc = lprocfs_str_to_s64(buffer, count, &least_qunit);
+       if (rc)
+               return rc;
+
+       /* Miminal qpi_soft_least_qunit */
+       qunit = pool->qpi_least_qunit << 2;
+       /* The value must be power of miminal qpi_soft_least_qunit, see
+        * how the qunit is adjusted in qmt_adjust_qunit(). */
+       while (qunit > 0 && qunit < least_qunit)
+               qunit <<= 2;
+       if (qunit <= 0)
+               qunit = INT_MAX & ~3;
+
+       pool->qpi_soft_least_qunit = qunit;
+       return count;
+}
+LPROC_SEQ_FOPS(qpi_soft_least_qunit);
+
 static struct lprocfs_vars lprocfs_quota_qpi_vars[] = {
        { .name =       "info",
          .fops =       &qpi_state_fops },
 static struct lprocfs_vars lprocfs_quota_qpi_vars[] = {
        { .name =       "info",
          .fops =       &qpi_state_fops },
+       { .name =       "soft_least_qunit",
+         .fops =       &qpi_soft_least_qunit_fops },
        { NULL }
 };
 
        { NULL }
 };
 
@@ -211,6 +254,10 @@ static int qmt_pool_alloc(const struct lu_env *env, struct qmt_device *qmt,
 
        /* set up least qunit size to use for this pool */
        pool->qpi_least_qunit = LQUOTA_LEAST_QUNIT(pool_type);
 
        /* set up least qunit size to use for this pool */
        pool->qpi_least_qunit = LQUOTA_LEAST_QUNIT(pool_type);
+       if (pool_type == LQUOTA_RES_DT)
+               pool->qpi_soft_least_qunit = pool->qpi_least_qunit << 2;
+       else
+               pool->qpi_soft_least_qunit = pool->qpi_least_qunit;
 
        /* create pool proc directory */
        sprintf(qti->qti_buf, "%s-0x%x", RES_NAME(pool_type), pool_id);
 
        /* create pool proc directory */
        sprintf(qti->qti_buf, "%s-0x%x", RES_NAME(pool_type), pool_id);