X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fquota%2Fquota_adjust_qunit.c;h=4659f21d746761279fa06af8081a0e989d8ed691;hb=f5fb215365791507ec98796ea624abeafa31901c;hp=a3ef7ef467986888cc14bf49fcf90064fe19362d;hpb=222305972a5d38b0fe111966da775e98a0ec8269;p=fs%2Flustre-release.git diff --git a/lustre/quota/quota_adjust_qunit.c b/lustre/quota/quota_adjust_qunit.c index a3ef7ef..4659f21 100644 --- a/lustre/quota/quota_adjust_qunit.c +++ b/lustre/quota/quota_adjust_qunit.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -26,16 +24,16 @@ * 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. + * + * Copyright (c) 2012, Whamcloud, Inc. */ /* * This file is part of Lustre, http://www.lustre.org/ * Lustre is a trademark of Sun Microsystems, Inc. */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif + #define DEBUG_SUBSYSTEM S_LQUOTA #ifdef __KERNEL__ @@ -45,7 +43,6 @@ # include # include # include -# include # include # include # include @@ -60,11 +57,8 @@ #include #include #include -#include #include "quota_internal.h" -#ifdef HAVE_QUOTA_SUPPORT - #ifdef __KERNEL__ /** * This function is charge of recording lqs_ino_rec and @@ -91,19 +85,45 @@ void quota_compute_lqs(struct qunit_data *qdata, struct lustre_qunit_size *lqs, } -static struct lustre_qunit_size * -quota_create_lqs(unsigned long long lqs_key, struct lustre_quota_ctxt *qctxt) +struct lustre_qunit_size *quota_search_lqs(unsigned long long lqs_key, + struct lustre_quota_ctxt *qctxt, + int create) { - struct lustre_qunit_size *lqs = NULL; + struct lustre_qunit_size *lqs; + struct lustre_qunit_size *lqs2; + cfs_hash_t *hs = NULL; int rc = 0; + 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); + + if (hs == NULL) { + rc = -EBUSY; + goto out; + } + + /* 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; + + if (!create) + goto out_put; + OBD_ALLOC_PTR(lqs); - if (!lqs) - GOTO(out, rc = -ENOMEM); + if (!lqs) { + rc = -ENOMEM; + goto out_put; + } 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; @@ -114,160 +134,120 @@ quota_create_lqs(unsigned long long lqs_key, struct lustre_quota_ctxt *qctxt) 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); - if (!rc) - lqs_getref(lqs); - out: - if (rc && lqs) - OBD_FREE_PTR(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); - if (rc) - return ERR_PTR(rc); - else - return 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; -struct lustre_qunit_size *quota_search_lqs(unsigned long long lqs_key, - struct lustre_quota_ctxt *qctxt, - int create) -{ - int rc = 0; - struct lustre_qunit_size *lqs; + create = 0; + lqs_putref(lqs); + lqs = lqs2; - search_lqs: - lqs = lustre_hash_lookup(qctxt->lqc_lqs_hash, &lqs_key); - if (lqs == NULL && create) { - lqs = quota_create_lqs(lqs_key, qctxt); - if (IS_ERR(lqs)) - rc = PTR_ERR(lqs); - if (rc == -EALREADY) { - rc = 0; - goto search_lqs; - } + out_put: + cfs_hash_putref(hs); + out: + if (rc != 0) { /* error */ + CERROR("get lqs error(rc: %d)\n", rc); + return ERR_PTR(rc); } - if (lqs) + if (lqs != NULL) { LQS_DEBUG(lqs, "%s\n", (create == 1 ? "create lqs" : "search lqs")); - - if (rc == 0) { - return lqs; - } else { - CDEBUG(D_ERROR, "get lqs error(rc: %d)\n", rc); - return ERR_PTR(rc); } + 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); lqs = quota_search_lqs(LQS_KEY(QAQ_IS_GRP(oqaq), oqaq->qaq_id), - qctxt, 1); - if (lqs == NULL || IS_ERR(lqs)) + 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)); - - /* 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)) { - LQS_DEBUG(lqs, "release lqs\n"); - /* this is for quota_search_lqs */ - lqs_putref(lqs); - /* kill lqs */ - lqs_putref(lqs); - RETURN(rc); } - 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; + 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; + + 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 id[MAXQUOTAS] = { 0, 0 }; @@ -299,75 +279,3 @@ int filter_quota_adjust_qunit(struct obd_export *exp, RETURN(rc); } #endif /* __KERNEL__ */ -#endif - -int client_quota_adjust_qunit(struct obd_export *exp, - struct quota_adjust_qunit *oqaq, - struct lustre_quota_ctxt *qctxt) -{ - struct ptlrpc_request *req; - struct quota_adjust_qunit *oqa; - int rc = 0; - ENTRY; - - /* client don't support this kind of operation, abort it */ - if (!(exp->exp_connect_flags & OBD_CONNECT_CHANGE_QS)) { - CDEBUG(D_QUOTA, "osc: %s don't support change qunit size\n", - exp->exp_obd->obd_name); - RETURN(rc); - } - if (strcmp(exp->exp_obd->obd_type->typ_name, LUSTRE_OSC_NAME)) - RETURN(-EINVAL); - - req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), - &RQF_OST_QUOTA_ADJUST_QUNIT, - LUSTRE_OST_VERSION, - OST_QUOTA_ADJUST_QUNIT); - if (req == NULL) - RETURN(-ENOMEM); - - oqa = req_capsule_client_get(&req->rq_pill, &RMF_QUOTA_ADJUST_QUNIT); - *oqa = *oqaq; - - 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); - RETURN (rc); -} - -int lov_quota_adjust_qunit(struct obd_export *exp, - struct quota_adjust_qunit *oqaq, - struct lustre_quota_ctxt *qctxt) -{ - struct obd_device *obd = class_exp2obd(exp); - struct lov_obd *lov = &obd->u.lov; - int i, rc = 0; - ENTRY; - - if (!QAQ_IS_ADJBLK(oqaq)) { - CERROR("bad qaq_flags %x for lov obd.\n", oqaq->qaq_flags); - RETURN(-EFAULT); - } - - for (i = 0; i < lov->desc.ld_tgt_count; i++) { - int err; - - if (!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); - if (err) { - if (lov->lov_tgts[i]->ltd_active && !rc) - rc = err; - continue; - } - } - RETURN(rc); -}