Linux Audio

Check our new training course

Loading...
v3.1
 
  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_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"
 43
 44STATIC int	xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
 45STATIC int	xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
 46					uint);
 47STATIC uint	xfs_qm_export_flags(uint);
 48STATIC uint	xfs_qm_export_qtype_flags(uint);
 49STATIC void	xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *,
 50					fs_disk_quota_t *);
 51
 52
 53/*
 54 * Turn off quota accounting and/or enforcement for all udquots and/or
 55 * gdquots. Called only at unmount time.
 56 *
 57 * This assumes that there are no dquots of this file system cached
 58 * incore, and modifies the ondisk dquot directly. Therefore, for example,
 59 * it is an error to call this twice, without purging the cache.
 60 */
 61int
 62xfs_qm_scall_quotaoff(
 63	xfs_mount_t		*mp,
 64	uint			flags)
 65{
 66	struct xfs_quotainfo	*q = mp->m_quotainfo;
 67	uint			dqtype;
 68	int			error;
 69	uint			inactivate_flags;
 70	xfs_qoff_logitem_t	*qoffstart;
 71	int			nculprits;
 72
 73	/*
 74	 * No file system can have quotas enabled on disk but not in core.
 75	 * Note that quota utilities (like quotaoff) _expect_
 76	 * errno == EEXIST here.
 77	 */
 78	if ((mp->m_qflags & flags) == 0)
 79		return XFS_ERROR(EEXIST);
 80	error = 0;
 81
 82	flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
 83
 84	/*
 85	 * We don't want to deal with two quotaoffs messing up each other,
 86	 * so we're going to serialize it. quotaoff isn't exactly a performance
 87	 * critical thing.
 88	 * If quotaoff, then we must be dealing with the root filesystem.
 89	 */
 90	ASSERT(q);
 91	mutex_lock(&q->qi_quotaofflock);
 92
 93	/*
 94	 * If we're just turning off quota enforcement, change mp and go.
 95	 */
 96	if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
 97		mp->m_qflags &= ~(flags);
 98
 99		spin_lock(&mp->m_sb_lock);
100		mp->m_sb.sb_qflags = mp->m_qflags;
101		spin_unlock(&mp->m_sb_lock);
102		mutex_unlock(&q->qi_quotaofflock);
103
104		/* XXX what to do if error ? Revert back to old vals incore ? */
105		error = xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS);
106		return (error);
107	}
108
109	dqtype = 0;
110	inactivate_flags = 0;
111	/*
112	 * If accounting is off, we must turn enforcement off, clear the
113	 * quota 'CHKD' certificate to make it known that we have to
114	 * do a quotacheck the next time this quota is turned on.
115	 */
116	if (flags & XFS_UQUOTA_ACCT) {
117		dqtype |= XFS_QMOPT_UQUOTA;
118		flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
119		inactivate_flags |= XFS_UQUOTA_ACTIVE;
120	}
121	if (flags & XFS_GQUOTA_ACCT) {
122		dqtype |= XFS_QMOPT_GQUOTA;
123		flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
124		inactivate_flags |= XFS_GQUOTA_ACTIVE;
125	} else if (flags & XFS_PQUOTA_ACCT) {
126		dqtype |= XFS_QMOPT_PQUOTA;
127		flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
128		inactivate_flags |= XFS_PQUOTA_ACTIVE;
129	}
130
131	/*
132	 * Nothing to do?  Don't complain. This happens when we're just
133	 * turning off quota enforcement.
134	 */
135	if ((mp->m_qflags & flags) == 0)
136		goto out_unlock;
137
138	/*
139	 * Write the LI_QUOTAOFF log record, and do SB changes atomically,
140	 * and synchronously. If we fail to write, we should abort the
141	 * operation as it cannot be recovered safely if we crash.
142	 */
143	error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
144	if (error)
145		goto out_unlock;
146
147	/*
148	 * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
149	 * to take care of the race between dqget and quotaoff. We don't take
150	 * any special locks to reset these bits. All processes need to check
151	 * these bits *after* taking inode lock(s) to see if the particular
152	 * quota type is in the process of being turned off. If *ACTIVE, it is
153	 * guaranteed that all dquot structures and all quotainode ptrs will all
154	 * stay valid as long as that inode is kept locked.
155	 *
156	 * There is no turning back after this.
157	 */
158	mp->m_qflags &= ~inactivate_flags;
159
160	/*
161	 * Give back all the dquot reference(s) held by inodes.
162	 * Here we go thru every single incore inode in this file system, and
163	 * do a dqrele on the i_udquot/i_gdquot that it may have.
164	 * Essentially, as long as somebody has an inode locked, this guarantees
165	 * that quotas will not be turned off. This is handy because in a
166	 * transaction once we lock the inode(s) and check for quotaon, we can
167	 * depend on the quota inodes (and other things) being valid as long as
168	 * we keep the lock(s).
169	 */
170	xfs_qm_dqrele_all_inodes(mp, flags);
171
172	/*
173	 * Next we make the changes in the quota flag in the mount struct.
174	 * This isn't protected by a particular lock directly, because we
175	 * don't want to take a mrlock every time we depend on quotas being on.
176	 */
177	mp->m_qflags &= ~(flags);
178
179	/*
180	 * Go through all the dquots of this file system and purge them,
181	 * according to what was turned off. We may not be able to get rid
182	 * of all dquots, because dquots can have temporary references that
183	 * are not attached to inodes. eg. xfs_setattr, xfs_create.
184	 * So, if we couldn't purge all the dquots from the filesystem,
185	 * we can't get rid of the incore data structures.
186	 */
187	while ((nculprits = xfs_qm_dqpurge_all(mp, dqtype)))
188		delay(10 * nculprits);
189
190	/*
191	 * Transactions that had started before ACTIVE state bit was cleared
192	 * could have logged many dquots, so they'd have higher LSNs than
193	 * the first QUOTAOFF log record does. If we happen to crash when
194	 * the tail of the log has gone past the QUOTAOFF record, but
195	 * before the last dquot modification, those dquots __will__
196	 * recover, and that's not good.
197	 *
198	 * So, we have QUOTAOFF start and end logitems; the start
199	 * logitem won't get overwritten until the end logitem appears...
200	 */
201	error = xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
202	if (error) {
203		/* We're screwed now. Shutdown is the only option. */
204		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
205		goto out_unlock;
206	}
207
208	/*
209	 * If quotas is completely disabled, close shop.
 
210	 */
211	if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
212	    ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
213		mutex_unlock(&q->qi_quotaofflock);
214		xfs_qm_destroy_quotainfo(mp);
215		return (0);
216	}
217
218	/*
219	 * Release our quotainode references if we don't need them anymore.
220	 */
221	if ((dqtype & XFS_QMOPT_UQUOTA) && q->qi_uquotaip) {
222		IRELE(q->qi_uquotaip);
223		q->qi_uquotaip = NULL;
224	}
225	if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && q->qi_gquotaip) {
226		IRELE(q->qi_gquotaip);
227		q->qi_gquotaip = NULL;
228	}
229
230out_unlock:
231	mutex_unlock(&q->qi_quotaofflock);
232	return error;
233}
234
235STATIC int
236xfs_qm_scall_trunc_qfile(
237	struct xfs_mount	*mp,
238	xfs_ino_t		ino)
239{
240	struct xfs_inode	*ip;
241	struct xfs_trans	*tp;
242	int			error;
243
244	if (ino == NULLFSINO)
 
245		return 0;
246
247	error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
248	if (error)
249		return error;
250
251	xfs_ilock(ip, XFS_IOLOCK_EXCL);
252
253	tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE);
254	error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0,
255				  XFS_TRANS_PERM_LOG_RES,
256				  XFS_ITRUNCATE_LOG_COUNT);
257	if (error) {
258		xfs_trans_cancel(tp, 0);
259		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
260		goto out_put;
261	}
262
263	xfs_ilock(ip, XFS_ILOCK_EXCL);
264	xfs_trans_ijoin(tp, ip);
 
 
 
