X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fquota%2Fquota_adjust_qunit.c;h=7d8211620e48673e213c7e1473d90174ddaaa211;hb=e44a6b616764810093a3c6f3d15254793865ffb7;hp=20ee26b502a1b365f9b4784fff894f662ba55952;hpb=cefa8cda2ba2d288ccaa4ec077a6c627592503ea;p=fs%2Flustre-release.git diff --git a/lustre/quota/quota_adjust_qunit.c b/lustre/quota/quota_adjust_qunit.c index 20ee26b..7d82116 100644 --- a/lustre/quota/quota_adjust_qunit.c +++ b/lustre/quota/quota_adjust_qunit.c @@ -45,14 +45,10 @@ # include # include # include -# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) -# include -# include -# include -# include -# else -# include -# endif +# include +# include +# include +# include #else /* __KERNEL__ */ # include #endif @@ -64,7 +60,6 @@ #include #include #include -#include #include "quota_internal.h" #ifdef HAVE_QUOTA_SUPPORT @@ -79,109 +74,42 @@ * is_acq: whether it is acquiring; otherwise, it is releasing */ void quota_compute_lqs(struct qunit_data *qdata, struct lustre_qunit_size *lqs, - int is_chk, int is_acq) + int is_chk, int is_acq) { - int is_blk; + long long *rec; LASSERT(qdata && lqs); LASSERT_SPIN_LOCKED(&lqs->lqs_lock); - is_blk = QDATA_IS_BLK(qdata); - - if (is_chk) { - if (is_acq) { - if (is_blk) - lqs->lqs_blk_rec += qdata->qd_count; - else - lqs->lqs_ino_rec += qdata->qd_count; - } else { - if (is_blk) - lqs->lqs_blk_rec -= qdata->qd_count; - else - lqs->lqs_ino_rec -= qdata->qd_count; - } - } else { - if (is_acq) { - if (is_blk) - lqs->lqs_blk_rec -= qdata->qd_count; - else - lqs->lqs_ino_rec -= qdata->qd_count; - } else { - if (is_blk) - lqs->lqs_blk_rec += qdata->qd_count; - else - lqs->lqs_ino_rec += qdata->qd_count; - } - } -} -void qdata_to_oqaq(struct qunit_data *qdata, struct quota_adjust_qunit *oqaq) -{ - LASSERT(qdata); - LASSERT(oqaq); + rec = QDATA_IS_BLK(qdata) ? &lqs->lqs_blk_rec : &lqs->lqs_ino_rec; - oqaq->qaq_flags = qdata->qd_flags; - oqaq->qaq_id = qdata->qd_id; - if (QDATA_IS_ADJBLK(qdata)) - oqaq->qaq_bunit_sz = qdata->qd_qunit; - if (QDATA_IS_ADJINO(qdata)) - oqaq->qaq_iunit_sz = qdata->qd_qunit; -} - -int quota_search_lqs(struct qunit_data *qdata, struct quota_adjust_qunit *oqaq, - struct lustre_quota_ctxt *qctxt, - struct lustre_qunit_size **lqs_return) -{ - struct quota_adjust_qunit *oqaq_tmp = NULL; - ENTRY; - - LASSERT(*lqs_return == NULL); - LASSERT(oqaq || qdata); - - if (!oqaq) { - OBD_ALLOC_PTR(oqaq_tmp); - if (!oqaq_tmp) - RETURN(-ENOMEM); - qdata_to_oqaq(qdata, oqaq_tmp); - } else { - oqaq_tmp = oqaq; - } - - *lqs_return = lustre_hash_lookup(qctxt->lqc_lqs_hash, oqaq_tmp); - if (*lqs_return) - LQS_DEBUG((*lqs_return), "show lqs\n"); + if (!!is_chk + !!is_acq == 1) + *rec -= qdata->qd_count; + else + *rec += qdata->qd_count; - if (!oqaq) - OBD_FREE_PTR(oqaq_tmp); - RETURN(0); } -int quota_create_lqs(struct qunit_data *qdata, struct quota_adjust_qunit *oqaq, - struct lustre_quota_ctxt *qctxt, - struct lustre_qunit_size **lqs_return) +static struct lustre_qunit_size * +quota_create_lqs(unsigned long long lqs_key, struct lustre_quota_ctxt *qctxt) { struct lustre_qunit_size *lqs = NULL; + cfs_hash_t *hs = NULL; int rc = 0; - ENTRY; - - LASSERT(*lqs_return == NULL); - LASSERT(oqaq || qdata); OBD_ALLOC_PTR(lqs); if (!lqs) GOTO(out, rc = -ENOMEM); - if (!oqaq) - qdata_to_oqaq(qdata, &lqs->lqs_key); - else - lqs->lqs_key = *oqaq; + lqs->lqs_key = lqs_key; - spin_lock_init(&lqs->lqs_lock); + cfs_spin_lock_init(&lqs->lqs_lock); lqs->lqs_bwrite_pending = 0; lqs->lqs_iwrite_pending = 0; lqs->lqs_ino_rec = 0; lqs->lqs_blk_rec = 0; - lqs->lqs_id = lqs->lqs_key.qaq_id; - lqs->lqs_flags = QAQ_IS_GRP(&lqs->lqs_key); + lqs->lqs_id = LQS_KEY_ID(lqs->lqs_key); + lqs->lqs_flags = LQS_KEY_GRP(lqs->lqs_key) ? LQUOTA_FLAGS_GRP : 0; lqs->lqs_bunit_sz = qctxt->lqc_bunit_sz; lqs->lqs_iunit_sz = qctxt->lqc_iunit_sz; lqs->lqs_btune_sz = qctxt->lqc_btune_sz; @@ -192,122 +120,145 @@ int quota_create_lqs(struct qunit_data *qdata, struct quota_adjust_qunit *oqaq, lqs->lqs_last_ishrink = 0; } lqs_initref(lqs); - rc = lustre_hash_add_unique(qctxt->lqc_lqs_hash, - &lqs->lqs_key, &lqs->lqs_hash); - LQS_DEBUG(lqs, "create lqs\n"); - if (!rc) { + + cfs_spin_lock(&qctxt->lqc_lock); + if (qctxt->lqc_valid) + hs = cfs_hash_getref(qctxt->lqc_lqs_hash); + cfs_spin_unlock(&qctxt->lqc_lock); + + if (hs) { lqs_getref(lqs); - *lqs_return = lqs; + rc = cfs_hash_add_unique(qctxt->lqc_lqs_hash, + &lqs->lqs_key, &lqs->lqs_hash); + if (rc) + lqs_putref(lqs); + cfs_hash_putref(hs); + } else { + rc = -EBUSY; } -out: + + out: if (rc && lqs) OBD_FREE_PTR(lqs); - RETURN(rc); + + if (rc) + return ERR_PTR(rc); + else + return lqs; +} + +struct lustre_qunit_size *quota_search_lqs(unsigned long long lqs_key, + struct lustre_quota_ctxt *qctxt, + int create) +{ + struct lustre_qunit_size *lqs; + int rc = 0; + + search_lqs: + lqs = cfs_hash_lookup(qctxt->lqc_lqs_hash, &lqs_key); + if (IS_ERR(lqs)) + GOTO(out, rc = PTR_ERR(lqs)); + + if (create && lqs == NULL) { + /* if quota_create_lqs is successful, it will get a + * ref to the lqs. The ref will be released when + * qctxt_cleanup() or quota is nullified */ + lqs = quota_create_lqs(lqs_key, qctxt); + if (IS_ERR(lqs)) + rc = PTR_ERR(lqs); + if (rc == -EALREADY) + GOTO(search_lqs, rc = 0); + /* get a reference for the caller when creating lqs + * successfully */ + if (rc == 0) + lqs_getref(lqs); + } + + if (lqs && rc == 0) + LQS_DEBUG(lqs, "%s\n", + (create == 1 ? "create lqs" : "search lqs")); + + out: + if (rc == 0) { + return lqs; + } else { + CERROR("get lqs error(rc: %d)\n", rc); + return ERR_PTR(rc); + } } int quota_adjust_slave_lqs(struct quota_adjust_qunit *oqaq, struct lustre_quota_ctxt *qctxt) { struct lustre_qunit_size *lqs = NULL; - unsigned long *lbunit, *liunit, *lbtune, *litune; - signed long b_tmp = 0, i_tmp = 0; - cfs_time_t time_limit = 0; - int rc = 0; + unsigned long *unit, *tune; + signed long tmp = 0; + cfs_time_t time_limit = 0, *shrink; + int i, rc = 0; ENTRY; LASSERT(qctxt); -search_lqs: - rc = quota_search_lqs(NULL, oqaq, qctxt, &lqs); - - /* deleting the lqs, because a user sets lfs quota 0 0 0 0 */ - if (!oqaq->qaq_bunit_sz && !oqaq->qaq_iunit_sz && QAQ_IS_ADJBLK(oqaq) && - QAQ_IS_ADJINO(oqaq)) { - if (lqs) { - LQS_DEBUG(lqs, "release lqs\n"); - /* this is for quota_search_lqs */ - lqs_putref(lqs); - /* kill lqs */ - lqs_putref(lqs); - } - RETURN(rc); + lqs = quota_search_lqs(LQS_KEY(QAQ_IS_GRP(oqaq), oqaq->qaq_id), + qctxt, QAQ_IS_CREATE_LQS(oqaq) ? 1 : 0); + if (lqs == NULL || IS_ERR(lqs)){ + CERROR("fail to find a lqs for %sid %u!\n", + QAQ_IS_GRP(oqaq) ? "g" : "u", oqaq->qaq_id); + RETURN(PTR_ERR(lqs)); } - if (!lqs) { - rc = quota_create_lqs(NULL, oqaq, qctxt, &lqs); - if (rc == -EALREADY) - goto search_lqs; - if (rc < 0) - RETURN(rc); - } + CDEBUG(D_QUOTA, "before: bunit: %lu, iunit: %lu.\n", + lqs->lqs_bunit_sz, lqs->lqs_iunit_sz); + cfs_spin_lock(&lqs->lqs_lock); + for (i = 0; i < 2; i++) { + if (i == 0 && !QAQ_IS_ADJBLK(oqaq)) + continue; + + if (i == 1 && !QAQ_IS_ADJINO(oqaq)) + continue; - lbunit = &lqs->lqs_bunit_sz; - liunit = &lqs->lqs_iunit_sz; - lbtune = &lqs->lqs_btune_sz; - litune = &lqs->lqs_itune_sz; - - CDEBUG(D_QUOTA, "before: bunit: %lu, iunit: %lu.\n", *lbunit, *liunit); - spin_lock(&lqs->lqs_lock); - /* adjust the slave's block qunit size */ - if (QAQ_IS_ADJBLK(oqaq)) { - cfs_duration_t sec = cfs_time_seconds(qctxt->lqc_switch_seconds); - - b_tmp = *lbunit - oqaq->qaq_bunit_sz; - - if (qctxt->lqc_handler && b_tmp > 0) - lqs->lqs_last_bshrink = cfs_time_current(); - - if (qctxt->lqc_handler && b_tmp < 0) { - time_limit = cfs_time_add(lqs->lqs_last_bshrink, sec); - if (!lqs->lqs_last_bshrink || - cfs_time_after(cfs_time_current(), time_limit)) { - *lbunit = oqaq->qaq_bunit_sz; - *lbtune = (*lbunit) / 2; - } else { - b_tmp = 0; - } - } else { - *lbunit = oqaq->qaq_bunit_sz; - *lbtune = (*lbunit) / 2; + tmp = i ? (lqs->lqs_iunit_sz - oqaq->qaq_iunit_sz) : + (lqs->lqs_bunit_sz - oqaq->qaq_bunit_sz); + shrink = i ? &lqs->lqs_last_ishrink : + &lqs->lqs_last_bshrink; + time_limit = cfs_time_add(i ? lqs->lqs_last_ishrink : + lqs->lqs_last_bshrink, + cfs_time_seconds(qctxt->lqc_switch_seconds)); + unit = i ? &lqs->lqs_iunit_sz : &lqs->lqs_bunit_sz; + tune = i ? &lqs->lqs_itune_sz : &lqs->lqs_btune_sz; + + /* quota master shrinks */ + if (qctxt->lqc_handler && tmp > 0) + *shrink = cfs_time_current(); + + /* quota master enlarges */ + if (qctxt->lqc_handler && tmp < 0) { + /* in case of ping-pong effect, don't enlarge lqs + * in a short time */ + if (*shrink && + cfs_time_before(cfs_time_current(), time_limit)) + tmp = 0; } - } - /* adjust the slave's file qunit size */ - if (QAQ_IS_ADJINO(oqaq)) { - i_tmp = *liunit - oqaq->qaq_iunit_sz; - - if (qctxt->lqc_handler && i_tmp > 0) - lqs->lqs_last_ishrink = cfs_time_current(); - - if (qctxt->lqc_handler && i_tmp < 0) { - time_limit = cfs_time_add(lqs->lqs_last_ishrink, - cfs_time_seconds(qctxt-> - lqc_switch_seconds)); - if (!lqs->lqs_last_ishrink || - cfs_time_after(cfs_time_current(), time_limit)) { - *liunit = oqaq->qaq_iunit_sz; - *litune = (*liunit) / 2; - } else { - i_tmp = 0; - } - } else { - *liunit = oqaq->qaq_iunit_sz; - *litune = (*liunit) / 2; + /* when setquota, don't enlarge lqs b=18616 */ + if (QAQ_IS_CREATE_LQS(oqaq) && tmp < 0) + tmp = 0; + + if (tmp != 0) { + *unit = i ? oqaq->qaq_iunit_sz : oqaq->qaq_bunit_sz; + *tune = (*unit) / 2; } - } - spin_unlock(&lqs->lqs_lock); - CDEBUG(D_QUOTA, "after: bunit: %lu, iunit: %lu.\n", *lbunit, *liunit); - lqs_putref(lqs); - if (b_tmp > 0) - rc |= LQS_BLK_DECREASE; - else if (b_tmp < 0) - rc |= LQS_BLK_INCREASE; + if (tmp > 0) + rc |= i ? LQS_INO_DECREASE : LQS_BLK_DECREASE; + if (tmp < 0) + rc |= i ? LQS_INO_INCREASE : LQS_BLK_INCREASE; + } + cfs_spin_unlock(&lqs->lqs_lock); + CDEBUG(D_QUOTA, "after: bunit: %lu, iunit: %lu.\n", + lqs->lqs_bunit_sz, lqs->lqs_iunit_sz); - if (i_tmp > 0) - rc |= LQS_INO_DECREASE; - else if (i_tmp < 0) - rc |= LQS_INO_INCREASE; + lqs_putref(lqs); RETURN(rc); } @@ -317,7 +268,7 @@ int filter_quota_adjust_qunit(struct obd_export *exp, struct lustre_quota_ctxt *qctxt) { struct obd_device *obd = exp->exp_obd; - unsigned int uid = 0, gid = 0; + unsigned int id[MAXQUOTAS] = { 0, 0 }; int rc = 0; ENTRY; @@ -329,13 +280,14 @@ int filter_quota_adjust_qunit(struct obd_export *exp, RETURN(rc); } if (QAQ_IS_GRP(oqaq)) - gid = oqaq->qaq_id; + id[GRPQUOTA] = oqaq->qaq_id; else - uid = oqaq->qaq_id; + id[USRQUOTA] = oqaq->qaq_id; if (rc > 0) { - rc = qctxt_adjust_qunit(obd, qctxt, uid, gid, 1, 0, NULL); - if (rc == -EDQUOT || rc == -EBUSY || rc == -EAGAIN) { + rc = qctxt_adjust_qunit(obd, qctxt, id, 1, 0, NULL); + if (rc == -EDQUOT || rc == -EBUSY || + rc == QUOTA_REQ_RETURNED || rc == -EAGAIN) { CDEBUG(D_QUOTA, "rc: %d.\n", rc); rc = 0; }