From 7b8c6cd976c584b4e965b24bf4369ded86cda811 Mon Sep 17 00:00:00 2001 From: Sergey Cheremencev Date: Wed, 15 Sep 2021 18:05:45 +0300 Subject: [PATCH] LU-15065 quota: fix BIO write performance drop Before the patch qti_lqes_qunit_min used int to store qunit value, while lqe_qunit type is _u64. lqe_qunit > 2G caused an overflow in a local integer argument. For example, when block hard limit was set to 500TB(i.e. lqe_qunit was about 64TB in a system with 2 OSTs), qti_lqes_qunit_min returned 0 instead of 64TB in a qmt_lvbo_fill. Thus new qunit was not set on OSTs(qsd_set_qunit wasn't called). Without the qunit, OST began to send release request after each acquire. For example, to write 10MB at the OST were sent 2 acquire and 2 release reuests(as qunit was not set on OST). With the fix, i.e. in a normal case, OST needs just one acquire request. The issue caused performance drop in a bufferred write up to 15%-20% if compare with a baseline without PQ patches. Note, the issue exists only when a hard limit is set to some high value(>100GB). The exact hard limit value depends on OSTs number in a system and on amount of used space, but let's think that issue doesn't exist on a clean system with 2 OSTs and hard block limit 100G(this case was checked). Remove qmt_pool_hash - it is not used anywhere since "LU-11023 quota: remove quota pool ID". HPE-bug-id: LUS-10250 Change-Id: I2c4ce38f5b9395ed1f4868d4c8efc00751116b15 Signed-off-by: Sergey Cheremencev Reviewed-on: https://review.whamcloud.com/45133 Reviewed-by: Petros Koutoupis Reviewed-by: Alexander Boyko Reviewed-by: Andreas Dilger Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/quota/qmt_entry.c | 8 +++++--- lustre/quota/qmt_internal.h | 13 +------------ lustre/quota/qmt_pool.c | 4 ++-- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/lustre/quota/qmt_entry.c b/lustre/quota/qmt_entry.c index 387806b..c858279 100644 --- a/lustre/quota/qmt_entry.c +++ b/lustre/quota/qmt_entry.c @@ -981,13 +981,15 @@ void qti_lqes_fini(const struct lu_env *env) qti->qti_lqes_cnt = 0; } -int qti_lqes_min_qunit(const struct lu_env *env) +__u64 qti_lqes_min_qunit(const struct lu_env *env) { - int i, min, qunit; + __u64 min, qunit; + int i; for (i = 1, min = qti_lqe_qunit(env, 0); i < qti_lqes_cnt(env); i++) { qunit = qti_lqe_qunit(env, i); - if (qunit < min) + /* if qunit is 0, lqe is not enforced and we can ignore it */ + if (qunit && qunit < min) min = qunit; } diff --git a/lustre/quota/qmt_internal.h b/lustre/quota/qmt_internal.h index 235782c..7d3b7ce 100644 --- a/lustre/quota/qmt_internal.h +++ b/lustre/quota/qmt_internal.h @@ -58,17 +58,6 @@ struct qmt_device { /* pointer to ldlm namespace to be used for quota locks */ struct ldlm_namespace *qmt_ns; - /* Hash table containing a qmt_pool_info structure for each pool - * this quota master is in charge of. We only have 2 pools in this - * hash for the time being: - * - one for quota management on the default metadata pool - * - one for quota managment on the default data pool - * - * Once we support quota on non-default pools, then more pools will - * be added to this hash table and pool master setup would have to be - * handled via configuration logs */ - struct cfs_hash *qmt_pool_hash; - /* List of pools managed by this master target */ struct list_head qmt_pool_list; /* rw semaphore to protect pool list */ @@ -499,7 +488,7 @@ void qti_lqes_init(const struct lu_env *env); int qti_lqes_add(const struct lu_env *env, struct lquota_entry *lqe); void qti_lqes_del(const struct lu_env *env, int index); void qti_lqes_fini(const struct lu_env *env); -int qti_lqes_min_qunit(const struct lu_env *env); +__u64 qti_lqes_min_qunit(const struct lu_env *env); int qti_lqes_edquot(const struct lu_env *env); int qti_lqes_restore_init(const struct lu_env *env); void qti_lqes_restore_fini(const struct lu_env *env); diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c index 755effd..d3b7704 100644 --- a/lustre/quota/qmt_pool.c +++ b/lustre/quota/qmt_pool.c @@ -117,8 +117,8 @@ qpi_soft_least_qunit_seq_write(struct file *file, const char __user *buffer, { struct seq_file *m = file->private_data; struct qmt_pool_info *pool = m->private; - long long least_qunit; - int qunit, rc; + long long least_qunit, qunit; + int rc; LASSERT(pool != NULL); -- 1.8.3.1