Linux Audio

Check our new training course

Loading...
v6.9.4
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  4 * All Rights Reserved.
  5 */
  6
  7
  8#include "xfs.h"
  9#include "xfs_fs.h"
 10#include "xfs_shared.h"
 11#include "xfs_format.h"
 12#include "xfs_log_format.h"
 13#include "xfs_trans_resv.h"
 14#include "xfs_sb.h"
 15#include "xfs_mount.h"
 16#include "xfs_inode.h"
 17#include "xfs_trans.h"
 18#include "xfs_quota.h"
 19#include "xfs_qm.h"
 20#include "xfs_icache.h"
 21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 22int
 23xfs_qm_scall_quotaoff(
 24	xfs_mount_t		*mp,
 25	uint			flags)
 26{
 
 
 
 
 
 
 27	/*
 28	 * No file system can have quotas enabled on disk but not in core.
 29	 * Note that quota utilities (like quotaoff) _expect_
 30	 * errno == -EEXIST here.
 31	 */
 32	if ((mp->m_qflags & flags) == 0)
 33		return -EEXIST;
 
 
 
 34
 35	/*
 36	 * We do not support actually turning off quota accounting any more.
 37	 * Just log a warning and ignore the accounting related flags.
 
 
 38	 */
 39	if (flags & XFS_ALL_QUOTA_ACCT)
 40		xfs_info(mp, "disabling of quota accounting not supported.");
 41
 42	mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
 43	mp->m_qflags &= ~(flags & XFS_ALL_QUOTA_ENFD);
 44	spin_lock(&mp->m_sb_lock);
 45	mp->m_sb.sb_qflags = mp->m_qflags;
 46	spin_unlock(&mp->m_sb_lock);
 47	mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 48
 49	/* XXX what to do if error ? Revert back to old vals incore ? */
 50	return xfs_sync_sb(mp, false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 51}
 52
 53STATIC int
 54xfs_qm_scall_trunc_qfile(
 55	struct xfs_mount	*mp,
 56	xfs_ino_t		ino)
 57{
 58	struct xfs_inode	*ip;
 59	struct xfs_trans	*tp;
 60	int			error;
 61
 62	if (ino == NULLFSINO)
 63		return 0;
 64
 65	error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
 66	if (error)
 67		return error;
 68
 69	xfs_ilock(ip, XFS_IOLOCK_EXCL);
 70
 71	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
 72	if (error) {
 73		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 74		goto out_put;
 75	}
 76
 77	xfs_ilock(ip, XFS_ILOCK_EXCL);
 78	xfs_trans_ijoin(tp, ip, 0);
 79
 80	ip->i_disk_size = 0;
 81	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 82
 83	error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
 84	if (error) {
 85		xfs_trans_cancel(tp);
 86		goto out_unlock;
 87	}
 88
 89	ASSERT(ip->i_df.if_nextents == 0);
 90
 91	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 92	error = xfs_trans_commit(tp);
 93
 94out_unlock:
 95	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 96out_put:
 97	xfs_irele(ip);
 98	return error;
 99}
100
101int
102xfs_qm_scall_trunc_qfiles(
103	xfs_mount_t	*mp,
104	uint		flags)
105{
106	int		error = -EINVAL;
107
108	if (!xfs_has_quota(mp) || flags == 0 ||
109	    (flags & ~XFS_QMOPT_QUOTALL)) {
110		xfs_debug(mp, "%s: flags=%x m_qflags=%x",
111			__func__, flags, mp->m_qflags);
112		return -EINVAL;
113	}
114
115	if (flags & XFS_QMOPT_UQUOTA) {
116		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
117		if (error)
118			return error;
119	}
120	if (flags & XFS_QMOPT_GQUOTA) {
121		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
122		if (error)
123			return error;
124	}
125	if (flags & XFS_QMOPT_PQUOTA)
126		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
127
128	return error;
129}
130
131/*
132 * Switch on (a given) quota enforcement for a filesystem.  This takes
133 * effect immediately.
134 * (Switching on quota accounting must be done at mount time.)
135 */
136int
137xfs_qm_scall_quotaon(
138	xfs_mount_t	*mp,
139	uint		flags)
140{
141	int		error;
142	uint		qf;
143
144	/*
145	 * Switching on quota accounting must be done at mount time,
146	 * only consider quota enforcement stuff here.
147	 */
148	flags &= XFS_ALL_QUOTA_ENFD;
149
150	if (flags == 0) {
151		xfs_debug(mp, "%s: zero flags, m_qflags=%x",
152			__func__, mp->m_qflags);
153		return -EINVAL;
154	}
155
156	/*
157	 * Can't enforce without accounting. We check the superblock
158	 * qflags here instead of m_qflags because rootfs can have
159	 * quota acct on ondisk without m_qflags' knowing.
160	 */
161	if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
162	     (flags & XFS_UQUOTA_ENFD)) ||
163	    ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
164	     (flags & XFS_GQUOTA_ENFD)) ||
165	    ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
166	     (flags & XFS_PQUOTA_ENFD))) {
167		xfs_debug(mp,
168			"%s: Can't enforce without acct, flags=%x sbflags=%x",
169			__func__, flags, mp->m_sb.sb_qflags);
170		return -EINVAL;
171	}
172	/*
173	 * If everything's up to-date incore, then don't waste time.
174	 */
175	if ((mp->m_qflags & flags) == flags)
176		return -EEXIST;
177
178	/*
179	 * Change sb_qflags on disk but not incore mp->qflags
180	 * if this is the root filesystem.
181	 */
182	spin_lock(&mp->m_sb_lock);
183	qf = mp->m_sb.sb_qflags;
184	mp->m_sb.sb_qflags = qf | flags;
185	spin_unlock(&mp->m_sb_lock);
186
187	/*
188	 * There's nothing to change if it's the same.
189	 */
190	if ((qf & flags) == flags)
191		return -EEXIST;
192
193	error = xfs_sync_sb(mp, false);
194	if (error)
195		return error;
196	/*
197	 * If we aren't trying to switch on quota enforcement, we are done.
198	 */
199	if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
200	     (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
201	     ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
202	     (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
203	     ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
204	     (mp->m_qflags & XFS_GQUOTA_ACCT)))
205		return 0;
206
207	if (!XFS_IS_QUOTA_ON(mp))
208		return -ESRCH;
209
210	/*
211	 * Switch on quota enforcement in core.
212	 */
213	mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
214	mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
215	mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
216
217	return 0;
218}
219
220#define XFS_QC_MASK (QC_LIMIT_MASK | QC_TIMER_MASK)
 
