quota_master.c

来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,592 行 · 第 1/4 页

C
1,592
字号
        struct quota_adjust_qunit *oqaq = NULL;        struct lustre_quota_info *qinfo = &mds->mds_quota_info;        __u64 ihardlimit, isoftlimit, bhardlimit, bsoftlimit;        time_t btime, itime;        struct lustre_dquot *dquot;        struct obd_dqblk *dqblk = &oqctl->qc_dqblk;        int set, rc, rc2 = 0, flag = 0;        ENTRY;        OBD_ALLOC_PTR(oqaq);        if (!oqaq)                RETURN(-ENOMEM);        down(&mds->mds_qonoff_sem);        init_oqaq(oqaq, qctxt, oqctl->qc_id, oqctl->qc_type);        if (qinfo->qi_files[oqctl->qc_type] == NULL)                GOTO(out_sem, rc = -ESRCH);        dquot = lustre_dqget(obd, qinfo, oqctl->qc_id, oqctl->qc_type);        if (IS_ERR(dquot))                GOTO(out_sem, rc = PTR_ERR(dquot));        DQUOT_DEBUG(dquot, "get dquot in mds_set_blk\n");        QINFO_DEBUG(dquot->dq_info, "get dquot in mds_set_blk\n");        down(&dquot->dq_sem);        if (dquot->dq_status) {                up(&dquot->dq_sem);                lustre_dqput(dquot);                GOTO(out_sem, rc = -EBUSY);        }        dquot->dq_status |= DQ_STATUS_SET;        ihardlimit = dquot->dq_dqb.dqb_ihardlimit;        isoftlimit = dquot->dq_dqb.dqb_isoftlimit;        bhardlimit = dquot->dq_dqb.dqb_bhardlimit;        bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;        btime = dquot->dq_dqb.dqb_btime;        itime = dquot->dq_dqb.dqb_itime;        if (dqblk->dqb_valid & QIF_BTIME)                dquot->dq_dqb.dqb_btime = dqblk->dqb_btime;        if (dqblk->dqb_valid & QIF_ITIME)                dquot->dq_dqb.dqb_itime = dqblk->dqb_itime;        if (dqblk->dqb_valid & QIF_BLIMITS) {                dquot->dq_dqb.dqb_bhardlimit = dqblk->dqb_bhardlimit;                dquot->dq_dqb.dqb_bsoftlimit = dqblk->dqb_bsoftlimit;                /* clear usage (limit pool) */                if (!dquot->dq_dqb.dqb_bhardlimit &&                    !dquot->dq_dqb.dqb_bsoftlimit)                        dquot->dq_dqb.dqb_curspace = 0;                /* clear grace time */                if (!dqblk->dqb_bsoftlimit ||                    toqb(dquot->dq_dqb.dqb_curspace) <= dqblk->dqb_bsoftlimit)                        dquot->dq_dqb.dqb_btime = 0;                /* set grace only if user hasn't provided his own */                else if (!(dqblk->dqb_valid & QIF_BTIME))                        dquot->dq_dqb.dqb_btime = cfs_time_current_sec() +                                qinfo->qi_info[dquot->dq_type].dqi_bgrace;                flag |= LQUOTA_FLAGS_ADJBLK;        }        if (dqblk->dqb_valid & QIF_ILIMITS) {                dquot->dq_dqb.dqb_ihardlimit = dqblk->dqb_ihardlimit;                dquot->dq_dqb.dqb_isoftlimit = dqblk->dqb_isoftlimit;                /* clear usage (limit pool) */                if (!dquot->dq_dqb.dqb_ihardlimit &&                    !dquot->dq_dqb.dqb_isoftlimit)                        dquot->dq_dqb.dqb_curinodes = 0;                if (!dqblk->dqb_isoftlimit ||                    dquot->dq_dqb.dqb_curinodes <= dqblk->dqb_isoftlimit)                        dquot->dq_dqb.dqb_itime = 0;                else if (!(dqblk->dqb_valid & QIF_ITIME))                        dquot->dq_dqb.dqb_itime = cfs_time_current_sec() +                                qinfo->qi_info[dquot->dq_type].dqi_igrace;                flag |= LQUOTA_FLAGS_ADJINO;        }        QAQ_DEBUG(oqaq, "before dquot_create_oqaq\n");        rc = dquot_create_oqaq(qctxt, dquot, lov->desc.ld_tgt_count, 1,                               flag, oqaq);        QAQ_DEBUG(oqaq, "after dquot_create_oqaq\n");        if (rc < 0)                CDEBUG(D_QUOTA, "adjust qunit size failed! (rc:%d)\n", rc);        rc = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);        up(&dquot->dq_sem);        if (rc) {                CERROR("set limit failed! (rc:%d)\n", rc);                goto out;        }        up(&mds->mds_qonoff_sem);        if (dqblk->dqb_valid & QIF_ILIMITS) {                set = !(ihardlimit || isoftlimit);                down(&dquot->dq_sem);                dquot->dq_dqb.dqb_curinodes = 0;                up(&dquot->dq_sem);                rc = mds_init_slave_ilimits(obd, oqctl, set, oqaq);                if (rc) {                        CERROR("init slave ilimits failed! (rc:%d)\n", rc);                        goto revoke_out;                }        }        if (dqblk->dqb_valid & QIF_BLIMITS) {                set = !(bhardlimit || bsoftlimit);                down(&dquot->dq_sem);                dquot->dq_dqb.dqb_curspace = 0;                up(&dquot->dq_sem);                rc = mds_init_slave_blimits(obd, oqctl, set, oqaq);                if (rc) {                        CERROR("init slave blimits failed! (rc:%d)\n", rc);                        goto revoke_out;                }        }revoke_out:        down(&mds->mds_qonoff_sem);        down(&dquot->dq_sem);        if (rc) {                /* cancel previous setting */                dquot->dq_dqb.dqb_ihardlimit = ihardlimit;                dquot->dq_dqb.dqb_isoftlimit = isoftlimit;                dquot->dq_dqb.dqb_bhardlimit = bhardlimit;                dquot->dq_dqb.dqb_bsoftlimit = bsoftlimit;                dquot->dq_dqb.dqb_btime = btime;                dquot->dq_dqb.dqb_itime = itime;        }        rc2 = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);        up(&dquot->dq_sem);out:        down(&dquot->dq_sem);        dquot->dq_status &= ~DQ_STATUS_SET;        up(&dquot->dq_sem);        lustre_dqput(dquot);        EXIT;out_sem:        up(&mds->mds_qonoff_sem);        if (oqaq)                OBD_FREE_PTR(oqaq);        return rc ? rc : rc2;}static int mds_get_space(struct obd_device *obd, struct obd_quotactl *oqctl){        struct obd_quotactl *soqc;        struct lvfs_run_ctxt saved;        int rc, rc1;        ENTRY;        OBD_ALLOC_PTR(soqc);        if (!soqc)                RETURN(-ENOMEM);        soqc->qc_cmd = Q_GETOQUOTA;        soqc->qc_id = oqctl->qc_id;        soqc->qc_type = oqctl->qc_type;        rc = obd_quotactl(obd->u.mds.mds_osc_exp, soqc);        oqctl->qc_dqblk.dqb_curspace = soqc->qc_dqblk.dqb_curspace;        push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);        soqc->qc_dqblk.dqb_curspace = 0;        rc1 = fsfilt_quotactl(obd, obd->u.obt.obt_sb, soqc);        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);        oqctl->qc_dqblk.dqb_curinodes += soqc->qc_dqblk.dqb_curinodes;        if (!rc1)                oqctl->qc_dqblk.dqb_valid |= QIF_INODES;        oqctl->qc_dqblk.dqb_curspace += soqc->qc_dqblk.dqb_curspace;        if (!rc && !rc1)                oqctl->qc_dqblk.dqb_valid |= QIF_USAGE;        OBD_FREE_PTR(soqc);        if (!rc)                rc = rc1;        RETURN(rc);}int mds_get_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl){        struct mds_obd *mds = &obd->u.mds;        struct lustre_quota_info *qinfo = &mds->mds_quota_info;        struct lustre_dquot *dquot;        struct obd_dqblk *dqblk = &oqctl->qc_dqblk;        int rc;        ENTRY;        down(&mds->mds_qonoff_sem);        dqblk->dqb_valid = 0;        if (qinfo->qi_files[oqctl->qc_type] == NULL)                GOTO(out, rc = -ESRCH);        dquot = lustre_dqget(obd, qinfo, oqctl->qc_id, oqctl->qc_type);        if (IS_ERR(dquot))                GOTO(out, rc = PTR_ERR(dquot));        down(&dquot->dq_sem);        dqblk->dqb_ihardlimit = dquot->dq_dqb.dqb_ihardlimit;        dqblk->dqb_isoftlimit = dquot->dq_dqb.dqb_isoftlimit;        dqblk->dqb_bhardlimit = dquot->dq_dqb.dqb_bhardlimit;        dqblk->dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;        dqblk->dqb_btime = dquot->dq_dqb.dqb_btime;        dqblk->dqb_itime = dquot->dq_dqb.dqb_itime;        dqblk->dqb_valid |= QIF_LIMITS | QIF_TIMES;        up(&dquot->dq_sem);        lustre_dqput(dquot);        /* the usages in admin quota file is inaccurate */        dqblk->dqb_curinodes = 0;        dqblk->dqb_curspace = 0;        rc = mds_get_space(obd, oqctl);        EXIT;out:        up(&mds->mds_qonoff_sem);        return rc;}int mds_get_obd_quota(struct obd_device *obd, struct obd_quotactl *oqctl){        struct lvfs_run_ctxt saved;        int rc;        ENTRY;        push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);        rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, oqctl);        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);        RETURN(rc);}/* FIXME we only recovery block limit by now, need recovery inode * limits also after CMD involved in */static int dquot_recovery(struct obd_device *obd, unsigned int id, unsigned short type){        struct mds_obd *mds = &obd->u.mds;        struct lustre_quota_info *qinfo= &obd->u.mds.mds_quota_info;        struct lustre_dquot *dquot;        struct obd_quotactl *qctl;        __u64 total_limits = 0;        int rc;        ENTRY;        OBD_ALLOC_PTR(qctl);        if (qctl == NULL)                RETURN(-ENOMEM);        dquot = lustre_dqget(obd, qinfo, id, type);        if (IS_ERR(dquot)) {                CERROR("Get dquot failed. (rc:%ld)\n", PTR_ERR(dquot));                OBD_FREE_PTR(qctl);                RETURN(PTR_ERR(dquot));        }        down(&dquot->dq_sem);        /* don't recovery the dquot without limits or under setting */        if (!(dquot->dq_dqb.dqb_bhardlimit || dquot->dq_dqb.dqb_bsoftlimit) ||            dquot->dq_status)                GOTO(skip, rc = 0);        dquot->dq_status |= DQ_STATUS_RECOVERY;        up(&dquot->dq_sem);        /* get real bhardlimit from all slaves. */        qctl->qc_cmd = Q_GETOQUOTA;        qctl->qc_type = type;        qctl->qc_id = id;        qctl->qc_stat = QUOTA_RECOVERING;        rc = obd_quotactl(obd->u.mds.mds_osc_exp, qctl);        if (rc)                GOTO(out, rc);        total_limits = qctl->qc_dqblk.dqb_bhardlimit;        /* get real bhardlimit from master */        rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, qctl);        if (rc)                GOTO(out, rc);        total_limits += qctl->qc_dqblk.dqb_bhardlimit;        /* amend the usage of the administrative quotafile */        down(&mds->mds_qonoff_sem);        down(&dquot->dq_sem);        dquot->dq_dqb.dqb_curspace = total_limits << QUOTABLOCK_BITS;        rc = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);        if (rc)                CERROR("write dquot failed! (rc:%d)\n", rc);        up(&dquot->dq_sem);        up(&mds->mds_qonoff_sem);        EXIT;out:        down(&dquot->dq_sem);        dquot->dq_status &= ~DQ_STATUS_RECOVERY;skip:        up(&dquot->dq_sem);        lustre_dqput(dquot);        OBD_FREE_PTR(qctl);        return rc;}struct qmaster_recov_thread_data {        struct obd_device *obd;        struct completion comp;};static int qmaster_recovery_main(void *arg){        struct qmaster_recov_thread_data *data = arg;        struct obd_device *obd = data->obd;        int rc = 0;        unsigned short type;        ENTRY;        ptlrpc_daemonize("qmaster_recovd");        complete(&data->comp);        for (type = USRQUOTA; type < MAXQUOTAS; type++) {                struct mds_obd *mds = &obd->u.mds;                struct lustre_quota_info *qinfo = &mds->mds_quota_info;                struct list_head id_list;                struct dquot_id *dqid, *tmp;                down(&mds->mds_qonoff_sem);                if (qinfo->qi_files[type] == NULL) {                        up(&mds->mds_qonoff_sem);                        continue;                }                INIT_LIST_HEAD(&id_list);                rc = fsfilt_qids(obd, qinfo->qi_files[type], NULL, type,                                 &id_list);                up(&mds->mds_qonoff_sem);                if (rc)                        CERROR("error get ids from admin quotafile.(%d)\n", rc);                list_for_each_entry_safe(dqid, tmp, &id_list, di_link) {                        list_del_init(&dqid->di_link);                        if (rc)                                goto free;                        rc = dquot_recovery(obd, dqid->di_id, type);                        if (rc)                                CERROR("qmaster recovery failed! (id:%d type:%d"                                       " rc:%d)\n", dqid->di_id, type, rc);free:                        kfree(dqid);                }        }        RETURN(rc);}int mds_quota_recovery(struct obd_device *obd){        struct lov_obd *lov = &obd->u.mds.mds_osc_obd->u.lov;        struct qmaster_recov_thread_data data;        int rc = 0;        ENTRY;        mutex_down(&lov->lov_lock);        if (lov->desc.ld_tgt_count != lov->desc.ld_active_tgt_count) {                CWARN("Not all osts are active, abort quota recovery\n");                mutex_up(&lov->lov_lock);                RETURN(rc);        }        mutex_up(&lov->lov_lock);        data.obd = obd;        init_completion(&data.comp);        rc = kernel_thread(qmaster_recovery_main, &data, CLONE_VM|CLONE_FILES);        if (rc < 0)                CERROR("Cannot start quota recovery thread: rc %d\n", rc);        wait_for_completion(&data.comp);        RETURN(rc);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?