Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Apr 14-17, 2025
Register
Loading...
v6.13.7
  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_dqtype_t		type)
 57{
 58	struct xfs_inode	*ip;
 59	struct xfs_trans	*tp;
 60	int			error;
 61
 62	error = xfs_qm_qino_load(mp, type, &ip);
 63	if (error == -ENOENT)
 64		return 0;
 
 
 65	if (error)
 66		return error;
 67
 68	xfs_ilock(ip, XFS_IOLOCK_EXCL);
 69
 70	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
 
 71	if (error) {
 
 72		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 73		goto out_put;
 74	}
 75
 76	xfs_ilock(ip, XFS_ILOCK_EXCL);
 77	xfs_trans_ijoin(tp, ip, 0);
 78
 79	ip->i_disk_size = 0;
 80	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 81
 82	error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
 83	if (error) {
 84		xfs_trans_cancel(tp);
 
 85		goto out_unlock;
 86	}
 87
 88	ASSERT(ip->i_df.if_nextents == 0);
 89
 90	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 91	error = xfs_trans_commit(tp);
 92
 93out_unlock:
 94	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 95out_put:
 96	xfs_irele(ip);
 97	return error;
 98}
 99
100int
101xfs_qm_scall_trunc_qfiles(
102	xfs_mount_t	*mp,
103	uint		flags)
104{
105	int		error = -EINVAL;
106
107	if (!xfs_has_quota(mp) || flags == 0 ||
108	    (flags & ~XFS_QMOPT_QUOTALL)) {
109		xfs_debug(mp, "%s: flags=%x m_qflags=%x",
110			__func__, flags, mp->m_qflags);
111		return -EINVAL;
112	}
113
114	if (flags & XFS_QMOPT_UQUOTA) {
115		error = xfs_qm_scall_trunc_qfile(mp, XFS_DQTYPE_USER);
116		if (error)
117			return error;
118	}
119	if (flags & XFS_QMOPT_GQUOTA) {
120		error = xfs_qm_scall_trunc_qfile(mp, XFS_DQTYPE_GROUP);
121		if (error)
122			return error;
123	}
124	if (flags & XFS_QMOPT_PQUOTA)
125		error = xfs_qm_scall_trunc_qfile(mp, XFS_DQTYPE_PROJ);
126
127	return error;
128}
129
130/*
131 * Switch on (a given) quota enforcement for a filesystem.  This takes
132 * effect immediately.
133 * (Switching on quota accounting must be done at mount time.)
134 */
135int
136xfs_qm_scall_quotaon(
137	xfs_mount_t	*mp,
138	uint		flags)
139{
140	int		error;
141	uint		qf;
 
142
 
143	/*
144	 * Switching on quota accounting must be done at mount time,
145	 * only consider quota enforcement stuff here.
146	 */
147	flags &= XFS_ALL_QUOTA_ENFD;
 
 
148
149	if (flags == 0) {
150		xfs_debug(mp, "%s: zero flags, m_qflags=%x",
151			__func__, mp->m_qflags);
152		return -EINVAL;
153	}
154
 
 
 
155	/*
156	 * Can't enforce without accounting. We check the superblock
157	 * qflags here instead of m_qflags because rootfs can have
158	 * quota acct on ondisk without m_qflags' knowing.
159	 */
160	if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
 
161	     (flags & XFS_UQUOTA_ENFD)) ||
162	    ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
 
163	     (flags & XFS_GQUOTA_ENFD)) ||
164	    ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
 
165	     (flags & XFS_PQUOTA_ENFD))) {
166		xfs_debug(mp,
167			"%s: Can't enforce without acct, flags=%x sbflags=%x",
168			__func__, flags, mp->m_sb.sb_qflags);
169		return -EINVAL;
170	}
171	/*
172	 * If everything's up to-date incore, then don't waste time.
173	 */
174	if ((mp->m_qflags & flags) == flags)
175		return -EEXIST;
176
177	/*
178	 * Change sb_qflags on disk but not incore mp->qflags
179	 * if this is the root filesystem.
180	 */
181	spin_lock(&mp->m_sb_lock);
182	qf = mp->m_sb.sb_qflags;
183	mp->m_sb.sb_qflags = qf | flags;
184	spin_unlock(&mp->m_sb_lock);
185
186	/*
187	 * There's nothing to change if it's the same.
188	 */
189	if ((qf & flags) == flags)
190		return -EEXIST;
 
191
192	error = xfs_sync_sb(mp, false);
193	if (error)
194		return error;
195	/*
196	 * If we aren't trying to switch on quota enforcement, we are done.
197	 */
198	if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
199	     (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
200	     ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
201	     (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
202	     ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
203	     (mp->m_qflags & XFS_GQUOTA_ACCT)))
204		return 0;
 
205
206	if (!XFS_IS_QUOTA_ON(mp))
207		return -ESRCH;
208
209	/*
210	 * Switch on quota enforcement in core.
211	 */
212	mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
213	mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
214	mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
215
216	return 0;
217}
218
219#define XFS_QC_MASK (QC_LIMIT_MASK | QC_TIMER_MASK)
220
221/*
222 * Adjust limits of this quota, and the defaults if passed in.  Returns true
223 * if the new limits made sense and were applied, false otherwise.
224 */
225static inline bool
226xfs_setqlim_limits(
227	struct xfs_mount	*mp,
228	struct xfs_dquot_res	*res,
229	struct xfs_quota_limits	*qlim,
230	xfs_qcnt_t		hard,
231	xfs_qcnt_t		soft,
232	const char		*tag)
233{
234	/* The hard limit can't be less than the soft limit. */
235	if (hard != 0 && hard < soft) {
236		xfs_debug(mp, "%shard %lld < %ssoft %lld", tag, hard, tag,
237				soft);
238		return false;
239	}
240
241	res->hardlimit = hard;
242	res->softlimit = soft;
243	if (qlim) {
244		qlim->hard = hard;
245		qlim->soft = soft;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246	}
247
248	return true;
249}
250
251static inline void
252xfs_setqlim_timer(
 
 
 
 
253	struct xfs_mount	*mp,
254	struct xfs_dquot_res	*res,
255	struct xfs_quota_limits	*qlim,
256	s64			timer)
257{
258	if (qlim) {
259		/* Set the length of the default grace period. */
260		res->timer = xfs_dquot_set_grace_period(timer);
261		qlim->time = res->timer;
262	} else {
263		/* Set the grace period expiration on a quota. */
264		res->timer = xfs_dquot_set_timeout(mp, timer);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265	}
 
266}
267
 
 
 
