Home | History | Annotate | Download | only in ufs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 /*
     30  * University Copyright- Copyright (c) 1982, 1986, 1988
     31  * The Regents of the University of California
     32  * All Rights Reserved
     33  *
     34  * University Acknowledgment- Portions of this document are derived from
     35  * software developed by the University of California, Berkeley, and its
     36  * contributors.
     37  */
     38 
     39 
     40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     41 
     42 /*
     43  * Quota system calls.
     44  */
     45 #include <sys/types.h>
     46 #include <sys/t_lock.h>
     47 #include <sys/param.h>
     48 #include <sys/time.h>
     49 #include <sys/systm.h>
     50 #include <sys/signal.h>
     51 #include <sys/cred.h>
     52 #include <sys/proc.h>
     53 #include <sys/user.h>
     54 #include <sys/proc.h>
     55 #include <sys/vfs.h>
     56 #include <sys/vnode.h>
     57 #include <sys/uio.h>
     58 #include <sys/buf.h>
     59 #include <sys/file.h>
     60 #include <sys/fs/ufs_inode.h>
     61 #include <sys/fs/ufs_fs.h>
     62 #include <sys/fs/ufs_quota.h>
     63 #include <sys/errno.h>
     64 #include <sys/debug.h>
     65 #include <sys/cmn_err.h>
     66 #include <sys/pathname.h>
     67 #include <sys/mntent.h>
     68 #include <sys/policy.h>
     69 
     70 static int opendq();
     71 static int setquota();
     72 static int getquota();
     73 static int quotasync();
     74 
     75 /*
     76  * Quota sub-system init flag.
     77  */
     78 int quotas_initialized = 0;
     79 
     80 /*
     81  * Sys call to allow users to find out
     82  * their current position wrt quota's
     83  * and to allow privileged users to alter it.
     84  */
     85 
     86 /*ARGSUSED*/
     87 int
     88 quotactl(struct vnode *vp, intptr_t arg, int flag, struct cred *cr)
     89 {
     90 	struct quotctl quot;
     91 	struct ufsvfs *ufsvfsp;
     92 	int error = 0;
     93 
     94 	if ((flag & DATAMODEL_MASK) == DATAMODEL_NATIVE) {
     95 		if (copyin((caddr_t)arg, &quot, sizeof (struct quotctl)))
     96 			return (EFAULT);
     97 	}
     98 #ifdef _SYSCALL32_IMPL
     99 	else {
    100 		/* quotctl struct from ILP32 callers */
    101 		struct quotctl32 quot32;
    102 		if (copyin((caddr_t)arg, &quot32, sizeof (struct quotctl32)))
    103 			return (EFAULT);
    104 		quot.op = quot32.op;
    105 		quot.uid = quot32.uid;
    106 		quot.addr = (caddr_t)(uintptr_t)quot32.addr;
    107 	}
    108 #endif /* _SYSCALL32_IMPL */
    109 
    110 	if (quot.uid < 0)
    111 		quot.uid = crgetruid(cr);
    112 	if (quot.op == Q_SYNC && vp == NULL) {
    113 		ufsvfsp = NULL;
    114 	} else if (quot.op != Q_ALLSYNC) {
    115 		ufsvfsp = (struct ufsvfs *)(vp->v_vfsp->vfs_data);
    116 	}
    117 	switch (quot.op) {
    118 
    119 	case Q_QUOTAON:
    120 		rw_enter(&dq_rwlock, RW_WRITER);
    121 		if (quotas_initialized == 0) {
    122 			qtinit2();
    123 			quotas_initialized = 1;
    124 		}
    125 		rw_exit(&dq_rwlock);
    126 		error = opendq(ufsvfsp, vp, cr);
    127 		break;
    128 
    129 	case Q_QUOTAOFF:
    130 		error = closedq(ufsvfsp, cr);
    131 		if (!error) {
    132 			invalidatedq(ufsvfsp);
    133 		}
    134 		break;
    135 
    136 	case Q_SETQUOTA:
    137 	case Q_SETQLIM:
    138 		error = setquota(quot.op, (uid_t)quot.uid, ufsvfsp,
    139 		    quot.addr, cr);
    140 		break;
    141 
    142 	case Q_GETQUOTA:
    143 		error = getquota((uid_t)quot.uid, ufsvfsp, (caddr_t)quot.addr,
    144 		    cr);
    145 		break;
    146 
    147 	case Q_SYNC:
    148 		error = qsync(ufsvfsp);
    149 		break;
    150 
    151 	case Q_ALLSYNC:
    152 		(void) qsync(NULL);
    153 		break;
    154 
    155 	default:
    156 		error = EINVAL;
    157 		break;
    158 	}
    159 	return (error);
    160 }
    161 
    162 static int
    163 opendq_scan_inode(struct inode *ip, void *arg)
    164 {
    165 	struct ufsvfs *ufsvfsp = ip->i_ufsvfs;
    166 
    167 	/*
    168 	 * wrong file system or this is the quota inode; keep looking
    169 	 */
    170 	if (ufsvfsp != (struct ufsvfs *)arg || ip == ip->i_ufsvfs->vfs_qinod) {
    171 		return (0);
    172 	}
    173 
    174 	ASSERT(RW_WRITE_HELD(&ufsvfsp->vfs_dqrwlock));
    175 	rw_enter(&ip->i_contents, RW_WRITER);
    176 	/*
    177 	 * This inode is in the cache (by definition), is still valid,
    178 	 * and is not a shadow inode or extended attribute directory inode,
    179 	 * but does not have a quota so get the quota information.
    180 	 */
    181 	if (ip->i_mode && (ip->i_mode & IFMT) != IFSHAD &&
    182 	    (ip->i_mode & IFMT) != IFATTRDIR && ip->i_dquot == NULL) {
    183 		ip->i_dquot = getinoquota(ip);
    184 	}
    185 	rw_exit(&ip->i_contents);
    186 
    187 	return (0);
    188 }
    189 
    190 /*
    191  * Set the quota file up for a particular file system.
    192  * Called as the result of a quotaon (Q_QUOTAON) ioctl.
    193  */
    194 static int
    195 opendq(
    196 	struct ufsvfs *ufsvfsp,
    197 	struct vnode *vp,		/* quota file */
    198 	struct cred *cr)
    199 {
    200 	struct inode *qip;
    201 	struct dquot *dqp;
    202 	int error;
    203 	int quotaon = 0;
    204 
    205 	if (secpolicy_fs_quota(cr, ufsvfsp->vfs_vfs) != 0)
    206 		return (EPERM);
    207 
    208 	VN_HOLD(vp);
    209 
    210 	/*
    211 	 * Check to be sure its a regular file.
    212 	 */
    213 	if (vp->v_type != VREG) {
    214 		VN_RELE(vp);
    215 		return (EACCES);
    216 	}
    217 
    218 	rw_enter(&ufsvfsp->vfs_dqrwlock, RW_WRITER);
    219 
    220 	/*
    221 	 * We have vfs_dqrwlock as writer, so if quotas are disabled,
    222 	 * then vfs_qinod should be NULL or we have a race somewhere.
    223 	 */
    224 	ASSERT((ufsvfsp->vfs_qflags & MQ_ENABLED) || (ufsvfsp->vfs_qinod == 0));
    225 
    226 	if ((ufsvfsp->vfs_qflags & MQ_ENABLED) != 0) {
    227 		/*
    228 		 * Quotas are already enabled on this file system.
    229 		 *
    230 		 * If the "quotas" file was replaced (different inode)
    231 		 * while quotas were enabled we don't want to re-enable
    232 		 * them with a new "quotas" file. Simply print a warning
    233 		 * message to the console, release the new vnode, and
    234 		 * return.
    235 		 * XXX - The right way to fix this is to return EBUSY
    236 		 * for the ioctl() issued by 'quotaon'.
    237 		 */
    238 		if (VTOI(vp) != ufsvfsp->vfs_qinod) {
    239 			cmn_err(CE_WARN, "Previous quota file still in use."
    240 			    " Disable quotas on %s before enabling.\n",
    241 			    VTOI(vp)->i_fs->fs_fsmnt);
    242 			VN_RELE(vp);
    243 			rw_exit(&ufsvfsp->vfs_dqrwlock);
    244 			return (0);
    245 		}
    246 		(void) quotasync(ufsvfsp, /* do_lock */ 0);
    247 		/* remove extra hold on quota file */
    248 		VN_RELE(vp);
    249 		quotaon++;
    250 		qip = ufsvfsp->vfs_qinod;
    251 	} else {
    252 		int qlen;
    253 
    254 		ufsvfsp->vfs_qinod = VTOI(vp);
    255 		qip = ufsvfsp->vfs_qinod;
    256 		/*
    257 		 * Force the file to have no partially allocated blocks
    258 		 * to prevent a realloc from changing the location of
    259 		 * the data. We must do this even if not logging in
    260 		 * case we later remount to logging.
    261 		 */
    262 		qlen = qip->i_fs->fs_bsize * NDADDR;
    263 
    264 		/*
    265 		 * Largefiles: i_size needs to be atomically accessed now.
    266 		 */
    267 		rw_enter(&qip->i_contents, RW_WRITER);
    268 		if (qip->i_size < qlen) {
    269 			if (ufs_itrunc(qip, (u_offset_t)qlen, (int)0, cr) != 0)
    270 				cmn_err(CE_WARN, "opendq failed to remove frags"
    271 				    " from quota file\n");
    272 			rw_exit(&qip->i_contents);
    273 			(void) VOP_PUTPAGE(vp, (offset_t)0, (size_t)qip->i_size,
    274 			    B_INVAL, kcred, NULL);
    275 		} else {
    276 			rw_exit(&qip->i_contents);
    277 		}
    278 		TRANS_MATA_IGET(ufsvfsp, qip);
    279 	}
    280 
    281 	/*
    282 	 * The file system time limits are in the dquot for uid 0.
    283 	 * The time limits set the relative time the other users
    284 	 * can be over quota for this file system.
    285 	 * If it is zero a default is used (see quota.h).
    286 	 */
    287 	error = getdiskquota((uid_t)0, ufsvfsp, 1, &dqp);
    288 	if (error == 0) {
    289 		mutex_enter(&dqp->dq_lock);
    290 		ufsvfsp->vfs_btimelimit =
    291 		    (dqp->dq_btimelimit? dqp->dq_btimelimit: DQ_BTIMELIMIT);
    292 		ufsvfsp->vfs_ftimelimit =
    293 		    (dqp->dq_ftimelimit? dqp->dq_ftimelimit: DQ_FTIMELIMIT);
    294 
    295 		ufsvfsp->vfs_qflags = MQ_ENABLED;	/* enable quotas */
    296 		vfs_setmntopt(ufsvfsp->vfs_vfs, MNTOPT_QUOTA, NULL, 0);
    297 		dqput(dqp);
    298 		mutex_exit(&dqp->dq_lock);
    299 	} else if (!quotaon) {
    300 		/*
    301 		 * Some sort of I/O error on the quota file, and quotas were
    302 		 * not already on when we got here so clean up.
    303 		 */
    304 		ufsvfsp->vfs_qflags = 0;
    305 		ufsvfsp->vfs_qinod = NULL;
    306 		VN_RELE(ITOV(qip));
    307 	}
    308 
    309 	/*
    310 	 * If quotas are enabled update all valid inodes in the
    311 	 * cache with quota information.
    312 	 */
    313 	if (ufsvfsp->vfs_qflags & MQ_ENABLED) {
    314 		(void) ufs_scan_inodes(0, opendq_scan_inode, ufsvfsp, ufsvfsp);
    315 	}
    316 
    317 	rw_exit(&ufsvfsp->vfs_dqrwlock);
    318 	return (error);
    319 }
    320 
    321 static int
    322 closedq_scan_inode(struct inode *ip, void *arg)
    323 {
    324 	struct dquot *dqp;
    325 	struct ufsvfs *ufsvfsp = ip->i_ufsvfs;
    326 
    327 	/*
    328 	 * wrong file system; keep looking
    329 	 */
    330 	if (ufsvfsp != (struct ufsvfs *)arg)
    331 		return (0);
    332 
    333 	ASSERT(RW_WRITE_HELD(&ufsvfsp->vfs_dqrwlock));
    334 	rw_enter(&ip->i_contents, RW_WRITER);
    335 
    336 	/*
    337 	 * Shadow inodes and extended attribute directories
    338 	 * do not have quota info records.
    339 	 */
    340 	if ((dqp = ip->i_dquot) != NULL) {
    341 		ASSERT((ip->i_mode & IFMT) != IFSHAD);
    342 		ASSERT((ip->i_mode & IFMT) != IFATTRDIR);
    343 		ip->i_dquot = NULL;
    344 		mutex_enter(&dqp->dq_lock);
    345 		dqput(dqp);
    346 
    347 		/*
    348 		 * If we have a pending logging file system quota
    349 		 * transaction, then cancel it.  Clear the flag to
    350 		 * prevent ufs_trans_push_quota() from trying to
    351 		 * deal with this transaction just in case it is
    352 		 * waiting for the mutex.  We decrement the counter
    353 		 * since the transaction won't be needing the quota
    354 		 * info record anymore.
    355 		 */
    356 		if (dqp->dq_flags & DQ_TRANS) {
    357 			dqp->dq_flags &= ~DQ_TRANS;
    358 			dqput(dqp);
    359 		}
    360 		mutex_exit(&dqp->dq_lock);
    361 	}
    362 	rw_exit(&ip->i_contents);
    363 
    364 	return (0);
    365 }
    366 
    367 /*
    368  * Close off disk quotas for a file system.
    369  */
    370 int
    371 closedq(struct ufsvfs *ufsvfsp, struct cred *cr)
    372 {
    373 	struct inode *qip;
    374 
    375 	if (secpolicy_fs_quota(cr, ufsvfsp->vfs_vfs) != 0)
    376 		return (EPERM);
    377 
    378 	rw_enter(&ufsvfsp->vfs_dqrwlock, RW_WRITER);
    379 
    380 	/*
    381 	 * Quotas are not enabled on this file system so there is
    382 	 * nothing more to do.
    383 	 */
    384 	if ((ufsvfsp->vfs_qflags & MQ_ENABLED) == 0) {
    385 		rw_exit(&ufsvfsp->vfs_dqrwlock);
    386 		return (0);
    387 	}
    388 
    389 	/*
    390 	 * At this point, the quota subsystem is quiescent on this file
    391 	 * system so we can do all the work necessary to dismantle the
    392 	 * quota stuff.
    393 	 */
    394 	qip = ufsvfsp->vfs_qinod;
    395 	if (!qip)
    396 		return (ufs_fault(ufsvfsp->vfs_root, "closedq: NULL qip"));
    397 
    398 	ufsvfsp->vfs_qflags = 0;	/* disable quotas */
    399 	vfs_setmntopt(ufsvfsp->vfs_vfs, MNTOPT_NOQUOTA, NULL, 0);
    400 
    401 	/*
    402 	 * ufs_scan_inodes() depends on vfs_qinod, so we can't
    403 	 * clear it until afterwards.
    404 	 */
    405 	(void) ufs_scan_inodes(0, closedq_scan_inode, ufsvfsp, ufsvfsp);
    406 
    407 	ufsvfsp->vfs_qinod = NULL;
    408 	rw_exit(&ufsvfsp->vfs_dqrwlock);
    409 
    410 	/*
    411 	 * Sync and release the quota file inode. Since we have a private
    412 	 * pointer to the quota inode and vfs_qinod is now clear we do not
    413 	 * need to hold vfs_dqrwlock.
    414 	 */
    415 	(void) TRANS_SYNCIP(qip, 0, I_SYNC, TOP_SYNCIP_CLOSEDQ);
    416 	VN_RELE(ITOV(qip));
    417 	return (0);
    418 }
    419 
    420 /*
    421  * Private data between setquota() and setquota_scan_inode().
    422  */
    423 struct setquota_data {
    424 #define	SQD_TYPE_NONE		0
    425 #define	SQD_TYPE_LIMIT		1
    426 #define	SQD_TYPE_NO_LIMIT	2
    427 	int sqd_type;
    428 	struct ufsvfs *sqd_ufsvfsp;
    429 	uid_t sqd_uid;
    430 };
    431 
    432 static int
    433 setquota_scan_inode(struct inode *ip, void *arg)
    434 {
    435 	struct setquota_data *sqdp = (struct setquota_data *)arg;
    436 	struct ufsvfs *ufsvfsp = ip->i_ufsvfs;
    437 
    438 	/*
    439 	 * wrong file system; keep looking
    440 	 */
    441 	if (ufsvfsp != sqdp->sqd_ufsvfsp)
    442 		return (0);
    443 
    444 	ASSERT(RW_WRITE_HELD(&ufsvfsp->vfs_dqrwlock));
    445 
    446 	/*
    447 	 * The file system does not have quotas enabled or this is the
    448 	 * file system's quota inode; keep looking.
    449 	 */
    450 	if ((ufsvfsp->vfs_qflags & MQ_ENABLED) == 0 ||
    451 	    ip == ufsvfsp->vfs_qinod) {
    452 		return (0);
    453 	}
    454 
    455 	rw_enter(&ip->i_contents, RW_WRITER);
    456 	/*
    457 	 * This inode is in the cache (by definition), is still valid,
    458 	 * is not a shadow inode or extended attribute directory inode
    459 	 * and has the right uid.
    460 	 */
    461 	if (ip->i_mode && (ip->i_mode & IFMT) != IFSHAD &&
    462 	    (ip->i_mode & IFMT) != IFATTRDIR && ip->i_uid == sqdp->sqd_uid) {
    463 		/*
    464 		 * Transition is "no limit" to "at least one limit":
    465 		 */
    466 		if (sqdp->sqd_type == SQD_TYPE_LIMIT &&
    467 		    ip->i_dquot == NULL) {
    468 			ip->i_dquot = getinoquota(ip);
    469 		}
    470 		/*
    471 		 * Transition is "at least one limit" to "no limit":
    472 		 */
    473 		else if (sqdp->sqd_type == SQD_TYPE_NO_LIMIT && ip->i_dquot) {
    474 			mutex_enter(&ip->i_dquot->dq_lock);
    475 			dqput(ip->i_dquot);
    476 			mutex_exit(&ip->i_dquot->dq_lock);
    477 			ip->i_dquot = NULL;
    478 		}
    479 	}
    480 	rw_exit(&ip->i_contents);
    481 
    482 	return (0);
    483 }
    484 
    485 /*
    486  * Set various fields of the dqblk according to the command.
    487  * Q_SETQUOTA - assign an entire dqblk structure.
    488  * Q_SETQLIM - assign a dqblk structure except for the usage.
    489  */
    490 static int
    491 setquota(int cmd, uid_t uid, struct ufsvfs *ufsvfsp,
    492     caddr_t addr, struct cred *cr)
    493 {
    494 	struct dquot *dqp;
    495 	struct inode	*qip;
    496 	struct dquot *xdqp;
    497 	struct dqblk newlim;
    498 	int error;
    499 	int scan_type = SQD_TYPE_NONE;
    500 	daddr_t bn;
    501 	int contig;
    502 
    503 	if (secpolicy_fs_quota(cr, ufsvfsp->vfs_vfs) != 0)
    504 		return (EPERM);
    505 
    506 	rw_enter(&ufsvfsp->vfs_dqrwlock, RW_WRITER);
    507 
    508 	/*
    509 	 * Quotas are not enabled on this file system so there is
    510 	 * nothing more to do.
    511 	 */
    512 	if ((ufsvfsp->vfs_qflags & MQ_ENABLED) == 0) {
    513 		rw_exit(&ufsvfsp->vfs_dqrwlock);
    514 		return (ESRCH);
    515 	}
    516 
    517 	/*
    518 	 * At this point, the quota subsystem is quiescent on this file
    519 	 * system so we can do all the work necessary to modify the quota
    520 	 * information for this user.
    521 	 */
    522 
    523 	if (copyin(addr, (caddr_t)&newlim, sizeof (struct dqblk)) != 0) {
    524 		rw_exit(&ufsvfsp->vfs_dqrwlock);
    525 		return (EFAULT);
    526 	}
    527 	error = getdiskquota(uid, ufsvfsp, 0, &xdqp);
    528 	if (error) {
    529 		rw_exit(&ufsvfsp->vfs_dqrwlock);
    530 		return (error);
    531 	}
    532 	dqp = xdqp;
    533 	/*
    534 	 * Don't change disk usage on Q_SETQLIM
    535 	 */
    536 	mutex_enter(&dqp->dq_lock);
    537 	if (cmd == Q_SETQLIM) {
    538 		newlim.dqb_curblocks = dqp->dq_curblocks;
    539 		newlim.dqb_curfiles = dqp->dq_curfiles;
    540 	}
    541 	if (uid == 0) {
    542 		/*
    543 		 * Timelimits for uid 0 set the relative time
    544 		 * the other users can be over quota for this file system.
    545 		 * If it is zero a default is used (see quota.h).
    546 		 */
    547 		ufsvfsp->vfs_btimelimit =
    548 		    newlim.dqb_btimelimit? newlim.dqb_btimelimit: DQ_BTIMELIMIT;
    549 		ufsvfsp->vfs_ftimelimit =
    550 		    newlim.dqb_ftimelimit? newlim.dqb_ftimelimit: DQ_FTIMELIMIT;
    551 	} else {
    552 		if (newlim.dqb_bsoftlimit &&
    553 		    newlim.dqb_curblocks >= newlim.dqb_bsoftlimit) {
    554 			if (dqp->dq_bsoftlimit == 0 ||
    555 			    dqp->dq_curblocks < dqp->dq_bsoftlimit) {
    556 				/* If we're suddenly over the limit(s),	*/
    557 				/* start the timer(s)			*/
    558 				newlim.dqb_btimelimit =
    559 				    (uint32_t)gethrestime_sec() +
    560 				    ufsvfsp->vfs_btimelimit;
    561 				dqp->dq_flags &= ~DQ_BLKS;
    562 			} else {
    563 				/* If we're currently over the soft	*/
    564 				/* limit and were previously over the	*/
    565 				/* soft limit then preserve the old	*/
    566 				/* time limit but make sure the DQ_BLKS	*/
    567 				/* flag is set since we must have been	*/
    568 				/* previously warned.			*/
    569 				newlim.dqb_btimelimit = dqp->dq_btimelimit;
    570 				dqp->dq_flags |= DQ_BLKS;
    571 			}
    572 		} else {
    573 			/* Either no quota or under quota, clear time limit */
    574 			newlim.dqb_btimelimit = 0;
    575 			dqp->dq_flags &= ~DQ_BLKS;
    576 		}
    577 
    578 		if (newlim.dqb_fsoftlimit &&
    579 		    newlim.dqb_curfiles >= newlim.dqb_fsoftlimit) {
    580 			if (dqp->dq_fsoftlimit == 0 ||
    581 			    dqp->dq_curfiles < dqp->dq_fsoftlimit) {
    582 				/* If we're suddenly over the limit(s),	*/
    583 				/* start the timer(s)			*/
    584 				newlim.dqb_ftimelimit =
    585 				    (uint32_t)gethrestime_sec() +
    586 				    ufsvfsp->vfs_ftimelimit;
    587 				dqp->dq_flags &= ~DQ_FILES;
    588 			} else {
    589 				/* If we're currently over the soft	*/
    590 				/* limit and were previously over the	*/
    591 				/* soft limit then preserve the old	*/
    592 				/* time limit but make sure the		*/
    593 				/* DQ_FILES flag is set since we must	*/
    594 				/* have been previously warned.		*/
    595 				newlim.dqb_ftimelimit = dqp->dq_ftimelimit;
    596 				dqp->dq_flags |= DQ_FILES;
    597 			}
    598 		} else {
    599 			/* Either no quota or under quota, clear time limit */
    600 			newlim.dqb_ftimelimit = 0;
    601 			dqp->dq_flags &= ~DQ_FILES;
    602 		}
    603 	}
    604 
    605 	/*
    606 	 * If there was previously no limit and there is now at least
    607 	 * one limit, then any inodes in the cache have NULL d_iquot
    608 	 * fields (getinoquota() returns NULL when there are no limits).
    609 	 */
    610 	if ((dqp->dq_fhardlimit == 0 && dqp->dq_fsoftlimit == 0 &&
    611 	    dqp->dq_bhardlimit == 0 && dqp->dq_bsoftlimit == 0) &&
    612 	    (newlim.dqb_fhardlimit || newlim.dqb_fsoftlimit ||
    613 	    newlim.dqb_bhardlimit || newlim.dqb_bsoftlimit)) {
    614 		scan_type = SQD_TYPE_LIMIT;
    615 	}
    616 
    617 	/*
    618 	 * If there was previously at least one limit and there is now
    619 	 * no limit, then any inodes in the cache have non-NULL d_iquot
    620 	 * fields need to be reset to NULL.
    621 	 */
    622 	else if ((dqp->dq_fhardlimit || dqp->dq_fsoftlimit ||
    623 	    dqp->dq_bhardlimit || dqp->dq_bsoftlimit) &&
    624 	    (newlim.dqb_fhardlimit == 0 && newlim.dqb_fsoftlimit == 0 &&
    625 	    newlim.dqb_bhardlimit == 0 && newlim.dqb_bsoftlimit == 0)) {
    626 		scan_type = SQD_TYPE_NO_LIMIT;
    627 	}
    628 
    629 	dqp->dq_dqb = newlim;
    630 	dqp->dq_flags |= DQ_MOD;
    631 
    632 	/*
    633 	 *  push the new quota to disk now.  If this is a trans device
    634 	 *  then force the page out with ufs_putpage so it will be deltaed
    635 	 *  by ufs_startio.
    636 	 */
    637 	qip = ufsvfsp->vfs_qinod;
    638 	rw_enter(&qip->i_contents, RW_WRITER);
    639 	(void) ufs_rdwri(UIO_WRITE, FWRITE | FSYNC, qip, (caddr_t)&dqp->dq_dqb,
    640 	    sizeof (struct dqblk), dqoff(uid), UIO_SYSSPACE,
    641 	    (int *)NULL, kcred);
    642 	rw_exit(&qip->i_contents);
    643 
    644 	(void) VOP_PUTPAGE(ITOV(qip), dqoff(dqp->dq_uid) & ~qip->i_fs->fs_bmask,
    645 	    qip->i_fs->fs_bsize, B_INVAL, kcred, NULL);
    646 
    647 	/*
    648 	 * We must set the dq_mof even if not we are not logging in case
    649 	 * we are later remount to logging.
    650 	 */
    651 	contig = 0;
    652 	rw_enter(&qip->i_contents, RW_WRITER);
    653 	error = bmap_read(qip, dqoff(dqp->dq_uid), &bn, &contig);
    654 	rw_exit(&qip->i_contents);
    655 	if (error || (bn == UFS_HOLE)) {
    656 		dqp->dq_mof = UFS_HOLE;
    657 	} else {
    658 		dqp->dq_mof = ldbtob(bn) +
    659 		    (offset_t)((dqoff(dqp->dq_uid)) & (DEV_BSIZE - 1));
    660 	}
    661 
    662 	dqp->dq_flags &= ~DQ_MOD;
    663 	dqput(dqp);
    664 	mutex_exit(&dqp->dq_lock);
    665 	if (scan_type) {
    666 		struct setquota_data sqd;
    667 
    668 		sqd.sqd_type = scan_type;
    669 		sqd.sqd_ufsvfsp = ufsvfsp;
    670 		sqd.sqd_uid = uid;
    671 		(void) ufs_scan_inodes(0, setquota_scan_inode, &sqd, ufsvfsp);
    672 	}
    673 	rw_exit(&ufsvfsp->vfs_dqrwlock);
    674 	return (0);
    675 }
    676 
    677 /*
    678  * Q_GETQUOTA - return current values in a dqblk structure.
    679  */
    680 static int
    681 getquota(uid_t uid, struct ufsvfs *ufsvfsp, caddr_t addr, cred_t *cr)
    682 {
    683 	struct dquot *dqp;
    684 	struct dquot *xdqp;
    685 	struct dqblk dqb;
    686 	int error = 0;
    687 
    688 	if (uid != crgetruid(cr) &&
    689 	    secpolicy_fs_quota(cr, ufsvfsp->vfs_vfs) != 0)
    690 		return (EPERM);
    691 	rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
    692 	if ((ufsvfsp->vfs_qflags & MQ_ENABLED) == 0) {
    693 		rw_exit(&ufsvfsp->vfs_dqrwlock);
    694 		return (ESRCH);
    695 	}
    696 	error = getdiskquota(uid, ufsvfsp, 0, &xdqp);
    697 	if (error) {
    698 		rw_exit(&ufsvfsp->vfs_dqrwlock);
    699 		return (error);
    700 	}
    701 	dqp = xdqp;
    702 	mutex_enter(&dqp->dq_lock);
    703 	if (dqp->dq_fhardlimit == 0 && dqp->dq_fsoftlimit == 0 &&
    704 	    dqp->dq_bhardlimit == 0 && dqp->dq_bsoftlimit == 0) {
    705 		error = ESRCH;
    706 	} else {
    707 		bcopy(&dqp->dq_dqb, &dqb, sizeof (struct dqblk));
    708 	}
    709 	dqput(dqp);
    710 	mutex_exit(&dqp->dq_lock);
    711 	rw_exit(&ufsvfsp->vfs_dqrwlock);
    712 	if (error == 0 && copyout(&dqb, addr, sizeof (struct dqblk)) != 0)
    713 		error = EFAULT;
    714 	return (error);
    715 }
    716 
    717 /*
    718  * Q_SYNC - sync quota files to disk.
    719  */
    720 int
    721 qsync(struct ufsvfs *ufsvfsp)
    722 {
    723 	return (quotasync(ufsvfsp, /* do_lock */ 1));
    724 }
    725 
    726 /*
    727  * Sync quota information records to disk for the specified file system
    728  * or all file systems with quotas if ufsvfsp == NULL.  Grabs a reader
    729  * lock on vfs_dqrwlock if it is needed.
    730  *
    731  * Currently, if ufsvfsp is NULL, then do_lock is always true, but the
    732  * routine is coded to account for either do_lock value.  This seemed
    733  * to be the safer thing to do.
    734  */
    735 int
    736 quotasync(struct ufsvfs *ufsvfsp, int do_lock)
    737 {
    738 	struct dquot *dqp;
    739 
    740 	rw_enter(&dq_rwlock, RW_READER);
    741 	if (!quotas_initialized) {
    742 		rw_exit(&dq_rwlock);
    743 		return (ESRCH);
    744 	}
    745 	rw_exit(&dq_rwlock);
    746 
    747 	/*
    748 	 * The operation applies to a specific file system only.
    749 	 */
    750 	if (ufsvfsp) {
    751 		if (do_lock) {
    752 			rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER);
    753 		}
    754 
    755 		/*
    756 		 * Quotas are not enabled on this file system so bail.
    757 		 */
    758 		if ((ufsvfsp->vfs_qflags & MQ_ENABLED) == 0) {
    759 			if (do_lock) {
    760 				rw_exit(&ufsvfsp->vfs_dqrwlock);
    761 			}
    762 			return (ESRCH);
    763 		}
    764 
    765 		/*
    766 		 * This operation is a no-op on a logging file system because
    767 		 * quota information is treated as metadata and is in the log.
    768 		 * This code path treats quota information as user data which
    769 		 * is not necessary on a logging file system.
    770 		 */
    771 		if (TRANS_ISTRANS(ufsvfsp)) {
    772 			if (do_lock) {
    773 				rw_exit(&ufsvfsp->vfs_dqrwlock);
    774 			}
    775 			return (0);
    776 		}
    777 
    778 		/*
    779 		 * Try to sync all the quota info records for this
    780 		 * file system:
    781 		 */
    782 		for (dqp = dquot; dqp < dquotNDQUOT; dqp++) {
    783 			/*
    784 			 * If someone else has it, then ignore it.
    785 			 */
    786 			if (!mutex_tryenter(&dqp->dq_lock)) {
    787 				continue;
    788 			}
    789 
    790 			/*
    791 			 * The quota info record is for this file system
    792 			 * and it has changes.
    793 			 */
    794 			if (dqp->dq_ufsvfsp == ufsvfsp &&
    795 			    (dqp->dq_flags & DQ_MOD)) {
    796 				ASSERT(ufsvfsp->vfs_qflags & MQ_ENABLED);
    797 				dqupdate(dqp);
    798 			}
    799 
    800 			mutex_exit(&dqp->dq_lock);
    801 		}
    802 		if (do_lock) {
    803 			rw_exit(&ufsvfsp->vfs_dqrwlock);
    804 		}
    805 
    806 		return (0);
    807 	}
    808 
    809 	/*
    810 	 * Try to sync all the quota info records for *all* file systems
    811 	 * for which quotas are enabled.
    812 	 */
    813 	for (dqp = dquot; dqp < dquotNDQUOT; dqp++) {
    814 		/*
    815 		 * If someone else has it, then ignore it.
    816 		 */
    817 		if (!mutex_tryenter(&dqp->dq_lock)) {
    818 			continue;
    819 		}
    820 
    821 		ufsvfsp = dqp->dq_ufsvfsp;	/* shorthand */
    822 
    823 		/*
    824 		 * This quota info record has no changes or is
    825 		 * not a valid quota info record yet.
    826 		 */
    827 		if ((dqp->dq_flags & DQ_MOD) == 0 || ufsvfsp == NULL) {
    828 			mutex_exit(&dqp->dq_lock);
    829 			continue;
    830 		}
    831 
    832 		/*
    833 		 * Now we have a potential lock order problem:
    834 		 *
    835 		 *	vfs_dqrwlock > dq_lock
    836 		 *
    837 		 * so if we have to get vfs_dqrwlock, then go thru hoops
    838 		 * to avoid deadlock.  If we cannot get the order right,
    839 		 * then we ignore this quota info record.
    840 		 */
    841 		if (do_lock) {
    842 			/*
    843 			 * If we can't grab vfs_dqrwlock, then we don't
    844 			 * want to wait to avoid deadlock.
    845 			 */
    846 			if (rw_tryenter(&ufsvfsp->vfs_dqrwlock,
    847 			    RW_READER) == 0) {
    848 				mutex_exit(&dqp->dq_lock);
    849 				continue;
    850 			}
    851 			/*
    852 			 * Okay, now we have both dq_lock and vfs_dqrwlock.
    853 			 * We should not deadlock for the following reasons:
    854 			 * - If another thread has a reader lock on
    855 			 *   vfs_dqrwlock and is waiting for dq_lock,
    856 			 *   there is no conflict because we can also have
    857 			 *   a reader lock on vfs_dqrwlock.
    858 			 * - If another thread has a writer lock on
    859 			 *   vfs_dqrwlock and is waiting for dq_lock,
    860 			 *   we would have failed the rw_tryenter() above
    861 			 *   and given up dq_lock.
    862 			 * - Since we have dq_lock another thread cannot
    863 			 *   have it and be waiting for vfs_dqrwlock.
    864 			 */
    865 		}
    866 
    867 		/*
    868 		 * Since we got to this file system via a quota info
    869 		 * record and we have vfs_dqrwlock this is paranoia
    870 		 * to make sure that quotas are enabled.
    871 		 */
    872 		ASSERT(ufsvfsp->vfs_qflags & MQ_ENABLED);
    873 
    874 		/*
    875 		 * We are not logging.  See above logging file system
    876 		 * comment.
    877 		 */
    878 		if (!TRANS_ISTRANS(ufsvfsp)) {
    879 			dqupdate(dqp);
    880 		}
    881 
    882 		/*
    883 		 * Since we have a private copy of dqp->dq_ufsvfsp,
    884 		 * we can drop dq_lock now.
    885 		 */
    886 		mutex_exit(&dqp->dq_lock);
    887 
    888 		if (do_lock) {
    889 			rw_exit(&ufsvfsp->vfs_dqrwlock);
    890 		}
    891 	}
    892 
    893 	return (0);
    894 }
    895