221
222/*
223 * Adjust limits of this quota, and the defaults if passed in.  Returns true
224 * if the new limits made sense and were applied, false otherwise.
225 */
226static inline bool
227xfs_setqlim_limits(
228	struct xfs_mount	*mp,
229	struct xfs_dquot_res	*res,
230	struct xfs_quota_limits	*qlim,
231	xfs_qcnt_t		hard,
232	xfs_qcnt_t		soft,
233	const char		*tag)
234{
235	/* The hard limit can't be less than the soft limit. */
236	if (hard != 0 && hard < soft) {
237		xfs_debug(mp, "%shard %lld < %ssoft %lld", tag, hard, tag,
238				soft);
239		return false;
240	}
241
242	res->hardlimit = hard;
243	res->softlimit = soft;
244	if (qlim) {
245		qlim->hard = hard;
246		qlim->soft = soft;
247	}
248
249	return true;
250}
251
252static inline void
 
 
 
 
 
 
 
 
 
 
 
253xfs_setqlim_timer(
254	struct xfs_mount	*mp,
255	struct xfs_dquot_res	*res,
256	struct xfs_quota_limits	*qlim,
257	s64			timer)
258{
259	if (qlim) {
260		/* Set the length of the default grace period. */
261		res->timer = xfs_dquot_set_grace_period(timer);
262		qlim->time = res->timer;
263	} else {
264		/* Set the grace period expiration on a quota. */
265		res->timer = xfs_dquot_set_timeout(mp, timer);
266	}
267}
268
269/*
270 * Adjust quota limits, and start/stop timers accordingly.
271 */
272int
273xfs_qm_scall_setqlim(
274	struct xfs_mount	*mp,
275	xfs_dqid_t		id,
276	xfs_dqtype_t		type,
277	struct qc_dqblk		*newlim)
278{
279	struct xfs_quotainfo	*q = mp->m_quotainfo;
280	struct xfs_dquot	*dqp;
281	struct xfs_trans	*tp;
282	struct xfs_def_quota	*defq;
283	struct xfs_dquot_res	*res;
284	struct xfs_quota_limits	*qlim;
285	int			error;
286	xfs_qcnt_t		hard, soft;
287
288	if (newlim->d_fieldmask & ~XFS_QC_MASK)
289		return -EINVAL;
290	if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
291		return 0;
292
293	/*
 
 
 
 
 
 
 
294	 * Get the dquot (locked) before we start, as we need to do a
295	 * transaction to allocate it if it doesn't exist. Once we have the
296	 * dquot, unlock it so we can start the next transaction safely. We hold
297	 * a reference to the dquot, so it's safe to do this unlock/lock without
298	 * it being reclaimed in the mean time.
299	 */
300	error = xfs_qm_dqget(mp, id, type, true, &dqp);
301	if (error) {
302		ASSERT(error != -ENOENT);
303		return error;
304	}
305
306	defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
307	xfs_dqunlock(dqp);
308
309	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
310	if (error)
311		goto out_rele;
312
313	xfs_dqlock(dqp);
314	xfs_trans_dqjoin(tp, dqp);
315
316	/*
317	 * Update quota limits, warnings, and timers, and the defaults
318	 * if we're touching id == 0.
319	 *
320	 * Make sure that hardlimits are >= soft limits before changing.
321	 *
322	 * Update warnings counter(s) if requested.
323	 *
324	 * Timelimits for the super user set the relative time the other users
325	 * can be over quota for this file system. If it is zero a default is
326	 * used.  Ditto for the default soft and hard limit values (already
327	 * done, above), and for warnings.
328	 *
329	 * For other IDs, userspace can bump out the grace period if over
330	 * the soft limit.
331	 */
332
333	/* Blocks on the data device. */
334	hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
335		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
336			dqp->q_blk.hardlimit;
337	soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
338		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
339			dqp->q_blk.softlimit;
340	res = &dqp->q_blk;
341	qlim = id == 0 ? &defq->blk : NULL;
342
343	if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
344		xfs_dquot_set_prealloc_limits(dqp);
 
 
345	if (newlim->d_fieldmask & QC_SPC_TIMER)
346		xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
347
348	/* Blocks on the realtime device. */
349	hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
350		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
351			dqp->q_rtb.hardlimit;
352	soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
353		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
354			dqp->q_rtb.softlimit;
355	res = &dqp->q_rtb;
356	qlim = id == 0 ? &defq->rtb : NULL;
357
358	xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
 
 
359	if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
360		xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
361
362	/* Inodes */
363	hard = (newlim->d_fieldmask & QC_INO_HARD) ?
364		(xfs_qcnt_t) newlim->d_ino_hardlimit :
365			dqp->q_ino.hardlimit;
366	soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
367		(xfs_qcnt_t) newlim->d_ino_softlimit :
368			dqp->q_ino.softlimit;
369	res = &dqp->q_ino;
370	qlim = id == 0 ? &defq->ino : NULL;
371
372	xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
 
 
373	if (newlim->d_fieldmask & QC_INO_TIMER)
374		xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
375
376	if (id != 0) {
377		/*
378		 * If the user is now over quota, start the timelimit.
379		 * The user will not be 'warned'.
380		 * Note that we keep the timers ticking, whether enforcement
381		 * is on or off. We don't really want to bother with iterating
382		 * over all ondisk dquots and turning the timers on/off.
383		 */
384		xfs_qm_adjust_dqtimers(dqp);
385	}
386	dqp->q_flags |= XFS_DQFLAG_DIRTY;
387	xfs_trans_log_dquot(tp, dqp);
388
389	error = xfs_trans_commit(tp);
390
391out_rele:
392	xfs_qm_dqrele(dqp);
 
 
393	return error;
394}
395
396/* Fill out the quota context. */
397static void
398xfs_qm_scall_getquota_fill_qc(
399	struct xfs_mount	*mp,
400	xfs_dqtype_t		type,
401	const struct xfs_dquot	*dqp,
402	struct qc_dqblk		*dst)
403{
404	memset(dst, 0, sizeof(*dst));
405	dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
406	dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
407	dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
408	dst->d_ino_softlimit = dqp->q_ino.softlimit;
409	dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
410	dst->d_ino_count = dqp->q_ino.reserved;
411	dst->d_spc_timer = dqp->q_blk.timer;
412	dst->d_ino_timer = dqp->q_ino.timer;
413	dst->d_ino_warns = 0;
414	dst->d_spc_warns = 0;
415	dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
416	dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
417	dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
418	dst->d_rt_spc_timer = dqp->q_rtb.timer;
419	dst->d_rt_spc_warns = 0;
420
421	/*
422	 * Internally, we don't reset all the timers when quota enforcement
423	 * gets turned off. No need to confuse the user level code,
424	 * so return zeroes in that case.
425	 */
426	if (!xfs_dquot_is_enforced(dqp)) {
427		dst->d_spc_timer = 0;
428		dst->d_ino_timer = 0;
429		dst->d_rt_spc_timer = 0;
430	}
431
432#ifdef DEBUG
433	if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
434		if ((dst->d_space > dst->d_spc_softlimit) &&
435		    (dst->d_spc_softlimit > 0)) {
436			ASSERT(dst->d_spc_timer != 0);
437		}
438		if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
439		    (dqp->q_ino.softlimit > 0)) {
440			ASSERT(dst->d_ino_timer != 0);
441		}
442	}
443#endif
444}
445
446/* Return the quota information for the dquot matching id. */
447int
448xfs_qm_scall_getquota(
449	struct xfs_mount	*mp,
450	xfs_dqid_t		id,
451	xfs_dqtype_t		type,
452	struct qc_dqblk		*dst)
453{
454	struct xfs_dquot	*dqp;
455	int			error;
456
457	/*
458	 * Expedite pending inodegc work at the start of a quota reporting
459	 * scan but don't block waiting for it to complete.
460	 */
461	if (id == 0)
462		xfs_inodegc_push(mp);
463
464	/*
465	 * Try to get the dquot. We don't want it allocated on disk, so don't
466	 * set doalloc. If it doesn't exist, we'll get ENOENT back.
467	 */
468	error = xfs_qm_dqget(mp, id, type, false, &dqp);
469	if (error)
470		return error;
471
472	/*
473	 * If everything's NULL, this dquot doesn't quite exist as far as
474	 * our utility programs are concerned.
475	 */
476	if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
477		error = -ENOENT;
478		goto out_put;
479	}
480
481	xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
482
483out_put:
484	xfs_qm_dqput(dqp);
485	return error;
486}
487
488/*
489 * Return the quota information for the first initialized dquot whose id
490 * is at least as high as id.
491 */
492int
493xfs_qm_scall_getquota_next(
494	struct xfs_mount	*mp,
495	xfs_dqid_t		*id,
496	xfs_dqtype_t		type,
497	struct qc_dqblk		*dst)
498{
499	struct xfs_dquot	*dqp;
500	int			error;
501
502	/* Flush inodegc work at the start of a quota reporting scan. */
503	if (*id == 0)
504		xfs_inodegc_push(mp);
505
506	error = xfs_qm_dqget_next(mp, *id, type, &dqp);
507	if (error)
508		return error;
509
510	/* Fill in the ID we actually read from disk */
511	*id = dqp->q_id;
512
513	xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
514
515	xfs_qm_dqput(dqp);
516	return error;
517}
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  4 * All Rights Reserved.
  5 */
  6
  7
  8#include "xfs.h"
  9#include "xfs_fs.h"
 10#include "xfs_shared.h"
 11#include "xfs_format.h"
 12#include "xfs_log_format.h"
 13#include "xfs_trans_resv.h"
 14#include "xfs_sb.h"
 15#include "xfs_mount.h"
 16#include "xfs_inode.h"
 17#include "xfs_trans.h"
 18#include "xfs_quota.h"
 19#include "xfs_qm.h"
 20#include "xfs_icache.h"
 21
 22STATIC int
 23xfs_qm_log_quotaoff(
 24	struct xfs_mount	*mp,
 25	struct xfs_qoff_logitem	**qoffstartp,
 26	uint			flags)
 27{
 28	struct xfs_trans	*tp;
 29	int			error;
 30	struct xfs_qoff_logitem	*qoffi;
 31
 32	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_quotaoff, 0, 0, 0, &tp);
 33	if (error)
 34		goto out;
 35
 36	qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
 37	xfs_trans_log_quotaoff_item(tp, qoffi);
 38
 39	spin_lock(&mp->m_sb_lock);
 40	mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
 41	spin_unlock(&mp->m_sb_lock);
 42
 43	xfs_log_sb(tp);
 44
 45	/*
 46	 * We have to make sure that the transaction is secure on disk before we
 47	 * return and actually stop quota accounting. So, make it synchronous.
 48	 * We don't care about quotoff's performance.
 49	 */
 50	xfs_trans_set_sync(tp);
 51	error = xfs_trans_commit(tp);
 52	if (error)
 53		goto out;
 54
 55	*qoffstartp = qoffi;
 56out:
 57	return error;
 58}
 59
 60STATIC int
 61xfs_qm_log_quotaoff_end(
 62	struct xfs_mount	*mp,
 63	struct xfs_qoff_logitem	**startqoff,
 64	uint			flags)
 65{
 66	struct xfs_trans	*tp;
 67	int			error;
 68	struct xfs_qoff_logitem	*qoffi;
 69
 70	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_equotaoff, 0, 0, 0, &tp);
 71	if (error)
 72		return error;
 73
 74	qoffi = xfs_trans_get_qoff_item(tp, *startqoff,
 75					flags & XFS_ALL_QUOTA_ACCT);
 76	xfs_trans_log_quotaoff_item(tp, qoffi);
 77	*startqoff = NULL;
 78
 79	/*
 80	 * We have to make sure that the transaction is secure on disk before we
 81	 * return and actually stop quota accounting. So, make it synchronous.
 82	 * We don't care about quotoff's performance.
 83	 */
 84	xfs_trans_set_sync(tp);
 85	return xfs_trans_commit(tp);
 86}
 87
 88/*
 89 * Turn off quota accounting and/or enforcement for all udquots and/or
 90 * gdquots. Called only at unmount time.
 91 *
 92 * This assumes that there are no dquots of this file system cached
 93 * incore, and modifies the ondisk dquot directly. Therefore, for example,
 94 * it is an error to call this twice, without purging the cache.
 95 */
 96int
 97xfs_qm_scall_quotaoff(
 98	xfs_mount_t		*mp,
 99	uint			flags)