265
266	error = xfs_itruncate_data(&tp, ip, 0);
267	if (error) {
268		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
269				     XFS_TRANS_ABORT);
270		goto out_unlock;
271	}
272
 
 
273	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
274	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
275
276out_unlock:
277	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
278out_put:
279	IRELE(ip);
280	return error;
281}
282
283int
284xfs_qm_scall_trunc_qfiles(
285	xfs_mount_t	*mp,
286	uint		flags)
287{
288	int		error = 0, error2 = 0;
289
290	if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
291		xfs_debug(mp, "%s: flags=%x m_qflags=%x\n",
 
292			__func__, flags, mp->m_qflags);
293		return XFS_ERROR(EINVAL);
294	}
295
296	if (flags & XFS_DQ_USER)
297		error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
298	if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ))
299		error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
 
 
 
 
 
 
 
 
300
301	return error ? error : error2;
302}
303
304/*
305 * Switch on (a given) quota enforcement for a filesystem.  This takes
306 * effect immediately.
307 * (Switching on quota accounting must be done at mount time.)
308 */
309int
310xfs_qm_scall_quotaon(
311	xfs_mount_t	*mp,
312	uint		flags)
313{
314	int		error;
315	uint		qf;
316	__int64_t	sbflags;
317
318	flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
319	/*
320	 * Switching on quota accounting must be done at mount time.
 
321	 */
322	flags &= ~(XFS_ALL_QUOTA_ACCT);
323
324	sbflags = 0;
325
326	if (flags == 0) {
327		xfs_debug(mp, "%s: zero flags, m_qflags=%x\n",
328			__func__, mp->m_qflags);
329		return XFS_ERROR(EINVAL);
330	}
331
332	/* No fs can turn on quotas with a delayed effect */
333	ASSERT((flags & XFS_ALL_QUOTA_ACCT) == 0);
334
335	/*
336	 * Can't enforce without accounting. We check the superblock
337	 * qflags here instead of m_qflags because rootfs can have
338	 * quota acct on ondisk without m_qflags' knowing.
339	 */
340	if (((flags & XFS_UQUOTA_ACCT) == 0 &&
341	    (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
342	    (flags & XFS_UQUOTA_ENFD))
343	    ||
344	    ((flags & XFS_PQUOTA_ACCT) == 0 &&
345	    (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
346	    (flags & XFS_GQUOTA_ACCT) == 0 &&
347	    (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
348	    (flags & XFS_OQUOTA_ENFD))) {
349		xfs_debug(mp,
350			"%s: Can't enforce without acct, flags=%x sbflags=%x\n",
351			__func__, flags, mp->m_sb.sb_qflags);
352		return XFS_ERROR(EINVAL);
353	}
354	/*
355	 * If everything's up to-date incore, then don't waste time.
356	 */
357	if ((mp->m_qflags & flags) == flags)
358		return XFS_ERROR(EEXIST);
359
360	/*
361	 * Change sb_qflags on disk but not incore mp->qflags
362	 * if this is the root filesystem.
363	 */
364	spin_lock(&mp->m_sb_lock);
365	qf = mp->m_sb.sb_qflags;
366	mp->m_sb.sb_qflags = qf | flags;
367	spin_unlock(&mp->m_sb_lock);
368
369	/*
370	 * There's nothing to change if it's the same.
371	 */
372	if ((qf & flags) == flags && sbflags == 0)
373		return XFS_ERROR(EEXIST);
374	sbflags |= XFS_SB_QFLAGS;
375
376	if ((error = xfs_qm_write_sb_changes(mp, sbflags)))
377		return (error);
 
378	/*
379	 * If we aren't trying to switch on quota enforcement, we are done.
380	 */
381	if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
382	     (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
383	     ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
384	     (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
385	     ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
386	     (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
387	    (flags & XFS_ALL_QUOTA_ENFD) == 0)
388		return (0);
389
390	if (! XFS_IS_QUOTA_RUNNING(mp))
391		return XFS_ERROR(ESRCH);
392
393	/*
394	 * Switch on quota enforcement in core.
395	 */
396	mutex_lock(&mp->m_quotainfo->qi_quotaofflock);
397	mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
398	mutex_unlock(&mp->m_quotainfo->qi_quotaofflock);
399
400	return (0);
401}
402
 
403
404/*
405 * Return quota status information, such as uquota-off, enforcements, etc.
 
406 */
407int
408xfs_qm_scall_getqstat(
409	struct xfs_mount	*mp,
410	struct fs_quota_stat	*out)
 
 
 
 
411{
412	struct xfs_quotainfo	*q = mp->m_quotainfo;
413	struct xfs_inode	*uip, *gip;
414	boolean_t		tempuqip, tempgqip;
 
 
 
415
416	uip = gip = NULL;
417	tempuqip = tempgqip = B_FALSE;
418	memset(out, 0, sizeof(fs_quota_stat_t));
419
420	out->qs_version = FS_QSTAT_VERSION;
421	if (!xfs_sb_version_hasquota(&mp->m_sb)) {
422		out->qs_uquota.qfs_ino = NULLFSINO;
423		out->qs_gquota.qfs_ino = NULLFSINO;
424		return (0);
425	}
426	out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
427							(XFS_ALL_QUOTA_ACCT|
428							 XFS_ALL_QUOTA_ENFD));
429	out->qs_pad = 0;
430	out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
431	out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
432
433	if (q) {
434		uip = q->qi_uquotaip;
435		gip = q->qi_gquotaip;
436	}
437	if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
438		if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
439					0, 0, &uip) == 0)
440			tempuqip = B_TRUE;
441	}
442	if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
443		if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
444					0, 0, &gip) == 0)
445			tempgqip = B_TRUE;
446	}
447	if (uip) {
448		out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
449		out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
450		if (tempuqip)
451			IRELE(uip);
452	}
453	if (gip) {
454		out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
455		out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
456		if (tempgqip)
457			IRELE(gip);
458	}
459	if (q) {
460		out->qs_incoredqs = q->qi_dquots;
461		out->qs_btimelimit = q->qi_btimelimit;
462		out->qs_itimelimit = q->qi_itimelimit;
463		out->qs_rtbtimelimit = q->qi_rtbtimelimit;
464		out->qs_bwarnlimit = q->qi_bwarnlimit;
465		out->qs_iwarnlimit = q->qi_iwarnlimit;
466	}
467	return 0;
 
