From 0cadce268a09a94824b82bc1a61e98963582c423 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Mon, 14 Mar 2016 03:01:09 -0400 Subject: [PATCH] LU-7795 quota: tuneable soft least qunit 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 Change-Id: I172d1d08494418a6f7bc261f022c587da34b784d Reviewed-on: http://review.whamcloud.com/18896 Tested-by: Jenkins Reviewed-by: Fan Yong Reviewed-by: Wang Shilong Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/include/lprocfs_status.h | 59 ----------------------------------------- lustre/quota/qmt_entry.c | 17 +++++------- lustre/quota/qmt_internal.h | 16 +++++++++++ lustre/quota/qmt_pool.c | 47 ++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 69 deletions(-) diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index f103aae..4b1ed5f 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -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); -/* 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 diff --git a/lustre/quota/qmt_entry.c b/lustre/quota/qmt_entry.c index 8997dec..d7a48f9 100644 --- a/lustre/quota/qmt_entry.c +++ b/lustre/quota/qmt_entry.c @@ -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) || - 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 */ @@ -443,9 +443,7 @@ void qmt_adjust_edquot(struct lquota_entry *lqe, __u64 now) 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; } @@ -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 */ - if (pool->qpi_key >> 16 == LQUOTA_RES_MD) + if (pool->qpi_key >> 16 != LQUOTA_RES_DT) return lqe->lqe_softlimit; - /* Added (least_qunit * 4) as margin */ 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; @@ -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 + - (pool->qpi_least_qunit << 2); + pool->qpi_soft_least_qunit; } 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 - * (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) - 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) { diff --git a/lustre/quota/qmt_internal.h b/lustre/quota/qmt_internal.h index e21c78f..7f02256 100644 --- a/lustre/quota/qmt_internal.h +++ b/lustre/quota/qmt_internal.h @@ -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; + + /* 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; }; /* diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c index 78e1acb..47f5b12 100644 --- a/lustre/quota/qmt_pool.c +++ b/lustre/quota/qmt_pool.c @@ -171,9 +171,52 @@ static int qpi_state_seq_show(struct seq_file *m, void *data) } 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 }, + { .name = "soft_least_qunit", + .fops = &qpi_soft_least_qunit_fops }, { 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); + 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); -- 1.8.3.1