1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * lustre/mds/quota_master.c
5 * Lustre Quota Master request handler
7 * Copyright (c) 2001-2003 Cluster File Systems, Inc.
8 * Author: Niu YaWei <niu@clusterfs.com>
10 * This file is part of Lustre, http://www.lustre.org.
12 * No redistribution or use is permitted outside of Cluster File Systems, Inc.
16 # define EXPORT_SYMTAB
19 #define DEBUG_SUBSYSTEM S_MDS
21 #include <linux/version.h>
23 #include <asm/unistd.h>
24 #include <linux/slab.h>
25 #include <linux/quotaops.h>
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/quota.h>
30 #include <linux/obd_class.h>
31 #include <linux/lustre_quota.h>
32 #include <linux/lustre_fsfilt.h>
33 #include <linux/lustre_mds.h>
35 #include "mds_internal.h"
37 static struct list_head lustre_dquot_hash[NR_DQHASH];
38 static spinlock_t dquot_hash_lock = SPIN_LOCK_UNLOCKED;
40 kmem_cache_t *lustre_dquot_cachep;
42 int lustre_dquot_init(void)
47 LASSERT(lustre_dquot_cachep == NULL);
48 lustre_dquot_cachep = kmem_cache_create("lustre_dquot_cache",
49 sizeof(struct lustre_dquot),
51 if (!lustre_dquot_cachep)
54 for (i = 0; i < NR_DQHASH; i++) {
55 INIT_LIST_HEAD(lustre_dquot_hash + i);
60 void lustre_dquot_exit(void)
64 /* FIXME cleanup work ?? */
66 for (i = 0; i < NR_DQHASH; i++) {
67 LASSERT(list_empty(lustre_dquot_hash + i));
69 if (lustre_dquot_cachep) {
70 LASSERTF(kmem_cache_destroy(lustre_dquot_cachep) == 0,
71 "Cannot destroy lustre_dquot_cache\n");
72 lustre_dquot_cachep = NULL;
77 static inline int const dquot_hashfn(struct lustre_quota_info *info,
78 unsigned int id, int type)
80 unsigned long tmp = ((unsigned long)info >> L1_CACHE_SHIFT) ^ id;
81 tmp = (tmp * (MAXQUOTAS - type)) % NR_DQHASH;
85 static struct lustre_dquot *find_dquot(int hashent,
86 struct lustre_quota_info *lqi, qid_t id,
89 struct list_head *head;
90 struct lustre_dquot *dquot;
93 for (head = lustre_dquot_hash[hashent].next;
94 head != lustre_dquot_hash + hashent; head = head->next) {
95 dquot = list_entry(head, struct lustre_dquot, dq_hash);
96 if (dquot->dq_info == lqi &&
97 dquot->dq_id == id && dquot->dq_type == type)
103 static struct lustre_dquot *alloc_dquot(struct lustre_quota_info *lqi,
106 struct lustre_dquot *dquot = NULL;
109 OBD_SLAB_ALLOC(dquot, lustre_dquot_cachep, SLAB_NOFS, sizeof(*dquot));
113 INIT_LIST_HEAD(&dquot->dq_hash);
114 INIT_LIST_HEAD(&dquot->dq_unused);
115 sema_init(&dquot->dq_sem, 1);
116 atomic_set(&dquot->dq_refcnt, 1);
117 dquot->dq_info = lqi;
119 dquot->dq_type = type;
124 static void free_dquot(struct lustre_dquot *dquot)
126 OBD_SLAB_FREE(dquot, lustre_dquot_cachep, sizeof(*dquot));
129 static void insert_dquot_nolock(struct lustre_dquot *dquot)
131 struct list_head *head = lustre_dquot_hash +
132 dquot_hashfn(dquot->dq_info, dquot->dq_id, dquot->dq_type);
133 list_add(&dquot->dq_hash, head);
136 static void remove_dquot_nolock(struct lustre_dquot *dquot)
138 LASSERT(!list_empty(&dquot->dq_hash));
139 list_del_init(&dquot->dq_hash);
142 static void lustre_dqput(struct lustre_dquot *dquot)
145 spin_lock(&dquot_hash_lock);
146 LASSERT(atomic_read(&dquot->dq_refcnt));
147 if (atomic_dec_and_test(&dquot->dq_refcnt)) {
148 remove_dquot_nolock(dquot);
151 spin_unlock(&dquot_hash_lock);
155 #define DQUOT_DEBUG(dquot, fmt, arg...) \
156 CDEBUG(D_QUOTA, "refcnt(%u) id(%u) type(%u) off(%llu) flags(%lu) " \
157 "bhardlimit(%u) curspace("LPX64") ihardlimit(%u) " \
158 "curinodes(%u): " fmt, atomic_read(&dquot->dq_refcnt), \
159 dquot->dq_id, dquot->dq_type, dquot->dq_off, dquot->dq_flags, \
160 dquot->dq_dqb.dqb_bhardlimit, dquot->dq_dqb.dqb_curspace, \
161 dquot->dq_dqb.dqb_ihardlimit, dquot->dq_dqb.dqb_curinodes, \
164 #define QINFO_DEBUG(qinfo, fmt, arg...) \
165 CDEBUG(D_QUOTA, "files (%p/%p) flags(%lu/%lu) blocks(%u/%u) " \
166 "free_blk(/%u/%u) free_entry(%u/%u): " fmt, \
167 qinfo->qi_files[0], qinfo->qi_files[1], \
168 qinfo->qi_info[0].dqi_flags, qinfo->qi_info[1].dqi_flags, \
169 qinfo->qi_info[0].dqi_blocks, qinfo->qi_info[1].dqi_blocks, \
170 qinfo->qi_info[0].dqi_free_blk, qinfo->qi_info[1].dqi_free_blk,\
171 qinfo->qi_info[0].dqi_free_entry, \
172 qinfo->qi_info[1].dqi_free_entry, ## arg);
174 static struct lustre_dquot *lustre_dqget(struct obd_device *obd,
175 struct lustre_quota_info *lqi,
178 unsigned int hashent = dquot_hashfn(lqi, id, type);
179 struct lustre_dquot *dquot = NULL;
183 spin_lock(&dquot_hash_lock);
184 if ((dquot = find_dquot(hashent, lqi, id, type)) != NULL) {
185 atomic_inc(&dquot->dq_refcnt);
187 dquot = alloc_dquot(lqi, id, type);
189 insert_dquot_nolock(dquot);
193 spin_unlock(&dquot_hash_lock);
196 RETURN(ERR_PTR(-ENOMEM));
201 down(&dquot->dq_info->qi_sem);
202 down(&dquot->dq_sem);
203 rc = fsfilt_dquot(obd, dquot, QFILE_RD_DQUOT);
205 up(&dquot->dq_info->qi_sem);
207 CERROR("can't read dquot from admin qutoafile! "
216 int dqacq_handler(struct obd_device *obd, struct qunit_data *qdata, int opc)
218 struct mds_obd *mds = &obd->u.mds;
219 struct lustre_quota_info *info = &mds->mds_quota_info;
220 struct lustre_dquot *dquot = NULL;
222 __u32 hlimit = 0, slimit = 0;
224 unsigned int grace = 0;
228 /* slaves never acquires qunit for user root */
229 LASSERT(qdata->qd_id || qdata->qd_type == GRPQUOTA);
231 dquot = lustre_dqget(obd, info, qdata->qd_id, qdata->qd_type);
233 RETURN(PTR_ERR(dquot));
235 DQUOT_DEBUG(dquot, "get dquot in dqacq_handler\n");
236 QINFO_DEBUG(dquot->dq_info, "get dquot in dqadq_handler\n");
238 down(&dquot->dq_info->qi_sem);
239 down(&dquot->dq_sem);
241 if (qdata->qd_isblk) {
242 grace = info->qi_info[qdata->qd_type].dqi_bgrace;
243 usage = &dquot->dq_dqb.dqb_curspace;
244 hlimit = dquot->dq_dqb.dqb_bhardlimit;
245 slimit = dquot->dq_dqb.dqb_bsoftlimit;
246 time = &dquot->dq_dqb.dqb_btime;
248 grace = info->qi_info[qdata->qd_type].dqi_igrace;
249 usage = (__u64 *) & dquot->dq_dqb.dqb_curinodes;
250 hlimit = dquot->dq_dqb.dqb_ihardlimit;
251 slimit = dquot->dq_dqb.dqb_isoftlimit;
252 time = &dquot->dq_dqb.dqb_itime;
255 /* if the quota limit in admin quotafile is zero, we just inform
256 * slave to clear quota limit with zero qd_count */
257 if (hlimit == 0 && slimit == 0) {
262 if (opc == QUOTA_DQACQ) {
264 QUSG(*usage + qdata->qd_count, qdata->qd_isblk) > hlimit)
265 GOTO(out, rc = -EDQUOT);
268 QUSG(*usage + qdata->qd_count, qdata->qd_isblk) > slimit) {
269 if (*time && CURRENT_SECONDS >= *time)
270 GOTO(out, rc = -EDQUOT);
272 *time = CURRENT_SECONDS + grace;
275 *usage += qdata->qd_count;
277 } else if (opc == QUOTA_DQREL) {
278 LASSERT(*usage - qdata->qd_count >= 0);
279 *usage -= qdata->qd_count;
281 /* (usage <= soft limit) but not (usage < soft limit) */
282 if (!slimit || QUSG(*usage, qdata->qd_isblk) <= slimit)
288 rc = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);
291 up(&dquot->dq_info->qi_sem);
296 void mds_adjust_qunit(struct obd_device *obd, uid_t cuid, gid_t cgid,
297 uid_t puid, gid_t pgid, int rc)
299 struct mds_obd *mds = &obd->u.mds;
300 struct lustre_quota_ctxt *qctxt = &mds->mds_quota_ctxt;
303 if (rc && rc != -EDQUOT) {
307 /* dqacq/dqrel file quota on owner of child */
308 rc = qctxt_adjust_qunit(obd, qctxt, cuid, cgid, 0);
310 CERROR("error mds adjust child qunit! (rc:%d)\n", rc);
311 /* dqacq/dqrel block quota on owner of parent directory */
312 rc = qctxt_adjust_qunit(obd, qctxt, puid, pgid, 1);
314 CERROR("error mds adjust parent qunit! (rc:%d)\n", rc);
318 int init_admin_quotafiles(struct obd_device *obd, struct obd_quotactl *oqctl)
320 struct mds_obd *mds = &obd->u.mds;
321 struct lustre_quota_info *qinfo = &mds->mds_quota_info;
322 const char *quotafiles[] = LUSTRE_ADMIN_QUOTAFILES;
323 struct lvfs_run_ctxt saved;
326 struct dentry *dparent = mds->mds_objects_dir;
327 struct inode *iparent = dparent->d_inode;
331 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
333 down(&qinfo->qi_sem);
334 for (i = 0; i < MAXQUOTAS; i++) {
335 struct dentry *de = NULL;
336 struct file *fp = NULL;
338 if (!Q_TYPESET(oqctl, i))
341 /* quota file has been opened ? */
342 if (qinfo->qi_files[i]) {
343 CWARN("init %s admin quotafile while quota on.\n",
344 i == USRQUOTA ? "user" : "group");
348 /* lookup quota file */
350 down(&iparent->i_sem);
352 de = lookup_one_len(quotafiles[i], dparent,
353 strlen(quotafiles[i]));
354 if (IS_ERR(de) || de->d_inode == NULL)
355 rc = IS_ERR(de) ? PTR_ERR(de) : -ENOENT;
360 if (rc && rc != -ENOENT) {
361 CERROR("error lookup quotafile %s! (rc:%d)\n",
368 sprintf(name, "OBJECTS/%s", quotafiles[i]);
370 LASSERT(rc == -ENOENT);
371 /* create quota file */
372 fp = filp_open(name, O_CREAT | O_EXCL, 0644);
375 CERROR("error creating admin quotafile %s (rc:%d)\n",
380 qinfo->qi_files[i] = fp;
381 rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_INIT_INFO);
383 qinfo->qi_files[i] = NULL;
386 CERROR("error init %s admin quotafile! (rc:%d)\n",
387 i == USRQUOTA ? "user" : "group", rc);
393 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
397 int mds_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl)
399 struct mds_obd *mds = &obd->u.mds;
400 struct lustre_quota_info *qinfo = &mds->mds_quota_info;
401 const char *quotafiles[] = LUSTRE_ADMIN_QUOTAFILES;
402 struct lvfs_run_ctxt saved;
405 struct inode *iparent = mds->mds_objects_dir->d_inode;
409 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
411 down(&qinfo->qi_sem);
412 /* open admin quota files and read quotafile info */
413 for (i = 0; i < MAXQUOTAS; i++) {
414 struct file *fp = NULL;
416 if (!Q_TYPESET(oqctl, i))
419 sprintf(name, "OBJECTS/%s", quotafiles[i]);
421 if (qinfo->qi_files[i] != NULL) {
426 fp = filp_open(name, O_RDWR | O_EXCL, 0644);
429 CERROR("error open %s! (rc:%d)\n", name, rc);
432 qinfo->qi_files[i] = fp;
434 rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_RD_INFO);
436 CERROR("error read quotainfo of %s! (rc:%d)\n",
443 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
445 if (rc && rc != -EBUSY) {
446 down(&qinfo->qi_sem);
447 for (i = 0; i < MAXQUOTAS; i++) {
448 if (!Q_TYPESET(oqctl, i))
450 if (qinfo->qi_files[i])
451 filp_close(qinfo->qi_files[i], 0);
452 qinfo->qi_files[i] = NULL;
459 int mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl)
461 struct mds_obd *mds = &obd->u.mds;
462 struct lustre_quota_info *qinfo = &mds->mds_quota_info;
466 down(&qinfo->qi_sem);
467 /* close admin quota files */
468 for (i = 0; i < MAXQUOTAS; i++) {
469 if (!Q_TYPESET(oqctl, i))
472 if (qinfo->qi_files[i] == NULL) {
476 filp_close(qinfo->qi_files[i], 0);
477 qinfo->qi_files[i] = NULL;
484 int mds_set_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl)
486 struct mds_obd *mds = &obd->u.mds;
487 struct lustre_quota_info *qinfo = &mds->mds_quota_info;
488 struct obd_dqinfo *dqinfo = &oqctl->qc_dqinfo;
492 if (qinfo->qi_files[oqctl->qc_type] == NULL)
495 down(&qinfo->qi_sem);
496 qinfo->qi_info[oqctl->qc_type].dqi_bgrace = dqinfo->dqi_bgrace;
497 qinfo->qi_info[oqctl->qc_type].dqi_igrace = dqinfo->dqi_igrace;
498 qinfo->qi_info[oqctl->qc_type].dqi_flags = dqinfo->dqi_flags;
500 rc = fsfilt_quotainfo(obd, qinfo, oqctl->qc_type, QFILE_WR_INFO);
506 int mds_get_dqinfo(struct obd_device *obd, struct obd_quotactl *oqctl)
508 struct mds_obd *mds = &obd->u.mds;
509 struct lustre_quota_info *qinfo = &mds->mds_quota_info;
510 struct obd_dqinfo *dqinfo = &oqctl->qc_dqinfo;
513 if (qinfo->qi_files[oqctl->qc_type] == NULL)
516 down(&qinfo->qi_sem);
517 dqinfo->dqi_bgrace = qinfo->qi_info[oqctl->qc_type].dqi_bgrace;
518 dqinfo->dqi_igrace = qinfo->qi_info[oqctl->qc_type].dqi_igrace;
519 dqinfo->dqi_flags = qinfo->qi_info[oqctl->qc_type].dqi_flags;
525 static int mds_init_slave_ilimits(struct obd_device *obd,
526 struct obd_quotactl *oqctl)
528 /* XXX: for file limits only adjust local now */
529 struct mds_obd *mds = &obd->u.mds;
530 unsigned int uid = 0, gid = 0;
531 struct obd_quotactl *ioqc;
535 /* if we are going to set zero limit, needn't init slaves */
536 if (!oqctl->qc_dqblk.dqb_ihardlimit && !oqctl->qc_dqblk.dqb_isoftlimit)
539 OBD_ALLOC(ioqc, sizeof(*ioqc));
543 ioqc->qc_cmd = Q_SETQUOTA;
544 ioqc->qc_id = oqctl->qc_id;
545 ioqc->qc_type = oqctl->qc_type;
546 ioqc->qc_dqblk.dqb_valid = QIF_ILIMITS;
547 ioqc->qc_dqblk.dqb_ihardlimit = MIN_QLIMIT;
549 /* set local limit to MIN_QLIMIT */
550 rc = fsfilt_quotactl(obd, mds->mds_sb, ioqc);
554 /* trigger local qunit pre-acquire */
555 if (oqctl->qc_type == USRQUOTA)
560 rc = qctxt_adjust_qunit(obd, &mds->mds_quota_ctxt, uid, gid, 0);
562 CERROR("error mds adjust local file quota! (rc:%d)\n", rc);
565 /* FIXME initialize all slaves in CMD */
567 OBD_FREE(ioqc, sizeof(*ioqc));
571 static int mds_init_slave_blimits(struct obd_device *obd,
572 struct obd_quotactl *oqctl)
574 struct mds_obd *mds = &obd->u.mds;
575 struct obd_quotactl *ioqc;
576 unsigned int uid = 0, gid = 0;
580 /* if we are going to set zero limit, needn't init slaves */
581 if (!oqctl->qc_dqblk.dqb_bhardlimit && !oqctl->qc_dqblk.dqb_bsoftlimit)
584 OBD_ALLOC(ioqc, sizeof(*ioqc));
588 ioqc->qc_cmd = Q_SETQUOTA;
589 ioqc->qc_id = oqctl->qc_id;
590 ioqc->qc_type = oqctl->qc_type;
591 ioqc->qc_dqblk.dqb_valid = QIF_BLIMITS;
592 ioqc->qc_dqblk.dqb_bhardlimit = MIN_QLIMIT;
594 /* set local limit to MIN_QLIMIT */
595 rc = fsfilt_quotactl(obd, mds->mds_sb, ioqc);
599 /* trigger local qunit pre-acquire */
600 if (oqctl->qc_type == USRQUOTA)
605 rc = qctxt_adjust_qunit(obd, &mds->mds_quota_ctxt, uid, gid, 1);
607 CERROR("error mds adjust local block quota! (rc:%d)\n", rc);
611 /* initialize all slave's limit */
612 ioqc->qc_cmd = Q_INITQUOTA;
613 rc = obd_quotactl(mds->mds_osc_exp, ioqc);
615 OBD_FREE(ioqc, sizeof(*ioqc));
619 int mds_set_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl)
621 struct mds_obd *mds = &obd->u.mds;
622 struct lustre_quota_info *qinfo = &mds->mds_quota_info;
623 __u32 ihardlimit, isoftlimit, bhardlimit, bsoftlimit;
625 struct lustre_dquot *dquot;
626 struct obd_dqblk *dqblk = &oqctl->qc_dqblk;
630 if (qinfo->qi_files[oqctl->qc_type] == NULL)
633 dquot = lustre_dqget(obd, qinfo, oqctl->qc_id, oqctl->qc_type);
635 RETURN(PTR_ERR(dquot));
636 DQUOT_DEBUG(dquot, "get dquot in mds_set_blk\n");
637 QINFO_DEBUG(dquot->dq_info, "get dquot in mds_set_blk\n");
639 down(&dquot->dq_info->qi_sem);
640 down(&dquot->dq_sem);
642 ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
643 isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
644 bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
645 bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
646 btime = dquot->dq_dqb.dqb_btime;
647 itime = dquot->dq_dqb.dqb_itime;
649 if (dqblk->dqb_valid & QIF_BLIMITS) {
650 dquot->dq_dqb.dqb_bhardlimit = dqblk->dqb_bhardlimit;
651 dquot->dq_dqb.dqb_bsoftlimit = dqblk->dqb_bsoftlimit;
652 /* clear usage (limit pool) */
653 if (!dquot->dq_dqb.dqb_bhardlimit &&
654 !dquot->dq_dqb.dqb_bsoftlimit)
655 dquot->dq_dqb.dqb_curspace = 0;
658 if (dqblk->dqb_valid & QIF_ILIMITS) {
659 dquot->dq_dqb.dqb_ihardlimit = dqblk->dqb_ihardlimit;
660 dquot->dq_dqb.dqb_isoftlimit = dqblk->dqb_isoftlimit;
661 /* clear usage (limit pool) */
662 if (!dquot->dq_dqb.dqb_ihardlimit &&
663 !dquot->dq_dqb.dqb_isoftlimit)
664 dquot->dq_dqb.dqb_curinodes = 0;
667 if (dqblk->dqb_valid & QIF_BTIME)
668 dquot->dq_dqb.dqb_btime = dqblk->dqb_btime;
670 if (dqblk->dqb_valid & QIF_ITIME)
671 dquot->dq_dqb.dqb_itime = dqblk->dqb_itime;
673 rc = fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);
676 up(&dquot->dq_info->qi_sem);
681 if (dqblk->dqb_valid & QIF_ILIMITS && !(ihardlimit || isoftlimit)) {
682 rc = mds_init_slave_ilimits(obd, oqctl);
684 CERROR("init slave ilimits failed! (rc:%d)\n", rc);
685 GOTO(revoke_out, rc);
689 if (dqblk->dqb_valid & QIF_BLIMITS && !(bhardlimit || bsoftlimit)) {
690 rc = mds_init_slave_blimits(obd, oqctl);
692 CERROR("init slave blimits failed! (rc:%d)\n", rc);
693 GOTO(revoke_out, rc);
699 /* cancel previous setting */
700 down(&dquot->dq_info->qi_sem);
701 down(&dquot->dq_sem);
702 dquot->dq_dqb.dqb_ihardlimit = ihardlimit;
703 dquot->dq_dqb.dqb_isoftlimit = isoftlimit;
704 dquot->dq_dqb.dqb_bhardlimit = bhardlimit;
705 dquot->dq_dqb.dqb_bsoftlimit = bsoftlimit;
706 dquot->dq_dqb.dqb_btime = btime;
707 dquot->dq_dqb.dqb_itime = itime;
708 fsfilt_dquot(obd, dquot, QFILE_WR_DQUOT);
710 up(&dquot->dq_info->qi_sem);
717 static int mds_get_space(struct obd_device *obd, struct obd_quotactl *oqctl)
719 struct obd_quotactl *soqc;
722 OBD_ALLOC(soqc, sizeof(*soqc));
726 soqc->qc_cmd = oqctl->qc_cmd;
727 soqc->qc_id = oqctl->qc_id;
728 soqc->qc_type = oqctl->qc_type;
730 rc = obd_quotactl(obd->u.mds.mds_osc_exp, soqc);
732 oqctl->qc_dqblk.dqb_curspace = soqc->qc_dqblk.dqb_curspace;
734 OBD_FREE(soqc, sizeof(*soqc));
738 int mds_get_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl)
740 struct mds_obd *mds = &obd->u.mds;
741 struct lustre_quota_info *qinfo = &mds->mds_quota_info;
742 struct lustre_dquot *dquot;
743 struct obd_dqblk *dqblk = &oqctl->qc_dqblk;
747 if (qinfo->qi_files[oqctl->qc_type] == NULL)
750 dquot = lustre_dqget(obd, qinfo, oqctl->qc_id, oqctl->qc_type);
752 RETURN(PTR_ERR(dquot));
754 down(&dquot->dq_sem);
755 dqblk->dqb_ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
756 dqblk->dqb_isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
757 dqblk->dqb_bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
758 dqblk->dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
759 dqblk->dqb_btime = dquot->dq_dqb.dqb_btime;
760 dqblk->dqb_itime = dquot->dq_dqb.dqb_itime;
763 /* the usages in admin quota file is inaccurate */
764 dqblk->dqb_curinodes = 0;
765 dqblk->dqb_curspace = 0;
766 rc = mds_get_space(obd, oqctl);