X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lustre%2Fquota%2Fqmt_entry.c;h=8997dec33b1935841350e61e831292abd139477a;hb=471ad1f679ad7c0193785f82abf6f249ffeb1e79;hp=59a06531258a82b033206587bff4f600a089c403;hpb=9680dabde70a9ec5f211e26d7c2f2988f296f455;p=fs%2Flustre-release.git diff --git a/lustre/quota/qmt_entry.c b/lustre/quota/qmt_entry.c index 59a0653..8997dec 100644 --- a/lustre/quota/qmt_entry.c +++ b/lustre/quota/qmt_entry.c @@ -21,17 +21,13 @@ * GPL HEADER END */ /* - * Copyright (c) 2012 Intel, Inc. + * Copyright (c) 2012, 2013, Intel Corporation. * Use is subject to license terms. * * Author: Johann Lombardi * Author: Niu Yawei */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif - #define DEBUG_SUBSYSTEM S_LQUOTA #include "qmt_internal.h" @@ -47,7 +43,7 @@ static void qmt_lqe_init(struct lquota_entry *lqe, void *arg) LASSERT(lqe_is_master(lqe)); lqe->lqe_revoke_time = 0; - cfs_init_rwsem(&lqe->lqe_sem); + init_rwsem(&lqe->lqe_sem); } /* @@ -261,21 +257,16 @@ int qmt_glb_write(const struct lu_env *env, struct thandle *th, LQUOTA_DEBUG(lqe, "write glb"); - if (!lqe->lqe_enforced && lqe->lqe_granted == 0 && - lqe->lqe_id.qid_uid != 0) { - /* quota isn't enforced any more for this entry and there is no - * more space granted to slaves, let's just remove the entry - * from the index */ - rec = NULL; - } else { - rec = &qti->qti_glb_rec; + /* never delete the entry even when the id isn't enforced and + * no any guota granted, otherwise, this entry will not be + * synced to slave during the reintegration. */ + rec = &qti->qti_glb_rec; - /* fill global index with updated quota settings */ - rec->qbr_granted = lqe->lqe_granted; - rec->qbr_hardlimit = lqe->lqe_hardlimit; - rec->qbr_softlimit = lqe->lqe_softlimit; - rec->qbr_time = lqe->lqe_gracetime; - } + /* fill global index with updated quota settings */ + rec->qbr_granted = lqe->lqe_granted; + rec->qbr_hardlimit = lqe->lqe_hardlimit; + rec->qbr_softlimit = lqe->lqe_softlimit; + rec->qbr_time = lqe->lqe_gracetime; /* write new quota settings */ rc = lquota_disk_write(env, th, LQE_GLB_OBJ(lqe), &lqe->lqe_id, @@ -372,16 +363,12 @@ int qmt_slv_write(const struct lu_env *env, struct thandle *th, LQUOTA_DEBUG(lqe, "write slv "DFID" granted:"LPU64, PFID(lu_object_fid(&slv_obj->do_lu)), granted); - if (granted == 0) { - /* this slave does not own any quota space for this ID any more, - * so let's just remove the entry from the index */ - rec = NULL; - } else { - rec = &qti->qti_slv_rec; + /* never delete the entry, otherwise, it'll not be transferred + * to slave during reintegration. */ + rec = &qti->qti_slv_rec; - /* updated space granted to this slave */ - rec->qsr_granted = granted; - } + /* updated space granted to this slave */ + rec->qsr_granted = granted; /* write new granted space */ rc = lquota_disk_write(env, th, slv_obj, &lqe->lqe_id, @@ -425,7 +412,7 @@ void qmt_adjust_edquot(struct lquota_entry *lqe, __u64 now) struct qmt_pool_info *pool = lqe2qpi(lqe); ENTRY; - if (!lqe->lqe_enforced) + if (!lqe->lqe_enforced || lqe->lqe_id.qid_uid == 0) RETURN_EXIT; if (!lqe->lqe_edquot) { @@ -436,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; @@ -481,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. * @@ -503,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); @@ -549,12 +577,12 @@ 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)); - if (!lqe->lqe_enforced) + if (!lqe->lqe_enforced || lqe->lqe_id.qid_uid == 0) /* no quota limits */ RETURN_EXIT; @@ -569,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 { @@ -605,8 +641,14 @@ void qmt_adjust_qunit(const struct lu_env *env, struct lquota_entry *lqe) /* current qunit value still fits, let's see if we can afford to * increase qunit now ... * To increase qunit again, we have to be under 25% */ - while (limit >= lqe->lqe_granted + 6 * qunit * slv_cnt) + while (qunit && limit >= lqe->lqe_granted + 6 * qunit * slv_cnt) qunit <<= 2; + + if (!qunit) { + qunit = limit; + do_div(qunit, 2 * slv_cnt); + } + } else { /* shrink qunit until we find a suitable value */ while (qunit > pool->qpi_least_qunit && @@ -614,6 +656,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;