X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fquota%2Fquota_adjust_qunit.c;h=45f8c388a65a4ef493eac0e9b694dc0cb8d9f1c6;hp=20ee26b502a1b365f9b4784fff894f662ba55952;hb=9364f1f12c830985b4d262c6a963bc0949facd17;hpb=cefa8cda2ba2d288ccaa4ec077a6c627592503ea diff --git a/lustre/quota/quota_adjust_qunit.c b/lustre/quota/quota_adjust_qunit.c index 20ee26b..45f8c38 100644 --- a/lustre/quota/quota_adjust_qunit.c +++ b/lustre/quota/quota_adjust_qunit.c @@ -26,7 +26,7 @@ * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ /* @@ -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,245 +74,188 @@ * 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; + + if (!!is_chk + !!is_acq == 1) + *rec -= qdata->qd_count; + else + *rec += qdata->qd_count; - 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 lustre_qunit_size *quota_search_lqs(unsigned long long lqs_key, + struct lustre_quota_ctxt *qctxt, + int create) { - struct quota_adjust_qunit *oqaq_tmp = NULL; - ENTRY; - - LASSERT(*lqs_return == NULL); - LASSERT(oqaq || qdata); + struct lustre_qunit_size *lqs; + struct lustre_qunit_size *lqs2; + cfs_hash_t *hs = NULL; + int rc = 0; - if (!oqaq) { - OBD_ALLOC_PTR(oqaq_tmp); - if (!oqaq_tmp) - RETURN(-ENOMEM); - qdata_to_oqaq(qdata, oqaq_tmp); - } else { - oqaq_tmp = oqaq; + cfs_spin_lock(&qctxt->lqc_lock); + if (qctxt->lqc_valid) { + LASSERT(qctxt->lqc_lqs_hash != NULL); + hs = cfs_hash_getref(qctxt->lqc_lqs_hash); } + cfs_spin_unlock(&qctxt->lqc_lock); - *lqs_return = lustre_hash_lookup(qctxt->lqc_lqs_hash, oqaq_tmp); - if (*lqs_return) - LQS_DEBUG((*lqs_return), "show lqs\n"); - - if (!oqaq) - OBD_FREE_PTR(oqaq_tmp); - RETURN(0); -} + if (hs == NULL) { + rc = -EBUSY; + goto out; + } -int quota_create_lqs(struct qunit_data *qdata, struct quota_adjust_qunit *oqaq, - struct lustre_quota_ctxt *qctxt, - struct lustre_qunit_size **lqs_return) -{ - struct lustre_qunit_size *lqs = NULL; - int rc = 0; - ENTRY; + /* cfs_hash_lookup will +1 refcount for caller */ + lqs = cfs_hash_lookup(qctxt->lqc_lqs_hash, &lqs_key); + if (lqs != NULL) /* found */ + goto out_put; - LASSERT(*lqs_return == NULL); - LASSERT(oqaq || qdata); + if (!create) + goto out_put; OBD_ALLOC_PTR(lqs); - if (!lqs) - GOTO(out, rc = -ENOMEM); + if (!lqs) { + rc = -ENOMEM; + goto out_put; + } - if (!oqaq) - qdata_to_oqaq(qdata, &lqs->lqs_key); - else - lqs->lqs_key = *oqaq; + lqs->lqs_key = lqs_key; + + cfs_spin_lock_init(&lqs->lqs_lock); - 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; lqs->lqs_itune_sz = qctxt->lqc_itune_sz; - lqs->lqs_ctxt = qctxt; if (qctxt->lqc_handler) { lqs->lqs_last_bshrink = 0; 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) { - lqs_getref(lqs); - *lqs_return = lqs; + + lqs->lqs_ctxt = qctxt; /* must be called before lqs_initref */ + cfs_atomic_set(&lqs->lqs_refcount, 1); /* 1 for caller */ + cfs_atomic_inc(&lqs->lqs_ctxt->lqc_lqs); + + /* lqc_lqs_hash will take +1 refcount on lqs on adding */ + lqs2 = cfs_hash_findadd_unique(qctxt->lqc_lqs_hash, + &lqs->lqs_key, &lqs->lqs_hash); + if (lqs2 == lqs) /* added to hash */ + goto out_put; + + create = 0; + lqs_putref(lqs); + lqs = lqs2; + + out_put: + cfs_hash_putref(hs); + out: + if (rc != 0) { /* error */ + CERROR("get lqs error(rc: %d)\n", rc); + return ERR_PTR(rc); } -out: - if (rc && lqs) - OBD_FREE_PTR(lqs); - RETURN(rc); + + if (lqs != NULL) { + LQS_DEBUG(lqs, "%s\n", + (create == 1 ? "create lqs" : "search lqs")); + } + return lqs; } 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); } int filter_quota_adjust_qunit(struct obd_export *exp, struct quota_adjust_qunit *oqaq, - struct lustre_quota_ctxt *qctxt) + struct lustre_quota_ctxt *qctxt, + struct ptlrpc_request_set *rqset) { 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 +267,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; } @@ -349,7 +288,8 @@ int filter_quota_adjust_qunit(struct obd_export *exp, int client_quota_adjust_qunit(struct obd_export *exp, struct quota_adjust_qunit *oqaq, - struct lustre_quota_ctxt *qctxt) + struct lustre_quota_ctxt *qctxt, + struct ptlrpc_request_set *rqset) { struct ptlrpc_request *req; struct quota_adjust_qunit *oqa; @@ -365,6 +305,8 @@ int client_quota_adjust_qunit(struct obd_export *exp, if (strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME)) RETURN(-EINVAL); + LASSERT(rqset); + req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_OST_QUOTA_ADJUST_QUNIT, LUSTRE_OST_VERSION, @@ -377,21 +319,19 @@ int client_quota_adjust_qunit(struct obd_export *exp, ptlrpc_request_set_replen(req); - rc = ptlrpc_queue_wait(req); - if (rc) - CERROR("%s: %s failed: rc = %d\n", exp->exp_obd->obd_name, - __FUNCTION__, rc); - ptlrpc_req_finished(req); + ptlrpc_set_add_req(rqset, req); RETURN (rc); } int lov_quota_adjust_qunit(struct obd_export *exp, struct quota_adjust_qunit *oqaq, - struct lustre_quota_ctxt *qctxt) + struct lustre_quota_ctxt *qctxt, + struct ptlrpc_request_set *rqset) { struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; - int i, rc = 0; + int i, err, rc = 0; + unsigned no_set = 0; ENTRY; if (!QAQ_IS_ADJBLK(oqaq)) { @@ -399,21 +339,39 @@ int lov_quota_adjust_qunit(struct obd_export *exp, RETURN(-EFAULT); } + + if (rqset == NULL) { + rqset = ptlrpc_prep_set(); + if (!rqset) + RETURN(-ENOMEM); + no_set = 1; + } + + obd_getref(obd); for (i = 0; i < lov->desc.ld_tgt_count; i++) { - int err; - if (!lov->lov_tgts[i]->ltd_active) { + if (!lov->lov_tgts[i] || !lov->lov_tgts[i]->ltd_active) { CDEBUG(D_HA, "ost %d is inactive\n", i); continue; } err = obd_quota_adjust_qunit(lov->lov_tgts[i]->ltd_exp, oqaq, - NULL); + NULL, rqset); if (err) { if (lov->lov_tgts[i]->ltd_active && !rc) rc = err; continue; } } + + err = ptlrpc_set_wait(rqset); + if (!rc) + rc = err; + + /* Destroy the set if none was provided by the caller */ + if (no_set) + ptlrpc_set_destroy(rqset); + + obd_putref(obd); RETURN(rc); }