quota_context.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,161 行 · 第 1/3 页
C
1,161 行
goto wait_completion; } qunit = empty; 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); quota_compute_lqs(qdata, lqs, 1, (opc == QUOTA_DQACQ) ? 1 : 0); /* when this qdata returned from mds, it will call lqs_putref */ lqs_getref(lqs); spin_unlock(&lqs->lqs_lock); /* this is for quota_search_lqs */ lqs_putref(lqs); } else { CDEBUG(D_ERROR, "Can't find the lustre qunit size!\n"); } QDATA_DEBUG(qdata, "obd(%s): send %s quota req\n", obd->obd_name, (opc == QUOTA_DQACQ) ? "acq" : "rel"); /* master is going to dqacq/dqrel from itself */ if (is_master(obd, qctxt, qdata->qd_id, QDATA_IS_GRP(qdata))) { int rc2; QDATA_DEBUG(qdata, "local %s.\n", opc == QUOTA_DQACQ ? "DQACQ" : "DQREL"); rc = qctxt->lqc_handler(obd, qdata, opc); rc2 = dqacq_completion(obd, qctxt, qdata, rc, opc); RETURN(rc ? rc : rc2); } spin_lock(&qctxt->lqc_lock); if (!qctxt->lqc_import) { spin_unlock(&qctxt->lqc_lock); QDATA_DEBUG(qdata, "lqc_import is invalid.\n"); spin_lock(&qunit_hash_lock); remove_qunit_nolock(qunit); spin_unlock(&qunit_hash_lock); compute_lqs_after_removing_qunit(qunit); QUNIT_SET_STATE_AND_RC(qunit, QUNIT_FINISHED, -EAGAIN); wake_up(&qunit->lq_waitq); qunit_put(qunit); RETURN(-EAGAIN); } imp = class_import_get(qctxt->lqc_import); spin_unlock(&qctxt->lqc_lock); /* build dqacq/dqrel request */ LASSERT(imp); size[1] = quota_get_qunit_data_size(imp-> imp_connect_data.ocd_connect_flags); req = ptlrpc_prep_req(imp, LUSTRE_MDS_VERSION, opc, 2, size, NULL); if (!req) { dqacq_completion(obd, qctxt, qdata, -ENOMEM, opc); class_import_put(imp); RETURN(-ENOMEM); } if (QDATA_IS_BLK(qdata)) factor = MAX_QUOTA_COUNT32 / qctxt->lqc_bunit_sz * qctxt->lqc_bunit_sz; else factor = MAX_QUOTA_COUNT32 / qctxt->lqc_iunit_sz * qctxt->lqc_iunit_sz; LASSERTF(!should_translate_quota(imp) || qdata->qd_count <= factor, "qd_count: "LPU64"; should_translate_quota: %d.\n", qdata->qd_count, should_translate_quota(imp)); rc = quota_copy_qdata(req, qdata, QUOTA_REQUEST, QUOTA_IMPORT); if (rc < 0) { CDEBUG(D_ERROR, "Can't pack qunit_data\n"); RETURN(-EPROTO); } ptlrpc_req_set_repsize(req, 2, size); 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; aa->aa_qunit = qunit; req->rq_interpret_reply = dqacq_interpret; ptlrpcd_add_req(req); QDATA_DEBUG(qdata, "%s scheduled.\n", opc == QUOTA_DQACQ ? "DQACQ" : "DQREL");wait_completion: if (wait && qunit) { struct qunit_data *p = &qunit->lq_data; QDATA_DEBUG(p, "qunit(%p) is waiting for dqacq.\n", qunit); l_wait_event(qunit->lq_waitq, got_qunit(qunit), &lwi); /* rc = -EAGAIN, it means a quota req is finished; * rc = -EDQUOT, it means out of quota * rc = -EBUSY, it means recovery is happening * other rc < 0, it means real errors, functions who call * schedule_dqacq should take care of this */ spin_lock(&qunit->lq_lock); if (qunit->lq_rc == 0) rc = -EAGAIN; else rc = qunit->lq_rc; spin_unlock(&qunit->lq_lock); CDEBUG(D_QUOTA, "qunit(%p) finishes waiting. (rc:%d)\n", qunit, rc); qunit_put(qunit); } RETURN(rc);}intqctxt_adjust_qunit(struct obd_device *obd, struct lustre_quota_ctxt *qctxt, uid_t uid, gid_t gid, __u32 isblk, int wait){ int ret, rc = 0, i = USRQUOTA; __u32 id[MAXQUOTAS] = { uid, gid }; struct qunit_data qdata[MAXQUOTAS]; ENTRY; CLASSERT(MAXQUOTAS < 4); if (!sb_any_quota_enabled(qctxt->lqc_sb)) RETURN(0); for (i = 0; i < MAXQUOTAS; i++) { qdata[i].qd_id = id[i]; qdata[i].qd_flags = i; if (isblk) QDATA_SET_BLK(&qdata[i]); qdata[i].qd_count = 0; ret = check_cur_qunit(obd, qctxt, &qdata[i]); if (ret > 0) { int opc; /* need acquire or release */ opc = ret == 1 ? QUOTA_DQACQ : QUOTA_DQREL; ret = split_before_schedule_dqacq(obd, qctxt, &qdata[i], opc, wait); if (!rc) rc = ret; } else if (wait == 1) { /* when wait equates 1, that means mds_quota_acquire * or filter_quota_acquire is calling it. */ qctxt_wait_pending_dqacq(qctxt, id[i], i, isblk); } } RETURN(rc);}intqctxt_wait_pending_dqacq(struct lustre_quota_ctxt *qctxt, unsigned int id, unsigned short type, int isblk){ struct lustre_qunit *qunit = NULL; struct qunit_data qdata; struct l_wait_info lwi = { 0 }; ENTRY; qdata.qd_id = id; qdata.qd_flags = type; if (isblk) QDATA_SET_BLK(&qdata); qdata.qd_count = 0; 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) { struct qunit_data *p = &qunit->lq_data; QDATA_DEBUG(p, "qunit(%p) is waiting for dqacq.\n", qunit); l_wait_event(qunit->lq_waitq, got_qunit(qunit), &lwi); CDEBUG(D_QUOTA, "qunit(%p) finishes waiting. (rc:%d)\n", qunit, qunit->lq_rc); qunit_put(qunit); } RETURN(0);}intqctxt_init(struct lustre_quota_ctxt *qctxt, struct super_block *sb, dqacq_handler_t handler){ int rc = 0; ENTRY; LASSERT(qctxt); rc = ptlrpcd_addref(); if (rc) RETURN(rc); spin_lock_init(&qctxt->lqc_lock); spin_lock(&qctxt->lqc_lock); qctxt->lqc_handler = handler; qctxt->lqc_sb = sb; qctxt->lqc_import = NULL; qctxt->lqc_recovery = 0; qctxt->lqc_switch_qs = 1; /* Change qunit size in default setting */ qctxt->lqc_cqs_boundary_factor = 4; qctxt->lqc_cqs_least_bunit = PTLRPC_MAX_BRW_SIZE; qctxt->lqc_cqs_least_iunit = 1; qctxt->lqc_cqs_qs_factor = 2; qctxt->lqc_atype = 0; qctxt->lqc_status= 0; qctxt->lqc_bunit_sz = default_bunit_sz; qctxt->lqc_btune_sz = default_bunit_sz / 100 * default_btune_ratio; qctxt->lqc_iunit_sz = default_iunit_sz; qctxt->lqc_itune_sz = default_iunit_sz * default_itune_ratio / 100; qctxt->lqc_switch_seconds = 300; /* enlarging will wait 5 minutes * after the last shrinking */ rc = lustre_hash_init(&LQC_HASH_BODY(qctxt), "LQS_HASH",128, &lqs_hash_operations); if (rc) { CDEBUG(D_ERROR, "initialize hash lqs on ost error!\n"); lustre_hash_exit(&LQC_HASH_BODY(qctxt)); } spin_unlock(&qctxt->lqc_lock); RETURN(rc);}void qctxt_cleanup(struct lustre_quota_ctxt *qctxt, int force){ struct lustre_qunit *qunit, *tmp; struct list_head tmp_list; int i; ENTRY; INIT_LIST_HEAD(&tmp_list); spin_lock(&qunit_hash_lock); for (i = 0; i < NR_DQHASH; i++) { list_for_each_entry_safe(qunit, tmp, &qunit_hash[i], lq_hash) { if (qunit->lq_ctxt != qctxt) continue; remove_qunit_nolock(qunit); list_add(&qunit->lq_hash, &tmp_list); } } spin_unlock(&qunit_hash_lock); list_for_each_entry_safe(qunit, tmp, &tmp_list, lq_hash) { list_del_init(&qunit->lq_hash); compute_lqs_after_removing_qunit(qunit); /* wake up all waiters */ QUNIT_SET_STATE_AND_RC(qunit, QUNIT_FINISHED, 0); wake_up(&qunit->lq_waitq); qunit_put(qunit); } lustre_hash_exit(&LQC_HASH_BODY(qctxt)); ptlrpcd_decref(); EXIT;}struct qslave_recov_thread_data { struct obd_device *obd; struct lustre_quota_ctxt *qctxt; struct completion comp;};/* FIXME only recovery block quota by now */static int qslave_recovery_main(void *arg){ struct qslave_recov_thread_data *data = arg; struct obd_device *obd = data->obd; struct lustre_quota_ctxt *qctxt = data->qctxt; unsigned int type; int rc = 0; ENTRY; ptlrpc_daemonize("qslave_recovd"); complete(&data->comp); if (qctxt->lqc_recovery) RETURN(0); qctxt->lqc_recovery = 1; for (type = USRQUOTA; type < MAXQUOTAS; type++) { struct qunit_data qdata; struct quota_info *dqopt = sb_dqopt(qctxt->lqc_sb); struct list_head id_list; struct dquot_id *dqid, *tmp; int ret; LOCK_DQONOFF_MUTEX(dqopt); if (!sb_has_quota_enabled(qctxt->lqc_sb, type)) { UNLOCK_DQONOFF_MUTEX(dqopt); break; } LASSERT(dqopt->files[type] != NULL); INIT_LIST_HEAD(&id_list);#ifndef KERNEL_SUPPORTS_QUOTA_READ rc = fsfilt_qids(obd, dqopt->files[type], NULL, type, &id_list);#else rc = fsfilt_qids(obd, NULL, dqopt->files[type], type, &id_list);#endif UNLOCK_DQONOFF_MUTEX(dqopt); if (rc) CERROR("Get ids from quota file failed. (rc:%d)\n", rc); list_for_each_entry_safe(dqid, tmp, &id_list, di_link) { list_del_init(&dqid->di_link); /* skip slave recovery on itself */ if (is_master(obd, qctxt, dqid->di_id, type)) goto free; if (rc && rc != -EBUSY) goto free; qdata.qd_id = dqid->di_id; qdata.qd_flags = type; QDATA_SET_BLK(&qdata); qdata.qd_count = 0; ret = check_cur_qunit(obd, qctxt, &qdata); if (ret > 0) { int opc; opc = ret == 1 ? QUOTA_DQACQ : QUOTA_DQREL; rc = split_before_schedule_dqacq(obd, qctxt, &qdata, opc, 0); if (rc == -EDQUOT) rc = 0; } else { rc = 0; } if (rc) CDEBUG(rc == -EBUSY ? D_QUOTA : D_ERROR, "qslave recovery failed! (id:%d type:%d " " rc:%d)\n", dqid->di_id, type, rc);free: kfree(dqid); } } qctxt->lqc_recovery = 0; RETURN(rc);}voidqslave_start_recovery(struct obd_device *obd, struct lustre_quota_ctxt *qctxt){ struct qslave_recov_thread_data data; int rc; ENTRY; if (!sb_any_quota_enabled(qctxt->lqc_sb)) goto exit; data.obd = obd; data.qctxt = qctxt; init_completion(&data.comp); rc = kernel_thread(qslave_recovery_main, &data, CLONE_VM|CLONE_FILES); if (rc < 0) { CERROR("Cannot start quota recovery thread: rc %d\n", rc); goto exit; } wait_for_completion(&data.comp);exit: EXIT;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?