quota_interface.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 948 行 · 第 1/3 页
C
948 行
memset(oqctl, 0, sizeof(*oqctl)); oqctl->qc_cmd = Q_GETQUOTA; oqctl->qc_type = cnt; oqctl->qc_id = (cnt == USRQUOTA) ? oa->o_uid : oa->o_gid; err = fsfilt_quotactl(obd, obt->obt_sb, oqctl); if (err) { if (!rc) rc = err; continue; } /* set over quota flags for a uid/gid */ oa->o_valid |= (cnt == USRQUOTA) ? OBD_MD_FLUSRQUOTA : OBD_MD_FLGRPQUOTA; if (oqctl->qc_dqblk.dqb_bhardlimit && (toqb(oqctl->qc_dqblk.dqb_curspace) >= oqctl->qc_dqblk.dqb_bhardlimit)) oa->o_flags |= (cnt == USRQUOTA) ? OBD_FL_NO_USRQUOTA : OBD_FL_NO_GRPQUOTA; } OBD_FREE_PTR(oqctl); RETURN(rc);}static int filter_quota_acquire(struct obd_device *obd, unsigned int uid, unsigned int gid){ struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; int rc; ENTRY; rc = qctxt_adjust_qunit(obd, qctxt, uid, gid, LQUOTA_FLAGS_BLK, 1); RETURN(rc);}/* check whether the left quota of certain uid and gid can satisfy a block_write * or inode_create rpc. When need to acquire quota, return QUOTA_RET_ACQUOTA */static int quota_check_common(struct obd_device *obd, unsigned int uid, unsigned int gid, int count, int cycle, int isblk){ struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; int i; __u32 id[MAXQUOTAS] = { uid, gid }; struct qunit_data qdata[MAXQUOTAS]; int rc = 0, rc2[2] = { 0, 0 }; ENTRY; CLASSERT(MAXQUOTAS < 4); if (!sb_any_quota_enabled(qctxt->lqc_sb)) RETURN(rc); for (i = 0; i < MAXQUOTAS; i++) { struct lustre_qunit_size *lqs = NULL; qdata[i].qd_id = id[i]; qdata[i].qd_flags = i; if (isblk) QDATA_SET_BLK(&qdata[i]); qdata[i].qd_count = 0; /* ignore root user */ if (qdata[i].qd_id == 0 && !QDATA_IS_GRP(&qdata[i])) continue; quota_search_lqs(&qdata[i], NULL, qctxt, &lqs); if (!lqs) continue; rc2[i] = compute_remquota(obd, qctxt, &qdata[i], isblk); spin_lock(&lqs->lqs_lock); if (!cycle) { rc = QUOTA_RET_INC_PENDING; if (isblk) lqs->lqs_bwrite_pending += count; else lqs->lqs_iwrite_pending += count; } CDEBUG(D_QUOTA, "write pending: %lu, qd_count: "LPU64".\n", isblk ? lqs->lqs_bwrite_pending : lqs->lqs_iwrite_pending, qdata[i].qd_count); if (rc2[i] == QUOTA_RET_OK) { if (isblk && qdata[i].qd_count < lqs->lqs_bwrite_pending * CFS_PAGE_SIZE) rc2[i] = QUOTA_RET_ACQUOTA; if (!isblk && qdata[i].qd_count < lqs->lqs_iwrite_pending) rc2[i] = QUOTA_RET_ACQUOTA; } spin_unlock(&lqs->lqs_lock); /* When cycle is zero, lqs_*_pending will be changed. We will * get reference of the lqs here and put reference of lqs in * quota_pending_commit b=14784 */ if (!cycle) lqs_getref(lqs); /* this is for quota_search_lqs */ lqs_putref(lqs); } if (rc2[0] == QUOTA_RET_ACQUOTA || rc2[1] == QUOTA_RET_ACQUOTA) RETURN(rc | QUOTA_RET_ACQUOTA); else RETURN(rc);}static int quota_chk_acq_common(struct obd_device *obd, unsigned int uid, unsigned int gid, int count, int *pending, int isblk, quota_acquire acquire){ int rc = 0, cycle = 0, count_err = 0; ENTRY; /* Unfortunately, if quota master is too busy to handle the * pre-dqacq in time and quota hash on ost is used up, we * have to wait for the completion of in flight dqacq/dqrel, * in order to get enough quota for write b=12588 */ while ((rc = quota_check_common(obd, uid, gid, count, cycle, isblk)) & QUOTA_RET_ACQUOTA) { if (rc & QUOTA_RET_INC_PENDING) *pending = 1; cycle++; if (isblk) OBD_FAIL_TIMEOUT(OBD_FAIL_OST_HOLD_WRITE_RPC, 90); /* after acquire(), we should run quota_check_common again * so that we confirm there are enough quota to finish write */ rc = acquire(obd, uid, gid); /* please reference to dqacq_completion for the below */ /* a new request is finished, try again */ if (rc == -EAGAIN) { CDEBUG(D_QUOTA, "finish a quota req, try again\n"); continue; } /* it is out of quota already */ if (rc == -EDQUOT) { CDEBUG(D_QUOTA, "out of quota, return -EDQUOT\n"); break; } /* -EBUSY and others, try 10 times */ if (rc < 0 && count_err < 10) { CDEBUG(D_QUOTA, "rc: %d, count_err: %d\n", rc, count_err++); cfs_schedule_timeout(CFS_TASK_INTERRUPTIBLE, HZ); continue; } if (count_err >= 10 || cycle >= 1000) { CDEBUG(D_ERROR, "we meet 10 errors or run too many" " cycles when acquiring quota, quit checking with" " rc: %d, cycle: %d.\n", rc, cycle); break; } CDEBUG(D_QUOTA, "recheck quota with rc: %d, cycle: %d\n", rc, cycle); } if (!cycle && rc & QUOTA_RET_INC_PENDING) *pending = 1; RETURN(rc);}static int filter_quota_check(struct obd_device *obd, unsigned int uid, unsigned int gid, int npage, int *flag, quota_acquire acquire){ return quota_chk_acq_common(obd, uid, gid, npage, flag, LQUOTA_FLAGS_BLK, acquire);}/* when a block_write or inode_create rpc is finished, adjust the record for * pending blocks and inodes*/static int quota_pending_commit(struct obd_device *obd, unsigned int uid, unsigned int gid, int count, int isblk){ struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; int i; __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++) { struct lustre_qunit_size *lqs = NULL; qdata[i].qd_id = id[i]; qdata[i].qd_flags = i; if (isblk) QDATA_SET_BLK(&qdata[i]); qdata[i].qd_count = 0; if (qdata[i].qd_id == 0 && !QDATA_IS_GRP(&qdata[i])) continue; quota_search_lqs(&qdata[i], NULL, qctxt, &lqs); if (lqs) { int flag = 0; spin_lock(&lqs->lqs_lock); CDEBUG(D_QUOTA, "pending: %lu, count: %d.\n", isblk ? lqs->lqs_bwrite_pending : lqs->lqs_iwrite_pending, count); if (isblk) { if (lqs->lqs_bwrite_pending >= count) { lqs->lqs_bwrite_pending -= count; flag = 1; } else { CDEBUG(D_ERROR, "there are too many blocks!\n"); } } else { if (lqs->lqs_iwrite_pending >= count) { lqs->lqs_iwrite_pending -= count; flag = 1; } else { CDEBUG(D_ERROR, "there are too many files!\n"); } } spin_unlock(&lqs->lqs_lock); lqs_putref(lqs); /* When lqs_*_pening is changed back, we'll putref lqs * here b=14784 */ if (flag) lqs_putref(lqs); } } RETURN(0);}static int filter_quota_pending_commit(struct obd_device *obd, unsigned int uid, unsigned int gid, int npage){ return quota_pending_commit(obd, uid, gid, npage, LQUOTA_FLAGS_BLK);}static int mds_quota_init(void){ return lustre_dquot_init();}static int mds_quota_exit(void){ lustre_dquot_exit(); return 0;}static int mds_quota_setup(struct obd_device *obd){ struct obd_device_target *obt = &obd->u.obt; struct mds_obd *mds = &obd->u.mds; int rc; ENTRY; mds->mds_quota_info.qi_version = LUSTRE_QUOTA_V2; atomic_set(&obt->obt_quotachecking, 1); /* initialize quota master and quota context */ sema_init(&mds->mds_qonoff_sem, 1); rc = qctxt_init(&obt->obt_qctxt, obt->obt_sb, dqacq_handler); if (rc) { CERROR("initialize quota context failed! (rc:%d)\n", rc); RETURN(rc); } RETURN(rc);}static int mds_quota_cleanup(struct obd_device *obd){ qctxt_cleanup(&obd->u.obt.obt_qctxt, 0); RETURN(0);}static int mds_quota_fs_cleanup(struct obd_device *obd){ struct mds_obd *mds = &obd->u.mds; int i; ENTRY; /* close admin quota files */ down(&mds->mds_qonoff_sem); for (i = 0; i < MAXQUOTAS; i++) { if (mds->mds_quota_info.qi_files[i]) { filp_close(mds->mds_quota_info.qi_files[i], 0); mds->mds_quota_info.qi_files[i] = NULL; } } up(&mds->mds_qonoff_sem); RETURN(0);}static int mds_quota_check(struct obd_device *obd, unsigned int uid, unsigned int gid, int inodes, int *flag, quota_acquire acquire){ return quota_chk_acq_common(obd, uid, gid, inodes, flag, 0, acquire);}static int mds_quota_acquire(struct obd_device *obd, unsigned int uid, unsigned int gid){ struct lustre_quota_ctxt *qctxt = &obd->u.obt.obt_qctxt; int rc;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?