* GPL HEADER END
*/
/*
- * Copyright (c) 2012 Intel, Inc.
+ * Copyright (c) 2012, Intel Corporation.
* Use is subject to license terms.
*
* Author: Johann Lombardi <johann.lombardi@intel.com>
* Author: Niu Yawei <yawei.niu@intel.com>
*/
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
-
#define DEBUG_SUBSYSTEM S_LQUOTA
#include "qmt_internal.h"
LASSERT(lqe_is_master(lqe));
lqe->lqe_revoke_time = 0;
- cfs_init_rwsem(&lqe->lqe_sem);
+ init_rwsem(&lqe->lqe_sem);
}
/*
libcfs_debug_vmsg2(msgdata, fmt, args,
"qmt:%s pool:%d-%s id:"LPU64" enforced:%d hard:"LPU64
" soft:"LPU64" granted:"LPU64" time:"LPU64" qunit:"
- LPU64" edquot:%d revoke:"LPU64"\n",
+ LPU64" edquot:%d may_rel:"LPU64" revoke:"LPU64"\n",
pool->qpi_qmt->qmt_svname,
pool->qpi_key & 0x0000ffff,
RES_NAME(pool->qpi_key >> 16),
lqe->lqe_id.qid_uid, lqe->lqe_enforced,
lqe->lqe_hardlimit, lqe->lqe_softlimit,
lqe->lqe_granted, lqe->lqe_gracetime,
- lqe->lqe_qunit, lqe->lqe_edquot,
+ lqe->lqe_qunit, lqe->lqe_edquot, lqe->lqe_may_rel,
lqe->lqe_revoke_time);
}
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,
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,
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) {
/* 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;
+
+ /* least qunit value not sent to all slaves yet */
+ if (lqe->lqe_revoke_time == 0)
+ RETURN_EXIT;
- if (lqe->lqe_may_rel != 0 &&
- cfs_time_beforeq_64(lqe->lqe_revoke_time,
- cfs_time_shift_64(-QMT_REBA_TIMEOUT)))
/* 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;
/* let's notify slave by issuing glimpse on per-ID lock.
* the rebalance thread will take care of this */
qmt_id_lock_notify(pool->qpi_qmt, lqe);
+ 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;
+ }
}
/*
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);
{
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;
* 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 {
qunit >>= 2;
}
+ if (qunit2 && qunit > qunit2)
+ qunit = qunit2;
+done:
if (lqe->lqe_qunit == qunit)
/* keep current qunit */
RETURN_EXIT;