+static void init_oqaq(struct quota_adjust_qunit *oqaq,
+ struct lustre_quota_ctxt *qctxt,
+ qid_t id, int type)
+{
+ struct lustre_qunit_size *lqs = NULL;
+
+ oqaq->qaq_id = id;
+ oqaq->qaq_flags = type;
+ lqs = quota_search_lqs(LQS_KEY(type, id), qctxt, 0);
+ if (lqs && !IS_ERR(lqs)) {
+ spin_lock(&lqs->lqs_lock);
+ oqaq->qaq_bunit_sz = lqs->lqs_bunit_sz;
+ oqaq->qaq_iunit_sz = lqs->lqs_iunit_sz;
+ oqaq->qaq_flags = lqs->lqs_flags;
+ spin_unlock(&lqs->lqs_lock);
+ lqs_putref(lqs);
+ } else {
+ CDEBUG(D_QUOTA, "Can't find the lustre qunit size!\n");
+ oqaq->qaq_bunit_sz = qctxt->lqc_bunit_sz;
+ oqaq->qaq_iunit_sz = qctxt->lqc_iunit_sz;
+ }
+}
+
+int dqacq_adjust_qunit_sz(struct obd_device *obd, qid_t id, int type,
+ __u32 is_blk)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct lustre_quota_ctxt *qctxt = &mds->mds_obt.obt_qctxt;
+ __u32 ost_num = mds->mds_lov_objid_count, mdt_num = 1;
+ struct quota_adjust_qunit *oqaq = NULL;
+ unsigned int qid[MAXQUOTAS] = { 0, 0 };
+ struct lustre_quota_info *info = &mds->mds_quota_info;
+ struct lustre_dquot *dquot = NULL;
+ int adjust_res = 0;
+ int rc = 0;
+ ENTRY;
+
+ LASSERT(mds);
+ dquot = lustre_dqget(obd, info, id, type);
+ if (IS_ERR(dquot))
+ RETURN(PTR_ERR(dquot));
+
+ OBD_ALLOC_PTR(oqaq);
+ if (!oqaq)
+ GOTO(out, rc = -ENOMEM);
+
+ down(&dquot->dq_sem);
+ init_oqaq(oqaq, qctxt, id, type);
+
+ rc = dquot_create_oqaq(qctxt, dquot, ost_num, mdt_num,
+ is_blk ? LQUOTA_FLAGS_ADJBLK :
+ LQUOTA_FLAGS_ADJINO, oqaq);
+
+ if (rc < 0) {
+ CERROR("create oqaq failed! (rc:%d)\n", rc);
+ GOTO(out_sem, rc);
+ }
+ QAQ_DEBUG(oqaq, "show oqaq.\n")
+
+ if (!QAQ_IS_ADJBLK(oqaq) && !QAQ_IS_ADJINO(oqaq))
+ GOTO(out_sem, rc);
+
+ /* adjust the mds slave qunit size */
+ adjust_res = quota_adjust_slave_lqs(oqaq, qctxt);
+ if (adjust_res <= 0) {
+ if (adjust_res < 0) {
+ rc = adjust_res;
+ CERROR("adjust mds slave's qunit size failed! "
+ "(rc:%d)\n", rc);
+ } else {
+ CDEBUG(D_QUOTA, "qunit doesn't need to be adjusted.\n");
+ }
+ GOTO(out_sem, rc);
+ }
+
+ if (type)
+ qid[GRPQUOTA] = dquot->dq_id;
+ else
+ qid[USRQUOTA] = dquot->dq_id;
+
+ up(&dquot->dq_sem);
+
+ rc = qctxt_adjust_qunit(obd, qctxt, qid, is_blk, 0, NULL);
+ if (rc == -EDQUOT || rc == -EBUSY) {
+ CDEBUG(D_QUOTA, "rc: %d.\n", rc);
+ rc = 0;
+ }
+ if (rc) {
+ CERROR("%s: mds fail to adjust file quota! (rc:%d)\n",
+ obd->obd_name, rc);
+ GOTO(out, rc);
+ }
+
+ /* only when block qunit is reduced, boardcast to osts */
+ if ((adjust_res & LQS_BLK_DECREASE) && QAQ_IS_ADJBLK(oqaq))
+ rc = obd_quota_adjust_qunit(mds->mds_osc_exp, oqaq, qctxt);
+
+out:
+ lustre_dqput(dquot);
+ if (oqaq)
+ OBD_FREE_PTR(oqaq);
+
+ RETURN(rc);
+out_sem:
+ up(&dquot->dq_sem);
+ goto out;
+}
+