468}
469
470#define XFS_DQ_MASK \
471	(FS_DQ_LIMIT_MASK | FS_DQ_TIMER_MASK | FS_DQ_WARNS_MASK)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472
473/*
474 * Adjust quota limits, and start/stop timers accordingly.
475 */
476int
477xfs_qm_scall_setqlim(
478	xfs_mount_t		*mp,
479	xfs_dqid_t		id,
480	uint			type,
481	fs_disk_quota_t		*newlim)
482{
483	struct xfs_quotainfo	*q = mp->m_quotainfo;
484	xfs_disk_dquot_t	*ddq;
485	xfs_dquot_t		*dqp;
486	xfs_trans_t		*tp;
 
 
487	int			error;
488	xfs_qcnt_t		hard, soft;
489
490	if (newlim->d_fieldmask & ~XFS_DQ_MASK)
491		return EINVAL;
492	if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0)
493		return 0;
494
495	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
496	if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_disk_dquot_t) + 128,
497				      0, 0, XFS_DEFAULT_LOG_COUNT))) {
498		xfs_trans_cancel(tp, 0);
499		return (error);
500	}
501
502	/*
503	 * We don't want to race with a quotaoff so take the quotaoff lock.
504	 * (We don't hold an inode lock, so there's nothing else to stop
505	 * a quotaoff from happening). (XXXThis doesn't currently happen
506	 * because we take the vfslock before calling xfs_qm_sysent).
 
507	 */
508	mutex_lock(&q->qi_quotaofflock);
509
510	/*
511	 * Get the dquot (locked), and join it to the transaction.
512	 * Allocate the dquot if this doesn't exist.
513	 */
514	if ((error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp))) {
515		xfs_trans_cancel(tp, XFS_TRANS_ABORT);
516		ASSERT(error != ENOENT);
517		goto out_unlock;
518	}
 
 
 
 
 
 
 
 
 
