From d73738c125c0bde5f7e5f4168d47ee2b8a1b0e3d Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Mon, 28 Oct 2013 12:03:15 -0400 Subject: [PATCH] LU-4139 quota: improve write performance when over softlimit To improve the write performance when over softlimit, we choose to lose some grace time accuracy: shrinking the qunit size to (4 * least_qunit_size) instead of least_qunit_size. Signed-off-by: Niu Yawei Change-Id: I20e341d53979ac42227197ec6fa04dd38974073f Reviewed-on: http://review.whamcloud.com/8078 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Johann Lombardi Reviewed-by: Fan Yong --- lustre/quota/qmt_entry.c | 84 ++++++++++++++++++++++++++++++++++++--------- lustre/quota/qmt_internal.h | 23 +++++++++---- 2 files changed, 85 insertions(+), 22 deletions(-) diff --git a/lustre/quota/qmt_entry.c b/lustre/quota/qmt_entry.c index 8bd9424..283a1c3 100644 --- a/lustre/quota/qmt_entry.c +++ b/lustre/quota/qmt_entry.c @@ -423,21 +423,31 @@ void qmt_adjust_edquot(struct lquota_entry *lqe, __u64 now) /* the qmt still has available space */ RETURN_EXIT; - if (lqe->lqe_qunit != pool->qpi_least_qunit) - /* we haven't reached the minimal qunit yet, so there is - * still hope that the rebalancing process might free up - * some quota space */ - RETURN_EXIT; + /* See comment in qmt_adjust_qunit(). LU-4139 */ + if (qmt_hard_exhausted(lqe) || + pool->qpi_key >> 16 == LQUOTA_RES_MD) { + /* we haven't reached the minimal qunit yet so there is + * still hope that the rebalancing process might free + * up some quota space */ + if (lqe->lqe_qunit != pool->qpi_least_qunit) + RETURN_EXIT; - if (lqe->lqe_revoke_time == 0) /* least qunit value not sent to all slaves yet */ - RETURN_EXIT; + if (lqe->lqe_revoke_time == 0) + RETURN_EXIT; - if (lqe->lqe_may_rel != 0 && - cfs_time_before_64(cfs_time_shift_64(-QMT_REBA_TIMEOUT), - lqe->lqe_revoke_time)) /* Let's give more time to slave to release space */ - RETURN_EXIT; + if (lqe->lqe_may_rel != 0 && + cfs_time_before_64(cfs_time_shift_64( + -QMT_REBA_TIMEOUT), + 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)) + RETURN_EXIT; + } /* set edquot flag */ lqe->lqe_edquot = true; @@ -468,6 +478,31 @@ void qmt_adjust_edquot(struct lquota_entry *lqe, __u64 now) EXIT; } +/* Using least_qunit when over block softlimit will seriously impact the + * write performance, we need to do some special tweaking on that. */ +static __u64 qmt_calc_softlimit(struct lquota_entry *lqe, bool *oversoft) +{ + struct qmt_pool_info *pool = lqe2qpi(lqe); + + LASSERT(lqe->lqe_softlimit != 0); + *oversoft = false; + /* No need to do special tweaking for inode limit */ + if (pool->qpi_key >> 16 == LQUOTA_RES_MD) + return lqe->lqe_softlimit; + + /* Added (least_qunit * 4) as margin */ + if (lqe->lqe_granted <= lqe->lqe_softlimit + + (pool->qpi_least_qunit << 2)) { + return lqe->lqe_softlimit; + } else if (lqe->lqe_hardlimit != 0) { + *oversoft = true; + return lqe->lqe_hardlimit; + } else { + *oversoft = true; + return 0; + } +} + /* * Try to grant more quota space back to slave. * @@ -490,10 +525,16 @@ __u64 qmt_alloc_expand(struct lquota_entry *lqe, __u64 granted, __u64 spare) slv_cnt = lqe2qpi(lqe)->qpi_slv_nr[lqe->lqe_site->lqs_qtype]; qunit = lqe->lqe_qunit; - if (lqe->lqe_softlimit != 0) - remaining = lqe->lqe_softlimit; - else + /* See comment in qmt_adjust_qunit(). LU-4139. */ + if (lqe->lqe_softlimit != 0) { + bool oversoft; + remaining = qmt_calc_softlimit(lqe, &oversoft); + if (remaining == 0) + remaining = lqe->lqe_granted + + (pool->qpi_least_qunit << 2); + } else { remaining = lqe->lqe_hardlimit; + } if (lqe->lqe_granted >= remaining) RETURN(0); @@ -536,7 +577,7 @@ void qmt_adjust_qunit(const struct lu_env *env, struct lquota_entry *lqe) { struct qmt_pool_info *pool = lqe2qpi(lqe); int slv_cnt; - __u64 qunit, limit; + __u64 qunit, limit, qunit2 = 0; ENTRY; LASSERT(lqe_is_locked(lqe)); @@ -556,7 +597,15 @@ void qmt_adjust_qunit(const struct lu_env *env, struct lquota_entry *lqe) * beyond the soft limit. This will impact performance, but that's the * price of an accurate grace time management. */ if (lqe->lqe_softlimit != 0) { - limit = lqe->lqe_softlimit; + 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. */ + limit = qmt_calc_softlimit(lqe, &oversoft); + if (oversoft) + qunit2 = pool->qpi_least_qunit << 2; + if (limit == 0) + GOTO(done, qunit = qunit2); } else if (lqe->lqe_hardlimit != 0) { limit = lqe->lqe_hardlimit; } else { @@ -601,6 +650,9 @@ void qmt_adjust_qunit(const struct lu_env *env, struct lquota_entry *lqe) qunit >>= 2; } + if (qunit2 && qunit > qunit2) + qunit = qunit2; +done: if (lqe->lqe_qunit == qunit) /* keep current qunit */ RETURN_EXIT; diff --git a/lustre/quota/qmt_internal.h b/lustre/quota/qmt_internal.h index 8938f6e..cfcfd57 100644 --- a/lustre/quota/qmt_internal.h +++ b/lustre/quota/qmt_internal.h @@ -248,21 +248,32 @@ static inline void qmt_restore(struct lquota_entry *lqe, (slv) -= (cnt); \ } while (0) -/* helper routine returning true when the id has run out of quota space, which - * means that it has either: - * - reached hardlimit - * OR - * - reached softlimit and grace time expired already */ -static inline bool qmt_space_exhausted(struct lquota_entry *lqe, __u64 now) +/* helper routine returning true when reached hardlimit */ +static inline bool qmt_hard_exhausted(struct lquota_entry *lqe) { if (lqe->lqe_hardlimit != 0 && lqe->lqe_granted >= lqe->lqe_hardlimit) return true; + return false; +} + +/* helper routine returning true when reached softlimit */ +static inline bool qmt_soft_exhausted(struct lquota_entry *lqe, __u64 now) +{ if (lqe->lqe_softlimit != 0 && lqe->lqe_granted > lqe->lqe_softlimit && lqe->lqe_gracetime != 0 && now >= lqe->lqe_gracetime) return true; return false; } +/* helper routine returning true when the id has run out of quota space: + * - reached hardlimit + * OR + * - reached softlimit and grace time expired already */ +static inline bool qmt_space_exhausted(struct lquota_entry *lqe, __u64 now) +{ + return (qmt_hard_exhausted(lqe) || qmt_soft_exhausted(lqe, now)); +} + /* number of seconds to wait for slaves to release quota space after * rebalancing */ #define QMT_REBA_TIMEOUT 2 -- 1.8.3.1