1 /*
2  * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.	 Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32 
33 #include "xfs.h"
34 #include "xfs_fs.h"
35 #include "xfs_inum.h"
36 #include "xfs_log.h"
37 #include "xfs_trans.h"
38 #include "xfs_sb.h"
39 #include "xfs_dir.h"
40 #include "xfs_dir2.h"
41 #include "xfs_alloc.h"
42 #include "xfs_dmapi.h"
43 #include "xfs_quota.h"
44 #include "xfs_mount.h"
45 #include "xfs_alloc_btree.h"
46 #include "xfs_bmap_btree.h"
47 #include "xfs_ialloc_btree.h"
48 #include "xfs_btree.h"
49 #include "xfs_ialloc.h"
50 #include "xfs_attr_sf.h"
51 #include "xfs_dir_sf.h"
52 #include "xfs_dir2_sf.h"
53 #include "xfs_dinode.h"
54 #include "xfs_inode.h"
55 #include "xfs_bmap.h"
56 #include "xfs_bit.h"
57 #include "xfs_rtalloc.h"
58 #include "xfs_error.h"
59 #include "xfs_itable.h"
60 #include "xfs_rw.h"
61 #include "xfs_acl.h"
62 #include "xfs_cap.h"
63 #include "xfs_mac.h"
64 #include "xfs_attr.h"
65 #include "xfs_buf_item.h"
66 #include "xfs_utils.h"
67 
68 #include "xfs_qm.h"
69 
70 #ifdef DEBUG
71 # define qdprintk(s, args...)	cmn_err(CE_DEBUG, s, ## args)
72 #else
73 # define qdprintk(s, args...)	do { } while (0)
74 #endif
75 
76 STATIC int	xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
77 STATIC int	xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
78 					fs_disk_quota_t *);
79 STATIC int	xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
80 STATIC int	xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint,
81 					fs_disk_quota_t *);
82 STATIC int	xfs_qm_scall_quotaon(xfs_mount_t *, uint);
83 STATIC int	xfs_qm_scall_quotaoff(xfs_mount_t *, uint, boolean_t);
84 STATIC int	xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
85 STATIC int	xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
86 					uint);
87 STATIC uint	xfs_qm_import_flags(uint);
88 STATIC uint	xfs_qm_export_flags(uint);
89 STATIC uint	xfs_qm_import_qtype_flags(uint);
90 STATIC uint	xfs_qm_export_qtype_flags(uint);
91 STATIC void	xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *,
92 					fs_disk_quota_t *);
93 
94 
95 /*
96  * The main distribution switch of all XFS quotactl system calls.
97  */
98 int
xfs_qm_quotactl(struct bhv_desc * bdp,int cmd,int id,xfs_caddr_t addr)99 xfs_qm_quotactl(
100 	struct bhv_desc *bdp,
101 	int		cmd,
102 	int		id,
103 	xfs_caddr_t	addr)
104 {
105 	xfs_mount_t	*mp;
106 	int		error;
107 	struct vfs	*vfsp;
108 
109 	vfsp = bhvtovfs(bdp);
110 	mp = XFS_VFSTOM(vfsp);
111 
112 	if (addr == NULL && cmd != Q_SYNC)
113 		return XFS_ERROR(EINVAL);
114 	if (id < 0 && cmd != Q_SYNC)
115 		return XFS_ERROR(EINVAL);
116 
117 	/*
118 	 * The following commands are valid even when quotaoff.
119 	 */
120 	switch (cmd) {
121 		/*
122 		 * truncate quota files. quota must be off.
123 		 */
124 	      case Q_XQUOTARM:
125 		if (XFS_IS_QUOTA_ON(mp) || addr == NULL)
126 			return XFS_ERROR(EINVAL);
127 		if (vfsp->vfs_flag & VFS_RDONLY)
128 			return XFS_ERROR(EROFS);
129 		return (xfs_qm_scall_trunc_qfiles(mp,
130 			       xfs_qm_import_qtype_flags(*(uint *)addr)));
131 		/*
132 		 * Get quota status information.
133 		 */
134 	      case Q_XGETQSTAT:
135 		return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
136 
137 		/*
138 		 * QUOTAON for root f/s and quota enforcement on others..
139 		 * Quota accounting for non-root f/s's must be turned on
140 		 * at mount time.
141 		 */
142 	      case Q_XQUOTAON:
143 		if (addr == NULL)
144 			return XFS_ERROR(EINVAL);
145 		if (vfsp->vfs_flag & VFS_RDONLY)
146 			return XFS_ERROR(EROFS);
147 		return (xfs_qm_scall_quotaon(mp,
148 					  xfs_qm_import_flags(*(uint *)addr)));
149 	      case Q_XQUOTAOFF:
150 		if (vfsp->vfs_flag & VFS_RDONLY)
151 			return XFS_ERROR(EROFS);
152 		break;
153 
154 	      default:
155 		break;
156 	}
157 
158 	if (! XFS_IS_QUOTA_ON(mp))
159 		return XFS_ERROR(ESRCH);
160 
161 	switch (cmd) {
162 	      case Q_XQUOTAOFF:
163 		if (vfsp->vfs_flag & VFS_RDONLY)
164 			return XFS_ERROR(EROFS);
165 		error = xfs_qm_scall_quotaoff(mp,
166 					    xfs_qm_import_flags(*(uint *)addr),
167 					    B_FALSE);
168 		break;
169 
170 		/*
171 		 * Defaults to XFS_GETUQUOTA.
172 		 */
173 	      case Q_XGETQUOTA:
174 		error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
175 					(fs_disk_quota_t *)addr);
176 		break;
177 		/*
178 		 * Set limits, both hard and soft. Defaults to Q_SETUQLIM.
179 		 */
180 	      case Q_XSETQLIM:
181 		if (vfsp->vfs_flag & VFS_RDONLY)
182 			return XFS_ERROR(EROFS);
183 		error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
184 					     (fs_disk_quota_t *)addr);
185 		break;
186 
187 	       case Q_XSETGQLIM:
188 		if (vfsp->vfs_flag & VFS_RDONLY)
189 			return XFS_ERROR(EROFS);
190 		error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
191 					     (fs_disk_quota_t *)addr);
192 		break;
193 
194 
195 	      case Q_XGETGQUOTA:
196 		error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
197 					(fs_disk_quota_t *)addr);
198 		break;
199 
200 		/*
201 		 * Quotas are entirely undefined after quotaoff in XFS quotas.
202 		 * For instance, there's no way to set limits when quotaoff.
203 		 */
204 
205 	      default:
206 		error = XFS_ERROR(EINVAL);
207 		break;
208 	}
209 
210 	return (error);
211 }
212 
213 /*
214  * Turn off quota accounting and/or enforcement for all udquots and/or
215  * gdquots. Called only at unmount time.
216  *
217  * This assumes that there are no dquots of this file system cached
218  * incore, and modifies the ondisk dquot directly. Therefore, for example,
219  * it is an error to call this twice, without purging the cache.
220  */
221 STATIC int
xfs_qm_scall_quotaoff(xfs_mount_t * mp,uint flags,boolean_t force)222 xfs_qm_scall_quotaoff(
223 	xfs_mount_t		*mp,
224 	uint			flags,
225 	boolean_t		force)
226 {
227 	uint			dqtype;
228 	unsigned long	s;
229 	int			error;
230 	uint			inactivate_flags;
231 	xfs_qoff_logitem_t	*qoffstart;
232 	int			nculprits;
233 
234 	if (!force && !capable(CAP_SYS_ADMIN))
235 		return XFS_ERROR(EPERM);
236 	/*
237 	 * No file system can have quotas enabled on disk but not in core.
238 	 * Note that quota utilities (like quotaoff) _expect_
239 	 * errno == EEXIST here.
240 	 */
241 	if ((mp->m_qflags & flags) == 0)
242 		return XFS_ERROR(EEXIST);
243 	error = 0;
244 
245 	flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
246 
247 	/*
248 	 * We don't want to deal with two quotaoffs messing up each other,
249 	 * so we're going to serialize it. quotaoff isn't exactly a performance
250 	 * critical thing.
251 	 * If quotaoff, then we must be dealing with the root filesystem.
252 	 */
253 	ASSERT(mp->m_quotainfo);
254 	if (mp->m_quotainfo)
255 		mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD);
256 
257 	ASSERT(mp->m_quotainfo);
258 
259 	/*
260 	 * If we're just turning off quota enforcement, change mp and go.
261 	 */
262 	if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
263 		mp->m_qflags &= ~(flags);
264 
265 		s = XFS_SB_LOCK(mp);
266 		mp->m_sb.sb_qflags = mp->m_qflags;
267 		XFS_SB_UNLOCK(mp, s);
268 		mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
269 
270 		/* XXX what to do if error ? Revert back to old vals incore ? */
271 		error = xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS);
272 		return (error);
273 	}
274 
275 	dqtype = 0;
276 	inactivate_flags = 0;
277 	/*
278 	 * If accounting is off, we must turn enforcement off, clear the
279 	 * quota 'CHKD' certificate to make it known that we have to
280 	 * do a quotacheck the next time this quota is turned on.
281 	 */
282 	if (flags & XFS_UQUOTA_ACCT) {
283 		dqtype |= XFS_QMOPT_UQUOTA;
284 		flags |= (XFS_UQUOTA_CHKD | XFS_UQUOTA_ENFD);
285 		inactivate_flags |= XFS_UQUOTA_ACTIVE;
286 	}
287 	if (flags & XFS_GQUOTA_ACCT) {
288 		dqtype |= XFS_QMOPT_GQUOTA;
289 		flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
290 		inactivate_flags |= XFS_GQUOTA_ACTIVE;
291 	}
292 
293 	/*
294 	 * Nothing to do?  Don't complain. This happens when we're just
295 	 * turning off quota enforcement.
296 	 */
297 	if ((mp->m_qflags & flags) == 0) {
298 		mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
299 		return (0);
300 	}
301 
302 	/*
303 	 * Write the LI_QUOTAOFF log record, and do SB changes atomically,
304 	 * and synchronously.
305 	 */
306 	xfs_qm_log_quotaoff(mp, &qoffstart, flags);
307 
308 	/*
309 	 * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
310 	 * to take care of the race between dqget and quotaoff. We don't take
311 	 * any special locks to reset these bits. All processes need to check
312 	 * these bits *after* taking inode lock(s) to see if the particular
313 	 * quota type is in the process of being turned off. If *ACTIVE, it is
314 	 * guaranteed that all dquot structures and all quotainode ptrs will all
315 	 * stay valid as long as that inode is kept locked.
316 	 *
317 	 * There is no turning back after this.
318 	 */
319 	mp->m_qflags &= ~inactivate_flags;
320 
321 	/*
322 	 * Give back all the dquot reference(s) held by inodes.
323 	 * Here we go thru every single incore inode in this file system, and
324 	 * do a dqrele on the i_udquot/i_gdquot that it may have.
325 	 * Essentially, as long as somebody has an inode locked, this guarantees
326 	 * that quotas will not be turned off. This is handy because in a
327 	 * transaction once we lock the inode(s) and check for quotaon, we can
328 	 * depend on the quota inodes (and other things) being valid as long as
329 	 * we keep the lock(s).
330 	 */
331 	xfs_qm_dqrele_all_inodes(mp, flags);
332 
333 	/*
334 	 * Next we make the changes in the quota flag in the mount struct.
335 	 * This isn't protected by a particular lock directly, because we
336 	 * don't want to take a mrlock everytime we depend on quotas being on.
337 	 */
338 	mp->m_qflags &= ~(flags);
339 
340 	/*
341 	 * Go through all the dquots of this file system and purge them,
342 	 * according to what was turned off. We may not be able to get rid
343 	 * of all dquots, because dquots can have temporary references that
344 	 * are not attached to inodes. eg. xfs_setattr, xfs_create.
345 	 * So, if we couldn't purge all the dquots from the filesystem,
346 	 * we can't get rid of the incore data structures.
347 	 */
348 	while ((nculprits = xfs_qm_dqpurge_all(mp, dqtype|XFS_QMOPT_QUOTAOFF)))
349 		delay(10 * nculprits);
350 
351 	/*
352 	 * Transactions that had started before ACTIVE state bit was cleared
353 	 * could have logged many dquots, so they'd have higher LSNs than
354 	 * the first QUOTAOFF log record does. If we happen to crash when
355 	 * the tail of the log has gone past the QUOTAOFF record, but
356 	 * before the last dquot modification, those dquots __will__
357 	 * recover, and that's not good.
358 	 *
359 	 * So, we have QUOTAOFF start and end logitems; the start
360 	 * logitem won't get overwritten until the end logitem appears...
361 	 */
362 	xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
363 
364 	/*
365 	 * If quotas is completely disabled, close shop.
366 	 */
367 	if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
368 		mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
369 		xfs_qm_destroy_quotainfo(mp);
370 		return (0);
371 	}
372 
373 	/*
374 	 * Release our quotainode references, and vn_purge them,
375 	 * if we don't need them anymore.
376 	 */
377 	if ((dqtype & XFS_QMOPT_UQUOTA) && XFS_QI_UQIP(mp)) {
378 		XFS_PURGE_INODE(XFS_QI_UQIP(mp));
379 		XFS_QI_UQIP(mp) = NULL;
380 	}
381 	if ((dqtype & XFS_QMOPT_GQUOTA) && XFS_QI_GQIP(mp)) {
382 		XFS_PURGE_INODE(XFS_QI_GQIP(mp));
383 		XFS_QI_GQIP(mp) = NULL;
384 	}
385 	mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
386 
387 	return (error);
388 }
389 
390 STATIC int
xfs_qm_scall_trunc_qfiles(xfs_mount_t * mp,uint flags)391 xfs_qm_scall_trunc_qfiles(
392 	xfs_mount_t	*mp,
393 	uint		flags)
394 {
395 	int		error;
396 	xfs_inode_t	*qip;
397 
398 	if (!capable(CAP_SYS_ADMIN))
399 		return XFS_ERROR(EPERM);
400 	error = 0;
401 	if (!XFS_SB_VERSION_HASQUOTA(&mp->m_sb) || flags == 0) {
402 		qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags);
403 		return XFS_ERROR(EINVAL);
404 	}
405 
406 	if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) {
407 		error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0);
408 		if (! error) {
409 			(void) xfs_truncate_file(mp, qip);
410 			VN_RELE(XFS_ITOV(qip));
411 		}
412 	}
413 
414 	if ((flags & XFS_DQ_GROUP) && mp->m_sb.sb_gquotino != NULLFSINO) {
415 		error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
416 		if (! error) {
417 			(void) xfs_truncate_file(mp, qip);
418 			VN_RELE(XFS_ITOV(qip));
419 		}
420 	}
421 
422 	return (error);
423 }
424 
425 
426 /*
427  * Switch on (a given) quota enforcement for a filesystem.  This takes
428  * effect immediately.
429  * (Switching on quota accounting must be done at mount time.)
430  */
431 STATIC int
xfs_qm_scall_quotaon(xfs_mount_t * mp,uint flags)432 xfs_qm_scall_quotaon(
433 	xfs_mount_t	*mp,
434 	uint		flags)
435 {
436 	int		error;
437 	unsigned long s;
438 	uint		qf;
439 	uint		accflags;
440 	__int64_t	sbflags;
441 
442 	if (!capable(CAP_SYS_ADMIN))
443 		return XFS_ERROR(EPERM);
444 
445 	flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
446 	/*
447 	 * Switching on quota accounting must be done at mount time.
448 	 */
449 	accflags = flags & XFS_ALL_QUOTA_ACCT;
450 	flags &= ~(XFS_ALL_QUOTA_ACCT);
451 
452 	sbflags = 0;
453 
454 	if (flags == 0) {
455 		qdprintk("quotaon: zero flags, m_qflags=%x\n", mp->m_qflags);
456 		return XFS_ERROR(EINVAL);
457 	}
458 
459 	/* No fs can turn on quotas with a delayed effect */
460 	ASSERT((flags & XFS_ALL_QUOTA_ACCT) == 0);
461 
462 	/*
463 	 * Can't enforce without accounting. We check the superblock
464 	 * qflags here instead of m_qflags because rootfs can have
465 	 * quota acct on ondisk without m_qflags' knowing.
466 	 */
467 	if (((flags & XFS_UQUOTA_ACCT) == 0 &&
468 	    (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
469 	    (flags & XFS_UQUOTA_ENFD))
470 	    ||
471 	    ((flags & XFS_GQUOTA_ACCT) == 0 &&
472 	    (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
473 	    (flags & XFS_GQUOTA_ENFD))) {
474 		qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
475 			flags, mp->m_sb.sb_qflags);
476 		return XFS_ERROR(EINVAL);
477 	}
478 	/*
479 	 * If everything's upto-date incore, then don't waste time.
480 	 */
481 	if ((mp->m_qflags & flags) == flags)
482 		return XFS_ERROR(EEXIST);
483 
484 	/*
485 	 * Change sb_qflags on disk but not incore mp->qflags
486 	 * if this is the root filesystem.
487 	 */
488 	s = XFS_SB_LOCK(mp);
489 	qf = mp->m_sb.sb_qflags;
490 	mp->m_sb.sb_qflags = qf | flags;
491 	XFS_SB_UNLOCK(mp, s);
492 
493 	/*
494 	 * There's nothing to change if it's the same.
495 	 */
496 	if ((qf & flags) == flags && sbflags == 0)
497 		return XFS_ERROR(EEXIST);
498 	sbflags |= XFS_SB_QFLAGS;
499 
500 	if ((error = xfs_qm_write_sb_changes(mp, sbflags)))
501 		return (error);
502 	/*
503 	 * If we aren't trying to switch on quota enforcement, we are done.
504 	 */
505 	if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
506 	     (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
507 	    (flags & XFS_ALL_QUOTA_ENFD) == 0)
508 		return (0);
509 
510 	if (! XFS_IS_QUOTA_RUNNING(mp))
511 		return XFS_ERROR(ESRCH);
512 
513 	/*
514 	 * Switch on quota enforcement in core.
515 	 */
516 	mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD);
517 	mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
518 	mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
519 
520 	return (0);
521 }
522 
523 
524 
525 /*
526  * Return quota status information, such as uquota-off, enforcements, etc.
527  */
528 STATIC int
xfs_qm_scall_getqstat(xfs_mount_t * mp,fs_quota_stat_t * out)529 xfs_qm_scall_getqstat(
530 	xfs_mount_t	*mp,
531 	fs_quota_stat_t *out)
532 {
533 	xfs_inode_t	*uip, *gip;
534 	boolean_t	tempuqip, tempgqip;
535 
536 	uip = gip = NULL;
537 	tempuqip = tempgqip = B_FALSE;
538 	memset(out, 0, sizeof(fs_quota_stat_t));
539 
540 	out->qs_version = FS_QSTAT_VERSION;
541 	if (! XFS_SB_VERSION_HASQUOTA(&mp->m_sb)) {
542 		out->qs_uquota.qfs_ino = NULLFSINO;
543 		out->qs_gquota.qfs_ino = NULLFSINO;
544 		return (0);
545 	}
546 	out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
547 							(XFS_ALL_QUOTA_ACCT|
548 							 XFS_ALL_QUOTA_ENFD));
549 	out->qs_pad = 0;
550 	out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
551 	out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
552 
553 	if (mp->m_quotainfo) {
554 		uip = mp->m_quotainfo->qi_uquotaip;
555 		gip = mp->m_quotainfo->qi_gquotaip;
556 	}
557 	if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
558 		if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
559 					0, 0, &uip, 0) == 0)
560 			tempuqip = B_TRUE;
561 	}
562 	if (!gip && mp->m_sb.sb_gquotino != NULLFSINO) {
563 		if (xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
564 					0, 0, &gip, 0) == 0)
565 			tempgqip = B_TRUE;
566 	}
567 	if (uip) {
568 		out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
569 		out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
570 		if (tempuqip)
571 			VN_RELE(XFS_ITOV(uip));
572 	}
573 	if (gip) {
574 		out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
575 		out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
576 		if (tempgqip)
577 			VN_RELE(XFS_ITOV(gip));
578 	}
579 	if (mp->m_quotainfo) {
580 		out->qs_incoredqs = XFS_QI_MPLNDQUOTS(mp);
581 		out->qs_btimelimit = XFS_QI_BTIMELIMIT(mp);
582 		out->qs_itimelimit = XFS_QI_ITIMELIMIT(mp);
583 		out->qs_rtbtimelimit = XFS_QI_RTBTIMELIMIT(mp);
584 		out->qs_bwarnlimit = XFS_QI_BWARNLIMIT(mp);
585 		out->qs_iwarnlimit = XFS_QI_IWARNLIMIT(mp);
586 	}
587 	return (0);
588 }
589 
590 /*
591  * Adjust quota limits, and start/stop timers accordingly.
592  */
593 STATIC int
xfs_qm_scall_setqlim(xfs_mount_t * mp,xfs_dqid_t id,uint type,fs_disk_quota_t * newlim)594 xfs_qm_scall_setqlim(
595 	xfs_mount_t		*mp,
596 	xfs_dqid_t		id,
597 	uint			type,
598 	fs_disk_quota_t		*newlim)
599 {
600 	xfs_disk_dquot_t	*ddq;
601 	xfs_dquot_t		*dqp;
602 	xfs_trans_t		*tp;
603 	int			error;
604 	xfs_qcnt_t		hard, soft;
605 
606 	if (!capable(CAP_SYS_ADMIN))
607 		return XFS_ERROR(EPERM);
608 
609 	if ((newlim->d_fieldmask & (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK)) == 0)
610 		return (0);
611 
612 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
613 	if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_disk_dquot_t) + 128,
614 				      0, 0, XFS_DEFAULT_LOG_COUNT))) {
615 		xfs_trans_cancel(tp, 0);
616 		return (error);
617 	}
618 
619 	/*
620 	 * We don't want to race with a quotaoff so take the quotaoff lock.
621 	 * (We don't hold an inode lock, so there's nothing else to stop
622 	 * a quotaoff from happening). (XXXThis doesn't currently happen
623 	 * because we take the vfslock before calling xfs_qm_sysent).
624 	 */
625 	mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD);
626 
627 	/*
628 	 * Get the dquot (locked), and join it to the transaction.
629 	 * Allocate the dquot if this doesn't exist.
630 	 */
631 	if ((error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp))) {
632 		xfs_trans_cancel(tp, XFS_TRANS_ABORT);
633 		mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
634 		ASSERT(error != ENOENT);
635 		return (error);
636 	}
637 	xfs_dqtrace_entry(dqp, "Q_SETQLIM: AFT DQGET");
638 	xfs_trans_dqjoin(tp, dqp);
639 	ddq = &dqp->q_core;
640 
641 	/*
642 	 * Make sure that hardlimits are >= soft limits before changing.
643 	 */
644 	hard = (newlim->d_fieldmask & FS_DQ_BHARD) ?
645 		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_hardlimit) :
646 			INT_GET(ddq->d_blk_hardlimit, ARCH_CONVERT);
647 	soft = (newlim->d_fieldmask & FS_DQ_BSOFT) ?
648 		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_softlimit) :
649 			INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT);
650 	if (hard == 0 || hard >= soft) {
651 		INT_SET(ddq->d_blk_hardlimit, ARCH_CONVERT, hard);
652 		INT_SET(ddq->d_blk_softlimit, ARCH_CONVERT, soft);
653 		if (id == 0) {
654 			mp->m_quotainfo->qi_bhardlimit = hard;
655 			mp->m_quotainfo->qi_bsoftlimit = soft;
656 		}
657 	} else {
658 		qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft);
659 	}
660 	hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
661 		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
662 			INT_GET(ddq->d_rtb_hardlimit, ARCH_CONVERT);
663 	soft = (newlim->d_fieldmask & FS_DQ_RTBSOFT) ?
664 		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_softlimit) :
665 			INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT);
666 	if (hard == 0 || hard >= soft) {
667 		INT_SET(ddq->d_rtb_hardlimit, ARCH_CONVERT, hard);
668 		INT_SET(ddq->d_rtb_softlimit, ARCH_CONVERT, soft);
669 		if (id == 0) {
670 			mp->m_quotainfo->qi_rtbhardlimit = hard;
671 			mp->m_quotainfo->qi_rtbsoftlimit = soft;
672 		}
673 	} else {
674 		qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
675 	}
676 
677 	hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
678 		(xfs_qcnt_t) newlim->d_ino_hardlimit :
679 			INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT);
680 	soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
681 		(xfs_qcnt_t) newlim->d_ino_softlimit :
682 			INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT);
683 	if (hard == 0 || hard >= soft) {
684 		INT_SET(ddq->d_ino_hardlimit, ARCH_CONVERT, hard);
685 		INT_SET(ddq->d_ino_softlimit, ARCH_CONVERT, soft);
686 		if (id == 0) {
687 			mp->m_quotainfo->qi_ihardlimit = hard;
688 			mp->m_quotainfo->qi_isoftlimit = soft;
689 		}
690 	} else {
691 		qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
692 	}
693 
694 	if (id == 0) {
695 		/*
696 		 * Timelimits for the super user set the relative time
697 		 * the other users can be over quota for this file system.
698 		 * If it is zero a default is used.  Ditto for the default
699 		 * soft and hard limit values (already done, above).
700 		 */
701 		if (newlim->d_fieldmask & FS_DQ_BTIMER) {
702 			mp->m_quotainfo->qi_btimelimit = newlim->d_btimer;
703 			INT_SET(ddq->d_btimer, ARCH_CONVERT, newlim->d_btimer);
704 		}
705 		if (newlim->d_fieldmask & FS_DQ_ITIMER) {
706 			mp->m_quotainfo->qi_itimelimit = newlim->d_itimer;
707 			INT_SET(ddq->d_itimer, ARCH_CONVERT, newlim->d_itimer);
708 		}
709 		if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
710 			mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer;
711 			INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
712 		}
713 	} else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ {
714 		/*
715 		 * If the user is now over quota, start the timelimit.
716 		 * The user will not be 'warned'.
717 		 * Note that we keep the timers ticking, whether enforcement
718 		 * is on or off. We don't really want to bother with iterating
719 		 * over all ondisk dquots and turning the timers on/off.
720 		 */
721 		xfs_qm_adjust_dqtimers(mp, ddq);
722 	}
723 	dqp->dq_flags |= XFS_DQ_DIRTY;
724 	xfs_trans_log_dquot(tp, dqp);
725 
726 	xfs_dqtrace_entry(dqp, "Q_SETQLIM: COMMIT");
727 	xfs_trans_commit(tp, 0, NULL);
728 	xfs_qm_dqprint(dqp);
729 	xfs_qm_dqrele(dqp);
730 	mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
731 
732 	return (0);
733 }
734 
735 STATIC int
xfs_qm_scall_getquota(xfs_mount_t * mp,xfs_dqid_t id,uint type,fs_disk_quota_t * out)736 xfs_qm_scall_getquota(
737 	xfs_mount_t	*mp,
738 	xfs_dqid_t	id,
739 	uint		type,
740 	fs_disk_quota_t *out)
741 {
742 	xfs_dquot_t	*dqp;
743 	int		error;
744 
745 	/*
746 	 * Try to get the dquot. We don't want it allocated on disk, so
747 	 * we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't
748 	 * exist, we'll get ENOENT back.
749 	 */
750 	if ((error = xfs_qm_dqget(mp, NULL, id, type, 0, &dqp))) {
751 		return (error);
752 	}
753 
754 	xfs_dqtrace_entry(dqp, "Q_GETQUOTA SUCCESS");
755 	/*
756 	 * If everything's NULL, this dquot doesn't quite exist as far as
757 	 * our utility programs are concerned.
758 	 */
759 	if (XFS_IS_DQUOT_UNINITIALIZED(dqp)) {
760 		xfs_qm_dqput(dqp);
761 		return XFS_ERROR(ENOENT);
762 	}
763 	/* xfs_qm_dqprint(dqp); */
764 	/*
765 	 * Convert the disk dquot to the exportable format
766 	 */
767 	xfs_qm_export_dquot(mp, &dqp->q_core, out);
768 	xfs_qm_dqput(dqp);
769 	return (error ? XFS_ERROR(EFAULT) : 0);
770 }
771 
772 
773 STATIC int
xfs_qm_log_quotaoff_end(xfs_mount_t * mp,xfs_qoff_logitem_t * startqoff,uint flags)774 xfs_qm_log_quotaoff_end(
775 	xfs_mount_t		*mp,
776 	xfs_qoff_logitem_t	*startqoff,
777 	uint			flags)
778 {
779 	xfs_trans_t	       *tp;
780 	int			error;
781 	xfs_qoff_logitem_t     *qoffi;
782 
783 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
784 
785 	if ((error = xfs_trans_reserve(tp, 0, sizeof(xfs_qoff_logitem_t) * 2,
786 				      0, 0, XFS_DEFAULT_LOG_COUNT))) {
787 		xfs_trans_cancel(tp, 0);
788 		return (error);
789 	}
790 
791 	qoffi = xfs_trans_get_qoff_item(tp, startqoff,
792 					flags & XFS_ALL_QUOTA_ACCT);
793 	xfs_trans_log_quotaoff_item(tp, qoffi);
794 
795 	/*
796 	 * We have to make sure that the transaction is secure on disk before we
797 	 * return and actually stop quota accounting. So, make it synchronous.
798 	 * We don't care about quotoff's performance.
799 	 */
800 	xfs_trans_set_sync(tp);
801 	error = xfs_trans_commit(tp, 0, NULL);
802 	return (error);
803 }
804 
805 
806 STATIC int
xfs_qm_log_quotaoff(xfs_mount_t * mp,xfs_qoff_logitem_t ** qoffstartp,uint flags)807 xfs_qm_log_quotaoff(
808 	xfs_mount_t	       *mp,
809 	xfs_qoff_logitem_t     **qoffstartp,
810 	uint		       flags)
811 {
812 	xfs_trans_t	       *tp;
813 	int			error;
814 	unsigned long	s;
815 	xfs_qoff_logitem_t     *qoffi=NULL;
816 	uint			oldsbqflag=0;
817 
818 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF);
819 	if ((error = xfs_trans_reserve(tp, 0,
820 				      sizeof(xfs_qoff_logitem_t) * 2 +
821 				      mp->m_sb.sb_sectsize + 128,
822 				      0,
823 				      0,
824 				      XFS_DEFAULT_LOG_COUNT))) {
825 		goto error0;
826 	}
827 
828 	qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
829 	xfs_trans_log_quotaoff_item(tp, qoffi);
830 
831 	s = XFS_SB_LOCK(mp);
832 	oldsbqflag = mp->m_sb.sb_qflags;
833 	mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
834 	XFS_SB_UNLOCK(mp, s);
835 
836 	xfs_mod_sb(tp, XFS_SB_QFLAGS);
837 
838 	/*
839 	 * We have to make sure that the transaction is secure on disk before we
840 	 * return and actually stop quota accounting. So, make it synchronous.
841 	 * We don't care about quotoff's performance.
842 	 */
843 	xfs_trans_set_sync(tp);
844 	error = xfs_trans_commit(tp, 0, NULL);
845 
846 error0:
847 	if (error) {
848 		xfs_trans_cancel(tp, 0);
849 		/*
850 		 * No one else is modifying sb_qflags, so this is OK.
851 		 * We still hold the quotaofflock.
852 		 */
853 		s = XFS_SB_LOCK(mp);
854 		mp->m_sb.sb_qflags = oldsbqflag;
855 		XFS_SB_UNLOCK(mp, s);
856 	}
857 	*qoffstartp = qoffi;
858 	return (error);
859 }
860 
861 
862 /*
863  * Translate an internal style on-disk-dquot to the exportable format.
864  * The main differences are that the counters/limits are all in Basic
865  * Blocks (BBs) instead of the internal FSBs, and all on-disk data has
866  * to be converted to the native endianness.
867  */
868 STATIC void
xfs_qm_export_dquot(xfs_mount_t * mp,xfs_disk_dquot_t * src,struct fs_disk_quota * dst)869 xfs_qm_export_dquot(
870 	xfs_mount_t		*mp,
871 	xfs_disk_dquot_t	*src,
872 	struct fs_disk_quota	*dst)
873 {
874 	memset(dst, 0, sizeof(*dst));
875 	dst->d_version = FS_DQUOT_VERSION;  /* different from src->d_version */
876 	dst->d_flags =
877 		xfs_qm_export_qtype_flags(INT_GET(src->d_flags, ARCH_CONVERT));
878 	dst->d_id = INT_GET(src->d_id, ARCH_CONVERT);
879 	dst->d_blk_hardlimit = (__uint64_t)
880 		XFS_FSB_TO_BB(mp, INT_GET(src->d_blk_hardlimit, ARCH_CONVERT));
881 	dst->d_blk_softlimit = (__uint64_t)
882 		XFS_FSB_TO_BB(mp, INT_GET(src->d_blk_softlimit, ARCH_CONVERT));
883 	dst->d_ino_hardlimit = (__uint64_t)
884 		INT_GET(src->d_ino_hardlimit, ARCH_CONVERT);
885 	dst->d_ino_softlimit = (__uint64_t)
886 		INT_GET(src->d_ino_softlimit, ARCH_CONVERT);
887 	dst->d_bcount = (__uint64_t)
888 		XFS_FSB_TO_BB(mp, INT_GET(src->d_bcount, ARCH_CONVERT));
889 	dst->d_icount = (__uint64_t) INT_GET(src->d_icount, ARCH_CONVERT);
890 	dst->d_btimer = (__uint32_t) INT_GET(src->d_btimer, ARCH_CONVERT);
891 	dst->d_itimer = (__uint32_t) INT_GET(src->d_itimer, ARCH_CONVERT);
892 	dst->d_iwarns = INT_GET(src->d_iwarns, ARCH_CONVERT);
893 	dst->d_bwarns = INT_GET(src->d_bwarns, ARCH_CONVERT);
894 
895 	dst->d_rtb_hardlimit = (__uint64_t)
896 		XFS_FSB_TO_BB(mp, INT_GET(src->d_rtb_hardlimit, ARCH_CONVERT));
897 	dst->d_rtb_softlimit = (__uint64_t)
898 		XFS_FSB_TO_BB(mp, INT_GET(src->d_rtb_softlimit, ARCH_CONVERT));
899 	dst->d_rtbcount = (__uint64_t)
900 		XFS_FSB_TO_BB(mp, INT_GET(src->d_rtbcount, ARCH_CONVERT));
901 	dst->d_rtbtimer = (__uint32_t) INT_GET(src->d_rtbtimer, ARCH_CONVERT);
902 	dst->d_rtbwarns = INT_GET(src->d_rtbwarns, ARCH_CONVERT);
903 
904 	/*
905 	 * Internally, we don't reset all the timers when quota enforcement
906 	 * gets turned off. No need to confuse the userlevel code,
907 	 * so return zeroes in that case.
908 	 */
909 	if (! XFS_IS_QUOTA_ENFORCED(mp)) {
910 		dst->d_btimer = 0;
911 		dst->d_itimer = 0;
912 		dst->d_rtbtimer = 0;
913 	}
914 
915 #ifdef DEBUG
916 	if (XFS_IS_QUOTA_ENFORCED(mp) && dst->d_id != 0) {
917 		if (((int) dst->d_bcount >= (int) dst->d_blk_softlimit) &&
918 		    (dst->d_blk_softlimit > 0)) {
919 			ASSERT(dst->d_btimer != 0);
920 		}
921 		if (((int) dst->d_icount >= (int) dst->d_ino_softlimit) &&
922 		    (dst->d_ino_softlimit > 0)) {
923 			ASSERT(dst->d_itimer != 0);
924 		}
925 	}
926 #endif
927 }
928 
929 STATIC uint
xfs_qm_import_qtype_flags(uint uflags)930 xfs_qm_import_qtype_flags(
931 	uint uflags)
932 {
933 	/*
934 	 * Can't be both at the same time.
935 	 */
936 	if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ==
937 	     (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
938 	    ((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 0))
939 		return (0);
940 
941 	return (uflags & XFS_USER_QUOTA) ?
942 		XFS_DQ_USER : XFS_DQ_GROUP;
943 }
944 
945 STATIC uint
xfs_qm_export_qtype_flags(uint flags)946 xfs_qm_export_qtype_flags(
947 	uint flags)
948 {
949 	/*
950 	 * Can't be both at the same time.
951 	 */
952 	ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) !=
953 		(XFS_GROUP_QUOTA | XFS_USER_QUOTA));
954 	ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 0);
955 
956 	return (flags & XFS_DQ_USER) ?
957 		XFS_USER_QUOTA : XFS_GROUP_QUOTA;
958 }
959 
960 STATIC uint
xfs_qm_import_flags(uint uflags)961 xfs_qm_import_flags(
962 	uint uflags)
963 {
964 	uint flags = 0;
965 
966 	if (uflags & XFS_QUOTA_UDQ_ACCT)
967 		flags |= XFS_UQUOTA_ACCT;
968 	if (uflags & XFS_QUOTA_GDQ_ACCT)
969 		flags |= XFS_GQUOTA_ACCT;
970 	if (uflags & XFS_QUOTA_UDQ_ENFD)
971 		flags |= XFS_UQUOTA_ENFD;
972 	if (uflags & XFS_QUOTA_GDQ_ENFD)
973 		flags |= XFS_GQUOTA_ENFD;
974 	return (flags);
975 }
976 
977 
978 STATIC uint
xfs_qm_export_flags(uint flags)979 xfs_qm_export_flags(
980 	uint flags)
981 {
982 	uint uflags;
983 
984 	uflags = 0;
985 	if (flags & XFS_UQUOTA_ACCT)
986 		uflags |= XFS_QUOTA_UDQ_ACCT;
987 	if (flags & XFS_GQUOTA_ACCT)
988 		uflags |= XFS_QUOTA_GDQ_ACCT;
989 	if (flags & XFS_UQUOTA_ENFD)
990 		uflags |= XFS_QUOTA_UDQ_ENFD;
991 	if (flags & XFS_GQUOTA_ENFD)
992 		uflags |= XFS_QUOTA_GDQ_ENFD;
993 	return (uflags);
994 }
995 
996 
997 /*
998  * Go thru all the inodes in the file system, releasing their dquots.
999  * Note that the mount structure gets modified to indicate that quotas are off
1000  * AFTER this, in the case of quotaoff. This also gets called from
1001  * xfs_rootumount.
1002  */
1003 void
xfs_qm_dqrele_all_inodes(struct xfs_mount * mp,uint flags)1004 xfs_qm_dqrele_all_inodes(
1005 	struct xfs_mount *mp,
1006 	uint		 flags)
1007 {
1008 	vmap_t		vmap;
1009 	xfs_inode_t	*ip, *topino;
1010 	uint		ireclaims;
1011 	vnode_t		*vp;
1012 	boolean_t	vnode_refd;
1013 
1014 	ASSERT(mp->m_quotainfo);
1015 
1016 again:
1017 	XFS_MOUNT_ILOCK(mp);
1018 	ip = mp->m_inodes;
1019 	if (ip == NULL) {
1020 		XFS_MOUNT_IUNLOCK(mp);
1021 		return;
1022 	}
1023 	do {
1024 		/* Skip markers inserted by xfs_sync */
1025 		if (ip->i_mount == NULL) {
1026 			ip = ip->i_mnext;
1027 			continue;
1028 		}
1029 		/* Root inode, rbmip and rsumip have associated blocks */
1030 		if (ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) {
1031 			ASSERT(ip->i_udquot == NULL);
1032 			ASSERT(ip->i_gdquot == NULL);
1033 			ip = ip->i_mnext;
1034 			continue;
1035 		}
1036 		vp = XFS_ITOV_NULL(ip);
1037 		if (!vp) {
1038 			ASSERT(ip->i_udquot == NULL);
1039 			ASSERT(ip->i_gdquot == NULL);
1040 			ip = ip->i_mnext;
1041 			continue;
1042 		}
1043 		vnode_refd = B_FALSE;
1044 		if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {
1045 			/*
1046 			 * Sample vp mapping while holding the mplock, lest
1047 			 * we come across a non-existent vnode.
1048 			 */
1049 			VMAP(vp, vmap);
1050 			ireclaims = mp->m_ireclaims;
1051 			topino = mp->m_inodes;
1052 			XFS_MOUNT_IUNLOCK(mp);
1053 
1054 			/* XXX restart limit ? */
1055 			if ( ! (vp = vn_get(vp, &vmap)))
1056 				goto again;
1057 			xfs_ilock(ip, XFS_ILOCK_EXCL);
1058 			vnode_refd = B_TRUE;
1059 		} else {
1060 			ireclaims = mp->m_ireclaims;
1061 			topino = mp->m_inodes;
1062 			XFS_MOUNT_IUNLOCK(mp);
1063 		}
1064 
1065 		/*
1066 		 * We don't keep the mountlock across the dqrele() call,
1067 		 * since it can take a while..
1068 		 */
1069 		if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
1070 			xfs_qm_dqrele(ip->i_udquot);
1071 			ip->i_udquot = NULL;
1072 		}
1073 		if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
1074 			xfs_qm_dqrele(ip->i_gdquot);
1075 			ip->i_gdquot = NULL;
1076 		}
1077 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
1078 		/*
1079 		 * Wait until we've dropped the ilock and mountlock to
1080 		 * do the vn_rele. Or be condemned to an eternity in the
1081 		 * inactive code in hell.
1082 		 */
1083 		if (vnode_refd)
1084 			VN_RELE(vp);
1085 		XFS_MOUNT_ILOCK(mp);
1086 		/*
1087 		 * If an inode was inserted or removed, we gotta
1088 		 * start over again.
1089 		 */
1090 		if (topino != mp->m_inodes || mp->m_ireclaims != ireclaims) {
1091 			/* XXX use a sentinel */
1092 			XFS_MOUNT_IUNLOCK(mp);
1093 			goto again;
1094 		}
1095 		ip = ip->i_mnext;
1096 	} while (ip != mp->m_inodes);
1097 
1098 	XFS_MOUNT_IUNLOCK(mp);
1099 }
1100 
1101 /*------------------------------------------------------------------------*/
1102 #ifdef DEBUG
1103 /*
1104  * This contains all the test functions for XFS disk quotas.
1105  * Currently it does a quota accounting check. ie. it walks through
1106  * all inodes in the file system, calculating the dquot accounting fields,
1107  * and prints out any inconsistencies.
1108  */
1109 xfs_dqhash_t *qmtest_udqtab;
1110 xfs_dqhash_t *qmtest_gdqtab;
1111 int	      qmtest_hashmask;
1112 int	      qmtest_nfails;
1113 mutex_t	      qcheck_lock;
1114 
1115 #define DQTEST_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \
1116 				 (__psunsigned_t)(id)) & \
1117 				(qmtest_hashmask - 1))
1118 
1119 #define DQTEST_HASH(mp, id, type)   ((type & XFS_DQ_USER) ? \
1120 				     (qmtest_udqtab + \
1121 				      DQTEST_HASHVAL(mp, id)) : \
1122 				     (qmtest_gdqtab + \
1123 				      DQTEST_HASHVAL(mp, id)))
1124 
1125 #define DQTEST_LIST_PRINT(l, NXT, title) \
1126 { \
1127 	  xfs_dqtest_t	*dqp; int i = 0;\
1128 	  cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \
1129 	  for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
1130 	       dqp = (xfs_dqtest_t *)dqp->NXT) { \
1131 		cmn_err(CE_DEBUG, "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
1132 			 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),	     \
1133 			 dqp->d_bcount, dqp->d_icount); } \
1134 }
1135 
1136 typedef struct dqtest {
1137 	xfs_dqmarker_t	q_lists;
1138 	xfs_dqhash_t	*q_hash;	/* the hashchain header */
1139 	xfs_mount_t	*q_mount;	/* filesystem this relates to */
1140 	xfs_dqid_t	d_id;		/* user id or group id */
1141 	xfs_qcnt_t	d_bcount;	/* # disk blocks owned by the user */
1142 	xfs_qcnt_t	d_icount;	/* # inodes owned by the user */
1143 } xfs_dqtest_t;
1144 
1145 STATIC void
xfs_qm_hashinsert(xfs_dqhash_t * h,xfs_dqtest_t * dqp)1146 xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
1147 {
1148 	xfs_dquot_t *d;
1149 	if (((d) = (h)->qh_next))
1150 		(d)->HL_PREVP = &((dqp)->HL_NEXT);
1151 	(dqp)->HL_NEXT = d;
1152 	(dqp)->HL_PREVP = &((h)->qh_next);
1153 	(h)->qh_next = (xfs_dquot_t *)dqp;
1154 	(h)->qh_version++;
1155 	(h)->qh_nelems++;
1156 }
1157 STATIC void
xfs_qm_dqtest_print(xfs_dqtest_t * d)1158 xfs_qm_dqtest_print(
1159 	xfs_dqtest_t	*d)
1160 {
1161 	cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
1162 	cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
1163 	cmn_err(CE_DEBUG, "---- type     = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP");
1164 	cmn_err(CE_DEBUG, "---- fs       = 0x%p", d->q_mount);
1165 	cmn_err(CE_DEBUG, "---- bcount   = %Lu (0x%x)",
1166 		d->d_bcount, (int)d->d_bcount);
1167 	cmn_err(CE_DEBUG, "---- icount   = %Lu (0x%x)",
1168 		d->d_icount, (int)d->d_icount);
1169 	cmn_err(CE_DEBUG, "---------------------------");
1170 }
1171 
1172 STATIC void
xfs_qm_dqtest_failed(xfs_dqtest_t * d,xfs_dquot_t * dqp,char * reason,xfs_qcnt_t a,xfs_qcnt_t b,int error)1173 xfs_qm_dqtest_failed(
1174 	xfs_dqtest_t	*d,
1175 	xfs_dquot_t	*dqp,
1176 	char		*reason,
1177 	xfs_qcnt_t	a,
1178 	xfs_qcnt_t	b,
1179 	int		error)
1180 {
1181 	qmtest_nfails++;
1182 	if (error)
1183 		cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s",
1184 		       INT_GET(d->d_id, ARCH_CONVERT), error, reason);
1185 	else
1186 		cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]",
1187 		       INT_GET(d->d_id, ARCH_CONVERT), reason, (int)a, (int)b);
1188 	xfs_qm_dqtest_print(d);
1189 	if (dqp)
1190 		xfs_qm_dqprint(dqp);
1191 }
1192 
1193 STATIC int
xfs_dqtest_cmp2(xfs_dqtest_t * d,xfs_dquot_t * dqp)1194 xfs_dqtest_cmp2(
1195 	xfs_dqtest_t	*d,
1196 	xfs_dquot_t	*dqp)
1197 {
1198 	int err = 0;
1199 	if (INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) != d->d_icount) {
1200 		xfs_qm_dqtest_failed(d, dqp, "icount mismatch",
1201 			INT_GET(dqp->q_core.d_icount, ARCH_CONVERT),
1202 			d->d_icount, 0);
1203 		err++;
1204 	}
1205 	if (INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) != d->d_bcount) {
1206 		xfs_qm_dqtest_failed(d, dqp, "bcount mismatch",
1207 			INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT),
1208 			d->d_bcount, 0);
1209 		err++;
1210 	}
1211 	if (INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT) &&
1212 	    INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) >=
1213 	    INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT)) {
1214 		if (INT_ISZERO(dqp->q_core.d_btimer, ARCH_CONVERT) &&
1215 		    !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT)) {
1216 			cmn_err(CE_DEBUG,
1217 				"%d [%s] [0x%p] BLK TIMER NOT STARTED",
1218 				d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
1219 			err++;
1220 		}
1221 	}
1222 	if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) &&
1223 	    INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
1224 	    INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
1225 		if (INT_ISZERO(dqp->q_core.d_itimer, ARCH_CONVERT) &&
1226 		    !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT)) {
1227 			cmn_err(CE_DEBUG,
1228 				"%d [%s] [0x%p] INO TIMER NOT STARTED",
1229 				d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
1230 			err++;
1231 		}
1232 	}
1233 #ifdef QUOTADEBUG
1234 	if (!err) {
1235 		cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
1236 			d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount);
1237 	}
1238 #endif
1239 	return (err);
1240 }
1241 
1242 STATIC void
xfs_dqtest_cmp(xfs_dqtest_t * d)1243 xfs_dqtest_cmp(
1244 	xfs_dqtest_t	*d)
1245 {
1246 	xfs_dquot_t	*dqp;
1247 	int		error;
1248 
1249 	/* xfs_qm_dqtest_print(d); */
1250 	if ((error = xfs_qm_dqget(d->q_mount, NULL, d->d_id, d->dq_flags, 0,
1251 				 &dqp))) {
1252 		xfs_qm_dqtest_failed(d, NULL, "dqget failed", 0, 0, error);
1253 		return;
1254 	}
1255 	xfs_dqtest_cmp2(d, dqp);
1256 	xfs_qm_dqput(dqp);
1257 }
1258 
1259 STATIC int
xfs_qm_internalqcheck_dqget(xfs_mount_t * mp,xfs_dqid_t id,uint type,xfs_dqtest_t ** O_dq)1260 xfs_qm_internalqcheck_dqget(
1261 	xfs_mount_t	*mp,
1262 	xfs_dqid_t	id,
1263 	uint		type,
1264 	xfs_dqtest_t	**O_dq)
1265 {
1266 	xfs_dqtest_t	*d;
1267 	xfs_dqhash_t	*h;
1268 
1269 	h = DQTEST_HASH(mp, id, type);
1270 	for (d = (xfs_dqtest_t *) h->qh_next; d != NULL;
1271 	     d = (xfs_dqtest_t *) d->HL_NEXT) {
1272 		/* DQTEST_LIST_PRINT(h, HL_NEXT, "@@@@@ dqtestlist @@@@@"); */
1273 		if (d->d_id == id && mp == d->q_mount) {
1274 			*O_dq = d;
1275 			return (0);
1276 		}
1277 	}
1278 	d = kmem_zalloc(sizeof(xfs_dqtest_t), KM_SLEEP);
1279 	d->dq_flags = type;
1280 	d->d_id = id;
1281 	d->q_mount = mp;
1282 	d->q_hash = h;
1283 	xfs_qm_hashinsert(h, d);
1284 	*O_dq = d;
1285 	return (0);
1286 }
1287 
1288 STATIC void
xfs_qm_internalqcheck_get_dquots(xfs_mount_t * mp,xfs_dqid_t uid,xfs_dqid_t gid,xfs_dqtest_t ** ud,xfs_dqtest_t ** gd)1289 xfs_qm_internalqcheck_get_dquots(
1290 	xfs_mount_t	*mp,
1291 	xfs_dqid_t	uid,
1292 	xfs_dqid_t	gid,
1293 	xfs_dqtest_t	**ud,
1294 	xfs_dqtest_t	**gd)
1295 {
1296 	if (XFS_IS_UQUOTA_ON(mp))
1297 		xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
1298 	if (XFS_IS_GQUOTA_ON(mp))
1299 		xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
1300 }
1301 
1302 
1303 STATIC void
xfs_qm_internalqcheck_dqadjust(xfs_inode_t * ip,xfs_dqtest_t * d)1304 xfs_qm_internalqcheck_dqadjust(
1305 	xfs_inode_t		*ip,
1306 	xfs_dqtest_t		*d)
1307 {
1308 	d->d_icount++;
1309 	d->d_bcount += (xfs_qcnt_t)ip->i_d.di_nblocks;
1310 }
1311 
1312 STATIC int
xfs_qm_internalqcheck_adjust(xfs_mount_t * mp,xfs_ino_t ino,void __user * buffer,int ubsize,void * private_data,xfs_daddr_t bno,int * ubused,void * dip,int * res)1313 xfs_qm_internalqcheck_adjust(
1314 	xfs_mount_t	*mp,		/* mount point for filesystem */
1315 	xfs_ino_t	ino,		/* inode number to get data for */
1316 	void		__user *buffer,	/* not used */
1317 	int		ubsize,		/* not used */
1318 	void		*private_data,	/* not used */
1319 	xfs_daddr_t	bno,		/* starting block of inode cluster */
1320 	int		*ubused,	/* not used */
1321 	void		*dip,		/* not used */
1322 	int		*res)		/* bulkstat result code */
1323 {
1324 	xfs_inode_t		*ip;
1325 	xfs_dqtest_t		*ud, *gd;
1326 	uint			lock_flags;
1327 	boolean_t		ipreleased;
1328 	int			error;
1329 
1330 	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
1331 
1332 	if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {
1333 		*res = BULKSTAT_RV_NOTHING;
1334 		qdprintk("internalqcheck: ino=%llu, uqino=%llu, gqino=%llu\n",
1335 			(unsigned long long) ino,
1336 			(unsigned long long) mp->m_sb.sb_uquotino,
1337 			(unsigned long long) mp->m_sb.sb_gquotino);
1338 		return XFS_ERROR(EINVAL);
1339 	}
1340 	ipreleased = B_FALSE;
1341  again:
1342 	lock_flags = XFS_ILOCK_SHARED;
1343 	if ((error = xfs_iget(mp, NULL, ino, 0, lock_flags, &ip, bno))) {
1344 		*res = BULKSTAT_RV_NOTHING;
1345 		return (error);
1346 	}
1347 
1348 	if (ip->i_d.di_mode == 0) {
1349 		xfs_iput_new(ip, lock_flags);
1350 		*res = BULKSTAT_RV_NOTHING;
1351 		return XFS_ERROR(ENOENT);
1352 	}
1353 
1354 	/*
1355 	 * This inode can have blocks after eof which can get released
1356 	 * when we send it to inactive. Since we don't check the dquot
1357 	 * until the after all our calculations are done, we must get rid
1358 	 * of those now.
1359 	 */
1360 	if (! ipreleased) {
1361 		xfs_iput(ip, lock_flags);
1362 		ipreleased = B_TRUE;
1363 		goto again;
1364 	}
1365 	xfs_qm_internalqcheck_get_dquots(mp,
1366 					(xfs_dqid_t) ip->i_d.di_uid,
1367 					(xfs_dqid_t) ip->i_d.di_gid,
1368 					&ud, &gd);
1369 	if (XFS_IS_UQUOTA_ON(mp)) {
1370 		ASSERT(ud);
1371 		xfs_qm_internalqcheck_dqadjust(ip, ud);
1372 	}
1373 	if (XFS_IS_GQUOTA_ON(mp)) {
1374 		ASSERT(gd);
1375 		xfs_qm_internalqcheck_dqadjust(ip, gd);
1376 	}
1377 	xfs_iput(ip, lock_flags);
1378 	*res = BULKSTAT_RV_DIDONE;
1379 	return (0);
1380 }
1381 
1382 
1383 /* PRIVATE, debugging */
1384 int
xfs_qm_internalqcheck(xfs_mount_t * mp)1385 xfs_qm_internalqcheck(
1386 	xfs_mount_t	*mp)
1387 {
1388 	xfs_ino_t	lastino;
1389 	int		done, count;
1390 	int		i;
1391 	xfs_dqtest_t	*d, *e;
1392 	xfs_dqhash_t	*h1;
1393 	int		error;
1394 
1395 	lastino = 0;
1396 	qmtest_hashmask = 32;
1397 	count = 5;
1398 	done = 0;
1399 	qmtest_nfails = 0;
1400 
1401 	if (! XFS_IS_QUOTA_ON(mp))
1402 		return XFS_ERROR(ESRCH);
1403 
1404 	xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
1405 	XFS_bflush(mp->m_ddev_targp);
1406 	xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
1407 	XFS_bflush(mp->m_ddev_targp);
1408 
1409 	mutex_lock(&qcheck_lock, PINOD);
1410 	/* There should be absolutely no quota activity while this
1411 	   is going on. */
1412 	qmtest_udqtab = kmem_zalloc(qmtest_hashmask *
1413 				    sizeof(xfs_dqhash_t), KM_SLEEP);
1414 	qmtest_gdqtab = kmem_zalloc(qmtest_hashmask *
1415 				    sizeof(xfs_dqhash_t), KM_SLEEP);
1416 	do {
1417 		/*
1418 		 * Iterate thru all the inodes in the file system,
1419 		 * adjusting the corresponding dquot counters
1420 		 */
1421 		if ((error = xfs_bulkstat(mp, &lastino, &count,
1422 				 xfs_qm_internalqcheck_adjust, NULL,
1423 				 0, NULL, BULKSTAT_FG_IGET, &done))) {
1424 			break;
1425 		}
1426 	} while (! done);
1427 	if (error) {
1428 		cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
1429 	}
1430 	cmn_err(CE_DEBUG, "Checking results against system dquots");
1431 	for (i = 0; i < qmtest_hashmask; i++) {
1432 		h1 = &qmtest_udqtab[i];
1433 		for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
1434 			xfs_dqtest_cmp(d);
1435 			e = (xfs_dqtest_t *) d->HL_NEXT;
1436 			kmem_free(d, sizeof(xfs_dqtest_t));
1437 			d = e;
1438 		}
1439 		h1 = &qmtest_gdqtab[i];
1440 		for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
1441 			xfs_dqtest_cmp(d);
1442 			e = (xfs_dqtest_t *) d->HL_NEXT;
1443 			kmem_free(d, sizeof(xfs_dqtest_t));
1444 			d = e;
1445 		}
1446 	}
1447 
1448 	if (qmtest_nfails) {
1449 		cmn_err(CE_DEBUG, "******** quotacheck failed  ********");
1450 		cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails);
1451 	} else {
1452 		cmn_err(CE_DEBUG, "******** quotacheck successful! ********");
1453 	}
1454 	kmem_free(qmtest_udqtab, qmtest_hashmask * sizeof(xfs_dqhash_t));
1455 	kmem_free(qmtest_gdqtab, qmtest_hashmask * sizeof(xfs_dqhash_t));
1456 	mutex_unlock(&qcheck_lock);
1457 	return (qmtest_nfails);
1458 }
1459 
1460 #endif /* DEBUG */
1461