519	xfs_trans_dqjoin(tp, dqp);
520	ddq = &dqp->q_core;
521
522	/*
 
 
 
523	 * Make sure that hardlimits are >= soft limits before changing.
 
 
 
 
 
 
 
 
 
 
524	 */
525	hard = (newlim->d_fieldmask & FS_DQ_BHARD) ?
526		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_hardlimit) :
527			be64_to_cpu(ddq->d_blk_hardlimit);
528	soft = (newlim->d_fieldmask & FS_DQ_BSOFT) ?
529		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_softlimit) :
530			be64_to_cpu(ddq->d_blk_softlimit);
531	if (hard == 0 || hard >= soft) {
532		ddq->d_blk_hardlimit = cpu_to_be64(hard);
533		ddq->d_blk_softlimit = cpu_to_be64(soft);
534		if (id == 0) {
535			q->qi_bhardlimit = hard;
536			q->qi_bsoftlimit = soft;
537		}
538	} else {
539		xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft);
540	}
541	hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
542		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
543			be64_to_cpu(ddq->d_rtb_hardlimit);
544	soft = (newlim->d_fieldmask & FS_DQ_RTBSOFT) ?
545		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_softlimit) :
546			be64_to_cpu(ddq->d_rtb_softlimit);
547	if (hard == 0 || hard >= soft) {
548		ddq->d_rtb_hardlimit = cpu_to_be64(hard);
549		ddq->d_rtb_softlimit = cpu_to_be64(soft);
550		if (id == 0) {
551			q->qi_rtbhardlimit = hard;
552			q->qi_rtbsoftlimit = soft;
553		}
554	} else {
555		xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
556	}
557
558	hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
559		(xfs_qcnt_t) newlim->d_ino_hardlimit :
560			be64_to_cpu(ddq->d_ino_hardlimit);
561	soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
562		(xfs_qcnt_t) newlim->d_ino_softlimit :
563			be64_to_cpu(ddq->d_ino_softlimit);
564	if (hard == 0 || hard >= soft) {
565		ddq->d_ino_hardlimit = cpu_to_be64(hard);
566		ddq->d_ino_softlimit = cpu_to_be64(soft);
567		if (id == 0) {
568			q->qi_ihardlimit = hard;
569			q->qi_isoftlimit = soft;
570		}
571	} else {
572		xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft);
573	}
574
575	/*
576	 * Update warnings counter(s) if requested
577	 */
578	if (newlim->d_fieldmask & FS_DQ_BWARNS)
579		ddq->d_bwarns = cpu_to_be16(newlim->d_bwarns);
580	if (newlim->d_fieldmask & FS_DQ_IWARNS)
581		ddq->d_iwarns = cpu_to_be16(newlim->d_iwarns);
582	if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
583		ddq->d_rtbwarns = cpu_to_be16(newlim->d_rtbwarns);
584
585	if (id == 0) {
586		/*
587		 * Timelimits for the super user set the relative time
588		 * the other users can be over quota for this file system.
589		 * If it is zero a default is used.  Ditto for the default
590		 * soft and hard limit values (already done, above), and
591		 * for warnings.
592		 */
593		if (newlim->d_fieldmask & FS_DQ_BTIMER) {
594			q->qi_btimelimit = newlim->d_btimer;
595			ddq->d_btimer = cpu_to_be32(newlim->d_btimer);
596		}
597		if (newlim->d_fieldmask & FS_DQ_ITIMER) {
598			q->qi_itimelimit = newlim->d_itimer;
599			ddq->d_itimer = cpu_to_be32(newlim->d_itimer);
600		}
601		if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
602			q->qi_rtbtimelimit = newlim->d_rtbtimer;
603			ddq->d_rtbtimer = cpu_to_be32(newlim->d_rtbtimer);
604		}
605		if (newlim->d_fieldmask & FS_DQ_BWARNS)
606			q->qi_bwarnlimit = newlim->d_bwarns;
607		if (newlim->d_fieldmask & FS_DQ_IWARNS)
608			q->qi_iwarnlimit = newlim->d_iwarns;
609		if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
610			q->qi_rtbwarnlimit = newlim->d_rtbwarns;
611	} else {
612		/*
613		 * If the user is now over quota, start the timelimit.
614		 * The user will not be 'warned'.
615		 * Note that we keep the timers ticking, whether enforcement
616		 * is on or off. We don't really want to bother with iterating
617		 * over all ondisk dquots and turning the timers on/off.
618		 */
619		xfs_qm_adjust_dqtimers(mp, ddq);
620	}
621	dqp->dq_flags |= XFS_DQ_DIRTY;
622	xfs_trans_log_dquot(tp, dqp);
623
624	error = xfs_trans_commit(tp, 0);
625	xfs_qm_dqrele(dqp);
626
627 out_unlock:
628	mutex_unlock(&q->qi_quotaofflock);
629	return error;
630}
631
632int
633xfs_qm_scall_getquota(
634	xfs_mount_t	*mp,
635	xfs_dqid_t	id,
636	uint		type,
637	fs_disk_quota_t *out)
 
