From: Johann Lombardi Date: Tue, 20 Nov 2012 15:55:28 +0000 (+0100) Subject: LU-2361 quota: keep slave's glb idx consistent with master's X-Git-Tag: 2.3.58~35 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=5171780a7b5301cdbb6f98d8c887899600ef098a LU-2361 quota: keep slave's glb idx consistent with master's Issue glimpse callback and bump global version each time quota settings are modified in the global index. This way, the global recovered if required. Signed-off-by: Johann Lombardi Change-Id: I91c11b8bce68c8f96289588e612295ece7664c3f Reviewed-on: http://review.whamcloud.com/4632 Reviewed-by: Fan Yong Tested-by: Hudson Reviewed-by: Niu Yawei Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index c658f8c..97e40da 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -1768,7 +1768,7 @@ struct ldlm_gl_lquota_desc { __u64 gl_ver; /* new index version */ __u64 gl_hardlimit; /* new hardlimit or qunit value */ __u64 gl_softlimit; /* new softlimit */ - __u64 gl_pad1; + __u64 gl_time; __u64 gl_pad2; }; #define gl_qunit gl_hardlimit /* current qunit value used when diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c index e94bef0..89491af 100644 --- a/lustre/ptlrpc/pack_generic.c +++ b/lustre/ptlrpc/pack_generic.c @@ -1829,7 +1829,7 @@ void lustre_swab_gl_desc(union ldlm_gl_desc *desc) __swab64s(&desc->lquota_desc.gl_ver); __swab64s(&desc->lquota_desc.gl_hardlimit); __swab64s(&desc->lquota_desc.gl_softlimit); - CLASSERT(offsetof(typeof(desc->lquota_desc), gl_pad1) != 0); + __swab64s(&desc->lquota_desc.gl_time); CLASSERT(offsetof(typeof(desc->lquota_desc), gl_pad2) != 0); } diff --git a/lustre/ptlrpc/wiretest.c b/lustre/ptlrpc/wiretest.c index 09e627c..a62e8ec 100644 --- a/lustre/ptlrpc/wiretest.c +++ b/lustre/ptlrpc/wiretest.c @@ -3196,10 +3196,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct ldlm_gl_lquota_desc, gl_softlimit)); LASSERTF((int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_softlimit) == 8, "found %lld\n", (long long)(int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_softlimit)); - LASSERTF((int)offsetof(struct ldlm_gl_lquota_desc, gl_pad1) == 48, "found %lld\n", - (long long)(int)offsetof(struct ldlm_gl_lquota_desc, gl_pad1)); - LASSERTF((int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_pad1) == 8, "found %lld\n", - (long long)(int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_pad1)); + LASSERTF((int)offsetof(struct ldlm_gl_lquota_desc, gl_time) == 48, "found %lld\n", + (long long)(int)offsetof(struct ldlm_gl_lquota_desc, gl_time)); + LASSERTF((int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_time) == 8, "found %lld\n", + (long long)(int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_time)); LASSERTF((int)offsetof(struct ldlm_gl_lquota_desc, gl_pad2) == 56, "found %lld\n", (long long)(int)offsetof(struct ldlm_gl_lquota_desc, gl_pad2)); LASSERTF((int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_pad2) == 8, "found %lld\n", diff --git a/lustre/quota/qmt_entry.c b/lustre/quota/qmt_entry.c index 9c6b9a3..1de9ba8 100644 --- a/lustre/quota/qmt_entry.c +++ b/lustre/quota/qmt_entry.c @@ -416,7 +416,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) { @@ -545,7 +545,7 @@ void qmt_adjust_qunit(const struct lu_env *env, struct lquota_entry *lqe) LASSERT(lqe_is_locked(lqe)); - if (!lqe->lqe_enforced) + if (!lqe->lqe_enforced || lqe->lqe_id.qid_uid == 0) /* no quota limits */ RETURN_EXIT; diff --git a/lustre/quota/qmt_handler.c b/lustre/quota/qmt_handler.c index 94a64d9..948e398 100644 --- a/lustre/quota/qmt_handler.c +++ b/lustre/quota/qmt_handler.c @@ -38,109 +38,6 @@ #include "qmt_internal.h" /* - * Fetch grace time for either inode or block. - * - * \param env - is the environment passed by the caller - * \param qmt - is the quota master target - * \param pool_id - is the 16-bit pool identifier - * \param restype - is the pool type, either block (i.e. LQUOTA_RES_DT) or inode - * (i.e. LQUOTA_RES_MD) - * \param qtype - is the quota type - * \param time - is the output variable where to copy the grace time - */ -static int qmt_getinfo(const struct lu_env *env, struct qmt_device *qmt, - __u16 pool_id, __u8 restype, __u8 qtype, __u64 *time) -{ - struct qmt_thread_info *qti = qmt_info(env); - union lquota_id *id = &qti->qti_id; - struct lquota_entry *lqe; - ENTRY; - - /* Global grace time is stored in quota settings of ID 0. */ - id->qid_uid = 0; - - /* look-up quota entry storing grace time */ - lqe = qmt_pool_lqe_lookup(env, qmt, pool_id, restype, qtype, id); - if (IS_ERR(lqe)) - RETURN(PTR_ERR(lqe)); - - lqe_read_lock(lqe); - LQUOTA_DEBUG(lqe, "getinfo"); - /* copy grace time */ - *time = lqe->lqe_gracetime; - lqe_read_unlock(lqe); - - lqe_putref(lqe); - RETURN(0); -} - -/* - * Update grace time for either inode or block. - * Global grace time is stored in quota settings of ID 0. - * - * \param env - is the environment passed by the caller - * \param qmt - is the quota master target - * \param pool_id - is the 16-bit pool identifier - * \param restype - is the pool type, either block (i.e. LQUOTA_RES_DT) or inode - * (i.e. LQUOTA_RES_MD) - * \param qtype - is the quota type - * \param time - is the new grace time - */ -static int qmt_setinfo(const struct lu_env *env, struct qmt_device *qmt, - __u16 pool_id, __u8 restype, __u8 qtype, __u64 time) -{ - struct qmt_thread_info *qti = qmt_info(env); - union lquota_id *id = &qti->qti_id; - struct lquota_entry *lqe; - struct thandle *th = NULL; - int rc; - ENTRY; - - /* Global grace time is stored in quota settings of ID 0. */ - id->qid_uid = 0; - - /* look-up quota entry storing the global grace time */ - lqe = qmt_pool_lqe_lookup(env, qmt, pool_id, restype, qtype, id); - if (IS_ERR(lqe)) - RETURN(PTR_ERR(lqe)); - - /* allocate & start transaction with enough credits to update grace - * time in the global index file */ - th = qmt_trans_start(env, lqe, &qti->qti_restore); - if (IS_ERR(th)) - GOTO(out_nolock, rc = PTR_ERR(th)); - - /* write lock quota entry storing the grace time */ - lqe_write_lock(lqe); - if (lqe->lqe_gracetime == time) - /* grace time is the same */ - GOTO(out, rc = 0); - - LQUOTA_DEBUG(lqe, "setinfo time:"LPU64, time); - - /* set new grace time */ - lqe->lqe_gracetime = time; - /* always set enforced bit for ID 0 to make sure it does not go away */ - lqe->lqe_enforced = true; - - /* write new grace time to disk, no need for version bump */ - rc = qmt_glb_write(env, th, lqe, 0, NULL); - if (rc) { - /* restore initial grace time */ - qmt_restore(lqe, &qti->qti_restore); - GOTO(out, rc); - } - EXIT; -out: - lqe_write_unlock(lqe); -out_nolock: - lqe_putref(lqe); - if (th != NULL && !IS_ERR(th)) - dt_trans_stop(env, qmt->qmt_child, th); - return rc; -} - -/* * Retrieve quota settings for a given identifier. * * \param env - is the environment passed by the caller @@ -155,10 +52,9 @@ out_nolock: * \param soft - is the output variable where to copy the soft limit * \param time - is the output variable where to copy the grace time */ -static int qmt_getquota(const struct lu_env *env, struct qmt_device *qmt, - __u16 pool_id, __u8 restype, __u8 qtype, - union lquota_id *id, __u64 *hard, __u64 *soft, - __u64 *time) +static int qmt_get(const struct lu_env *env, struct qmt_device *qmt, + __u16 pool_id, __u8 restype, __u8 qtype, union lquota_id *id, + __u64 *hard, __u64 *soft, __u64 *time) { struct lquota_entry *lqe; ENTRY; @@ -170,10 +66,13 @@ static int qmt_getquota(const struct lu_env *env, struct qmt_device *qmt, /* copy quota settings */ lqe_read_lock(lqe); - LQUOTA_DEBUG(lqe, "getquota"); - *hard = lqe->lqe_hardlimit; - *soft = lqe->lqe_softlimit; - *time = lqe->lqe_gracetime; + LQUOTA_DEBUG(lqe, "fetch settings"); + if (hard != NULL) + *hard = lqe->lqe_hardlimit; + if (soft != NULL) + *soft = lqe->lqe_softlimit; + if (time != NULL) + *time = lqe->lqe_gracetime; lqe_read_unlock(lqe); lqe_putref(lqe); @@ -196,16 +95,16 @@ static int qmt_getquota(const struct lu_env *env, struct qmt_device *qmt, * \param time - is the new grace time * \param valid - is the list of settings to change */ -static int qmt_setquota(const struct lu_env *env, struct qmt_device *qmt, - __u16 pool_id, __u8 restype, __u8 qtype, - union lquota_id *id, __u64 hard, __u64 soft, __u64 time, - __u32 valid) +static int qmt_set(const struct lu_env *env, struct qmt_device *qmt, + __u16 pool_id, __u8 restype, __u8 qtype, + union lquota_id *id, __u64 hard, __u64 soft, __u64 time, + __u32 valid) { struct qmt_thread_info *qti = qmt_info(env); struct lquota_entry *lqe; struct thandle *th = NULL; __u64 ver, now; - bool dirtied = false, bump_version = false; + bool dirtied = false; int rc = 0; ENTRY; @@ -223,8 +122,8 @@ static int qmt_setquota(const struct lu_env *env, struct qmt_device *qmt, now = cfs_time_current_sec(); lqe_write_lock(lqe); - LQUOTA_DEBUG(lqe, "setquota valid:%x hard:"LPU64" soft:"LPU64 - " time:"LPU64, valid, hard, soft, time); + LQUOTA_DEBUG(lqe, "changing quota settings valid:%x hard:"LPU64" soft:" + LPU64" time:"LPU64, valid, hard, soft, time); if ((valid & QIF_TIMES) != 0 && lqe->lqe_gracetime != time) { /* change time settings */ @@ -234,8 +133,6 @@ static int qmt_setquota(const struct lu_env *env, struct qmt_device *qmt, if ((valid & QIF_LIMITS) != 0 && (lqe->lqe_hardlimit != hard || lqe->lqe_softlimit != soft)) { - bool enforced = lqe->lqe_enforced; - rc = qmt_validate_limits(lqe, hard, soft); if (rc) GOTO(out, rc); @@ -263,19 +160,12 @@ static int qmt_setquota(const struct lu_env *env, struct qmt_device *qmt, else lqe->lqe_enforced = true; - if ((enforced && !lqe->lqe_enforced) || - (!enforced && lqe->lqe_enforced)) - /* if enforced status has changed, we need to inform - * slave, therefore we need to bump the version */ - bump_version = true; - dirtied = true; } if (dirtied) { /* write new quota settings to disk */ - rc = qmt_glb_write(env, th, lqe, - bump_version ? LQUOTA_BUMP_VER : 0, &ver); + rc = qmt_glb_write(env, th, lqe, LQUOTA_BUMP_VER, &ver); if (rc) { /* restore initial quota settings */ qmt_restore(lqe, &qti->qti_restore); @@ -298,7 +188,7 @@ out_nolock: if (th != NULL && !IS_ERR(th)) dt_trans_stop(env, qmt->qmt_child, th); - if (rc == 0 && bump_version) + if (rc == 0 && dirtied) qmt_glb_lock_notify(env, lqe, ver); return rc; @@ -330,35 +220,42 @@ static int qmt_quotactl(const struct lu_env *env, struct lu_device *ld, switch (oqctl->qc_cmd) { case Q_GETINFO: /* read grace times */ + /* Global grace time is stored in quota settings of ID 0. */ + id->qid_uid = 0; + /* read inode grace time */ - rc = qmt_getinfo(env, qmt, 0, LQUOTA_RES_MD, oqctl->qc_type, - &oqctl->qc_dqinfo.dqi_igrace); + rc = qmt_get(env, qmt, 0, LQUOTA_RES_MD, oqctl->qc_type, id, + NULL, NULL, &oqctl->qc_dqinfo.dqi_igrace); if (rc) break; /* read block grace time */ - rc = qmt_getinfo(env, qmt, 0, LQUOTA_RES_DT, oqctl->qc_type, - &oqctl->qc_dqinfo.dqi_bgrace); + rc = qmt_get(env, qmt, 0, LQUOTA_RES_DT, oqctl->qc_type, id, + NULL, NULL, &oqctl->qc_dqinfo.dqi_bgrace); break; case Q_SETINFO: /* modify grace times */ /* setinfo should be using dqi->dqi_valid, but lfs incorrectly * sets the valid flags in dqb->dqb_valid instead, try to live * with that ... */ + + /* Global grace time is stored in quota settings of ID 0. */ + id->qid_uid = 0; + if ((dqb->dqb_valid & QIF_ITIME) != 0) { /* set inode grace time */ - rc = qmt_setinfo(env, qmt, 0, LQUOTA_RES_MD, - oqctl->qc_type, - oqctl->qc_dqinfo.dqi_igrace); + rc = qmt_set(env, qmt, 0, LQUOTA_RES_MD, oqctl->qc_type, + id, 0, 0, oqctl->qc_dqinfo.dqi_igrace, + QIF_TIMES); if (rc) break; } if ((dqb->dqb_valid & QIF_BTIME) != 0) /* set block grace time */ - rc = qmt_setinfo(env, qmt, 0, LQUOTA_RES_DT, - oqctl->qc_type, - oqctl->qc_dqinfo.dqi_bgrace); + rc = qmt_set(env, qmt, 0, LQUOTA_RES_DT, oqctl->qc_type, + id, 0, 0, oqctl->qc_dqinfo.dqi_bgrace, + QIF_TIMES); break; case Q_GETQUOTA: /* consult quota limit */ @@ -372,9 +269,9 @@ static int qmt_quotactl(const struct lu_env *env, struct lu_device *ld, id->qid_uid = oqctl->qc_id; /* look-up inode quota settings */ - rc = qmt_getquota(env, qmt, 0, LQUOTA_RES_MD, oqctl->qc_type, - id, &dqb->dqb_ihardlimit, - &dqb->dqb_isoftlimit, &dqb->dqb_itime); + rc = qmt_get(env, qmt, 0, LQUOTA_RES_MD, oqctl->qc_type, id, + &dqb->dqb_ihardlimit, &dqb->dqb_isoftlimit, + &dqb->dqb_itime); if (rc) break; @@ -383,9 +280,9 @@ static int qmt_quotactl(const struct lu_env *env, struct lu_device *ld, dqb->dqb_curinodes = 0; /* look-up block quota settings */ - rc = qmt_getquota(env, qmt, 0, LQUOTA_RES_DT, oqctl->qc_type, - id, &dqb->dqb_bhardlimit, - &dqb->dqb_bsoftlimit, &dqb->dqb_btime); + rc = qmt_get(env, qmt, 0, LQUOTA_RES_DT, oqctl->qc_type, id, + &dqb->dqb_bhardlimit, &dqb->dqb_bsoftlimit, + &dqb->dqb_btime); if (rc) break; @@ -403,22 +300,20 @@ static int qmt_quotactl(const struct lu_env *env, struct lu_device *ld, if ((dqb->dqb_valid & QIF_IFLAGS) != 0) { /* update inode quota settings */ - rc = qmt_setquota(env, qmt, 0, LQUOTA_RES_MD, - oqctl->qc_type, id, - dqb->dqb_ihardlimit, - dqb->dqb_isoftlimit, dqb->dqb_itime, - dqb->dqb_valid & QIF_IFLAGS); + rc = qmt_set(env, qmt, 0, LQUOTA_RES_MD, oqctl->qc_type, + id, dqb->dqb_ihardlimit, + dqb->dqb_isoftlimit, dqb->dqb_itime, + dqb->dqb_valid & QIF_IFLAGS); if (rc) break; } if ((dqb->dqb_valid & QIF_BFLAGS) != 0) /* update block quota settings */ - rc = qmt_setquota(env, qmt, 0, LQUOTA_RES_DT, - oqctl->qc_type, id, - dqb->dqb_bhardlimit, - dqb->dqb_bsoftlimit, dqb->dqb_btime, - dqb->dqb_valid & QIF_BFLAGS); + rc = qmt_set(env, qmt, 0, LQUOTA_RES_DT, oqctl->qc_type, + id, dqb->dqb_bhardlimit, + dqb->dqb_bsoftlimit, dqb->dqb_btime, + dqb->dqb_valid & QIF_BFLAGS); break; case Q_QUOTAON: diff --git a/lustre/quota/qmt_lock.c b/lustre/quota/qmt_lock.c index 70ab3b4..9466c6c 100644 --- a/lustre/quota/qmt_lock.c +++ b/lustre/quota/qmt_lock.c @@ -550,6 +550,7 @@ void qmt_glb_lock_notify(const struct lu_env *env, struct lquota_entry *lqe, qti->qti_gl_desc.lquota_desc.gl_flags = 0; qti->qti_gl_desc.lquota_desc.gl_hardlimit = lqe->lqe_hardlimit; qti->qti_gl_desc.lquota_desc.gl_softlimit = lqe->lqe_softlimit; + qti->qti_gl_desc.lquota_desc.gl_time = lqe->lqe_gracetime; qti->qti_gl_desc.lquota_desc.gl_ver = ver; /* look up ldlm resource associated with global index */ diff --git a/lustre/quota/qsd_lock.c b/lustre/quota/qsd_lock.c index 68c8352..d62ea86 100644 --- a/lustre/quota/qsd_lock.c +++ b/lustre/quota/qsd_lock.c @@ -243,7 +243,7 @@ static int qsd_glb_glimpse_ast(struct ldlm_lock *lock, void *data) /* extract new hard & soft limits from the glimpse descriptor */ rec.qbr_hardlimit = desc->gl_hardlimit; rec.qbr_softlimit = desc->gl_softlimit; - rec.qbr_time = 0; + rec.qbr_time = desc->gl_time; rec.qbr_granted = 0; /* We can't afford disk io in the context of glimpse callback handling diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c index b038e2c..ae3120f 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -1380,7 +1380,7 @@ check_ldlm_gl_lquota_desc(void) CHECK_MEMBER(ldlm_gl_lquota_desc, gl_ver); CHECK_MEMBER(ldlm_gl_lquota_desc, gl_hardlimit); CHECK_MEMBER(ldlm_gl_lquota_desc, gl_softlimit); - CHECK_MEMBER(ldlm_gl_lquota_desc, gl_pad1); + CHECK_MEMBER(ldlm_gl_lquota_desc, gl_time); CHECK_MEMBER(ldlm_gl_lquota_desc, gl_pad2); } diff --git a/lustre/utils/wiretest.c b/lustre/utils/wiretest.c index 6ca6c20..6e45692 100644 --- a/lustre/utils/wiretest.c +++ b/lustre/utils/wiretest.c @@ -3204,10 +3204,10 @@ void lustre_assert_wire_constants(void) (long long)(int)offsetof(struct ldlm_gl_lquota_desc, gl_softlimit)); LASSERTF((int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_softlimit) == 8, "found %lld\n", (long long)(int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_softlimit)); - LASSERTF((int)offsetof(struct ldlm_gl_lquota_desc, gl_pad1) == 48, "found %lld\n", - (long long)(int)offsetof(struct ldlm_gl_lquota_desc, gl_pad1)); - LASSERTF((int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_pad1) == 8, "found %lld\n", - (long long)(int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_pad1)); + LASSERTF((int)offsetof(struct ldlm_gl_lquota_desc, gl_time) == 48, "found %lld\n", + (long long)(int)offsetof(struct ldlm_gl_lquota_desc, gl_time)); + LASSERTF((int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_time) == 8, "found %lld\n", + (long long)(int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_time)); LASSERTF((int)offsetof(struct ldlm_gl_lquota_desc, gl_pad2) == 56, "found %lld\n", (long long)(int)offsetof(struct ldlm_gl_lquota_desc, gl_pad2)); LASSERTF((int)sizeof(((struct ldlm_gl_lquota_desc *)0)->gl_pad2) == 8, "found %lld\n",