268/*
269 * Adjust quota limits, and start/stop timers accordingly.
270 */
271int
272xfs_qm_scall_setqlim(
273	struct xfs_mount	*mp,
274	xfs_dqid_t		id,
275	xfs_dqtype_t		type,
276	struct qc_dqblk		*newlim)
277{
278	struct xfs_quotainfo	*q = mp->m_quotainfo;
 
279	struct xfs_dquot	*dqp;
280	struct xfs_trans	*tp;
281	struct xfs_def_quota	*defq;
282	struct xfs_dquot_res	*res;
283	struct xfs_quota_limits	*qlim;
284	int			error;
285	xfs_qcnt_t		hard, soft;
286
287	if (newlim->d_fieldmask & ~XFS_QC_MASK)
288		return -EINVAL;
289	if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
290		return 0;
291
292	/*
 
 
 
 
 
 
 
293	 * Get the dquot (locked) before we start, as we need to do a
294	 * transaction to allocate it if it doesn't exist. Once we have the
295	 * dquot, unlock it so we can start the next transaction safely. We hold
296	 * a reference to the dquot, so it's safe to do this unlock/lock without
297	 * it being reclaimed in the mean time.
298	 */
299	error = xfs_qm_dqget(mp, id, type, true, &dqp);
300	if (error) {
301		ASSERT(error != -ENOENT);
302		return error;
303	}
304
305	defq = xfs_get_defquota(q, xfs_dquot_type(dqp));
306	xfs_dqunlock(dqp);
307
308	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_qm_setqlim, 0, 0, 0, &tp);
309	if (error)
 
 
310		goto out_rele;
 
311
312	xfs_dqlock(dqp);
313	xfs_trans_dqjoin(tp, dqp);
 