638{
639	xfs_dquot_t	*dqp;
640	int		error;
641
642	/*
643	 * Try to get the dquot. We don't want it allocated on disk, so
644	 * we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't
645	 * exist, we'll get ENOENT back.
646	 */
647	if ((error = xfs_qm_dqget(mp, NULL, id, type, 0, &dqp))) {
648		return (error);
649	}
 
 
 
 
 
650
651	/*
652	 * If everything's NULL, this dquot doesn't quite exist as far as
653	 * our utility programs are concerned.
 
654	 */
655	if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
656		xfs_qm_dqput(dqp);
657		return XFS_ERROR(ENOENT);
 
658	}
659	/*
660	 * Convert the disk dquot to the exportable format
661	 */
662	xfs_qm_export_dquot(mp, &dqp->q_core, out);
663	xfs_qm_dqput(dqp);
664	return (error ? XFS_ERROR(EFAULT) : 0);
665}
666
667
668STATIC int
669xfs_qm_log_quotaoff_end(
670	xfs_mount_t		*mp,
671	xfs_qoff_logitem_t	*startqoff,
672	uint			flags)
 
673{
674	xfs_trans_t		*tp;
675	int			error;
676	xfs_qoff_logitem_t	*qoffi;
677
678	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
679
680	if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_qoff_logitem_t) * 2,
681				      0, 0, XFS_DEFAULT_LOG_COUNT))) {
682		xfs_trans_cancel(tp, 0);
683		return (error);
684	}
685
686	qoffi = xfs_trans_get_qoff_item(tp, startqoff,
687					flags & XFS_ALL_QUOTA_ACCT);
688	xfs_trans_log_quotaoff_item(tp, qoffi);
689
690	/*
691	 * We have to make sure that the transaction is secure on disk before we
692	 * return and actually stop quota accounting. So, make it synchronous.
693	 * We don't care about quotoff's performance.
694	 */
695	xfs_trans_set_sync(tp);
696	error = xfs_trans_commit(tp, 0);
697	return (error);
698}
699
700
701STATIC int
702xfs_qm_log_quotaoff(
703	xfs_mount_t	       *mp,
704	xfs_qoff_logitem_t     **qoffstartp,
705	uint		       flags)
706{
707	xfs_trans_t	       *tp;
708	int			error;
709	xfs_qoff_logitem_t     *qoffi=NULL;
710	uint			oldsbqflag=0;
711
712	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF);
713	if ((error = xfs_trans_reserve(tp, 0,
714				      sizeof(xfs_qoff_logitem_t) * 2 +
715				      mp->m_sb.sb_sectsize + 128,
716				      0,
717				      0,
718				      XFS_DEFAULT_LOG_COUNT))) {
719		goto error0;
720	}
721
722	qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
723	xfs_trans_log_quotaoff_item(tp, qoffi);
724
725	spin_lock(&mp->m_sb_lock);
726	oldsbqflag = mp->m_sb.sb_qflags;
727	mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
728	spin_unlock(&mp->m_sb_lock);
729
730	xfs_mod_sb(tp, XFS_SB_QFLAGS);
731
732	/*
733	 * We have to make sure that the transaction is secure on disk before we
734	 * return and actually stop quota accounting. So, make it synchronous.
735	 * We don't care about quotoff's performance.
736	 */
737	xfs_trans_set_sync(tp);
738	error = xfs_trans_commit(tp, 0);
739
740error0:
741	if (error) {
742		xfs_trans_cancel(tp, 0);
743		/*
744		 * No one else is modifying sb_qflags, so this is OK.
745		 * We still hold the quotaofflock.
746		 */
747		spin_lock(&mp->m_sb_lock);
748		mp->m_sb.sb_qflags = oldsbqflag;
749		spin_unlock(&mp->m_sb_lock);
750	}
751	*qoffstartp = qoffi;
752	return (error);
753}
754
755
756/*
757 * Translate an internal style on-disk-dquot to the exportable format.
758 * The main differences are that the counters/limits are all in Basic
759 * Blocks (BBs) instead of the internal FSBs, and all on-disk data has
760 * to be converted to the native endianness.
761 */
762STATIC void
763xfs_qm_export_dquot(
764	xfs_mount_t		*mp,
765	xfs_disk_dquot_t	*src,
766	struct fs_disk_quota	*dst)
767{
768	memset(dst, 0, sizeof(*dst));
769	dst->d_version = FS_DQUOT_VERSION;  /* different from src->d_version */
770	dst->d_flags = xfs_qm_export_qtype_flags(src->d_flags);
771	dst->d_id = be32_to_cpu(src->d_id);
772	dst->d_blk_hardlimit =
773		XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_blk_hardlimit));
774	dst->d_blk_softlimit =
775		XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_blk_softlimit));
776	dst->d_ino_hardlimit = be64_to_cpu(src->d_ino_hardlimit);
777	dst->d_ino_softlimit = be64_to_cpu(src->d_ino_softlimit);
778	dst->d_bcount = XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_bcount));
779	dst->d_icount = be64_to_cpu(src->d_icount);
780	dst->d_btimer = be32_to_cpu(src->d_btimer);
781	dst->d_itimer = be32_to_cpu(src->d_itimer);
782	dst->d_iwarns = be16_to_cpu(src->d_iwarns);
783	dst->d_bwarns = be16_to_cpu(src->d_bwarns);
784	dst->d_rtb_hardlimit =
785		XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_rtb_hardlimit));
786	dst->d_rtb_softlimit =
787		XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_rtb_softlimit));
788	dst->d_rtbcount = XFS_FSB_TO_BB(mp, be64_to_cpu(src->d_rtbcount));
789	dst->d_rtbtimer = be32_to_cpu(src->d_rtbtimer);
790	dst->d_rtbwarns = be16_to_cpu(src->d_rtbwarns);
791
792	/*
793	 * Internally, we don't reset all the timers when quota enforcement
794	 * gets turned off. No need to confuse the user level code,
795	 * so return zeroes in that case.
796	 */
797	if ((!XFS_IS_UQUOTA_ENFORCED(mp) && src->d_flags == XFS_DQ_USER) ||
798	    (!XFS_IS_OQUOTA_ENFORCED(mp) &&
799			(src->d_flags & (XFS_DQ_PROJ | XFS_DQ_GROUP)))) {
800		dst->d_btimer = 0;
801		dst->d_itimer = 0;
802		dst->d_rtbtimer = 0;
803	}
804
805#ifdef DEBUG
806	if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == FS_USER_QUOTA) ||
807	     (XFS_IS_OQUOTA_ENFORCED(mp) &&
808			(dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) &&
809	    dst->d_id != 0) {
810		if (((int) dst->d_bcount >= (int) dst->d_blk_softlimit) &&
811		    (dst->d_blk_softlimit > 0)) {
812			ASSERT(dst->d_btimer != 0);
813		}
814		if (((int) dst->d_icount >= (int) dst->d_ino_softlimit) &&
815		    (dst->d_ino_softlimit > 0)) {
816			ASSERT(dst->d_itimer != 0);
817		}
818	}
819#endif
820}
821
822STATIC uint
823xfs_qm_export_qtype_flags(
824	uint flags)
825{
826	/*
827	 * Can't be more than one, or none.
828	 */
829	ASSERT((flags & (FS_PROJ_QUOTA | FS_USER_QUOTA)) !=
830		(FS_PROJ_QUOTA | FS_USER_QUOTA));
831	ASSERT((flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)) !=
832		(FS_PROJ_QUOTA | FS_GROUP_QUOTA));
833	ASSERT((flags & (FS_USER_QUOTA | FS_GROUP_QUOTA)) !=
834		(FS_USER_QUOTA | FS_GROUP_QUOTA));
835	ASSERT((flags & (FS_PROJ_QUOTA|FS_USER_QUOTA|FS_GROUP_QUOTA)) != 0);
836
837	return (flags & XFS_DQ_USER) ?
838		FS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
839			FS_PROJ_QUOTA : FS_GROUP_QUOTA;
840}
841
842STATIC uint
843xfs_qm_export_flags(
844	uint flags)
 
 
 
 
 
 
 
