diff --git a/lustre/quota/quota_context.c b/lustre/quota/quota_context.c index 21e3cc4f5edf1da864d5bf43a55faf6dee3e1eff..a238fabec80b07fbbc9e733f7e4c6c375c5a51f0 100644 --- a/lustre/quota/quota_context.c +++ b/lustre/quota/quota_context.c @@ -410,19 +410,6 @@ out: return ret; } -/* caller must hold qunit_hash_lock */ -static struct lustre_qunit *dqacq_in_flight(struct lustre_quota_ctxt *qctxt, - struct qunit_data *qdata) -{ - unsigned int hashent = qunit_hashfn(qctxt, qdata); - struct lustre_qunit *qunit; - ENTRY; - - LASSERT_SPIN_LOCKED(&qunit_hash_lock); - qunit = find_qunit(hashent, qctxt, qdata); - RETURN(qunit); -} - static struct lustre_qunit *alloc_qunit(struct lustre_quota_ctxt *qctxt, struct qunit_data *qdata, int opc) { @@ -461,6 +448,21 @@ static void qunit_put(struct lustre_qunit *qunit) free_qunit(qunit); } +/* caller must hold qunit_hash_lock and release ref of qunit after using it */ +static struct lustre_qunit *dqacq_in_flight(struct lustre_quota_ctxt *qctxt, + struct qunit_data *qdata) +{ + unsigned int hashent = qunit_hashfn(qctxt, qdata); + struct lustre_qunit *qunit; + ENTRY; + + LASSERT_SPIN_LOCKED(&qunit_hash_lock); + qunit = find_qunit(hashent, qctxt, qdata); + if (qunit) + qunit_get(qunit); + RETURN(qunit); +} + static void insert_qunit_nolock(struct lustre_quota_ctxt *qctxt, struct lustre_qunit *qunit) { @@ -684,6 +686,9 @@ out: QUNIT_SET_STATE_AND_RC(qunit, QUNIT_FINISHED, rc); wake_up(&qunit->lq_waitq); + /* this is for dqacq_in_flight() */ + qunit_put(qunit); + /* this is for alloc_qunit() */ qunit_put(qunit); if (rc < 0 && rc != -EDQUOT) RETURN(err); @@ -855,19 +860,16 @@ schedule_dqacq(struct obd_device *obd, struct lustre_quota_ctxt *qctxt, spin_lock(&qunit_hash_lock); qunit = dqacq_in_flight(qctxt, qdata); if (qunit) { - if (wait) - qunit_get(qunit); spin_unlock(&qunit_hash_lock); qunit_put(empty); goto wait_completion; } qunit = empty; + qunit_get(qunit); insert_qunit_nolock(qctxt, qunit); spin_unlock(&qunit_hash_lock); - LASSERT(qunit); - quota_search_lqs(qdata, NULL, qctxt, &lqs); if (lqs) { spin_lock(&lqs->lqs_lock); @@ -891,6 +893,8 @@ schedule_dqacq(struct obd_device *obd, struct lustre_quota_ctxt *qctxt, QDATA_SET_CHANGE_QS(qdata); rc = qctxt->lqc_handler(obd, qdata, opc); rc2 = dqacq_completion(obd, qctxt, qdata, rc, opc); + /* this is for qunit_get() */ + qunit_put(qunit); RETURN(rc ? rc : rc2); } @@ -908,6 +912,9 @@ schedule_dqacq(struct obd_device *obd, struct lustre_quota_ctxt *qctxt, QUNIT_SET_STATE_AND_RC(qunit, QUNIT_FINISHED, -EAGAIN); wake_up(&qunit->lq_waitq); + /* this is for qunit_get() */ + qunit_put(qunit); + /* this for alloc_qunit() */ qunit_put(qunit); spin_lock(&qctxt->lqc_lock); if (wait && !qctxt->lqc_import) { @@ -941,6 +948,8 @@ schedule_dqacq(struct obd_device *obd, struct lustre_quota_ctxt *qctxt, if (!req) { dqacq_completion(obd, qctxt, qdata, -ENOMEM, opc); class_import_put(imp); + /* this is for qunit_get() */ + qunit_put(qunit); RETURN(-ENOMEM); } @@ -957,16 +966,17 @@ schedule_dqacq(struct obd_device *obd, struct lustre_quota_ctxt *qctxt, rc = quota_copy_qdata(req, qdata, QUOTA_REQUEST, QUOTA_IMPORT); if (rc < 0) { CDEBUG(D_ERROR, "Can't pack qunit_data(rc: %d)\n", rc); + dqacq_completion(obd, qctxt, qdata, rc, opc); class_import_put(imp); + /* this is for qunit_get() */ + qunit_put(qunit); RETURN(rc); } + ptlrpc_req_set_repsize(req, 2, size); req->rq_no_resend = req->rq_no_delay = 1; class_import_put(imp); - if (wait && qunit) - qunit_get(qunit); - CLASSERT(sizeof(*aa) <= sizeof(req->rq_async_args)); aa = (struct dqacq_async_args *)&req->rq_async_args; aa->aa_ctxt = qctxt; @@ -996,8 +1006,8 @@ wait_completion: spin_unlock(&qunit->lq_lock); CDEBUG(D_QUOTA, "qunit(%p) finishes waiting. (rc:%d)\n", qunit, rc); - qunit_put(qunit); } + qunit_put(qunit); RETURN(rc); } @@ -1065,11 +1075,6 @@ qctxt_wait_pending_dqacq(struct lustre_quota_ctxt *qctxt, unsigned int id, spin_lock(&qunit_hash_lock); qunit = dqacq_in_flight(qctxt, &qdata); - if (qunit) - /* grab reference on this qunit to handle races with - * dqacq_completion(). Otherwise, this qunit could be freed just - * after we release the qunit_hash_lock */ - qunit_get(qunit); spin_unlock(&qunit_hash_lock); if (qunit) { @@ -1086,6 +1091,7 @@ qctxt_wait_pending_dqacq(struct lustre_quota_ctxt *qctxt, unsigned int id, else rc = qunit->lq_rc; spin_unlock(&qunit->lq_lock); + /* this is for dqacq_in_flight() */ qunit_put(qunit); do_gettimeofday(&work_end); timediff = cfs_timeval_sub(&work_end, &work_start, NULL);