314
315	/*
316	 * Update quota limits, warnings, and timers, and the defaults
317	 * if we're touching id == 0.
318	 *
319	 * Make sure that hardlimits are >= soft limits before changing.
320	 *
321	 * Update warnings counter(s) if requested.
322	 *
323	 * Timelimits for the super user set the relative time the other users
324	 * can be over quota for this file system. If it is zero a default is
325	 * used.  Ditto for the default soft and hard limit values (already
326	 * done, above), and for warnings.
327	 *
328	 * For other IDs, userspace can bump out the grace period if over
329	 * the soft limit.
330	 */
331
332	/* Blocks on the data device. */
333	hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
334		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
335			dqp->q_blk.hardlimit;
336	soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
337		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
338			dqp->q_blk.softlimit;
339	res = &dqp->q_blk;
340	qlim = id == 0 ? &defq->blk : NULL;
341
342	if (xfs_setqlim_limits(mp, res, qlim, hard, soft, "blk"))
343		xfs_dquot_set_prealloc_limits(dqp);
344	if (newlim->d_fieldmask & QC_SPC_TIMER)
345		xfs_setqlim_timer(mp, res, qlim, newlim->d_spc_timer);
346
347	/* Blocks on the realtime device. */
348	hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
349		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
350			dqp->q_rtb.hardlimit;
351	soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
352		(xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
353			dqp->q_rtb.softlimit;
354	res = &dqp->q_rtb;
355	qlim = id == 0 ? &defq->rtb : NULL;
356
357	xfs_setqlim_limits(mp, res, qlim, hard, soft, "rtb");
358	if (newlim->d_fieldmask & QC_RT_SPC_TIMER)
359		xfs_setqlim_timer(mp, res, qlim, newlim->d_rt_spc_timer);
 
 
 
 
 
 
 
360
361	/* Inodes */
362	hard = (newlim->d_fieldmask & QC_INO_HARD) ?
363		(xfs_qcnt_t) newlim->d_ino_hardlimit :
364			dqp->q_ino.hardlimit;
365	soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
366		(xfs_qcnt_t) newlim->d_ino_softlimit :
367			dqp->q_ino.softlimit;
368	res = &dqp->q_ino;
369	qlim = id == 0 ? &defq->ino : NULL;
370
371	xfs_setqlim_limits(mp, res, qlim, hard, soft, "ino");
372	if (newlim->d_fieldmask & QC_INO_TIMER)
373		xfs_setqlim_timer(mp, res, qlim, newlim->d_ino_timer);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
375	if (id != 0) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376		/*
377		 * If the user is now over quota, start the timelimit.
378		 * The user will not be 'warned'.
379		 * Note that we keep the timers ticking, whether enforcement
380		 * is on or off. We don't really want to bother with iterating
381		 * over all ondisk dquots and turning the timers on/off.
382		 */
383		xfs_qm_adjust_dqtimers(dqp);
384	}
385	dqp->q_flags |= XFS_DQFLAG_DIRTY;
386	xfs_trans_log_dquot(tp, dqp);
387
388	error = xfs_trans_commit(tp);
389
390out_rele:
391	xfs_qm_dqrele(dqp);
 
 
392	return error;
393}
394
395/* Fill out the quota context. */
396static void
397xfs_qm_scall_getquota_fill_qc(
398	struct xfs_mount	*mp,
399	xfs_dqtype_t		type,
400	const struct xfs_dquot	*dqp,
401	struct qc_dqblk		*dst)
402{
403	memset(dst, 0, sizeof(*dst));
404	dst->d_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_blk.hardlimit);
405	dst->d_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_blk.softlimit);
406	dst->d_ino_hardlimit = dqp->q_ino.hardlimit;
407	dst->d_ino_softlimit = dqp->q_ino.softlimit;
408	dst->d_space = XFS_FSB_TO_B(mp, dqp->q_blk.reserved);
409	dst->d_ino_count = dqp->q_ino.reserved;
410	dst->d_spc_timer = dqp->q_blk.timer;
411	dst->d_ino_timer = dqp->q_ino.timer;
412	dst->d_ino_warns = 0;
413	dst->d_spc_warns = 0;
414	dst->d_rt_spc_hardlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.hardlimit);
415	dst->d_rt_spc_softlimit = XFS_FSB_TO_B(mp, dqp->q_rtb.softlimit);
416	dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_rtb.reserved);
417	dst->d_rt_spc_timer = dqp->q_rtb.timer;
418	dst->d_rt_spc_warns = 0;
419
420	/*
421	 * Internally, we don't reset all the timers when quota enforcement
422	 * gets turned off. No need to confuse the user level code,
423	 * so return zeroes in that case.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424	 */
425	if (!xfs_dquot_is_enforced(dqp)) {
426		dst->d_spc_timer = 0;
427		dst->d_ino_timer = 0;
428		dst->d_rt_spc_timer = 0;
 
 
 
 
 
 
 
 
 
429	}
 
 
430}
431
432/* Return the quota information for the dquot matching id. */
433int
434xfs_qm_scall_getquota(
435	struct xfs_mount	*mp,
436	xfs_dqid_t		id,
437	xfs_dqtype_t		type,
438	struct qc_dqblk		*dst)
439{
440	struct xfs_dquot	*dqp;
441	int			error;
442
443	/*
444	 * Expedite pending inodegc work at the start of a quota reporting
445	 * scan but don't block waiting for it to complete.
446	 */
447	if (id == 0)
448		xfs_inodegc_push(mp);
449
450	/*
451	 * Try to get the dquot. We don't want it allocated on disk, so don't
452	 * set doalloc. If it doesn't exist, we'll get ENOENT back.
453	 */
454	error = xfs_qm_dqget(mp, id, type, false, &dqp);
455	if (error)
456		return error;
457
458	/*
459	 * If everything's NULL, this dquot doesn't quite exist as far as
460	 * our utility programs are concerned.
461	 */
462	if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
463		error = -ENOENT;
464		goto out_put;
465	}
466
467	xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469out_put:
470	xfs_qm_dqput(dqp);
471	return error;
472}
473
474/*
475 * Return the quota information for the first initialized dquot whose id
476 * is at least as high as id.
477 */
478int
479xfs_qm_scall_getquota_next(
480	struct xfs_mount	*mp,
481	xfs_dqid_t		*id,
482	xfs_dqtype_t		type,
483	struct qc_dqblk		*dst)
484{
485	struct xfs_dquot	*dqp;
486	int			error;
 
 
 
 
 
 
 
 
 
 
 
 
 
487
488	/* Flush inodegc work at the start of a quota reporting scan. */
489	if (*id == 0)
490		xfs_inodegc_push(mp);
 
 
491
492	error = xfs_qm_dqget_next(mp, *id, type, &dqp);
493	if (error)
494		return error;
 
 
 
 
 
 
 
 
 
 
 
 
495
496	/* Fill in the ID we actually read from disk */
497	*id = dqp->q_id;
498
499	xfs_qm_scall_getquota_fill_qc(mp, type, dqp, dst);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
500
501	xfs_qm_dqput(dqp);
502	return error;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503}
v3.15
 
   1/*
   2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   3 * All Rights Reserved.
   4 *
   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.
   8 *
   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.
  13 *
  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
  17 */
  18
  19#include <linux/capability.h>
  20
  21#include "xfs.h"
  22#include "xfs_fs.h"
  23#include "xfs_shared.h"
  24#include "xfs_format.h"
  25#include "xfs_log_format.h"
  26#include "xfs_trans_resv.h"
  27#include "xfs_bit.h"
  28#include "xfs_sb.h"
  29#include "xfs_ag.h"
  30#include "xfs_mount.h"
  31#include "xfs_inode.h"
  32#include "xfs_trans.h"
  33#include "xfs_error.h"
  34#include "xfs_quota.h"
  35#include "xfs_qm.h"
  36#include "xfs_trace.h"
  37#include "xfs_icache.h"
  38
  39STATIC int	xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
  40STATIC int	xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
  41					uint);
  42STATIC uint	xfs_qm_export_flags(uint);
  43STATIC uint	xfs_qm_export_qtype_flags(uint);
  44
  45/*
  46 * Turn off quota accounting and/or enforcement for all udquots and/or
  47 * gdquots. Called only at unmount time.
  48 *
  49 * This assumes that there are no dquots of this file system cached
  50 * incore, and modifies the ondisk dquot directly. Therefore, for example,
  51 * it is an error to call this twice, without purging the cache.
  52 */
  53int
  54xfs_qm_scall_quotaoff(
  55	xfs_mount_t		*mp,
  56	uint			flags)
  57{
  58	struct xfs_quotainfo	*q = mp->m_quotainfo;
  59	uint			dqtype;
  60	int			error;
  61	uint			inactivate_flags;
  62	xfs_qoff_logitem_t	*qoffstart;
  63
  64	/*
  65	 * No file system can have quotas enabled on disk but not in core.
  66	 * Note that quota utilities (like quotaoff) _expect_
  67	 * errno == EEXIST here.
  68	 */
  69	if ((mp->m_qflags & flags) == 0)
  70		return XFS_ERROR(EEXIST);
  71	error = 0;
  72
  73	flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
  74
  75	/*
  76	 * We don't want to deal with two quotaoffs messing up each other,
  77	 * so we're going to serialize it. quotaoff isn't exactly a performance
  78	 * critical thing.
  79	 * If quotaoff, then we must be dealing with the root filesystem.
  80	 */
  81	ASSERT(q);
  82	mutex_lock(&q->qi_quotaofflock);
  83
  84	/*
  85	 * If we're just turning off quota enforcement, change mp and go.
  86	 */
  87	if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
  88		mp->m_qflags &= ~(flags);
  89
  90		spin_lock(&mp->m_sb_lock);
  91		mp->m_sb.sb_qflags = mp->m_qflags;
  92		spin_unlock(&mp->m_sb_lock);
  93		mutex_unlock(&q->qi_quotaofflock);
  94
  95		/* XXX what to do if error ? Revert back to old vals incore ? */
  96		error = xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS);
  97		return (error);
  98	}
  99
 100	dqtype = 0;
 101	inactivate_flags = 0;
 102	/*
 103	 * If accounting is off, we must turn enforcement off, clear the
 104	 * quota 'CHKD' certificate to make it known that we have to
 105	 * do a quotacheck the next time this quota is turned on.
 106	 */
 107	if (flags & XFS_UQUOTA_ACCT) {
 108		dqtype |= XFS_QMOPT_UQUOTA;
 109		flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
 110		inactivate_flags |= XFS_UQUOTA_ACTIVE;
 111	}
 112	if (flags & XFS_GQUOTA_ACCT) {
 113		dqtype |= XFS_QMOPT_GQUOTA;
 114		flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
 115		inactivate_flags |= XFS_GQUOTA_ACTIVE;
 116	}
 117	if (flags & XFS_PQUOTA_ACCT) {
 118		dqtype |= XFS_QMOPT_PQUOTA;
 119		flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
 120		inactivate_flags |= XFS_PQUOTA_ACTIVE;
 121	}
 122
 123	/*
 124	 * Nothing to do?  Don't complain. This happens when we're just
 125	 * turning off quota enforcement.
 126	 */
 127	if ((mp->m_qflags & flags) == 0)
 128		goto out_unlock;
 129
 130	/*
 131	 * Write the LI_QUOTAOFF log record, and do SB changes atomically,
 132	 * and synchronously. If we fail to write, we should abort the
 133	 * operation as it cannot be recovered safely if we crash.
 134	 */
 135	error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
 136	if (error)
 137		goto out_unlock;
 138
 139	/*
 140	 * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
 141	 * to take care of the race between dqget and quotaoff. We don't take
 142	 * any special locks to reset these bits. All processes need to check
 143	 * these bits *after* taking inode lock(s) to see if the particular
 144	 * quota type is in the process of being turned off. If *ACTIVE, it is
 145	 * guaranteed that all dquot structures and all quotainode ptrs will all
 146	 * stay valid as long as that inode is kept locked.
 147	 *
 148	 * There is no turning back after this.
 149	 */
 150	mp->m_qflags &= ~inactivate_flags;
 151
 152	/*
 153	 * Give back all the dquot reference(s) held by inodes.
 154	 * Here we go thru every single incore inode in this file system, and
 155	 * do a dqrele on the i_udquot/i_gdquot that it may have.
 156	 * Essentially, as long as somebody has an inode locked, this guarantees
 157	 * that quotas will not be turned off. This is handy because in a
 158	 * transaction once we lock the inode(s) and check for quotaon, we can
 159	 * depend on the quota inodes (and other things) being valid as long as
 160	 * we keep the lock(s).
 161	 */
 162	xfs_qm_dqrele_all_inodes(mp, flags);
 163
 164	/*
 165	 * Next we make the changes in the quota flag in the mount struct.
 166	 * This isn't protected by a particular lock directly, because we
 167	 * don't want to take a mrlock every time we depend on quotas being on.
 168	 */
 169	mp->m_qflags &= ~flags;
 170
 171	/*
 172	 * Go through all the dquots of this file system and purge them,
 173	 * according to what was turned off.
 174	 */
 175	xfs_qm_dqpurge_all(mp, dqtype);
 176
 177	/*
 178	 * Transactions that had started before ACTIVE state bit was cleared
 179	 * could have logged many dquots, so they'd have higher LSNs than
 180	 * the first QUOTAOFF log record does. If we happen to crash when
 181	 * the tail of the log has gone past the QUOTAOFF record, but
 182	 * before the last dquot modification, those dquots __will__
 183	 * recover, and that's not good.
 184	 *
 185	 * So, we have QUOTAOFF start and end logitems; the start
 186	 * logitem won't get overwritten until the end logitem appears...
 187	 */
 188	error = xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
 189	if (error) {
 190		/* We're screwed now. Shutdown is the only option. */
 191		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 192		goto out_unlock;
 193	}
 194
 195	/*
 196	 * If all quotas are completely turned off, close shop.
 197	 */
 198	if (mp->m_qflags == 0) {
 199		mutex_unlock(&q->qi_quotaofflock);
 200		xfs_qm_destroy_quotainfo(mp);
 201		return (0);
 202	}
 203
 204	/*
 205	 * Release our quotainode references if we don't need them anymore.
 206	 */
 207	if ((dqtype & XFS_QMOPT_UQUOTA) && q->qi_uquotaip) {
 208		IRELE(q->qi_uquotaip);
 209		q->qi_uquotaip = NULL;
 210	}
 211	if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
 212		IRELE(q->qi_gquotaip);
 213		q->qi_gquotaip = NULL;
 214	}
 215	if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
 216		IRELE(q->qi_pquotaip);
 217		q->qi_pquotaip = NULL;
 218	}
 219
 220out_unlock:
 221	mutex_unlock(&q->qi_quotaofflock);
 222	return error;
 223}
 224
 225STATIC int
 226xfs_qm_scall_trunc_qfile(
 227	struct xfs_mount	*mp,
 228	xfs_ino_t		ino)
 229{
 230	struct xfs_inode	*ip;
 231	struct xfs_trans	*tp;
 232	int			error;
 233
 234	if (ino == NULLFSINO)
 
 235		return 0;
 236
 237	error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
 238	if (error)
 239		return error;
 240
 241	xfs_ilock(ip, XFS_IOLOCK_EXCL);
 242
 243	tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE);
 244	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0);
 245	if (error) {
 246		xfs_trans_cancel(tp, 0);
 247		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 248		goto out_put;
 249	}
 250
 251	xfs_ilock(ip, XFS_ILOCK_EXCL);
 252	xfs_trans_ijoin(tp, ip, 0);
 253
 254	ip->i_d.di_size = 0;
 255	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 256
 257	error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0);
 258	if (error) {
 259		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
 260				     XFS_TRANS_ABORT);
 261		goto out_unlock;
 262	}
 263
 264	ASSERT(ip->i_d.di_nextents == 0);
 265
 266	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 267	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 268
 269out_unlock:
 270	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 271out_put:
 272	IRELE(ip);
 273	return error;
 274}
 275
 276int
 277xfs_qm_scall_trunc_qfiles(
 278	xfs_mount_t	*mp,
 279	uint		flags)
 280{
 281	int		error;
 282
 283	if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
 
 284		xfs_debug(mp, "%s: flags=%x m_qflags=%x",
 285			__func__, flags, mp->m_qflags);
 286		return XFS_ERROR(EINVAL);
 287	}
 288
 289	if (flags & XFS_DQ_USER) {
 290		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
 291		if (error)
 292			return error;
 293	}
 294	if (flags & XFS_DQ_GROUP) {
 295		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
 296		if (error)
 297			return error;
 298	}
 299	if (flags & XFS_DQ_PROJ)
 300		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
 301
 302	return error;
 303}
 304
 305/*
 306 * Switch on (a given) quota enforcement for a filesystem.  This takes
 307 * effect immediately.
 308 * (Switching on quota accounting must be done at mount time.)
 309 */
 310int
 311xfs_qm_scall_quotaon(
 312	xfs_mount_t	*mp,
 313	uint		flags)
 314{
 315	int		error;
 316	uint		qf;
 317	__int64_t	sbflags;
 318
 319	flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
 320	/*
 321	 * Switching on quota accounting must be done at mount time.
 
 322	 */
 323	flags &= ~(XFS_ALL_QUOTA_ACCT);
 324
 325	sbflags = 0;
 326
 327	if (flags == 0) {
 328		xfs_debug(mp, "%s: zero flags, m_qflags=%x",
 329			__func__, mp->m_qflags);
 330		return XFS_ERROR(EINVAL);
 331	}
 332
 333	/* No fs can turn on quotas with a delayed effect */
 334	ASSERT((flags & XFS_ALL_QUOTA_ACCT) == 0);
 335
 336	/*
 337	 * Can't enforce without accounting. We check the superblock
 338	 * qflags here instead of m_qflags because rootfs can have
 339	 * quota acct on ondisk without m_qflags' knowing.
 340	 */
 341	if (((flags & XFS_UQUOTA_ACCT) == 0 &&
 342	     (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
 343	     (flags & XFS_UQUOTA_ENFD)) ||
 344	    ((flags & XFS_GQUOTA_ACCT) == 0 &&
 345	     (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
 346	     (flags & XFS_GQUOTA_ENFD)) ||
 347	    ((flags & XFS_PQUOTA_ACCT) == 0 &&
 348	     (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
 349	     (flags & XFS_PQUOTA_ENFD))) {
 350		xfs_debug(mp,
 351			"%s: Can't enforce without acct, flags=%x sbflags=%x",
 352			__func__, flags, mp->m_sb.sb_qflags);
 353		return XFS_ERROR(EINVAL);
 354	}
 355	/*
 356	 * If everything's up to-date incore, then don't waste time.
 357	 */
 358	if ((mp->m_qflags & flags) == flags)
 359		return XFS_ERROR(EEXIST);
 360
 361	/*
 362	 * Change sb_qflags on disk but not incore mp->qflags
 363	 * if this is the root filesystem.
 364	 */
 365	spin_lock(&mp->m_sb_lock);
 366	qf = mp->m_sb.sb_qflags;
 367	mp->m_sb.sb_qflags = qf | flags;
 368	spin_unlock(&mp->m_sb_lock);
 369
 370	/*
 371	 * There's nothing to change if it's the same.
 372	 */
 373	if ((qf & flags) == flags && sbflags == 0)
 374		return XFS_ERROR(EEXIST);
 375	sbflags |= XFS_SB_QFLAGS;
 376
 377	if ((error = xfs_qm_write_sb_changes(mp, sbflags)))
 378		return (error);
 
 379	/*
 380	 * If we aren't trying to switch on quota enforcement, we are done.
 381	 */
 382	if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
 383	     (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
 384	     ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
 385	     (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
 386	     ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
 387	     (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
 388	    (flags & XFS_ALL_QUOTA_ENFD) == 0)
 389		return (0);
 390
 391	if (! XFS_IS_QUOTA_RUNNING(mp))
 392		return XFS_ERROR(ESRCH);
 393
 394	/*
 395	 * Switch on quota enforcement in core.
 396	 */
 397	mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
 398	mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
 399	mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
 400
 401	return (0);
 402}
 403
 
 404
 405/*
 406 * Return quota status information, such as uquota-off, enforcements, etc.
 407 * for Q_XGETQSTAT command.
 408 */
 409int
 410xfs_qm_scall_getqstat(
 411	struct xfs_mount	*mp,
 412	struct fs_quota_stat	*out)
 
 
 
 
 413{
 414	struct xfs_quotainfo	*q = mp->m_quotainfo;
 415	struct xfs_inode	*uip = NULL;
 416	struct xfs_inode	*gip = NULL;
 417	struct xfs_inode	*pip = NULL;
 418	bool                    tempuqip = false;
 419	bool                    tempgqip = false;
 420	bool                    temppqip = false;
 421
 422	memset(out, 0, sizeof(fs_quota_stat_t));
 423
 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);
 429	}
 430
 431	out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
 432							(XFS_ALL_QUOTA_ACCT|
 433							 XFS_ALL_QUOTA_ENFD));
 434	if (q) {
 435		uip = q->qi_uquotaip;
 436		gip = q->qi_gquotaip;
 437		pip = q->qi_pquotaip;
 438	}
 439	if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
 440		if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
 441					0, 0, &uip) == 0)
 442			tempuqip = true;
 443	}
 444	if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
 445		if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
 446					0, 0, &gip) == 0)
 447			tempgqip = true;
 448	}
 449	/*
 450	 * Q_XGETQSTAT doesn't have room for both group and project quotas.
 451	 * So, allow the project quota values to be copied out only if
 452	 * there is no group quota information available.
 453	 */
 454	if (!gip) {
 455		if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
 456			if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
 457						0, 0, &pip) == 0)
 458				temppqip = true;
 459		}
 460	} else
 461		pip = NULL;
 462	if (uip) {
 463		out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
 464		out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
 465		out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
 466		if (tempuqip)
 467			IRELE(uip);
 468	}
 469
 470	if (gip) {
 471		out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
 472		out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
 473		out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
 474		if (tempgqip)
 475			IRELE(gip);
 476	}
 477	if (pip) {
 478		out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
 479		out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
 480		out->qs_gquota.qfs_nextents = pip->i_d.di_nextents;
 481		if (temppqip)
 482			IRELE(pip);
 483	}
 484	if (q) {
 485		out->qs_incoredqs = q->qi_dquots;
 486		out->qs_btimelimit = q->qi_btimelimit;
 487		out->qs_itimelimit = q->qi_itimelimit;
 488		out->qs_rtbtimelimit = q->qi_rtbtimelimit;
 489		out->qs_bwarnlimit = q->qi_bwarnlimit;
 490		out->qs_iwarnlimit = q->qi_iwarnlimit;
 491	}
 492	return 0;
 
 493}
 494
 495/*
 496 * Return quota status information, such as uquota-off, enforcements, etc.
 497 * for Q_XGETQSTATV command, to support separate project quota field.
 498 */
 499int
 500xfs_qm_scall_getqstatv(
 501	struct xfs_mount	*mp,
 502	struct fs_quota_statv	*out)
 503{
 504	struct xfs_quotainfo	*q = mp->m_quotainfo;
 505	struct xfs_inode	*uip = NULL;
 506	struct xfs_inode	*gip = NULL;
 507	struct xfs_inode	*pip = NULL;
 508	bool                    tempuqip = false;
 509	bool                    tempgqip = false;
 510	bool                    temppqip = false;
 511
 512	if (!xfs_sb_version_hasquota(&mp->m_sb)) {
 513		out->qs_uquota.qfs_ino = NULLFSINO;
 514		out->qs_gquota.qfs_ino = NULLFSINO;
 515		out->qs_pquota.qfs_ino = NULLFSINO;
 516		return (0);
 517	}
 518
 519	out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
 520							(XFS_ALL_QUOTA_ACCT|
 521							 XFS_ALL_QUOTA_ENFD));
 522	out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
 523	out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
 524	out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino;
 525
 526	if (q) {
 527		uip = q->qi_uquotaip;
 528		gip = q->qi_gquotaip;
 529		pip = q->qi_pquotaip;
 530	}
 531	if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
 532		if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
 533					0, 0, &uip) == 0)
 534			tempuqip = true;
 535	}
 536	if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
 537		if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
 538					0, 0, &gip) == 0)
 539			tempgqip = true;
 540	}
 541	if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
 542		if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
 543					0, 0, &pip) == 0)
 544			temppqip = true;
 545	}
 546	if (uip) {
 547		out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
 548		out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
 549		if (tempuqip)
 550			IRELE(uip);
 551	}
 552
 553	if (gip) {
 554		out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
 555		out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
 556		if (tempgqip)
 557			IRELE(gip);
 558	}
 559	if (pip) {
 560		out->qs_pquota.qfs_nblks = pip->i_d.di_nblocks;
 561		out->qs_pquota.qfs_nextents = pip->i_d.di_nextents;
 562		if (temppqip)
 563			IRELE(pip);
 564	}
 565	if (q) {
 566		out->qs_incoredqs = q->qi_dquots;
 567		out->qs_btimelimit = q->qi_btimelimit;
 568		out->qs_itimelimit = q->qi_itimelimit;
 569		out->qs_rtbtimelimit = q->qi_rtbtimelimit;
 570		out->qs_bwarnlimit = q->qi_bwarnlimit;
 571		out->qs_iwarnlimit = q->qi_iwarnlimit;
 572	}
 573	return 0;
 574}
 575
 576#define XFS_DQ_MASK \
 577	(FS_DQ_LIMIT_MASK | FS_DQ_TIMER_MASK | FS_DQ_WARNS_MASK)
 578
 579/*
 580 * Adjust quota limits, and start/stop timers accordingly.
 581 */
 582int
 583xfs_qm_scall_setqlim(
 584	struct xfs_mount	*mp,
 585	xfs_dqid_t		id,
 586	uint			type,
 587	fs_disk_quota_t		*newlim)
 588{
 589	struct xfs_quotainfo	*q = mp->m_quotainfo;
 590	struct xfs_disk_dquot	*ddq;
 591	struct xfs_dquot	*dqp;
 592	struct xfs_trans	*tp;
 
 
 
 593	int			error;
 594	xfs_qcnt_t		hard, soft;
 595
 596	if (newlim->d_fieldmask & ~XFS_DQ_MASK)
 597		return EINVAL;
 598	if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0)
 599		return 0;
 600
 601	/*
 602	 * We don't want to race with a quotaoff so take the quotaoff lock.
 603	 * We don't hold an inode lock, so there's nothing else to stop
 604	 * a quotaoff from happening.
 605	 */
 606	mutex_lock(&q->qi_quotaofflock);
 607
 608	/*
 609	 * Get the dquot (locked) before we start, as we need to do a
 610	 * transaction to allocate it if it doesn't exist. Once we have the
 611	 * dquot, unlock it so we can start the next transaction safely. We hold
 612	 * a reference to the dquot, so it's safe to do this unlock/lock without
 613	 * it being reclaimed in the mean time.
 614	 */
 615	error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp);
 616	if (error) {
 617		ASSERT(error != ENOENT);
 618		goto out_unlock;
 619	}
 
 
 620	xfs_dqunlock(dqp);
 621
 622	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
 623	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_setqlim, 0, 0);
 624	if (error) {
 625		xfs_trans_cancel(tp, 0);
 626		goto out_rele;
 627	}
 628
 629	xfs_dqlock(dqp);
 630	xfs_trans_dqjoin(tp, dqp);
 631	ddq = &dqp->q_core;
 632
 633	/*
 
 
 
 634	 * Make sure that hardlimits are >= soft limits before changing.
 
 
 
 
 
 
 
 
 
 
 635	 */
 636	hard = (newlim->d_fieldmask & FS_DQ_BHARD) ?
 637		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_hardlimit) :
 638			be64_to_cpu(ddq->d_blk_hardlimit);
 639	soft = (newlim->d_fieldmask & FS_DQ_BSOFT) ?
 640		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_softlimit) :
 641			be64_to_cpu(ddq->d_blk_softlimit);
 642	if (hard == 0 || hard >= soft) {
 643		ddq->d_blk_hardlimit = cpu_to_be64(hard);
 644		ddq->d_blk_softlimit = cpu_to_be64(soft);
 
 
 
 645		xfs_dquot_set_prealloc_limits(dqp);
 646		if (id == 0) {
 647			q->qi_bhardlimit = hard;
 648			q->qi_bsoftlimit = soft;
 649		}
 650	} else {
 651		xfs_debug(mp, "blkhard %Ld < blksoft %Ld", hard, soft);
 652	}
 653	hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
 654		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
 655			be64_to_cpu(ddq->d_rtb_hardlimit);
 656	soft = (newlim->d_fieldmask & FS_DQ_RTBSOFT) ?
 657		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_softlimit) :
 658			be64_to_cpu(ddq->d_rtb_softlimit);
 659	if (hard == 0 || hard >= soft) {
 660		ddq->d_rtb_hardlimit = cpu_to_be64(hard);
 661		ddq->d_rtb_softlimit = cpu_to_be64(soft);
 662		if (id == 0) {
 663			q->qi_rtbhardlimit = hard;
 664			q->qi_rtbsoftlimit = soft;
 665		}
 666	} else {
 667		xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld", hard, soft);
 668	}
 669
 670	hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
 
 671		(xfs_qcnt_t) newlim->d_ino_hardlimit :
 672			be64_to_cpu(ddq->d_ino_hardlimit);
 673	soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
 674		(xfs_qcnt_t) newlim->d_ino_softlimit :
 675			be64_to_cpu(ddq->d_ino_softlimit);
 676	if (hard == 0 || hard >= soft) {
 677		ddq->d_ino_hardlimit = cpu_to_be64(hard);
 678		ddq->d_ino_softlimit = cpu_to_be64(soft);
 679		if (id == 0) {
 680			q->qi_ihardlimit = hard;
 681			q->qi_isoftlimit = soft;
 682		}
 683	} else {
 684		xfs_debug(mp, "ihard %Ld < isoft %Ld", hard, soft);
 685	}
 686
 687	/*
 688	 * Update warnings counter(s) if requested
 689	 */
 690	if (newlim->d_fieldmask & FS_DQ_BWARNS)
 691		ddq->d_bwarns = cpu_to_be16(newlim->d_bwarns);
 692	if (newlim->d_fieldmask & FS_DQ_IWARNS)
 693		ddq->d_iwarns = cpu_to_be16(newlim->d_iwarns);
 694	if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
 695		ddq->d_rtbwarns = cpu_to_be16(newlim->d_rtbwarns);
 696
 697	if (id == 0) {
 698		/*
 699		 * Timelimits for the super user set the relative time
 700		 * the other users can be over quota for this file system.
 701		 * If it is zero a default is used.  Ditto for the default
 702		 * soft and hard limit values (already done, above), and
 703		 * for warnings.
 704		 */
 705		if (newlim->d_fieldmask & FS_DQ_BTIMER) {
 706			q->qi_btimelimit = newlim->d_btimer;
 707			ddq->d_btimer = cpu_to_be32(newlim->d_btimer);
 708		}
 709		if (newlim->d_fieldmask & FS_DQ_ITIMER) {
 710			q->qi_itimelimit = newlim->d_itimer;
 711			ddq->d_itimer = cpu_to_be32(newlim->d_itimer);
 712		}
 713		if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
 714			q->qi_rtbtimelimit = newlim->d_rtbtimer;
 715			ddq->d_rtbtimer = cpu_to_be32(newlim->d_rtbtimer);
 716		}
 717		if (newlim->d_fieldmask & FS_DQ_BWARNS)
 718			q->qi_bwarnlimit = newlim->d_bwarns;
 719		if (newlim->d_fieldmask & FS_DQ_IWARNS)
 720			q->qi_iwarnlimit = newlim->d_iwarns;
 721		if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
 722			q->qi_rtbwarnlimit = newlim->d_rtbwarns;
 723	} else {
 724		/*
 725		 * If the user is now over quota, start the timelimit.
 726		 * The user will not be 'warned'.
 727		 * Note that we keep the timers ticking, whether enforcement
 728		 * is on or off. We don't really want to bother with iterating
 729		 * over all ondisk dquots and turning the timers on/off.
 730		 */
 731		xfs_qm_adjust_dqtimers(mp, ddq);
 732	}
 733	dqp->dq_flags |= XFS_DQ_DIRTY;
 734	xfs_trans_log_dquot(tp, dqp);
 735
 736	error = xfs_trans_commit(tp, 0);
 737
 738out_rele:
 739	xfs_qm_dqrele(dqp);
 740out_unlock:
 741	mutex_unlock(&q->qi_quotaofflock);
 742	return error;
 743}
 744
 745STATIC int
 746xfs_qm_log_quotaoff_end(
 747	xfs_mount_t		*mp,
 748	xfs_qoff_logitem_t	*startqoff,
 749	uint			flags)
 
 
 750{
 751	xfs_trans_t		*tp;
 752	int			error;
 753	xfs_qoff_logitem_t	*qoffi;
 754
 755	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
 756
 757	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_equotaoff, 0, 0);
 758	if (error) {
 759		xfs_trans_cancel(tp, 0);
 760		return (error);
 761	}
 762
 763	qoffi = xfs_trans_get_qoff_item(tp, startqoff,
 764					flags & XFS_ALL_QUOTA_ACCT);
 765	xfs_trans_log_quotaoff_item(tp, qoffi);
 
 766
 767	/*
 768	 * We have to make sure that the transaction is secure on disk before we
 769	 * return and actually stop quota accounting. So, make it synchronous.
 770	 * We don't care about quotoff's performance.
 771	 */
 772	xfs_trans_set_sync(tp);
 773	error = xfs_trans_commit(tp, 0);
 774	return (error);
 775}
 776
 777
 778STATIC int
 779xfs_qm_log_quotaoff(
 780	xfs_mount_t	       *mp,
 781	xfs_qoff_logitem_t     **qoffstartp,
 782	uint		       flags)
 783{
 784	xfs_trans_t	       *tp;
 785	int			error;
 786	xfs_qoff_logitem_t     *qoffi=NULL;
 787	uint			oldsbqflag=0;
 788
 789	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF);
 790	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_quotaoff, 0, 0);
 791	if (error)
 792		goto error0;
 793
 794	qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
 795	xfs_trans_log_quotaoff_item(tp, qoffi);
 796
 797	spin_lock(&mp->m_sb_lock);
 798	oldsbqflag = mp->m_sb.sb_qflags;
 799	mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
 800	spin_unlock(&mp->m_sb_lock);
 801
 802	xfs_mod_sb(tp, XFS_SB_QFLAGS);
 803
 804	/*
 805	 * We have to make sure that the transaction is secure on disk before we
 806	 * return and actually stop quota accounting. So, make it synchronous.
 807	 * We don't care about quotoff's performance.
 808	 */
 809	xfs_trans_set_sync(tp);
 810	error = xfs_trans_commit(tp, 0);
 811
 812error0:
 813	if (error) {
 814		xfs_trans_cancel(tp, 0);
 815		/*
 816		 * No one else is modifying sb_qflags, so this is OK.
 817		 * We still hold the quotaofflock.
 818		 */
 819		spin_lock(&mp->m_sb_lock);
 820		mp->m_sb.sb_qflags = oldsbqflag;
 821		spin_unlock(&mp->m_sb_lock);
 822	}
 823	*qoffstartp = qoffi;
 824	return (error);
 825}
 826
 827
 828int
 829xfs_qm_scall_getquota(
 830	struct xfs_mount	*mp,
 831	xfs_dqid_t		id,
 832	uint			type,
 833	struct fs_disk_quota	*dst)
 834{
 835	struct xfs_dquot	*dqp;
 836	int			error;
 837
 838	/*
 839	 * Try to get the dquot. We don't want it allocated on disk, so
 840	 * we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't
 841	 * exist, we'll get ENOENT back.
 
 
 
 
 
 
 842	 */
 843	error = xfs_qm_dqget(mp, NULL, id, type, 0, &dqp);
 844	if (error)
 845		return error;
 846
 847	/*
 848	 * If everything's NULL, this dquot doesn't quite exist as far as
 849	 * our utility programs are concerned.
 850	 */
 851	if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
 852		error = XFS_ERROR(ENOENT);
 853		goto out_put;
 854	}
 855
 856	memset(dst, 0, sizeof(*dst));
 857	dst->d_version = FS_DQUOT_VERSION;
 858	dst->d_flags = xfs_qm_export_qtype_flags(dqp->q_core.d_flags);
 859	dst->d_id = be32_to_cpu(dqp->q_core.d_id);
 860	dst->d_blk_hardlimit =
 861		XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_hardlimit));
 862	dst->d_blk_softlimit =
 863		XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_softlimit));
 864	dst->d_ino_hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);
 865	dst->d_ino_softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);
 866	dst->d_bcount = XFS_FSB_TO_BB(mp, dqp->q_res_bcount);
 867	dst->d_icount = dqp->q_res_icount;
 868	dst->d_btimer = be32_to_cpu(dqp->q_core.d_btimer);
 869	dst->d_itimer = be32_to_cpu(dqp->q_core.d_itimer);
 870	dst->d_iwarns = be16_to_cpu(dqp->q_core.d_iwarns);
 871	dst->d_bwarns = be16_to_cpu(dqp->q_core.d_bwarns);
 872	dst->d_rtb_hardlimit =
 873		XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_rtb_hardlimit));
 874	dst->d_rtb_softlimit =
 875		XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_rtb_softlimit));
 876	dst->d_rtbcount = XFS_FSB_TO_BB(mp, dqp->q_res_rtbcount);
 877	dst->d_rtbtimer = be32_to_cpu(dqp->q_core.d_rtbtimer);
 878	dst->d_rtbwarns = be16_to_cpu(dqp->q_core.d_rtbwarns);
 879
 880	/*
 881	 * Internally, we don't reset all the timers when quota enforcement
 882	 * gets turned off. No need to confuse the user level code,
 883	 * so return zeroes in that case.
 884	 */
 885	if ((!XFS_IS_UQUOTA_ENFORCED(mp) &&
 886	     dqp->q_core.d_flags == XFS_DQ_USER) ||
 887	    (!XFS_IS_GQUOTA_ENFORCED(mp) &&
 888	     dqp->q_core.d_flags == XFS_DQ_GROUP) ||
 889	    (!XFS_IS_PQUOTA_ENFORCED(mp) &&
 890	     dqp->q_core.d_flags == XFS_DQ_PROJ)) {
 891		dst->d_btimer = 0;
 892		dst->d_itimer = 0;
 893		dst->d_rtbtimer = 0;
 894	}
 895
 896#ifdef DEBUG
 897	if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == FS_USER_QUOTA) ||
 898	     (XFS_IS_GQUOTA_ENFORCED(mp) && dst->d_flags == FS_GROUP_QUOTA) ||
 899	     (XFS_IS_PQUOTA_ENFORCED(mp) && dst->d_flags == FS_PROJ_QUOTA)) &&
 900	    dst->d_id != 0) {
 901		if ((dst->d_bcount > dst->d_blk_softlimit) &&
 902		    (dst->d_blk_softlimit > 0)) {
 903			ASSERT(dst->d_btimer != 0);
 904		}
 905		if ((dst->d_icount > dst->d_ino_softlimit) &&
 906		    (dst->d_ino_softlimit > 0)) {
 907			ASSERT(dst->d_itimer != 0);
 908		}
 909	}
 910#endif
 911out_put:
 912	xfs_qm_dqput(dqp);
 913	return error;
 914}
 915
 916STATIC uint
 917xfs_qm_export_qtype_flags(
 918	uint flags)
 
 
 
 
 
 
 
 919{
 920	/*
 921	 * Can't be more than one, or none.
 922	 */
 923	ASSERT((flags & (FS_PROJ_QUOTA | FS_USER_QUOTA)) !=
 924		(FS_PROJ_QUOTA | FS_USER_QUOTA));
 925	ASSERT((flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)) !=
 926		(FS_PROJ_QUOTA | FS_GROUP_QUOTA));
 927	ASSERT((flags & (FS_USER_QUOTA | FS_GROUP_QUOTA)) !=
 928		(FS_USER_QUOTA | FS_GROUP_QUOTA));
 929	ASSERT((flags & (FS_PROJ_QUOTA|FS_USER_QUOTA|FS_GROUP_QUOTA)) != 0);
 930
 931	return (flags & XFS_DQ_USER) ?
 932		FS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
 933			FS_PROJ_QUOTA : FS_GROUP_QUOTA;
 934}
 935
 936STATIC uint
 937xfs_qm_export_flags(
 938	uint flags)
 939{
 940	uint uflags;
 941
 942	uflags = 0;
 943	if (flags & XFS_UQUOTA_ACCT)
 944		uflags |= FS_QUOTA_UDQ_ACCT;
 945	if (flags & XFS_GQUOTA_ACCT)
 946		uflags |= FS_QUOTA_GDQ_ACCT;
 947	if (flags & XFS_PQUOTA_ACCT)
 948		uflags |= FS_QUOTA_PDQ_ACCT;
 949	if (flags & XFS_UQUOTA_ENFD)
 950		uflags |= FS_QUOTA_UDQ_ENFD;
 951	if (flags & XFS_GQUOTA_ENFD)
 952		uflags |= FS_QUOTA_GDQ_ENFD;
 953	if (flags & XFS_PQUOTA_ENFD)
 954		uflags |= FS_QUOTA_PDQ_ENFD;
 955	return (uflags);
 956}
 957
 
 
 958
 959STATIC int
 960xfs_dqrele_inode(
 961	struct xfs_inode	*ip,
 962	struct xfs_perag	*pag,
 963	int			flags,
 964	void			*args)
 965{
 966	/* skip quota inodes */
 967	if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
 968	    ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
 969	    ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
 970		ASSERT(ip->i_udquot == NULL);
 971		ASSERT(ip->i_gdquot == NULL);
 972		ASSERT(ip->i_pdquot == NULL);
 973		return 0;
 974	}
 975
 976	xfs_ilock(ip, XFS_ILOCK_EXCL);
 977	if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
 978		xfs_qm_dqrele(ip->i_udquot);
 979		ip->i_udquot = NULL;
 980	}
 981	if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
 982		xfs_qm_dqrele(ip->i_gdquot);
 983		ip->i_gdquot = NULL;
 984	}
 985	if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
 986		xfs_qm_dqrele(ip->i_pdquot);
 987		ip->i_pdquot = NULL;
 988	}
 989	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 990	return 0;
 991}
 992
 993
 994/*
 995 * Go thru all the inodes in the file system, releasing their dquots.
 996 *
 997 * Note that the mount structure gets modified to indicate that quotas are off
 998 * AFTER this, in the case of quotaoff.
 999 */
1000void
1001xfs_qm_dqrele_all_inodes(
1002	struct xfs_mount *mp,
1003	uint		 flags)
1004{
1005	ASSERT(mp->m_quotainfo);
1006	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags, NULL);
1007}