845{
846	uint uflags;
847
848	uflags = 0;
849	if (flags & XFS_UQUOTA_ACCT)
850		uflags |= FS_QUOTA_UDQ_ACCT;
851	if (flags & XFS_PQUOTA_ACCT)
852		uflags |= FS_QUOTA_PDQ_ACCT;
853	if (flags & XFS_GQUOTA_ACCT)
854		uflags |= FS_QUOTA_GDQ_ACCT;
855	if (flags & XFS_UQUOTA_ENFD)
856		uflags |= FS_QUOTA_UDQ_ENFD;
857	if (flags & (XFS_OQUOTA_ENFD)) {
858		uflags |= (flags & XFS_GQUOTA_ACCT) ?
859			FS_QUOTA_GDQ_ENFD : FS_QUOTA_PDQ_ENFD;
860	}
861	return (uflags);
862}
863
 
 
 
864
865STATIC int
866xfs_dqrele_inode(
867	struct xfs_inode	*ip,
868	struct xfs_perag	*pag,
869	int			flags)
870{
871	/* skip quota inodes */
872	if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
873	    ip == ip->i_mount->m_quotainfo->qi_gquotaip) {
874		ASSERT(ip->i_udquot == NULL);
875		ASSERT(ip->i_gdquot == NULL);
876		return 0;
877	}
878
879	xfs_ilock(ip, XFS_ILOCK_EXCL);
880	if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
881		xfs_qm_dqrele(ip->i_udquot);
882		ip->i_udquot = NULL;
883	}
884	if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
885		xfs_qm_dqrele(ip->i_gdquot);
886		ip->i_gdquot = NULL;
887	}
888	xfs_iunlock(ip, XFS_ILOCK_EXCL);
889	return 0;
890}
891
 
892
893/*
894 * Go thru all the inodes in the file system, releasing their dquots.
895 *
896 * Note that the mount structure gets modified to indicate that quotas are off
897 * AFTER this, in the case of quotaoff.
898 */
899void
900xfs_qm_dqrele_all_inodes(
901	struct xfs_mount *mp,
902	uint		 flags)
903{
904	ASSERT(mp->m_quotainfo);
905	xfs_inode_ag_iterator(mp, xfs_dqrele_inode, flags);
906}
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}