100{
101	struct xfs_quotainfo	*q = mp->m_quotainfo;
102	uint			dqtype;
103	int			error;
104	uint			inactivate_flags;
105	struct xfs_qoff_logitem	*qoffstart = NULL;
106
107	/*
108	 * No file system can have quotas enabled on disk but not in core.
109	 * Note that quota utilities (like quotaoff) _expect_
110	 * errno == -EEXIST here.
111	 */
112	if ((mp->m_qflags & flags) == 0)
113		return -EEXIST;
114	error = 0;
115
116	flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
117
118	/*
119	 * We don't want to deal with two quotaoffs messing up each other,
120	 * so we're going to serialize it. quotaoff isn't exactly a performance
121	 * critical thing.
122	 * If quotaoff, then we must be dealing with the root filesystem.
123	 */
124	ASSERT(q);
125	mutex_lock(&q->qi_quotaofflock);
126
127	/*
128	 * If we're just turning off quota enforcement, change mp and go.
129	 */
130	if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
131		mp->m_qflags &= ~(flags);
132
133		spin_lock(&mp->m_sb_lock);
134		mp->m_sb.sb_qflags = mp->m_qflags;
135		spin_unlock(&mp->m_sb_lock);
136		mutex_unlock(&q->qi_quotaofflock);
137
138		/* XXX what to do if error ? Revert back to old vals incore ? */
139		return xfs_sync_sb(mp, false);
140	}
141
142	dqtype = 0;
143	inactivate_flags = 0;
144	/*
145	 * If accounting is off, we must turn enforcement off, clear the
146	 * quota 'CHKD' certificate to make it known that we have to
147	 * do a quotacheck the next time this quota is turned on.
148	 */
149	if (flags & XFS_UQUOTA_ACCT) {
150		dqtype |= XFS_QMOPT_UQUOTA;
151		flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
152		inactivate_flags |= XFS_UQUOTA_ACTIVE;
153	}
154	if (flags & XFS_GQUOTA_ACCT) {
155		dqtype |= XFS_QMOPT_GQUOTA;
156		flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
157		inactivate_flags |= XFS_GQUOTA_ACTIVE;
158	}
159	if (flags & XFS_PQUOTA_ACCT) {
160		dqtype |= XFS_QMOPT_PQUOTA;
161		flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
162		inactivate_flags |= XFS_PQUOTA_ACTIVE;
163	}
164
165	/*
166	 * Nothing to do?  Don't complain. This happens when we're just
167	 * turning off quota enforcement.
168	 */
169	if ((mp->m_qflags & flags) == 0)
170		goto out_unlock;
171
172	/*
173	 * Write the LI_QUOTAOFF log record, and do SB changes atomically,
174	 * and synchronously. If we fail to write, we should abort the
175	 * operation as it cannot be recovered safely if we crash.
176	 */
177	error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
178	if (error)
179		goto out_unlock;
180
181	/*
182	 * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
183	 * to take care of the race between dqget and quotaoff. We don't take
184	 * any special locks to reset these bits. All processes need to check
185	 * these bits *after* taking inode lock(s) to see if the particular
186	 * quota type is in the process of being turned off. If *ACTIVE, it is
187	 * guaranteed that all dquot structures and all quotainode ptrs will all
188	 * stay valid as long as that inode is kept locked.
189	 *
190	 * There is no turning back after this.
191	 */
192	mp->m_qflags &= ~inactivate_flags;
193
194	/*
195	 * Give back all the dquot reference(s) held by inodes.
196	 * Here we go thru every single incore inode in this file system, and
197	 * do a dqrele on the i_udquot/i_gdquot that it may have.
198	 * Essentially, as long as somebody has an inode locked, this guarantees
199	 * that quotas will not be turned off. This is handy because in a
200	 * transaction once we lock the inode(s) and check for quotaon, we can
201	 * depend on the quota inodes (and other things) being valid as long as
202	 * we keep the lock(s).
203	 */
204	error = xfs_dqrele_all_inodes(mp, flags);
205	ASSERT(!error);
206
207	/*
208	 * Next we make the changes in the quota flag in the mount struct.
209	 * This isn't protected by a particular lock directly, because we
210	 * don't want to take a mrlock every time we depend on quotas being on.
211	 */
212	mp->m_qflags &= ~flags;
213
214	/*
215	 * Go through all the dquots of this file system and purge them,
216	 * according to what was turned off.
217	 */
218	xfs_qm_dqpurge_all(mp, dqtype);
219
220	/*
221	 * Transactions that had started before ACTIVE state bit was cleared
222	 * could have logged many dquots, so they'd have higher LSNs than
223	 * the first QUOTAOFF log record does. If we happen to crash when
224	 * the tail of the log has gone past the QUOTAOFF record, but
225	 * before the last dquot modification, those dquots __will__
226	 * recover, and that's not good.
227	 *
228	 * So, we have QUOTAOFF start and end logitems; the start
229	 * logitem won't get overwritten until the end logitem appears...
230	 */
231	error = xfs_qm_log_quotaoff_end(mp, &qoffstart, flags);
232	if (error) {
233		/* We're screwed now. Shutdown is the only option. */
234		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
235		goto out_unlock;
236	}
237
238	/*
239	 * If all quotas are completely turned off, close shop.
240	 */
241	if (mp->m_qflags == 0) {
242		mutex_unlock(&q->qi_quotaofflock);
243		xfs_qm_destroy_quotainfo(mp);
244		return 0;
245	}
246
247	/*
248	 * Release our quotainode references if we don't need them anymore.
249	 */
250	if ((dqtype & XFS_QMOPT_UQUOTA) && q->qi_uquotaip) {
251		xfs_irele(q->qi_uquotaip);
252		q->qi_uquotaip = NULL;
253	}
254	if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
255		xfs_irele(q->qi_gquotaip);
256		q->qi_gquotaip = NULL;
257	}
258	if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
259		xfs_irele(q->qi_pquotaip);
260		q->qi_pquotaip = NULL;
261	}
262
263out_unlock:
264	if (error && qoffstart)
265		xfs_qm_qoff_logitem_relse(qoffstart);
266	mutex_unlock(&q->qi_quotaofflock);
267	return error;
268}
269
270STATIC int
271xfs_qm_scall_trunc_qfile(
272	struct xfs_mount	*mp,
273	xfs_ino_t		ino)
274{
275	struct xfs_inode	*ip;
276	struct xfs_trans	*tp;
277	int			error;
278
279	if (ino == NULLFSINO)
280		return 0;
281
282	error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
283	if (error)
284		return error;
285
286	xfs_ilock(ip, XFS_IOLOCK_EXCL);
287
288	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
289	if (error) {
290		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
291		goto out_put;
292	}
293
294	xfs_ilock(ip, XFS_ILOCK_EXCL);
295	xfs_trans_ijoin(tp, ip, 0);
296
297	ip->i_disk_size = 0;
298	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
299
300	error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
301	if (error) {
302		xfs_trans_cancel(tp);
303		goto out_unlock;
304	}
305
306	ASSERT(ip->i_df.if_nextents == 0);
307
308	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
309	error = xfs_trans_commit(tp);
310
311out_unlock:
312	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
313out_put:
314	xfs_irele(ip);
315	return error;
316}
317
318int
319xfs_qm_scall_trunc_qfiles(
320	xfs_mount_t	*mp,
321	uint		flags)
322{
323	int		error = -EINVAL;
324
325	if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0 ||
326	    (flags & ~XFS_QMOPT_QUOTALL)) {
327		xfs_debug(mp, "%s: flags=%x m_qflags=%x",
328			__func__, flags, mp->m_qflags);
329		return -EINVAL;
330	}
331
332	if (flags & XFS_QMOPT_UQUOTA) {
333		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
334		if (error)
335			return error;
336	}
337	if (flags & XFS_QMOPT_GQUOTA) {
338		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
339		if (error)
340			return error;
341	}
342	if (flags & XFS_QMOPT_PQUOTA)
343		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
344
345	return error;
346}
347
348/*
349 * Switch on (a given) quota enforcement for a filesystem.  This takes
350 * effect immediately.
351 * (Switching on quota accounting must be done at mount time.)
352 */
353int
354xfs_qm_scall_quotaon(
355	xfs_mount_t	*mp,
356	uint		flags)
357{
358	int		error;
359	uint		qf;
360
361	/*
362	 * Switching on quota accounting must be done at mount time,
363	 * only consider quota enforcement stuff here.
364	 */
365	flags &= XFS_ALL_QUOTA_ENFD;
366
367	if (flags == 0) {
368		xfs_debug(mp, "%s: zero flags, m_qflags=%x",
369			__func__, mp->m_qflags);
370		return -EINVAL;
371	}
372
373	/*
374	 * Can't enforce without accounting. We check the superblock
375	 * qflags here instead of m_qflags because rootfs can have
376	 * quota acct on ondisk without m_qflags' knowing.
377	 */
378	if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
379	     (flags & XFS_UQUOTA_ENFD)) ||
380	    ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
381	     (flags & XFS_GQUOTA_ENFD)) ||
382	    ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
383	     (flags & XFS_PQUOTA_ENFD))) {
384		xfs_debug(mp,
385			"%s: Can't enforce without acct, flags=%x sbflags=%x",
386			__func__, flags, mp->m_sb.sb_qflags);
387		return -EINVAL;
388	}
389	/*
390	 * If everything's up to-date incore, then don't waste time.
391	 */
392	if ((mp->m_qflags & flags) == flags)
393		return -EEXIST;
394
395	/*
396	 * Change sb_qflags on disk but not incore mp->qflags
397	 * if this is the root filesystem.
398	 */
399	spin_lock(&mp->m_sb_lock);
400	qf = mp->m_sb.sb_qflags;
401	mp->m_sb.sb_qflags = qf | flags;
402	spin_unlock(&mp->m_sb_lock);
403
404	/*
405	 * There's nothing to change if it's the same.
406	 */
407	if ((qf & flags) == flags)
408		return -EEXIST;
409
410	error = xfs_sync_sb(mp, false);
411	if (error)
412		return error;
413	/*
414	 * If we aren't trying to switch on quota enforcement, we are done.
415	 */
416	if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
417	     (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
418	     ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
419	     (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
420	     ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
421	     (mp->m_qflags & XFS_GQUOTA_ACCT)))
422		return 0;
423
424	if (! XFS_IS_QUOTA_RUNNING(mp))
425		return -ESRCH;
426
427	/*
428	 * Switch on quota enforcement in core.
429	 */
430	mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
431	mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
432	mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
433
434	return 0;
435}
436
437#define XFS_QC_MASK \
438	(QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
439
440/*
441 * Adjust limits of this quota, and the defaults if passed in.  Returns true
442 * if the new limits made sense and were applied, false otherwise.
443 */
444static inline bool
445xfs_setqlim_limits(
446	struct xfs_mount	*mp,
447	struct xfs_dquot_res	*res,
448	struct xfs_quota_limits	*qlim,
449	xfs_qcnt_t		hard,
450	xfs_qcnt_t		soft,
451	const char		*tag)
452{
453	/* The hard limit can't be less than the soft limit. */
454	if (hard != 0 && hard < soft) {
455		xfs_debug(mp, "%shard %lld < %ssoft %lld", tag, hard, tag,
456				soft);
457		return false;
458	}
459
460	res->hardlimit = hard;
461	res->softlimit = soft;
462	if (qlim) {
463		qlim->hard = hard;
464		qlim->soft = soft;
465	}
466
467	return true;
468}
469
470static inline void
471xfs_setqlim_warns(
472	struct xfs_dquot_res	*res,
473	struct xfs_quota_limits	*qlim,
474	int			warns)
475{
476	res->warnings = warns;
477	if (qlim)
478		qlim->warn = warns;
479}
480
481static inline void
482xfs_setqlim_timer(
483	struct xfs_mount	*mp,
484	struct xfs_dquot_res	*res,
485	struct xfs_quota_limits	*qlim,
486	s64			timer)
487{
488	if (qlim) {
489		/* Set the length of the default grace period. */
490		res->timer = xfs_dquot_set_grace_period(timer);
491		qlim->time = res->timer;
492	} else {
493		/* Set the grace period expiration on a quota. */
494		res->timer = xfs_dquot_set_timeout(mp, timer);
495	}
496}
497
498/*
499 * Adjust quota limits, and start/stop timers accordingly.
500 */
501int
502xfs_qm_scall_setqlim(
503	struct xfs_mount	*mp,
504	xfs_dqid_t		id,
505	xfs_dqtype_t		type,
506	struct qc_dqblk		*newlim)
507{
508	struct xfs_quotainfo	*q = mp->m_quotainfo;
509	struct xfs_dquot	*dqp;
510	struct xfs_trans	*tp;
511	struct xfs_def_quota	*defq;
512	struct xfs_dquot_res	*res;
513	struct xfs_quota_limits	*qlim;
514	int			error;
515	xfs_qcnt_t		hard, soft;
516
517	if (newlim->d_fieldmask & ~XFS_QC_MASK)
518		return -EINVAL;
519	if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
520		return 0;
521
522	/*
523	 * We don't want to race with a quotaoff so take the quotaoff lock.
524	 * We don't hold an inode lock, so there's nothing else to stop
525	 * a quotaoff from happening.
526	 */
527	mutex_lock(&q->qi_quotaofflock);
528
529	/*
530	 * Get the dquot (locked) before we start, as we need to do a
531	 * transaction to allocate it if it doesn't exist. Once we have the
532	 * dquot, unlock it so we can start the next transaction safely. We hold
533	 * a reference to the dquot, so it's safe to do this unlock/lock without
534	 * it being reclaimed in the mean time.
535	 */
536	error = xfs_qm_dqget(mp, id, type, true, &dqp);
537	if (error) {
538		ASSERT(error != -ENOENT);
539		goto out_unlock;
540	}
541
542	defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
543	xfs_dqunlock(dqp);
544
545	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
546	if (error)
547		goto out_rele;
548
549	xfs_dqlock(dqp);
550	xfs_trans_dqjoin(tp, dqp);
551
552	/*
553	 * Update quota limits, warnings, and timers, and the defaults
554	 * if we're touching id == 0.
555	 *
556	 * Make sure that hardlimits are >= soft limits before changing.
557	 *
558	 * Update warnings counter(s) if requested.
559	 *
560	 * Timelimits for the super user set the relative time the other users
561	 * can be over quota for this file system. If it is zero a default is
562	 * used.  Ditto for the default soft and hard limit values (already
563	 * done, above), and for warnings.
564	 *
565	 * For other IDs, userspace can bump out the grace period if over
566	 * the soft limit.
567	 */
568
569	/* Blocks on the data device. */
570	hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
571		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
572			dqp->q_blk.hardlimit;
573	soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
574		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
575			dqp->q_blk.softlimit;
576	res = &dqp->q_blk;
577	qlim = id == 0 ? &defq->blk : NULL;
578
579	if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
580		xfs_dquot_set_prealloc_limits(dqp);
581	if (newlim->d_fieldmask & QC_SPC_WARNS)
582		xfs_setqlim_warns(res, qlim, newlim->d_spc_warns);
583	if (newlim->d_fieldmask & QC_SPC_TIMER)
584		xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
585
586	/* Blocks on the realtime device. */
587	hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
588		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
589			dqp->q_rtb.hardlimit;
590	soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
591		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
592			dqp->q_rtb.softlimit;
593	res = &dqp->q_rtb;
594	qlim = id == 0 ? &defq->rtb : NULL;
595
596	xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
597	if (newlim->d_fieldmask & QC_RT_SPC_WARNS)
598		xfs_setqlim_warns(res, qlim, newlim->d_rt_spc_warns);
599	if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
600		xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
601
602	/* Inodes */
603	hard = (newlim->d_fieldmask & QC_INO_HARD) ?
604		(xfs_qcnt_t) newlim->d_ino_hardlimit :
605			dqp->q_ino.hardlimit;
606	soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
607		(xfs_qcnt_t) newlim->d_ino_softlimit :
608			dqp->q_ino.softlimit;
609	res = &dqp->q_ino;
610	qlim = id == 0 ? &defq->ino : NULL;
611
612	xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
613	if (newlim->d_fieldmask & QC_INO_WARNS)
614		xfs_setqlim_warns(res, qlim, newlim->d_ino_warns);
615	if (newlim->d_fieldmask & QC_INO_TIMER)
616		xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
617
618	if (id != 0) {
619		/*
620		 * If the user is now over quota, start the timelimit.
621		 * The user will not be 'warned'.
622		 * Note that we keep the timers ticking, whether enforcement
623		 * is on or off. We don't really want to bother with iterating
624		 * over all ondisk dquots and turning the timers on/off.
625		 */
626		xfs_qm_adjust_dqtimers(dqp);
627	}
628	dqp->q_flags |= XFS_DQFLAG_DIRTY;
629	xfs_trans_log_dquot(tp, dqp);
630
631	error = xfs_trans_commit(tp);
632
633out_rele:
634	xfs_qm_dqrele(dqp);
635out_unlock:
636	mutex_unlock(&q->qi_quotaofflock);
637	return error;
638}
639
640/* Fill out the quota context. */
641static void
642xfs_qm_scall_getquota_fill_qc(
643	struct xfs_mount	*mp,
644	xfs_dqtype_t		type,
645	const struct xfs_dquot	*dqp,
646	struct qc_dqblk		*dst)
647{
648	memset(dst, 0, sizeof(*dst));
649	dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
650	dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
651	dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
652	dst->d_ino_softlimit = dqp->q_ino.softlimit;
653	dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
654	dst->d_ino_count = dqp->q_ino.reserved;
655	dst->d_spc_timer = dqp->q_blk.timer;
656	dst->d_ino_timer = dqp->q_ino.timer;
657	dst->d_ino_warns = dqp->q_ino.warnings;
658	dst->d_spc_warns = dqp->q_blk.warnings;
659	dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
660	dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
661	dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
662	dst->d_rt_spc_timer = dqp->q_rtb.timer;
663	dst->d_rt_spc_warns = dqp->q_rtb.warnings;
664
665	/*
666	 * Internally, we don't reset all the timers when quota enforcement
667	 * gets turned off. No need to confuse the user level code,
668	 * so return zeroes in that case.
669	 */
670	if (!xfs_dquot_is_enforced(dqp)) {
671		dst->d_spc_timer = 0;
672		dst->d_ino_timer = 0;
673		dst->d_rt_spc_timer = 0;
674	}
675
676#ifdef DEBUG
677	if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
678		if ((dst->d_space > dst->d_spc_softlimit) &&
679		    (dst->d_spc_softlimit > 0)) {
680			ASSERT(dst->d_spc_timer != 0);
681		}
682		if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
683		    (dqp->q_ino.softlimit > 0)) {
684			ASSERT(dst->d_ino_timer != 0);
685		}
686	}
687#endif
688}
689
690/* Return the quota information for the dquot matching id. */
691int
692xfs_qm_scall_getquota(
693	struct xfs_mount	*mp,
694	xfs_dqid_t		id,
695	xfs_dqtype_t		type,
696	struct qc_dqblk		*dst)
697{
698	struct xfs_dquot	*dqp;
699	int			error;
700
701	/*
 
 
 
 
 
 
 
702	 * Try to get the dquot. We don't want it allocated on disk, so don't
703	 * set doalloc. If it doesn't exist, we'll get ENOENT back.
704	 */
705	error = xfs_qm_dqget(mp, id, type, false, &dqp);
706	if (error)
707		return error;
708
709	/*
710	 * If everything's NULL, this dquot doesn't quite exist as far as
711	 * our utility programs are concerned.
712	 */
713	if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
714		error = -ENOENT;
715		goto out_put;
716	}
717
718	xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
719
720out_put:
721	xfs_qm_dqput(dqp);
722	return error;
723}
724
725/*
726 * Return the quota information for the first initialized dquot whose id
727 * is at least as high as id.
728 */
729int
730xfs_qm_scall_getquota_next(
731	struct xfs_mount	*mp,
732	xfs_dqid_t		*id,
733	xfs_dqtype_t		type,
734	struct qc_dqblk		*dst)
735{
736	struct xfs_dquot	*dqp;
737	int			error;
 
 
 
 
738
739	error = xfs_qm_dqget_next(mp, *id, type, &dqp);
740	if (error)
741		return error;
742
743	/* Fill in the ID we actually read from disk */
744	*id = dqp->q_id;
745
746	xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
747
748	xfs_qm_dqput(dqp);
749	return error;
750}