RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / fs / xfs / quota / xfs_qm_syscalls.c
blob470d7ade5af966323b5495ddb039083580246aa0
1 /*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <linux/capability.h>
21 #include "xfs.h"
22 #include "xfs_fs.h"
23 #include "xfs_bit.h"
24 #include "xfs_log.h"
25 #include "xfs_inum.h"
26 #include "xfs_trans.h"
27 #include "xfs_sb.h"
28 #include "xfs_ag.h"
29 #include "xfs_alloc.h"
30 #include "xfs_quota.h"
31 #include "xfs_mount.h"
32 #include "xfs_bmap_btree.h"
33 #include "xfs_inode.h"
34 #include "xfs_itable.h"
35 #include "xfs_bmap.h"
36 #include "xfs_rtalloc.h"
37 #include "xfs_error.h"
38 #include "xfs_attr.h"
39 #include "xfs_buf_item.h"
40 #include "xfs_utils.h"
41 #include "xfs_qm.h"
42 #include "xfs_trace.h"
44 #ifdef DEBUG
45 # define qdprintk(s, args...) cmn_err(CE_DEBUG, s, ## args)
46 #else
47 # define qdprintk(s, args...) do { } while (0)
48 #endif
50 STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
51 STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
52 uint);
53 STATIC uint xfs_qm_export_flags(uint);
54 STATIC uint xfs_qm_export_qtype_flags(uint);
55 STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *,
56 fs_disk_quota_t *);
60 * Turn off quota accounting and/or enforcement for all udquots and/or
61 * gdquots. Called only at unmount time.
63 * This assumes that there are no dquots of this file system cached
64 * incore, and modifies the ondisk dquot directly. Therefore, for example,
65 * it is an error to call this twice, without purging the cache.
67 int
68 xfs_qm_scall_quotaoff(
69 xfs_mount_t *mp,
70 uint flags)
72 struct xfs_quotainfo *q = mp->m_quotainfo;
73 uint dqtype;
74 int error;
75 uint inactivate_flags;
76 xfs_qoff_logitem_t *qoffstart;
77 int nculprits;
80 * No file system can have quotas enabled on disk but not in core.
81 * Note that quota utilities (like quotaoff) _expect_
82 * errno == EEXIST here.
84 if ((mp->m_qflags & flags) == 0)
85 return XFS_ERROR(EEXIST);
86 error = 0;
88 flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
91 * We don't want to deal with two quotaoffs messing up each other,
92 * so we're going to serialize it. quotaoff isn't exactly a performance
93 * critical thing.
94 * If quotaoff, then we must be dealing with the root filesystem.
96 ASSERT(q);
97 mutex_lock(&q->qi_quotaofflock);
100 * If we're just turning off quota enforcement, change mp and go.
102 if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
103 mp->m_qflags &= ~(flags);
105 spin_lock(&mp->m_sb_lock);
106 mp->m_sb.sb_qflags = mp->m_qflags;
107 spin_unlock(&mp->m_sb_lock);
108 mutex_unlock(&q->qi_quotaofflock);
110 error = xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS);
111 return (error);
114 dqtype = 0;
115 inactivate_flags = 0;
117 * If accounting is off, we must turn enforcement off, clear the
118 * quota 'CHKD' certificate to make it known that we have to
119 * do a quotacheck the next time this quota is turned on.
121 if (flags & XFS_UQUOTA_ACCT) {
122 dqtype |= XFS_QMOPT_UQUOTA;
123 flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
124 inactivate_flags |= XFS_UQUOTA_ACTIVE;
126 if (flags & XFS_GQUOTA_ACCT) {
127 dqtype |= XFS_QMOPT_GQUOTA;
128 flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
129 inactivate_flags |= XFS_GQUOTA_ACTIVE;
130 } else if (flags & XFS_PQUOTA_ACCT) {
131 dqtype |= XFS_QMOPT_PQUOTA;
132 flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
133 inactivate_flags |= XFS_PQUOTA_ACTIVE;
137 * Nothing to do? Don't complain. This happens when we're just
138 * turning off quota enforcement.
140 if ((mp->m_qflags & flags) == 0)
141 goto out_unlock;
144 * Write the LI_QUOTAOFF log record, and do SB changes atomically,
145 * and synchronously. If we fail to write, we should abort the
146 * operation as it cannot be recovered safely if we crash.
148 error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
149 if (error)
150 goto out_unlock;
153 * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
154 * to take care of the race between dqget and quotaoff. We don't take
155 * any special locks to reset these bits. All processes need to check
156 * these bits *after* taking inode lock(s) to see if the particular
157 * quota type is in the process of being turned off. If *ACTIVE, it is
158 * guaranteed that all dquot structures and all quotainode ptrs will all
159 * stay valid as long as that inode is kept locked.
161 * There is no turning back after this.
163 mp->m_qflags &= ~inactivate_flags;
166 * Give back all the dquot reference(s) held by inodes.
167 * Here we go thru every single incore inode in this file system, and
168 * do a dqrele on the i_udquot/i_gdquot that it may have.
169 * Essentially, as long as somebody has an inode locked, this guarantees
170 * that quotas will not be turned off. This is handy because in a
171 * transaction once we lock the inode(s) and check for quotaon, we can
172 * depend on the quota inodes (and other things) being valid as long as
173 * we keep the lock(s).
175 xfs_qm_dqrele_all_inodes(mp, flags);
178 * Next we make the changes in the quota flag in the mount struct.
179 * This isn't protected by a particular lock directly, because we
180 * don't want to take a mrlock everytime we depend on quotas being on.
182 mp->m_qflags &= ~(flags);
185 * Go through all the dquots of this file system and purge them,
186 * according to what was turned off. We may not be able to get rid
187 * of all dquots, because dquots can have temporary references that
188 * are not attached to inodes. eg. xfs_setattr, xfs_create.
189 * So, if we couldn't purge all the dquots from the filesystem,
190 * we can't get rid of the incore data structures.
192 while ((nculprits = xfs_qm_dqpurge_all(mp, dqtype)))
193 delay(10 * nculprits);
196 * Transactions that had started before ACTIVE state bit was cleared
197 * could have logged many dquots, so they'd have higher LSNs than
198 * the first QUOTAOFF log record does. If we happen to crash when
199 * the tail of the log has gone past the QUOTAOFF record, but
200 * before the last dquot modification, those dquots __will__
201 * recover, and that's not good.
203 * So, we have QUOTAOFF start and end logitems; the start
204 * logitem won't get overwritten until the end logitem appears...
206 error = xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
207 if (error) {
208 /* We're screwed now. Shutdown is the only option. */
209 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
210 goto out_unlock;
214 * If quotas is completely disabled, close shop.
216 if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
217 ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
218 mutex_unlock(&q->qi_quotaofflock);
219 xfs_qm_destroy_quotainfo(mp);
220 return (0);
224 * Release our quotainode references if we don't need them anymore.
226 if ((dqtype & XFS_QMOPT_UQUOTA) && q->qi_uquotaip) {
227 IRELE(q->qi_uquotaip);
228 q->qi_uquotaip = NULL;
230 if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && q->qi_gquotaip) {
231 IRELE(q->qi_gquotaip);
232 q->qi_gquotaip = NULL;
235 out_unlock:
236 mutex_unlock(&q->qi_quotaofflock);
237 return error;
240 STATIC int
241 xfs_qm_scall_trunc_qfile(
242 struct xfs_mount *mp,
243 xfs_ino_t ino)
245 struct xfs_inode *ip;
246 struct xfs_trans *tp;
247 int error;
249 if (ino == NULLFSINO)
250 return 0;
252 error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
253 if (error)
254 return error;
256 xfs_ilock(ip, XFS_IOLOCK_EXCL);
258 tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE);
259 error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
260 XFS_TRANS_PERM_LOG_RES,
261 XFS_ITRUNCATE_LOG_COUNT);
262 if (error) {
263 xfs_trans_cancel(tp, 0);
264 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
265 goto out_put;
268 xfs_ilock(ip, XFS_ILOCK_EXCL);
269 xfs_trans_ijoin(tp, ip);
271 error = xfs_itruncate_finish(&tp, ip, 0, XFS_DATA_FORK, 1);
272 if (error) {
273 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
274 XFS_TRANS_ABORT);
275 goto out_unlock;
278 xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
279 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
281 out_unlock:
282 xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
283 out_put:
284 IRELE(ip);
285 return error;
289 xfs_qm_scall_trunc_qfiles(
290 xfs_mount_t *mp,
291 uint flags)
293 int error = 0, error2 = 0;
295 if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
296 qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags);
297 return XFS_ERROR(EINVAL);
300 if (flags & XFS_DQ_USER)
301 error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
302 if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ))
303 error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
305 return error ? error : error2;
309 * Switch on (a given) quota enforcement for a filesystem. This takes
310 * effect immediately.
311 * (Switching on quota accounting must be done at mount time.)
314 xfs_qm_scall_quotaon(
315 xfs_mount_t *mp,
316 uint flags)
318 int error;
319 uint qf;
320 uint accflags;
321 __int64_t sbflags;
323 flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
325 * Switching on quota accounting must be done at mount time.
327 accflags = flags & XFS_ALL_QUOTA_ACCT;
328 flags &= ~(XFS_ALL_QUOTA_ACCT);
330 sbflags = 0;
332 if (flags == 0) {
333 qdprintk("quotaon: zero flags, m_qflags=%x\n", mp->m_qflags);
334 return XFS_ERROR(EINVAL);
337 /* No fs can turn on quotas with a delayed effect */
338 ASSERT((flags & XFS_ALL_QUOTA_ACCT) == 0);
341 * Can't enforce without accounting. We check the superblock
342 * qflags here instead of m_qflags because rootfs can have
343 * quota acct on ondisk without m_qflags' knowing.
345 if (((flags & XFS_UQUOTA_ACCT) == 0 &&
346 (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
347 (flags & XFS_UQUOTA_ENFD))
349 ((flags & XFS_PQUOTA_ACCT) == 0 &&
350 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
351 (flags & XFS_GQUOTA_ACCT) == 0 &&
352 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
353 (flags & XFS_OQUOTA_ENFD))) {
354 qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
355 flags, mp->m_sb.sb_qflags);
356 return XFS_ERROR(EINVAL);
359 * If everything's upto-date incore, then don't waste time.
361 if ((mp->m_qflags & flags) == flags)
362 return XFS_ERROR(EEXIST);
365 * Change sb_qflags on disk but not incore mp->qflags
366 * if this is the root filesystem.
368 spin_lock(&mp->m_sb_lock);
369 qf = mp->m_sb.sb_qflags;
370 mp->m_sb.sb_qflags = qf | flags;
371 spin_unlock(&mp->m_sb_lock);
374 * There's nothing to change if it's the same.
376 if ((qf & flags) == flags && sbflags == 0)
377 return XFS_ERROR(EEXIST);
378 sbflags |= XFS_SB_QFLAGS;
380 if ((error = xfs_qm_write_sb_changes(mp, sbflags)))
381 return (error);
383 * If we aren't trying to switch on quota enforcement, we are done.
385 if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
386 (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
387 ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
388 (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
389 ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
390 (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
391 (flags & XFS_ALL_QUOTA_ENFD) == 0)
392 return (0);
394 if (! XFS_IS_QUOTA_RUNNING(mp))
395 return XFS_ERROR(ESRCH);
398 * Switch on quota enforcement in core.
400 mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
401 mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
402 mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
404 return (0);
409 * Return quota status information, such as uquota-off, enforcements, etc.
412 xfs_qm_scall_getqstat(
413 struct xfs_mount *mp,
414 struct fs_quota_stat *out)
416 struct xfs_quotainfo *q = mp->m_quotainfo;
417 struct xfs_inode *uip, *gip;
418 boolean_t tempuqip, tempgqip;
420 uip = gip = NULL;
421 tempuqip = tempgqip = B_FALSE;
422 memset(out, 0, sizeof(fs_quota_stat_t));
424 out->qs_version = FS_QSTAT_VERSION;
425 if (!xfs_sb_version_hasquota(&mp->m_sb)) {
426 out->qs_uquota.qfs_ino = NULLFSINO;
427 out->qs_gquota.qfs_ino = NULLFSINO;
428 return (0);
430 out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
431 (XFS_ALL_QUOTA_ACCT|
432 XFS_ALL_QUOTA_ENFD));
433 out->qs_pad = 0;
434 out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
435 out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
437 if (q) {
438 uip = q->qi_uquotaip;
439 gip = q->qi_gquotaip;
441 if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
442 if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
443 0, 0, &uip) == 0)
444 tempuqip = B_TRUE;
446 if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
447 if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
448 0, 0, &gip) == 0)
449 tempgqip = B_TRUE;
451 if (uip) {
452 out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
453 out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
454 if (tempuqip)
455 IRELE(uip);
457 if (gip) {
458 out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
459 out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
460 if (tempgqip)
461 IRELE(gip);
463 if (q) {
464 out->qs_incoredqs = q->qi_dquots;
465 out->qs_btimelimit = q->qi_btimelimit;
466 out->qs_itimelimit = q->qi_itimelimit;
467 out->qs_rtbtimelimit = q->qi_rtbtimelimit;
468 out->qs_bwarnlimit = q->qi_bwarnlimit;
469 out->qs_iwarnlimit = q->qi_iwarnlimit;
471 return 0;
474 #define XFS_DQ_MASK \
475 (FS_DQ_LIMIT_MASK | FS_DQ_TIMER_MASK | FS_DQ_WARNS_MASK)
478 * Adjust quota limits, and start/stop timers accordingly.
481 xfs_qm_scall_setqlim(
482 xfs_mount_t *mp,
483 xfs_dqid_t id,
484 uint type,
485 fs_disk_quota_t *newlim)
487 struct xfs_quotainfo *q = mp->m_quotainfo;
488 xfs_disk_dquot_t *ddq;
489 xfs_dquot_t *dqp;
490 xfs_trans_t *tp;
491 int error;
492 xfs_qcnt_t hard, soft;
494 if (newlim->d_fieldmask & ~XFS_DQ_MASK)
495 return EINVAL;
496 if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0)
497 return 0;
499 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
500 if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_disk_dquot_t) + 128,
501 0, 0, XFS_DEFAULT_LOG_COUNT))) {
502 xfs_trans_cancel(tp, 0);
503 return (error);
507 * We don't want to race with a quotaoff so take the quotaoff lock.
508 * (We don't hold an inode lock, so there's nothing else to stop
509 * a quotaoff from happening). (XXXThis doesn't currently happen
510 * because we take the vfslock before calling xfs_qm_sysent).
512 mutex_lock(&q->qi_quotaofflock);
515 * Get the dquot (locked), and join it to the transaction.
516 * Allocate the dquot if this doesn't exist.
518 if ((error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp))) {
519 xfs_trans_cancel(tp, XFS_TRANS_ABORT);
520 ASSERT(error != ENOENT);
521 goto out_unlock;
523 xfs_trans_dqjoin(tp, dqp);
524 ddq = &dqp->q_core;
527 * Make sure that hardlimits are >= soft limits before changing.
529 hard = (newlim->d_fieldmask & FS_DQ_BHARD) ?
530 (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_hardlimit) :
531 be64_to_cpu(ddq->d_blk_hardlimit);
532 soft = (newlim->d_fieldmask & FS_DQ_BSOFT) ?
533 (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_softlimit) :
534 be64_to_cpu(ddq->d_blk_softlimit);
535 if (hard == 0 || hard >= soft) {
536 ddq->d_blk_hardlimit = cpu_to_be64(hard);
537 ddq->d_blk_softlimit = cpu_to_be64(soft);
538 if (id == 0) {
539 q->qi_bhardlimit = hard;
540 q->qi_bsoftlimit = soft;
542 } else {
543 qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft);
545 hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
546 (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
547 be64_to_cpu(ddq->d_rtb_hardlimit);
548 soft = (newlim->d_fieldmask & FS_DQ_RTBSOFT) ?
549 (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_softlimit) :
550 be64_to_cpu(ddq->d_rtb_softlimit);
551 if (hard == 0 || hard >= soft) {
552 ddq->d_rtb_hardlimit = cpu_to_be64(hard);
553 ddq->d_rtb_softlimit = cpu_to_be64(soft);
554 if (id == 0) {
555 q->qi_rtbhardlimit = hard;
556 q->qi_rtbsoftlimit = soft;
558 } else {
559 qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
562 hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
563 (xfs_qcnt_t) newlim->d_ino_hardlimit :
564 be64_to_cpu(ddq->d_ino_hardlimit);
565 soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
566 (xfs_qcnt_t) newlim->d_ino_softlimit :
567 be64_to_cpu(ddq->d_ino_softlimit);
568 if (hard == 0 || hard >= soft) {
569 ddq->d_ino_hardlimit = cpu_to_be64(hard);
570 ddq->d_ino_softlimit = cpu_to_be64(soft);
571 if (id == 0) {
572 q->qi_ihardlimit = hard;
573 q->qi_isoftlimit = soft;
575 } else {
576 qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
580 * Update warnings counter(s) if requested
582 if (newlim->d_fieldmask & FS_DQ_BWARNS)
583 ddq->d_bwarns = cpu_to_be16(newlim->d_bwarns);
584 if (newlim->d_fieldmask & FS_DQ_IWARNS)
585 ddq->d_iwarns = cpu_to_be16(newlim->d_iwarns);
586 if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
587 ddq->d_rtbwarns = cpu_to_be16(newlim->d_rtbwarns);
589 if (id == 0) {
591 * Timelimits for the super user set the relative time
592 * the other users can be over quota for this file system.
593 * If it is zero a default is used. Ditto for the default
594 * soft and hard limit values (already done, above), and
595 * for warnings.
597 if (newlim->d_fieldmask & FS_DQ_BTIMER) {
598 q->qi_btimelimit = newlim->d_btimer;
599 ddq->d_btimer = cpu_to_be32(newlim->d_btimer);
601 if (newlim->d_fieldmask & FS_DQ_ITIMER) {
602 q->qi_itimelimit = newlim->d_itimer;
603 ddq->d_itimer = cpu_to_be32(newlim->d_itimer);
605 if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
606 q->qi_rtbtimelimit = newlim->d_rtbtimer;
607 ddq->d_rtbtimer = cpu_to_be32(newlim->d_rtbtimer);
609 if (newlim->d_fieldmask & FS_DQ_BWARNS)
610 q->qi_bwarnlimit = newlim->d_bwarns;
611 if (newlim->d_fieldmask & FS_DQ_IWARNS)
612 q->qi_iwarnlimit = newlim->d_iwarns;
613 if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
614 q->qi_rtbwarnlimit = newlim->d_rtbwarns;
615 } else {
617 * If the user is now over quota, start the timelimit.
618 * The user will not be 'warned'.
619 * Note that we keep the timers ticking, whether enforcement
620 * is on or off. We don't really want to bother with iterating
621 * over all ondisk dquots and turning the timers on/off.
623 xfs_qm_adjust_dqtimers(mp, ddq);
625 dqp->dq_flags |= XFS_DQ_DIRTY;
626 xfs_trans_log_dquot(tp, dqp);
628 error = xfs_trans_commit(tp, 0);
629 xfs_qm_dqprint(dqp);
630 xfs_qm_dqrele(dqp);
632 out_unlock:
633 mutex_unlock(&q->qi_quotaofflock);
634 return error;
638 xfs_qm_scall_getquota(
639 xfs_mount_t *mp,
640 xfs_dqid_t id,
641 uint type,
642 fs_disk_quota_t *out)
644 xfs_dquot_t *dqp;
645 int error;
648 * Try to get the dquot. We don't want it allocated on disk, so
649 * we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't
650 * exist, we'll get ENOENT back.
652 if ((error = xfs_qm_dqget(mp, NULL, id, type, 0, &dqp))) {
653 return (error);
657 * If everything's NULL, this dquot doesn't quite exist as far as
658 * our utility programs are concerned.
660 if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
661 xfs_qm_dqput(dqp);
662 return XFS_ERROR(ENOENT);
664 /* xfs_qm_dqprint(dqp); */
666 * Convert the disk dquot to the exportable format
668 xfs_qm_export_dquot(mp, &dqp->q_core, out);
669 xfs_qm_dqput(dqp);
670 return (error ? XFS_ERROR(EFAULT) : 0);
674 STATIC int
675 xfs_qm_log_quotaoff_end(
676 xfs_mount_t *mp,
677 xfs_qoff_logitem_t *startqoff,
678 uint flags)
680 xfs_trans_t *tp;
681 int error;
682 xfs_qoff_logitem_t *qoffi;
684 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
686 if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_qoff_logitem_t) * 2,
687 0, 0, XFS_DEFAULT_LOG_COUNT))) {
688 xfs_trans_cancel(tp, 0);
689 return (error);
692 qoffi = xfs_trans_get_qoff_item(tp, startqoff,
693 flags & XFS_ALL_QUOTA_ACCT);
694 xfs_trans_log_quotaoff_item(tp, qoffi);
697 * We have to make sure that the transaction is secure on disk before we
698 * return and actually stop quota accounting. So, make it synchronous.
699 * We don't care about quotoff's performance.
701 xfs_trans_set_sync(tp);
702 error = xfs_trans_commit(tp, 0);
703 return (error);
707 STATIC int
708 xfs_qm_log_quotaoff(
709 xfs_mount_t *mp,
710 xfs_qoff_logitem_t **qoffstartp,
711 uint flags)
713 xfs_trans_t *tp;
714 int error;
715 xfs_qoff_logitem_t *qoffi=NULL;
716 uint oldsbqflag=0;
718 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF);
719 if ((error = xfs_trans_reserve(tp, 0,
720 sizeof(xfs_qoff_logitem_t) * 2 +
721 mp->m_sb.sb_sectsize + 128,
724 XFS_DEFAULT_LOG_COUNT))) {
725 goto error0;
728 qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
729 xfs_trans_log_quotaoff_item(tp, qoffi);
731 spin_lock(&mp->m_sb_lock);
732 oldsbqflag = mp->m_sb.sb_qflags;
733 mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
734 spin_unlock(&mp->m_sb_lock);
736 xfs_mod_sb(tp, XFS_SB_QFLAGS);
739 * We have to make sure that the transaction is secure on disk before we
740 * return and actually stop quota accounting. So, make it synchronous.
741 * We don't care about quotoff's performance.
743 xfs_trans_set_sync(tp);
744 error = xfs_trans_commit(tp, 0);
746 error0:
747 if (error) {
748 xfs_trans_cancel(tp, 0);
750 * No one else is modifying sb_qflags, so this is OK.
751 * We still hold the quotaofflock.
753 spin_lock(&mp->m_sb_lock);
754 mp->m_sb.sb_qflags = oldsbqflag;
755 spin_unlock(&mp->m_sb_lock);
757 *qoffstartp = qoffi;
758 return (error);
763 * Translate an internal style on-disk-dquot to the exportable format.
764 * The main differences are that the counters/limits are all in Basic
765 * Blocks (BBs) instead of the internal FSBs, and all on-disk data has
766 * to be converted to the native endianness.
768 STATIC void
769 xfs_qm_export_dquot(
770 xfs_mount_t *mp,
771 xfs_disk_dquot_t *src,
772 struct fs_disk_quota *dst)
774 memset(dst, 0, sizeof(*dst));
775 dst->d_version = FS_DQUOT_VERSION; /* different from src->d_version */
776 dst->d_flags = xfs_qm_export_qtype_flags(src->d_flags);
777 dst->d_id = be32_to_cpu(src->d_id);
778 dst->d_blk_hardlimit =
779 XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_blk_hardlimit));
780 dst->d_blk_softlimit =
781 XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_blk_softlimit));
782 dst->d_ino_hardlimit = be64_to_cpu(src->d_ino_hardlimit);
783 dst->d_ino_softlimit = be64_to_cpu(src->d_ino_softlimit);
784 dst->d_bcount = XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_bcount));
785 dst->d_icount = be64_to_cpu(src->d_icount);
786 dst->d_btimer = be32_to_cpu(src->d_btimer);
787 dst->d_itimer = be32_to_cpu(src->d_itimer);
788 dst->d_iwarns = be16_to_cpu(src->d_iwarns);
789 dst->d_bwarns = be16_to_cpu(src->d_bwarns);
790 dst->d_rtb_hardlimit =
791 XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_rtb_hardlimit));
792 dst->d_rtb_softlimit =
793 XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_rtb_softlimit));
794 dst->d_rtbcount = XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_rtbcount));
795 dst->d_rtbtimer = be32_to_cpu(src->d_rtbtimer);
796 dst->d_rtbwarns = be16_to_cpu(src->d_rtbwarns);
799 * Internally, we don't reset all the timers when quota enforcement
800 * gets turned off. No need to confuse the user level code,
801 * so return zeroes in that case.
803 if ((!XFS_IS_UQUOTA_ENFORCED(mp) && src->d_flags == XFS_DQ_USER) ||
804 (!XFS_IS_OQUOTA_ENFORCED(mp) &&
805 (src->d_flags & (XFS_DQ_PROJ | XFS_DQ_GROUP)))) {
806 dst->d_btimer = 0;
807 dst->d_itimer = 0;
808 dst->d_rtbtimer = 0;
811 #ifdef DEBUG
812 if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == FS_USER_QUOTA) ||
813 (XFS_IS_OQUOTA_ENFORCED(mp) &&
814 (dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) &&
815 dst->d_id != 0) {
816 if (((int) dst->d_bcount >= (int) dst->d_blk_softlimit) &&
817 (dst->d_blk_softlimit > 0)) {
818 ASSERT(dst->d_btimer != 0);
820 if (((int) dst->d_icount >= (int) dst->d_ino_softlimit) &&
821 (dst->d_ino_softlimit > 0)) {
822 ASSERT(dst->d_itimer != 0);
825 #endif
828 STATIC uint
829 xfs_qm_export_qtype_flags(
830 uint flags)
833 * Can't be more than one, or none.
835 ASSERT((flags & (FS_PROJ_QUOTA | FS_USER_QUOTA)) !=
836 (FS_PROJ_QUOTA | FS_USER_QUOTA));
837 ASSERT((flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)) !=
838 (FS_PROJ_QUOTA | FS_GROUP_QUOTA));
839 ASSERT((flags & (FS_USER_QUOTA | FS_GROUP_QUOTA)) !=
840 (FS_USER_QUOTA | FS_GROUP_QUOTA));
841 ASSERT((flags & (FS_PROJ_QUOTA|FS_USER_QUOTA|FS_GROUP_QUOTA)) != 0);
843 return (flags & XFS_DQ_USER) ?
844 FS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
845 FS_PROJ_QUOTA : FS_GROUP_QUOTA;
848 STATIC uint
849 xfs_qm_export_flags(
850 uint flags)
852 uint uflags;
854 uflags = 0;
855 if (flags & XFS_UQUOTA_ACCT)
856 uflags |= FS_QUOTA_UDQ_ACCT;
857 if (flags & XFS_PQUOTA_ACCT)
858 uflags |= FS_QUOTA_PDQ_ACCT;
859 if (flags & XFS_GQUOTA_ACCT)
860 uflags |= FS_QUOTA_GDQ_ACCT;
861 if (flags & XFS_UQUOTA_ENFD)
862 uflags |= FS_QUOTA_UDQ_ENFD;
863 if (flags & (XFS_OQUOTA_ENFD)) {
864 uflags |= (flags & XFS_GQUOTA_ACCT) ?
865 FS_QUOTA_GDQ_ENFD : FS_QUOTA_PDQ_ENFD;
867 return (uflags);
871 STATIC int
872 xfs_dqrele_inode(
873 struct xfs_inode *ip,
874 struct xfs_perag *pag,
875 int flags)
877 int error;
879 /* skip quota inodes */
880 if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
881 ip == ip->i_mount->m_quotainfo->qi_gquotaip) {
882 ASSERT(ip->i_udquot == NULL);
883 ASSERT(ip->i_gdquot == NULL);
884 read_unlock(&pag->pag_ici_lock);
885 return 0;
888 error = xfs_sync_inode_valid(ip, pag);
889 if (error)
890 return error;
892 xfs_ilock(ip, XFS_ILOCK_EXCL);
893 if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
894 xfs_qm_dqrele(ip->i_udquot);
895 ip->i_udquot = NULL;
897 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
898 xfs_qm_dqrele(ip->i_gdquot);
899 ip->i_gdquot = NULL;
901 xfs_iunlock(ip, XFS_ILOCK_EXCL);
903 IRELE(ip);
904 return 0;
909 * Go thru all the inodes in the file system, releasing their dquots.
911 * Note that the mount structure gets modified to indicate that quotas are off
912 * AFTER this, in the case of quotaoff.
914 void
915 xfs_qm_dqrele_all_inodes(
916 struct xfs_mount *mp,
917 uint flags)
919 ASSERT(mp->m_quotainfo);
920 xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags,
921 XFS_ICI_NO_TAG, 0, NULL);
924 /*------------------------------------------------------------------------*/
925 #ifdef DEBUG
927 * This contains all the test functions for XFS disk quotas.
928 * Currently it does a quota accounting check. ie. it walks through
929 * all inodes in the file system, calculating the dquot accounting fields,
930 * and prints out any inconsistencies.
932 xfs_dqhash_t *qmtest_udqtab;
933 xfs_dqhash_t *qmtest_gdqtab;
934 int qmtest_hashmask;
935 int qmtest_nfails;
936 struct mutex qcheck_lock;
938 #define DQTEST_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \
939 (__psunsigned_t)(id)) & \
940 (qmtest_hashmask - 1))
942 #define DQTEST_HASH(mp, id, type) ((type & XFS_DQ_USER) ? \
943 (qmtest_udqtab + \
944 DQTEST_HASHVAL(mp, id)) : \
945 (qmtest_gdqtab + \
946 DQTEST_HASHVAL(mp, id)))
948 #define DQTEST_LIST_PRINT(l, NXT, title) \
950 xfs_dqtest_t *dqp; int i = 0;\
951 cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \
952 for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
953 dqp = (xfs_dqtest_t *)dqp->NXT) { \
954 cmn_err(CE_DEBUG, " %d. \"%d (%s)\" bcnt = %d, icnt = %d", \
955 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp), \
956 dqp->d_bcount, dqp->d_icount); } \
959 typedef struct dqtest {
960 uint dq_flags; /* various flags (XFS_DQ_*) */
961 struct list_head q_hashlist;
962 xfs_dqhash_t *q_hash; /* the hashchain header */
963 xfs_mount_t *q_mount; /* filesystem this relates to */
964 xfs_dqid_t d_id; /* user id or group id */
965 xfs_qcnt_t d_bcount; /* # disk blocks owned by the user */
966 xfs_qcnt_t d_icount; /* # inodes owned by the user */
967 } xfs_dqtest_t;
969 STATIC void
970 xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
972 list_add(&dqp->q_hashlist, &h->qh_list);
973 h->qh_version++;
974 h->qh_nelems++;
976 STATIC void
977 xfs_qm_dqtest_print(
978 xfs_dqtest_t *d)
980 cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
981 cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
982 cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount);
983 cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)",
984 d->d_bcount, (int)d->d_bcount);
985 cmn_err(CE_DEBUG, "---- icount = %Lu (0x%x)",
986 d->d_icount, (int)d->d_icount);
987 cmn_err(CE_DEBUG, "---------------------------");
990 STATIC void
991 xfs_qm_dqtest_failed(
992 xfs_dqtest_t *d,
993 xfs_dquot_t *dqp,
994 char *reason,
995 xfs_qcnt_t a,
996 xfs_qcnt_t b,
997 int error)
999 qmtest_nfails++;
1000 if (error)
1001 cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s",
1002 d->d_id, error, reason);
1003 else
1004 cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]",
1005 d->d_id, reason, (int)a, (int)b);
1006 xfs_qm_dqtest_print(d);
1007 if (dqp)
1008 xfs_qm_dqprint(dqp);
1011 STATIC int
1012 xfs_dqtest_cmp2(
1013 xfs_dqtest_t *d,
1014 xfs_dquot_t *dqp)
1016 int err = 0;
1017 if (be64_to_cpu(dqp->q_core.d_icount) != d->d_icount) {
1018 xfs_qm_dqtest_failed(d, dqp, "icount mismatch",
1019 be64_to_cpu(dqp->q_core.d_icount),
1020 d->d_icount, 0);
1021 err++;
1023 if (be64_to_cpu(dqp->q_core.d_bcount) != d->d_bcount) {
1024 xfs_qm_dqtest_failed(d, dqp, "bcount mismatch",
1025 be64_to_cpu(dqp->q_core.d_bcount),
1026 d->d_bcount, 0);
1027 err++;
1029 if (dqp->q_core.d_blk_softlimit &&
1030 be64_to_cpu(dqp->q_core.d_bcount) >=
1031 be64_to_cpu(dqp->q_core.d_blk_softlimit)) {
1032 if (!dqp->q_core.d_btimer && dqp->q_core.d_id) {
1033 cmn_err(CE_DEBUG,
1034 "%d [%s] [0x%p] BLK TIMER NOT STARTED",
1035 d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
1036 err++;
1039 if (dqp->q_core.d_ino_softlimit &&
1040 be64_to_cpu(dqp->q_core.d_icount) >=
1041 be64_to_cpu(dqp->q_core.d_ino_softlimit)) {
1042 if (!dqp->q_core.d_itimer && dqp->q_core.d_id) {
1043 cmn_err(CE_DEBUG,
1044 "%d [%s] [0x%p] INO TIMER NOT STARTED",
1045 d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
1046 err++;
1049 #ifdef QUOTADEBUG
1050 if (!err) {
1051 cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
1052 d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
1054 #endif
1055 return (err);
1058 STATIC void
1059 xfs_dqtest_cmp(
1060 xfs_dqtest_t *d)
1062 xfs_dquot_t *dqp;
1063 int error;
1065 /* xfs_qm_dqtest_print(d); */
1066 if ((error = xfs_qm_dqget(d->q_mount, NULL, d->d_id, d->dq_flags, 0,
1067 &dqp))) {
1068 xfs_qm_dqtest_failed(d, NULL, "dqget failed", 0, 0, error);
1069 return;
1071 xfs_dqtest_cmp2(d, dqp);
1072 xfs_qm_dqput(dqp);
1075 STATIC int
1076 xfs_qm_internalqcheck_dqget(
1077 xfs_mount_t *mp,
1078 xfs_dqid_t id,
1079 uint type,
1080 xfs_dqtest_t **O_dq)
1082 xfs_dqtest_t *d;
1083 xfs_dqhash_t *h;
1085 h = DQTEST_HASH(mp, id, type);
1086 list_for_each_entry(d, &h->qh_list, q_hashlist) {
1087 if (d->d_id == id && mp == d->q_mount) {
1088 *O_dq = d;
1089 return (0);
1092 d = kmem_zalloc(sizeof(xfs_dqtest_t), KM_SLEEP);
1093 d->dq_flags = type;
1094 d->d_id = id;
1095 d->q_mount = mp;
1096 d->q_hash = h;
1097 INIT_LIST_HEAD(&d->q_hashlist);
1098 xfs_qm_hashinsert(h, d);
1099 *O_dq = d;
1100 return (0);
1103 STATIC void
1104 xfs_qm_internalqcheck_get_dquots(
1105 xfs_mount_t *mp,
1106 xfs_dqid_t uid,
1107 xfs_dqid_t projid,
1108 xfs_dqid_t gid,
1109 xfs_dqtest_t **ud,
1110 xfs_dqtest_t **gd)
1112 if (XFS_IS_UQUOTA_ON(mp))
1113 xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
1114 if (XFS_IS_GQUOTA_ON(mp))
1115 xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
1116 else if (XFS_IS_PQUOTA_ON(mp))
1117 xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);
1121 STATIC void
1122 xfs_qm_internalqcheck_dqadjust(
1123 xfs_inode_t *ip,
1124 xfs_dqtest_t *d)
1126 d->d_icount++;
1127 d->d_bcount += (xfs_qcnt_t)ip->i_d.di_nblocks;
1130 STATIC int
1131 xfs_qm_internalqcheck_adjust(
1132 xfs_mount_t *mp, /* mount point for filesystem */
1133 xfs_ino_t ino, /* inode number to get data for */
1134 void __user *buffer, /* not used */
1135 int ubsize, /* not used */
1136 int *ubused, /* not used */
1137 int *res) /* bulkstat result code */
1139 xfs_inode_t *ip;
1140 xfs_dqtest_t *ud, *gd;
1141 uint lock_flags;
1142 boolean_t ipreleased;
1143 int error;
1145 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
1147 if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {
1148 *res = BULKSTAT_RV_NOTHING;
1149 qdprintk("internalqcheck: ino=%llu, uqino=%llu, gqino=%llu\n",
1150 (unsigned long long) ino,
1151 (unsigned long long) mp->m_sb.sb_uquotino,
1152 (unsigned long long) mp->m_sb.sb_gquotino);
1153 return XFS_ERROR(EINVAL);
1155 ipreleased = B_FALSE;
1156 again:
1157 lock_flags = XFS_ILOCK_SHARED;
1158 if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip))) {
1159 *res = BULKSTAT_RV_NOTHING;
1160 return (error);
1164 * This inode can have blocks after eof which can get released
1165 * when we send it to inactive. Since we don't check the dquot
1166 * until the after all our calculations are done, we must get rid
1167 * of those now.
1169 if (! ipreleased) {
1170 xfs_iunlock(ip, lock_flags);
1171 IRELE(ip);
1172 ipreleased = B_TRUE;
1173 goto again;
1175 xfs_qm_internalqcheck_get_dquots(mp,
1176 (xfs_dqid_t) ip->i_d.di_uid,
1177 (xfs_dqid_t) ip->i_d.di_projid,
1178 (xfs_dqid_t) ip->i_d.di_gid,
1179 &ud, &gd);
1180 if (XFS_IS_UQUOTA_ON(mp)) {
1181 ASSERT(ud);
1182 xfs_qm_internalqcheck_dqadjust(ip, ud);
1184 if (XFS_IS_OQUOTA_ON(mp)) {
1185 ASSERT(gd);
1186 xfs_qm_internalqcheck_dqadjust(ip, gd);
1188 xfs_iunlock(ip, lock_flags);
1189 IRELE(ip);
1190 *res = BULKSTAT_RV_DIDONE;
1191 return (0);
1195 /* PRIVATE, debugging */
1197 xfs_qm_internalqcheck(
1198 xfs_mount_t *mp)
1200 xfs_ino_t lastino;
1201 int done, count;
1202 int i;
1203 int error;
1205 lastino = 0;
1206 qmtest_hashmask = 32;
1207 count = 5;
1208 done = 0;
1209 qmtest_nfails = 0;
1211 if (! XFS_IS_QUOTA_ON(mp))
1212 return XFS_ERROR(ESRCH);
1214 xfs_log_force(mp, XFS_LOG_SYNC);
1215 XFS_bflush(mp->m_ddev_targp);
1216 xfs_log_force(mp, XFS_LOG_SYNC);
1217 XFS_bflush(mp->m_ddev_targp);
1219 mutex_lock(&qcheck_lock);
1220 /* There should be absolutely no quota activity while this
1221 is going on. */
1222 qmtest_udqtab = kmem_zalloc(qmtest_hashmask *
1223 sizeof(xfs_dqhash_t), KM_SLEEP);
1224 qmtest_gdqtab = kmem_zalloc(qmtest_hashmask *
1225 sizeof(xfs_dqhash_t), KM_SLEEP);
1226 do {
1228 * Iterate thru all the inodes in the file system,
1229 * adjusting the corresponding dquot counters
1231 error = xfs_bulkstat(mp, &lastino, &count,
1232 xfs_qm_internalqcheck_adjust,
1233 0, NULL, &done);
1234 if (error) {
1235 cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
1236 break;
1238 } while (!done);
1240 cmn_err(CE_DEBUG, "Checking results against system dquots");
1241 for (i = 0; i < qmtest_hashmask; i++) {
1242 xfs_dqtest_t *d, *n;
1243 xfs_dqhash_t *h;
1245 h = &qmtest_udqtab[i];
1246 list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
1247 xfs_dqtest_cmp(d);
1248 kmem_free(d);
1250 h = &qmtest_gdqtab[i];
1251 list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
1252 xfs_dqtest_cmp(d);
1253 kmem_free(d);
1257 if (qmtest_nfails) {
1258 cmn_err(CE_DEBUG, "******** quotacheck failed ********");
1259 cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails);
1260 } else {
1261 cmn_err(CE_DEBUG, "******** quotacheck successful! ********");
1263 kmem_free(qmtest_udqtab);
1264 kmem_free(qmtest_gdqtab);
1265 mutex_unlock(&qcheck_lock);
1266 return (qmtest_nfails);
1269 #endif /* DEBUG */