1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1982, 1986, 1990, 1993, 1995 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Robert Elz at The University of Melbourne. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_ffs.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/endian.h> 45 #include <sys/fcntl.h> 46 #include <sys/kernel.h> 47 #include <sys/lock.h> 48 #include <sys/malloc.h> 49 #include <sys/mount.h> 50 #include <sys/mutex.h> 51 #include <sys/namei.h> 52 #include <sys/priv.h> 53 #include <sys/proc.h> 54 #include <sys/socket.h> 55 #include <sys/stat.h> 56 #include <sys/sysctl.h> 57 #include <sys/vnode.h> 58 59 #include <ufs/ufs/extattr.h> 60 #include <ufs/ufs/quota.h> 61 #include <ufs/ufs/inode.h> 62 #include <ufs/ufs/ufsmount.h> 63 #include <ufs/ufs/ufs_extern.h> 64 65 CTASSERT(sizeof(struct dqblk64) == sizeof(struct dqhdr64)); 66 67 static int unprivileged_get_quota = 0; 68 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_get_quota, CTLFLAG_RW, 69 &unprivileged_get_quota, 0, 70 "Unprivileged processes may retrieve quotas for other uids and gids"); 71 72 static MALLOC_DEFINE(M_DQUOT, "ufs_quota", "UFS quota entries"); 73 74 /* 75 * Quota name to error message mapping. 76 */ 77 static char *quotatypes[] = INITQFNAMES; 78 79 static int chkdqchg(struct inode *, ufs2_daddr_t, struct ucred *, int, int *); 80 static int chkiqchg(struct inode *, int, struct ucred *, int, int *); 81 static int dqopen(struct vnode *, struct ufsmount *, int); 82 static int dqget(struct vnode *, 83 u_long, struct ufsmount *, int, struct dquot **); 84 static int dqsync(struct vnode *, struct dquot *); 85 static int dqflush(struct vnode *); 86 static int quotaoff1(struct thread *td, struct mount *mp, int type); 87 static int quotaoff_inchange(struct thread *td, struct mount *mp, int type); 88 89 /* conversion functions - from_to() */ 90 static void dqb32_dq(const struct dqblk32 *, struct dquot *); 91 static void dqb64_dq(const struct dqblk64 *, struct dquot *); 92 static void dq_dqb32(const struct dquot *, struct dqblk32 *); 93 static void dq_dqb64(const struct dquot *, struct dqblk64 *); 94 static void dqb32_dqb64(const struct dqblk32 *, struct dqblk64 *); 95 static void dqb64_dqb32(const struct dqblk64 *, struct dqblk32 *); 96 97 #ifdef DIAGNOSTIC 98 static void dqref(struct dquot *); 99 static void chkdquot(struct inode *); 100 #endif 101 102 /* 103 * Set up the quotas for an inode. 104 * 105 * This routine completely defines the semantics of quotas. 106 * If other criterion want to be used to establish quotas, the 107 * MAXQUOTAS value in quota.h should be increased, and the 108 * additional dquots set up here. 109 */ 110 int 111 getinoquota(struct inode *ip) 112 { 113 struct ufsmount *ump; 114 struct vnode *vp; 115 int error; 116 117 vp = ITOV(ip); 118 119 /* 120 * Disk quotas must be turned off for system files. Currently 121 * snapshot and quota files. 122 */ 123 if ((vp->v_vflag & VV_SYSTEM) != 0) 124 return (0); 125 /* 126 * XXX: Turn off quotas for files with a negative UID or GID. 127 * This prevents the creation of 100GB+ quota files. 128 */ 129 if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0) 130 return (0); 131 ump = VFSTOUFS(vp->v_mount); 132 /* 133 * Set up the user quota based on file uid. 134 * EINVAL means that quotas are not enabled. 135 */ 136 if ((error = 137 dqget(vp, ip->i_uid, ump, USRQUOTA, &ip->i_dquot[USRQUOTA])) && 138 error != EINVAL) 139 return (error); 140 /* 141 * Set up the group quota based on file gid. 142 * EINVAL means that quotas are not enabled. 143 */ 144 if ((error = 145 dqget(vp, ip->i_gid, ump, GRPQUOTA, &ip->i_dquot[GRPQUOTA])) && 146 error != EINVAL) 147 return (error); 148 return (0); 149 } 150 151 /* 152 * Update disk usage, and take corrective action. 153 */ 154 int 155 chkdq(struct inode *ip, ufs2_daddr_t change, struct ucred *cred, int flags) 156 { 157 struct dquot *dq; 158 ufs2_daddr_t ncurblocks; 159 struct vnode *vp = ITOV(ip); 160 int i, error, warn, do_check; 161 162 /* 163 * Disk quotas must be turned off for system files. Currently 164 * snapshot and quota files. 165 */ 166 if ((vp->v_vflag & VV_SYSTEM) != 0) 167 return (0); 168 /* 169 * XXX: Turn off quotas for files with a negative UID or GID. 170 * This prevents the creation of 100GB+ quota files. 171 */ 172 if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0) 173 return (0); 174 #ifdef DIAGNOSTIC 175 if ((flags & CHOWN) == 0) 176 chkdquot(ip); 177 #endif 178 if (change == 0) 179 return (0); 180 if (change < 0) { 181 for (i = 0; i < MAXQUOTAS; i++) { 182 if ((dq = ip->i_dquot[i]) == NODQUOT) 183 continue; 184 DQI_LOCK(dq); 185 DQI_WAIT(dq, PINOD+1, "chkdq1"); 186 ncurblocks = dq->dq_curblocks + change; 187 if (ncurblocks >= 0) 188 dq->dq_curblocks = ncurblocks; 189 else 190 dq->dq_curblocks = 0; 191 dq->dq_flags &= ~DQ_BLKS; 192 dq->dq_flags |= DQ_MOD; 193 DQI_UNLOCK(dq); 194 } 195 return (0); 196 } 197 if ((flags & FORCE) == 0 && 198 priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA)) 199 do_check = 1; 200 else 201 do_check = 0; 202 for (i = 0; i < MAXQUOTAS; i++) { 203 if ((dq = ip->i_dquot[i]) == NODQUOT) 204 continue; 205 warn = 0; 206 DQI_LOCK(dq); 207 DQI_WAIT(dq, PINOD+1, "chkdq2"); 208 if (do_check) { 209 error = chkdqchg(ip, change, cred, i, &warn); 210 if (error) { 211 /* 212 * Roll back user quota changes when 213 * group quota failed. 214 */ 215 while (i > 0) { 216 --i; 217 dq = ip->i_dquot[i]; 218 if (dq == NODQUOT) 219 continue; 220 DQI_LOCK(dq); 221 DQI_WAIT(dq, PINOD+1, "chkdq3"); 222 ncurblocks = dq->dq_curblocks - change; 223 if (ncurblocks >= 0) 224 dq->dq_curblocks = ncurblocks; 225 else 226 dq->dq_curblocks = 0; 227 dq->dq_flags &= ~DQ_BLKS; 228 dq->dq_flags |= DQ_MOD; 229 DQI_UNLOCK(dq); 230 } 231 return (error); 232 } 233 } 234 /* Reset timer when crossing soft limit */ 235 if (dq->dq_curblocks + change >= dq->dq_bsoftlimit && 236 dq->dq_curblocks < dq->dq_bsoftlimit) 237 dq->dq_btime = time_second + ITOUMP(ip)->um_btime[i]; 238 dq->dq_curblocks += change; 239 dq->dq_flags |= DQ_MOD; 240 DQI_UNLOCK(dq); 241 if (warn) 242 uprintf("\n%s: warning, %s disk quota exceeded\n", 243 ITOVFS(ip)->mnt_stat.f_mntonname, 244 quotatypes[i]); 245 } 246 return (0); 247 } 248 249 /* 250 * Check for a valid change to a users allocation. 251 * Issue an error message if appropriate. 252 */ 253 static int 254 chkdqchg(struct inode *ip, ufs2_daddr_t change, struct ucred *cred, 255 int type, int *warn) 256 { 257 struct dquot *dq = ip->i_dquot[type]; 258 ufs2_daddr_t ncurblocks = dq->dq_curblocks + change; 259 260 /* 261 * If user would exceed their hard limit, disallow space allocation. 262 */ 263 if (ncurblocks >= dq->dq_bhardlimit && dq->dq_bhardlimit) { 264 if ((dq->dq_flags & DQ_BLKS) == 0 && 265 ip->i_uid == cred->cr_uid) { 266 dq->dq_flags |= DQ_BLKS; 267 DQI_UNLOCK(dq); 268 uprintf("\n%s: write failed, %s disk limit reached\n", 269 ITOVFS(ip)->mnt_stat.f_mntonname, 270 quotatypes[type]); 271 return (EDQUOT); 272 } 273 DQI_UNLOCK(dq); 274 return (EDQUOT); 275 } 276 /* 277 * If user is over their soft limit for too long, disallow space 278 * allocation. Reset time limit as they cross their soft limit. 279 */ 280 if (ncurblocks >= dq->dq_bsoftlimit && dq->dq_bsoftlimit) { 281 if (dq->dq_curblocks < dq->dq_bsoftlimit) { 282 dq->dq_btime = time_second + ITOUMP(ip)->um_btime[type]; 283 if (ip->i_uid == cred->cr_uid) 284 *warn = 1; 285 return (0); 286 } 287 if (time_second > dq->dq_btime) { 288 if ((dq->dq_flags & DQ_BLKS) == 0 && 289 ip->i_uid == cred->cr_uid) { 290 dq->dq_flags |= DQ_BLKS; 291 DQI_UNLOCK(dq); 292 uprintf("\n%s: write failed, %s " 293 "disk quota exceeded for too long\n", 294 ITOVFS(ip)->mnt_stat.f_mntonname, 295 quotatypes[type]); 296 return (EDQUOT); 297 } 298 DQI_UNLOCK(dq); 299 return (EDQUOT); 300 } 301 } 302 return (0); 303 } 304 305 /* 306 * Check the inode limit, applying corrective action. 307 */ 308 int 309 chkiq(struct inode *ip, int change, struct ucred *cred, int flags) 310 { 311 struct dquot *dq; 312 int i, error, warn, do_check; 313 314 #ifdef DIAGNOSTIC 315 if ((flags & CHOWN) == 0) 316 chkdquot(ip); 317 #endif 318 if (change == 0) 319 return (0); 320 if (change < 0) { 321 for (i = 0; i < MAXQUOTAS; i++) { 322 if ((dq = ip->i_dquot[i]) == NODQUOT) 323 continue; 324 DQI_LOCK(dq); 325 DQI_WAIT(dq, PINOD+1, "chkiq1"); 326 if (dq->dq_curinodes >= -change) 327 dq->dq_curinodes += change; 328 else 329 dq->dq_curinodes = 0; 330 dq->dq_flags &= ~DQ_INODS; 331 dq->dq_flags |= DQ_MOD; 332 DQI_UNLOCK(dq); 333 } 334 return (0); 335 } 336 if ((flags & FORCE) == 0 && 337 priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA)) 338 do_check = 1; 339 else 340 do_check = 0; 341 for (i = 0; i < MAXQUOTAS; i++) { 342 if ((dq = ip->i_dquot[i]) == NODQUOT) 343 continue; 344 warn = 0; 345 DQI_LOCK(dq); 346 DQI_WAIT(dq, PINOD+1, "chkiq2"); 347 if (do_check) { 348 error = chkiqchg(ip, change, cred, i, &warn); 349 if (error) { 350 /* 351 * Roll back user quota changes when 352 * group quota failed. 353 */ 354 while (i > 0) { 355 --i; 356 dq = ip->i_dquot[i]; 357 if (dq == NODQUOT) 358 continue; 359 DQI_LOCK(dq); 360 DQI_WAIT(dq, PINOD+1, "chkiq3"); 361 if (dq->dq_curinodes >= change) 362 dq->dq_curinodes -= change; 363 else 364 dq->dq_curinodes = 0; 365 dq->dq_flags &= ~DQ_INODS; 366 dq->dq_flags |= DQ_MOD; 367 DQI_UNLOCK(dq); 368 } 369 return (error); 370 } 371 } 372 /* Reset timer when crossing soft limit */ 373 if (dq->dq_curinodes + change >= dq->dq_isoftlimit && 374 dq->dq_curinodes < dq->dq_isoftlimit) 375 dq->dq_itime = time_second + ITOUMP(ip)->um_itime[i]; 376 dq->dq_curinodes += change; 377 dq->dq_flags |= DQ_MOD; 378 DQI_UNLOCK(dq); 379 if (warn) 380 uprintf("\n%s: warning, %s inode quota exceeded\n", 381 ITOVFS(ip)->mnt_stat.f_mntonname, 382 quotatypes[i]); 383 } 384 return (0); 385 } 386 387 /* 388 * Check for a valid change to a users allocation. 389 * Issue an error message if appropriate. 390 */ 391 static int 392 chkiqchg(struct inode *ip, int change, struct ucred *cred, int type, int *warn) 393 { 394 struct dquot *dq = ip->i_dquot[type]; 395 ino_t ncurinodes = dq->dq_curinodes + change; 396 397 /* 398 * If user would exceed their hard limit, disallow inode allocation. 399 */ 400 if (ncurinodes >= dq->dq_ihardlimit && dq->dq_ihardlimit) { 401 if ((dq->dq_flags & DQ_INODS) == 0 && 402 ip->i_uid == cred->cr_uid) { 403 dq->dq_flags |= DQ_INODS; 404 DQI_UNLOCK(dq); 405 uprintf("\n%s: write failed, %s inode limit reached\n", 406 ITOVFS(ip)->mnt_stat.f_mntonname, 407 quotatypes[type]); 408 return (EDQUOT); 409 } 410 DQI_UNLOCK(dq); 411 return (EDQUOT); 412 } 413 /* 414 * If user is over their soft limit for too long, disallow inode 415 * allocation. Reset time limit as they cross their soft limit. 416 */ 417 if (ncurinodes >= dq->dq_isoftlimit && dq->dq_isoftlimit) { 418 if (dq->dq_curinodes < dq->dq_isoftlimit) { 419 dq->dq_itime = time_second + ITOUMP(ip)->um_itime[type]; 420 if (ip->i_uid == cred->cr_uid) 421 *warn = 1; 422 return (0); 423 } 424 if (time_second > dq->dq_itime) { 425 if ((dq->dq_flags & DQ_INODS) == 0 && 426 ip->i_uid == cred->cr_uid) { 427 dq->dq_flags |= DQ_INODS; 428 DQI_UNLOCK(dq); 429 uprintf("\n%s: write failed, %s " 430 "inode quota exceeded for too long\n", 431 ITOVFS(ip)->mnt_stat.f_mntonname, 432 quotatypes[type]); 433 return (EDQUOT); 434 } 435 DQI_UNLOCK(dq); 436 return (EDQUOT); 437 } 438 } 439 return (0); 440 } 441 442 #ifdef DIAGNOSTIC 443 /* 444 * On filesystems with quotas enabled, it is an error for a file to change 445 * size and not to have a dquot structure associated with it. 446 */ 447 static void 448 chkdquot(struct inode *ip) 449 { 450 struct ufsmount *ump; 451 struct vnode *vp; 452 int i; 453 454 ump = ITOUMP(ip); 455 vp = ITOV(ip); 456 457 /* 458 * Disk quotas must be turned off for system files. Currently 459 * these are snapshots and quota files. 460 */ 461 if ((vp->v_vflag & VV_SYSTEM) != 0) 462 return; 463 /* 464 * XXX: Turn off quotas for files with a negative UID or GID. 465 * This prevents the creation of 100GB+ quota files. 466 */ 467 if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0) 468 return; 469 470 UFS_LOCK(ump); 471 for (i = 0; i < MAXQUOTAS; i++) { 472 if (ump->um_quotas[i] == NULLVP || 473 (ump->um_qflags[i] & (QTF_OPENING|QTF_CLOSING))) 474 continue; 475 if (ip->i_dquot[i] == NODQUOT) { 476 UFS_UNLOCK(ump); 477 vn_printf(ITOV(ip), "chkdquot: missing dquot "); 478 panic("chkdquot: missing dquot"); 479 } 480 } 481 UFS_UNLOCK(ump); 482 } 483 #endif 484 485 /* 486 * Code to process quotactl commands. 487 */ 488 489 /* 490 * Q_QUOTAON - set up a quota file for a particular filesystem. 491 */ 492 int 493 quotaon(struct thread *td, struct mount *mp, int type, void *fname) 494 { 495 struct ufsmount *ump; 496 struct vnode *vp, **vpp; 497 struct vnode *mvp; 498 struct dquot *dq; 499 int error, flags; 500 struct nameidata nd; 501 502 error = priv_check(td, PRIV_UFS_QUOTAON); 503 if (error != 0) { 504 vfs_unbusy(mp); 505 return (error); 506 } 507 508 if ((mp->mnt_flag & MNT_RDONLY) != 0) { 509 vfs_unbusy(mp); 510 return (EROFS); 511 } 512 513 ump = VFSTOUFS(mp); 514 dq = NODQUOT; 515 516 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, td); 517 flags = FREAD | FWRITE; 518 vfs_ref(mp); 519 vfs_unbusy(mp); 520 error = vn_open(&nd, &flags, 0, NULL); 521 if (error != 0) { 522 vfs_rel(mp); 523 return (error); 524 } 525 NDFREE(&nd, NDF_ONLY_PNBUF); 526 vp = nd.ni_vp; 527 error = vfs_busy(mp, MBF_NOWAIT); 528 vfs_rel(mp); 529 if (error == 0) { 530 if (vp->v_type != VREG) { 531 error = EACCES; 532 vfs_unbusy(mp); 533 } 534 } 535 if (error != 0) { 536 VOP_UNLOCK(vp, 0); 537 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); 538 return (error); 539 } 540 541 UFS_LOCK(ump); 542 if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) { 543 UFS_UNLOCK(ump); 544 VOP_UNLOCK(vp, 0); 545 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); 546 vfs_unbusy(mp); 547 return (EALREADY); 548 } 549 ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING; 550 UFS_UNLOCK(ump); 551 if ((error = dqopen(vp, ump, type)) != 0) { 552 VOP_UNLOCK(vp, 0); 553 UFS_LOCK(ump); 554 ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING); 555 UFS_UNLOCK(ump); 556 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); 557 vfs_unbusy(mp); 558 return (error); 559 } 560 VOP_UNLOCK(vp, 0); 561 MNT_ILOCK(mp); 562 mp->mnt_flag |= MNT_QUOTA; 563 MNT_IUNLOCK(mp); 564 565 vpp = &ump->um_quotas[type]; 566 if (*vpp != vp) 567 quotaoff1(td, mp, type); 568 569 /* 570 * When the directory vnode containing the quota file is 571 * inactivated, due to the shared lookup of the quota file 572 * vput()ing the dvp, the qsyncvp() call for the containing 573 * directory would try to acquire the quota lock exclusive. 574 * At the same time, lookup already locked the quota vnode 575 * shared. Mark the quota vnode lock as allowing recursion 576 * and automatically converting shared locks to exclusive. 577 * 578 * Also mark quota vnode as system. 579 */ 580 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 581 vp->v_vflag |= VV_SYSTEM; 582 VN_LOCK_AREC(vp); 583 VN_LOCK_DSHARE(vp); 584 VOP_UNLOCK(vp, 0); 585 *vpp = vp; 586 /* 587 * Save the credential of the process that turned on quotas. 588 * Set up the time limits for this quota. 589 */ 590 ump->um_cred[type] = crhold(td->td_ucred); 591 ump->um_btime[type] = MAX_DQ_TIME; 592 ump->um_itime[type] = MAX_IQ_TIME; 593 if (dqget(NULLVP, 0, ump, type, &dq) == 0) { 594 if (dq->dq_btime > 0) 595 ump->um_btime[type] = dq->dq_btime; 596 if (dq->dq_itime > 0) 597 ump->um_itime[type] = dq->dq_itime; 598 dqrele(NULLVP, dq); 599 } 600 /* 601 * Allow the getdq from getinoquota below to read the quota 602 * from file. 603 */ 604 UFS_LOCK(ump); 605 ump->um_qflags[type] &= ~QTF_CLOSING; 606 UFS_UNLOCK(ump); 607 /* 608 * Search vnodes associated with this mount point, 609 * adding references to quota file being opened. 610 * NB: only need to add dquot's for inodes being modified. 611 */ 612 again: 613 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { 614 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { 615 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp); 616 goto again; 617 } 618 if (vp->v_type == VNON || vp->v_writecount == 0) { 619 VOP_UNLOCK(vp, 0); 620 vrele(vp); 621 continue; 622 } 623 error = getinoquota(VTOI(vp)); 624 VOP_UNLOCK(vp, 0); 625 vrele(vp); 626 if (error) { 627 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp); 628 break; 629 } 630 } 631 632 if (error) 633 quotaoff_inchange(td, mp, type); 634 UFS_LOCK(ump); 635 ump->um_qflags[type] &= ~QTF_OPENING; 636 KASSERT((ump->um_qflags[type] & QTF_CLOSING) == 0, 637 ("quotaon: leaking flags")); 638 UFS_UNLOCK(ump); 639 640 vfs_unbusy(mp); 641 return (error); 642 } 643 644 /* 645 * Main code to turn off disk quotas for a filesystem. Does not change 646 * flags. 647 */ 648 static int 649 quotaoff1(struct thread *td, struct mount *mp, int type) 650 { 651 struct vnode *vp; 652 struct vnode *qvp, *mvp; 653 struct ufsmount *ump; 654 struct dquot *dq; 655 struct inode *ip; 656 struct ucred *cr; 657 int error; 658 659 ump = VFSTOUFS(mp); 660 661 UFS_LOCK(ump); 662 KASSERT((ump->um_qflags[type] & QTF_CLOSING) != 0, 663 ("quotaoff1: flags are invalid")); 664 if ((qvp = ump->um_quotas[type]) == NULLVP) { 665 UFS_UNLOCK(ump); 666 return (0); 667 } 668 cr = ump->um_cred[type]; 669 UFS_UNLOCK(ump); 670 671 /* 672 * Search vnodes associated with this mount point, 673 * deleting any references to quota file being closed. 674 */ 675 again: 676 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { 677 if (vp->v_type == VNON) { 678 VI_UNLOCK(vp); 679 continue; 680 } 681 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { 682 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp); 683 goto again; 684 } 685 ip = VTOI(vp); 686 dq = ip->i_dquot[type]; 687 ip->i_dquot[type] = NODQUOT; 688 dqrele(vp, dq); 689 VOP_UNLOCK(vp, 0); 690 vrele(vp); 691 } 692 693 error = dqflush(qvp); 694 if (error != 0) 695 return (error); 696 697 /* 698 * Clear um_quotas before closing the quota vnode to prevent 699 * access to the closed vnode from dqget/dqsync 700 */ 701 UFS_LOCK(ump); 702 ump->um_quotas[type] = NULLVP; 703 ump->um_cred[type] = NOCRED; 704 UFS_UNLOCK(ump); 705 706 vn_lock(qvp, LK_EXCLUSIVE | LK_RETRY); 707 qvp->v_vflag &= ~VV_SYSTEM; 708 VOP_UNLOCK(qvp, 0); 709 error = vn_close(qvp, FREAD|FWRITE, td->td_ucred, td); 710 crfree(cr); 711 712 return (error); 713 } 714 715 static int 716 quotaoff_inchange1(struct thread *td, struct mount *mp, int type) 717 { 718 int error; 719 bool need_resume; 720 721 /* 722 * mp is already suspended on unmount. If not, suspend it, to 723 * avoid the situation where quotaoff operation eventually 724 * failing due to SU structures still keeping references on 725 * dquots, but vnode's references are already clean. This 726 * would cause quota accounting leak and asserts otherwise. 727 * Note that the thread has already called vn_start_write(). 728 */ 729 if (mp->mnt_susp_owner == td) { 730 need_resume = false; 731 } else { 732 error = vfs_write_suspend_umnt(mp); 733 if (error != 0) 734 return (error); 735 need_resume = true; 736 } 737 error = quotaoff1(td, mp, type); 738 if (need_resume) 739 vfs_write_resume(mp, VR_START_WRITE); 740 return (error); 741 } 742 743 /* 744 * Turns off quotas, assumes that ump->um_qflags are already checked 745 * and QTF_CLOSING is set to indicate operation in progress. Fixes 746 * ump->um_qflags and mp->mnt_flag after. 747 */ 748 int 749 quotaoff_inchange(struct thread *td, struct mount *mp, int type) 750 { 751 struct ufsmount *ump; 752 int error, i; 753 754 error = quotaoff_inchange1(td, mp, type); 755 756 ump = VFSTOUFS(mp); 757 UFS_LOCK(ump); 758 ump->um_qflags[type] &= ~QTF_CLOSING; 759 for (i = 0; i < MAXQUOTAS; i++) 760 if (ump->um_quotas[i] != NULLVP) 761 break; 762 if (i == MAXQUOTAS) { 763 MNT_ILOCK(mp); 764 mp->mnt_flag &= ~MNT_QUOTA; 765 MNT_IUNLOCK(mp); 766 } 767 UFS_UNLOCK(ump); 768 return (error); 769 } 770 771 /* 772 * Q_QUOTAOFF - turn off disk quotas for a filesystem. 773 */ 774 int 775 quotaoff(struct thread *td, struct mount *mp, int type) 776 { 777 struct ufsmount *ump; 778 int error; 779 780 error = priv_check(td, PRIV_UFS_QUOTAOFF); 781 if (error) 782 return (error); 783 784 ump = VFSTOUFS(mp); 785 UFS_LOCK(ump); 786 if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) { 787 UFS_UNLOCK(ump); 788 return (EALREADY); 789 } 790 ump->um_qflags[type] |= QTF_CLOSING; 791 UFS_UNLOCK(ump); 792 793 return (quotaoff_inchange(td, mp, type)); 794 } 795 796 /* 797 * Q_GETQUOTA - return current values in a dqblk structure. 798 */ 799 static int 800 _getquota(struct thread *td, struct mount *mp, u_long id, int type, 801 struct dqblk64 *dqb) 802 { 803 struct dquot *dq; 804 int error; 805 806 switch (type) { 807 case USRQUOTA: 808 if ((td->td_ucred->cr_uid != id) && !unprivileged_get_quota) { 809 error = priv_check(td, PRIV_VFS_GETQUOTA); 810 if (error) 811 return (error); 812 } 813 break; 814 815 case GRPQUOTA: 816 if (!groupmember(id, td->td_ucred) && 817 !unprivileged_get_quota) { 818 error = priv_check(td, PRIV_VFS_GETQUOTA); 819 if (error) 820 return (error); 821 } 822 break; 823 824 default: 825 return (EINVAL); 826 } 827 828 dq = NODQUOT; 829 error = dqget(NULLVP, id, VFSTOUFS(mp), type, &dq); 830 if (error) 831 return (error); 832 *dqb = dq->dq_dqb; 833 dqrele(NULLVP, dq); 834 return (error); 835 } 836 837 /* 838 * Q_SETQUOTA - assign an entire dqblk structure. 839 */ 840 static int 841 _setquota(struct thread *td, struct mount *mp, u_long id, int type, 842 struct dqblk64 *dqb) 843 { 844 struct dquot *dq; 845 struct dquot *ndq; 846 struct ufsmount *ump; 847 struct dqblk64 newlim; 848 int error; 849 850 error = priv_check(td, PRIV_VFS_SETQUOTA); 851 if (error) 852 return (error); 853 854 newlim = *dqb; 855 856 ndq = NODQUOT; 857 ump = VFSTOUFS(mp); 858 859 error = dqget(NULLVP, id, ump, type, &ndq); 860 if (error) 861 return (error); 862 dq = ndq; 863 DQI_LOCK(dq); 864 DQI_WAIT(dq, PINOD+1, "setqta"); 865 /* 866 * Copy all but the current values. 867 * Reset time limit if previously had no soft limit or were 868 * under it, but now have a soft limit and are over it. 869 */ 870 newlim.dqb_curblocks = dq->dq_curblocks; 871 newlim.dqb_curinodes = dq->dq_curinodes; 872 if (dq->dq_id != 0) { 873 newlim.dqb_btime = dq->dq_btime; 874 newlim.dqb_itime = dq->dq_itime; 875 } 876 if (newlim.dqb_bsoftlimit && 877 dq->dq_curblocks >= newlim.dqb_bsoftlimit && 878 (dq->dq_bsoftlimit == 0 || dq->dq_curblocks < dq->dq_bsoftlimit)) 879 newlim.dqb_btime = time_second + ump->um_btime[type]; 880 if (newlim.dqb_isoftlimit && 881 dq->dq_curinodes >= newlim.dqb_isoftlimit && 882 (dq->dq_isoftlimit == 0 || dq->dq_curinodes < dq->dq_isoftlimit)) 883 newlim.dqb_itime = time_second + ump->um_itime[type]; 884 dq->dq_dqb = newlim; 885 if (dq->dq_curblocks < dq->dq_bsoftlimit) 886 dq->dq_flags &= ~DQ_BLKS; 887 if (dq->dq_curinodes < dq->dq_isoftlimit) 888 dq->dq_flags &= ~DQ_INODS; 889 if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 && 890 dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0) 891 dq->dq_flags |= DQ_FAKE; 892 else 893 dq->dq_flags &= ~DQ_FAKE; 894 dq->dq_flags |= DQ_MOD; 895 DQI_UNLOCK(dq); 896 dqrele(NULLVP, dq); 897 return (0); 898 } 899 900 /* 901 * Q_SETUSE - set current inode and block usage. 902 */ 903 static int 904 _setuse(struct thread *td, struct mount *mp, u_long id, int type, 905 struct dqblk64 *dqb) 906 { 907 struct dquot *dq; 908 struct ufsmount *ump; 909 struct dquot *ndq; 910 struct dqblk64 usage; 911 int error; 912 913 error = priv_check(td, PRIV_UFS_SETUSE); 914 if (error) 915 return (error); 916 917 usage = *dqb; 918 919 ump = VFSTOUFS(mp); 920 ndq = NODQUOT; 921 922 error = dqget(NULLVP, id, ump, type, &ndq); 923 if (error) 924 return (error); 925 dq = ndq; 926 DQI_LOCK(dq); 927 DQI_WAIT(dq, PINOD+1, "setuse"); 928 /* 929 * Reset time limit if have a soft limit and were 930 * previously under it, but are now over it. 931 */ 932 if (dq->dq_bsoftlimit && dq->dq_curblocks < dq->dq_bsoftlimit && 933 usage.dqb_curblocks >= dq->dq_bsoftlimit) 934 dq->dq_btime = time_second + ump->um_btime[type]; 935 if (dq->dq_isoftlimit && dq->dq_curinodes < dq->dq_isoftlimit && 936 usage.dqb_curinodes >= dq->dq_isoftlimit) 937 dq->dq_itime = time_second + ump->um_itime[type]; 938 dq->dq_curblocks = usage.dqb_curblocks; 939 dq->dq_curinodes = usage.dqb_curinodes; 940 if (dq->dq_curblocks < dq->dq_bsoftlimit) 941 dq->dq_flags &= ~DQ_BLKS; 942 if (dq->dq_curinodes < dq->dq_isoftlimit) 943 dq->dq_flags &= ~DQ_INODS; 944 dq->dq_flags |= DQ_MOD; 945 DQI_UNLOCK(dq); 946 dqrele(NULLVP, dq); 947 return (0); 948 } 949 950 int 951 getquota32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 952 { 953 struct dqblk32 dqb32; 954 struct dqblk64 dqb64; 955 int error; 956 957 error = _getquota(td, mp, id, type, &dqb64); 958 if (error) 959 return (error); 960 dqb64_dqb32(&dqb64, &dqb32); 961 error = copyout(&dqb32, addr, sizeof(dqb32)); 962 return (error); 963 } 964 965 int 966 setquota32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 967 { 968 struct dqblk32 dqb32; 969 struct dqblk64 dqb64; 970 int error; 971 972 error = copyin(addr, &dqb32, sizeof(dqb32)); 973 if (error) 974 return (error); 975 dqb32_dqb64(&dqb32, &dqb64); 976 error = _setquota(td, mp, id, type, &dqb64); 977 return (error); 978 } 979 980 int 981 setuse32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 982 { 983 struct dqblk32 dqb32; 984 struct dqblk64 dqb64; 985 int error; 986 987 error = copyin(addr, &dqb32, sizeof(dqb32)); 988 if (error) 989 return (error); 990 dqb32_dqb64(&dqb32, &dqb64); 991 error = _setuse(td, mp, id, type, &dqb64); 992 return (error); 993 } 994 995 int 996 getquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 997 { 998 struct dqblk64 dqb64; 999 int error; 1000 1001 error = _getquota(td, mp, id, type, &dqb64); 1002 if (error) 1003 return (error); 1004 error = copyout(&dqb64, addr, sizeof(dqb64)); 1005 return (error); 1006 } 1007 1008 int 1009 setquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 1010 { 1011 struct dqblk64 dqb64; 1012 int error; 1013 1014 error = copyin(addr, &dqb64, sizeof(dqb64)); 1015 if (error) 1016 return (error); 1017 error = _setquota(td, mp, id, type, &dqb64); 1018 return (error); 1019 } 1020 1021 int 1022 setuse(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 1023 { 1024 struct dqblk64 dqb64; 1025 int error; 1026 1027 error = copyin(addr, &dqb64, sizeof(dqb64)); 1028 if (error) 1029 return (error); 1030 error = _setuse(td, mp, id, type, &dqb64); 1031 return (error); 1032 } 1033 1034 /* 1035 * Q_GETQUOTASIZE - get bit-size of quota file fields 1036 */ 1037 int 1038 getquotasize(struct thread *td, struct mount *mp, u_long id, int type, 1039 void *sizep) 1040 { 1041 struct ufsmount *ump = VFSTOUFS(mp); 1042 int bitsize; 1043 1044 UFS_LOCK(ump); 1045 if (ump->um_quotas[type] == NULLVP || 1046 (ump->um_qflags[type] & QTF_CLOSING)) { 1047 UFS_UNLOCK(ump); 1048 return (EINVAL); 1049 } 1050 if ((ump->um_qflags[type] & QTF_64BIT) != 0) 1051 bitsize = 64; 1052 else 1053 bitsize = 32; 1054 UFS_UNLOCK(ump); 1055 return (copyout(&bitsize, sizep, sizeof(int))); 1056 } 1057 1058 /* 1059 * Q_SYNC - sync quota files to disk. 1060 */ 1061 int 1062 qsync(struct mount *mp) 1063 { 1064 struct ufsmount *ump = VFSTOUFS(mp); 1065 struct thread *td = curthread; /* XXX */ 1066 struct vnode *vp, *mvp; 1067 struct dquot *dq; 1068 int i, error; 1069 1070 /* 1071 * Check if the mount point has any quotas. 1072 * If not, simply return. 1073 */ 1074 for (i = 0; i < MAXQUOTAS; i++) 1075 if (ump->um_quotas[i] != NULLVP) 1076 break; 1077 if (i == MAXQUOTAS) 1078 return (0); 1079 /* 1080 * Search vnodes associated with this mount point, 1081 * synchronizing any modified dquot structures. 1082 */ 1083 again: 1084 MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) { 1085 if (vp->v_type == VNON) { 1086 VI_UNLOCK(vp); 1087 continue; 1088 } 1089 error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td); 1090 if (error) { 1091 if (error == ENOENT) { 1092 MNT_VNODE_FOREACH_ACTIVE_ABORT(mp, mvp); 1093 goto again; 1094 } 1095 continue; 1096 } 1097 for (i = 0; i < MAXQUOTAS; i++) { 1098 dq = VTOI(vp)->i_dquot[i]; 1099 if (dq != NODQUOT) 1100 dqsync(vp, dq); 1101 } 1102 vput(vp); 1103 } 1104 return (0); 1105 } 1106 1107 /* 1108 * Sync quota file for given vnode to disk. 1109 */ 1110 int 1111 qsyncvp(struct vnode *vp) 1112 { 1113 struct ufsmount *ump = VFSTOUFS(vp->v_mount); 1114 struct dquot *dq; 1115 int i; 1116 1117 /* 1118 * Check if the mount point has any quotas. 1119 * If not, simply return. 1120 */ 1121 for (i = 0; i < MAXQUOTAS; i++) 1122 if (ump->um_quotas[i] != NULLVP) 1123 break; 1124 if (i == MAXQUOTAS) 1125 return (0); 1126 /* 1127 * Search quotas associated with this vnode 1128 * synchronizing any modified dquot structures. 1129 */ 1130 for (i = 0; i < MAXQUOTAS; i++) { 1131 dq = VTOI(vp)->i_dquot[i]; 1132 if (dq != NODQUOT) 1133 dqsync(vp, dq); 1134 } 1135 return (0); 1136 } 1137 1138 /* 1139 * Code pertaining to management of the in-core dquot data structures. 1140 */ 1141 #define DQHASH(dqvp, id) \ 1142 (&dqhashtbl[((((intptr_t)(dqvp)) >> 8) + id) & dqhash]) 1143 static LIST_HEAD(dqhash, dquot) *dqhashtbl; 1144 static u_long dqhash; 1145 1146 /* 1147 * Dquot free list. 1148 */ 1149 #define DQUOTINC 5 /* minimum free dquots desired */ 1150 static TAILQ_HEAD(dqfreelist, dquot) dqfreelist; 1151 static long numdquot, desireddquot = DQUOTINC; 1152 1153 /* 1154 * Lock to protect quota hash, dq free list and dq_cnt ref counters of 1155 * _all_ dqs. 1156 */ 1157 struct mtx dqhlock; 1158 1159 #define DQH_LOCK() mtx_lock(&dqhlock) 1160 #define DQH_UNLOCK() mtx_unlock(&dqhlock) 1161 1162 static struct dquot *dqhashfind(struct dqhash *dqh, u_long id, 1163 struct vnode *dqvp); 1164 1165 /* 1166 * Initialize the quota system. 1167 */ 1168 void 1169 dqinit(void) 1170 { 1171 1172 mtx_init(&dqhlock, "dqhlock", NULL, MTX_DEF); 1173 dqhashtbl = hashinit(desiredvnodes, M_DQUOT, &dqhash); 1174 TAILQ_INIT(&dqfreelist); 1175 } 1176 1177 /* 1178 * Shut down the quota system. 1179 */ 1180 void 1181 dquninit(void) 1182 { 1183 struct dquot *dq; 1184 1185 hashdestroy(dqhashtbl, M_DQUOT, dqhash); 1186 while ((dq = TAILQ_FIRST(&dqfreelist)) != NULL) { 1187 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); 1188 mtx_destroy(&dq->dq_lock); 1189 free(dq, M_DQUOT); 1190 } 1191 mtx_destroy(&dqhlock); 1192 } 1193 1194 static struct dquot * 1195 dqhashfind(struct dqhash *dqh, u_long id, struct vnode *dqvp) 1196 { 1197 struct dquot *dq; 1198 1199 mtx_assert(&dqhlock, MA_OWNED); 1200 LIST_FOREACH(dq, dqh, dq_hash) { 1201 if (dq->dq_id != id || 1202 dq->dq_ump->um_quotas[dq->dq_type] != dqvp) 1203 continue; 1204 /* 1205 * Cache hit with no references. Take 1206 * the structure off the free list. 1207 */ 1208 if (dq->dq_cnt == 0) 1209 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); 1210 DQREF(dq); 1211 return (dq); 1212 } 1213 return (NODQUOT); 1214 } 1215 1216 /* 1217 * Determine the quota file type. 1218 * 1219 * A 32-bit quota file is simply an array of struct dqblk32. 1220 * 1221 * A 64-bit quota file is a struct dqhdr64 followed by an array of struct 1222 * dqblk64. The header contains various magic bits which allow us to be 1223 * reasonably confident that it is indeeda 64-bit quota file and not just 1224 * a 32-bit quota file that just happens to "look right". 1225 * 1226 */ 1227 static int 1228 dqopen(struct vnode *vp, struct ufsmount *ump, int type) 1229 { 1230 struct dqhdr64 dqh; 1231 struct iovec aiov; 1232 struct uio auio; 1233 int error; 1234 1235 ASSERT_VOP_LOCKED(vp, "dqopen"); 1236 auio.uio_iov = &aiov; 1237 auio.uio_iovcnt = 1; 1238 aiov.iov_base = &dqh; 1239 aiov.iov_len = sizeof(dqh); 1240 auio.uio_resid = sizeof(dqh); 1241 auio.uio_offset = 0; 1242 auio.uio_segflg = UIO_SYSSPACE; 1243 auio.uio_rw = UIO_READ; 1244 auio.uio_td = (struct thread *)0; 1245 error = VOP_READ(vp, &auio, 0, ump->um_cred[type]); 1246 1247 if (error != 0) 1248 return (error); 1249 if (auio.uio_resid > 0) { 1250 /* assume 32 bits */ 1251 return (0); 1252 } 1253 1254 UFS_LOCK(ump); 1255 if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) == 0 && 1256 be32toh(dqh.dqh_version) == Q_DQHDR64_VERSION && 1257 be32toh(dqh.dqh_hdrlen) == (uint32_t)sizeof(struct dqhdr64) && 1258 be32toh(dqh.dqh_reclen) == (uint32_t)sizeof(struct dqblk64)) { 1259 /* XXX: what if the magic matches, but the sizes are wrong? */ 1260 ump->um_qflags[type] |= QTF_64BIT; 1261 } else { 1262 ump->um_qflags[type] &= ~QTF_64BIT; 1263 } 1264 UFS_UNLOCK(ump); 1265 1266 return (0); 1267 } 1268 1269 /* 1270 * Obtain a dquot structure for the specified identifier and quota file 1271 * reading the information from the file if necessary. 1272 */ 1273 static int 1274 dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, 1275 struct dquot **dqp) 1276 { 1277 uint8_t buf[sizeof(struct dqblk64)]; 1278 off_t base, recsize; 1279 struct dquot *dq, *dq1; 1280 struct dqhash *dqh; 1281 struct vnode *dqvp; 1282 struct iovec aiov; 1283 struct uio auio; 1284 int dqvplocked, error; 1285 1286 #ifdef DEBUG_VFS_LOCKS 1287 if (vp != NULLVP) 1288 ASSERT_VOP_ELOCKED(vp, "dqget"); 1289 #endif 1290 1291 if (vp != NULLVP && *dqp != NODQUOT) { 1292 return (0); 1293 } 1294 1295 /* XXX: Disallow negative id values to prevent the 1296 * creation of 100GB+ quota data files. 1297 */ 1298 if ((int)id < 0) 1299 return (EINVAL); 1300 1301 UFS_LOCK(ump); 1302 dqvp = ump->um_quotas[type]; 1303 if (dqvp == NULLVP || (ump->um_qflags[type] & QTF_CLOSING)) { 1304 *dqp = NODQUOT; 1305 UFS_UNLOCK(ump); 1306 return (EINVAL); 1307 } 1308 vref(dqvp); 1309 UFS_UNLOCK(ump); 1310 error = 0; 1311 dqvplocked = 0; 1312 1313 /* 1314 * Check the cache first. 1315 */ 1316 dqh = DQHASH(dqvp, id); 1317 DQH_LOCK(); 1318 dq = dqhashfind(dqh, id, dqvp); 1319 if (dq != NULL) { 1320 DQH_UNLOCK(); 1321 hfound: DQI_LOCK(dq); 1322 DQI_WAIT(dq, PINOD+1, "dqget"); 1323 DQI_UNLOCK(dq); 1324 if (dq->dq_ump == NULL) { 1325 dqrele(vp, dq); 1326 dq = NODQUOT; 1327 error = EIO; 1328 } 1329 *dqp = dq; 1330 if (dqvplocked) 1331 vput(dqvp); 1332 else 1333 vrele(dqvp); 1334 return (error); 1335 } 1336 1337 /* 1338 * Quota vnode lock is before DQ_LOCK. Acquire dqvp lock there 1339 * since new dq will appear on the hash chain DQ_LOCKed. 1340 */ 1341 if (vp != dqvp) { 1342 DQH_UNLOCK(); 1343 vn_lock(dqvp, LK_SHARED | LK_RETRY); 1344 dqvplocked = 1; 1345 DQH_LOCK(); 1346 /* 1347 * Recheck the cache after sleep for quota vnode lock. 1348 */ 1349 dq = dqhashfind(dqh, id, dqvp); 1350 if (dq != NULL) { 1351 DQH_UNLOCK(); 1352 goto hfound; 1353 } 1354 } 1355 1356 /* 1357 * Not in cache, allocate a new one or take it from the 1358 * free list. 1359 */ 1360 if (TAILQ_FIRST(&dqfreelist) == NODQUOT && 1361 numdquot < MAXQUOTAS * desiredvnodes) 1362 desireddquot += DQUOTINC; 1363 if (numdquot < desireddquot) { 1364 numdquot++; 1365 DQH_UNLOCK(); 1366 dq1 = malloc(sizeof *dq1, M_DQUOT, M_WAITOK | M_ZERO); 1367 mtx_init(&dq1->dq_lock, "dqlock", NULL, MTX_DEF); 1368 DQH_LOCK(); 1369 /* 1370 * Recheck the cache after sleep for memory. 1371 */ 1372 dq = dqhashfind(dqh, id, dqvp); 1373 if (dq != NULL) { 1374 numdquot--; 1375 DQH_UNLOCK(); 1376 mtx_destroy(&dq1->dq_lock); 1377 free(dq1, M_DQUOT); 1378 goto hfound; 1379 } 1380 dq = dq1; 1381 } else { 1382 if ((dq = TAILQ_FIRST(&dqfreelist)) == NULL) { 1383 DQH_UNLOCK(); 1384 tablefull("dquot"); 1385 *dqp = NODQUOT; 1386 if (dqvplocked) 1387 vput(dqvp); 1388 else 1389 vrele(dqvp); 1390 return (EUSERS); 1391 } 1392 if (dq->dq_cnt || (dq->dq_flags & DQ_MOD)) 1393 panic("dqget: free dquot isn't %p", dq); 1394 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); 1395 if (dq->dq_ump != NULL) 1396 LIST_REMOVE(dq, dq_hash); 1397 } 1398 1399 /* 1400 * Dq is put into hash already locked to prevent parallel 1401 * usage while it is being read from file. 1402 */ 1403 dq->dq_flags = DQ_LOCK; 1404 dq->dq_id = id; 1405 dq->dq_type = type; 1406 dq->dq_ump = ump; 1407 LIST_INSERT_HEAD(dqh, dq, dq_hash); 1408 DQREF(dq); 1409 DQH_UNLOCK(); 1410 1411 /* 1412 * Read the requested quota record from the quota file, performing 1413 * any necessary conversions. 1414 */ 1415 if (ump->um_qflags[type] & QTF_64BIT) { 1416 recsize = sizeof(struct dqblk64); 1417 base = sizeof(struct dqhdr64); 1418 } else { 1419 recsize = sizeof(struct dqblk32); 1420 base = 0; 1421 } 1422 auio.uio_iov = &aiov; 1423 auio.uio_iovcnt = 1; 1424 aiov.iov_base = buf; 1425 aiov.iov_len = recsize; 1426 auio.uio_resid = recsize; 1427 auio.uio_offset = base + id * recsize; 1428 auio.uio_segflg = UIO_SYSSPACE; 1429 auio.uio_rw = UIO_READ; 1430 auio.uio_td = (struct thread *)0; 1431 1432 error = VOP_READ(dqvp, &auio, 0, ump->um_cred[type]); 1433 if (auio.uio_resid == recsize && error == 0) { 1434 bzero(&dq->dq_dqb, sizeof(dq->dq_dqb)); 1435 } else { 1436 if (ump->um_qflags[type] & QTF_64BIT) 1437 dqb64_dq((struct dqblk64 *)buf, dq); 1438 else 1439 dqb32_dq((struct dqblk32 *)buf, dq); 1440 } 1441 if (dqvplocked) 1442 vput(dqvp); 1443 else 1444 vrele(dqvp); 1445 /* 1446 * I/O error in reading quota file, release 1447 * quota structure and reflect problem to caller. 1448 */ 1449 if (error) { 1450 DQH_LOCK(); 1451 dq->dq_ump = NULL; 1452 LIST_REMOVE(dq, dq_hash); 1453 DQH_UNLOCK(); 1454 DQI_LOCK(dq); 1455 if (dq->dq_flags & DQ_WANT) 1456 wakeup(dq); 1457 dq->dq_flags = 0; 1458 DQI_UNLOCK(dq); 1459 dqrele(vp, dq); 1460 *dqp = NODQUOT; 1461 return (error); 1462 } 1463 DQI_LOCK(dq); 1464 /* 1465 * Check for no limit to enforce. 1466 * Initialize time values if necessary. 1467 */ 1468 if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 && 1469 dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0) 1470 dq->dq_flags |= DQ_FAKE; 1471 if (dq->dq_id != 0) { 1472 if (dq->dq_btime == 0) { 1473 dq->dq_btime = time_second + ump->um_btime[type]; 1474 if (dq->dq_bsoftlimit && 1475 dq->dq_curblocks >= dq->dq_bsoftlimit) 1476 dq->dq_flags |= DQ_MOD; 1477 } 1478 if (dq->dq_itime == 0) { 1479 dq->dq_itime = time_second + ump->um_itime[type]; 1480 if (dq->dq_isoftlimit && 1481 dq->dq_curinodes >= dq->dq_isoftlimit) 1482 dq->dq_flags |= DQ_MOD; 1483 } 1484 } 1485 DQI_WAKEUP(dq); 1486 DQI_UNLOCK(dq); 1487 *dqp = dq; 1488 return (0); 1489 } 1490 1491 #ifdef DIAGNOSTIC 1492 /* 1493 * Obtain a reference to a dquot. 1494 */ 1495 static void 1496 dqref(struct dquot *dq) 1497 { 1498 1499 dq->dq_cnt++; 1500 } 1501 #endif 1502 1503 /* 1504 * Release a reference to a dquot. 1505 */ 1506 void 1507 dqrele(struct vnode *vp, struct dquot *dq) 1508 { 1509 1510 if (dq == NODQUOT) 1511 return; 1512 DQH_LOCK(); 1513 KASSERT(dq->dq_cnt > 0, ("Lost dq %p reference 1", dq)); 1514 if (dq->dq_cnt > 1) { 1515 dq->dq_cnt--; 1516 DQH_UNLOCK(); 1517 return; 1518 } 1519 DQH_UNLOCK(); 1520 sync: 1521 (void) dqsync(vp, dq); 1522 1523 DQH_LOCK(); 1524 KASSERT(dq->dq_cnt > 0, ("Lost dq %p reference 2", dq)); 1525 if (--dq->dq_cnt > 0) 1526 { 1527 DQH_UNLOCK(); 1528 return; 1529 } 1530 1531 /* 1532 * The dq may become dirty after it is synced but before it is 1533 * put to the free list. Checking the DQ_MOD there without 1534 * locking dq should be safe since no other references to the 1535 * dq exist. 1536 */ 1537 if ((dq->dq_flags & DQ_MOD) != 0) { 1538 dq->dq_cnt++; 1539 DQH_UNLOCK(); 1540 goto sync; 1541 } 1542 TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist); 1543 DQH_UNLOCK(); 1544 } 1545 1546 /* 1547 * Update the disk quota in the quota file. 1548 */ 1549 static int 1550 dqsync(struct vnode *vp, struct dquot *dq) 1551 { 1552 uint8_t buf[sizeof(struct dqblk64)]; 1553 off_t base, recsize; 1554 struct vnode *dqvp; 1555 struct iovec aiov; 1556 struct uio auio; 1557 int error; 1558 struct mount *mp; 1559 struct ufsmount *ump; 1560 1561 #ifdef DEBUG_VFS_LOCKS 1562 if (vp != NULL) 1563 ASSERT_VOP_ELOCKED(vp, "dqsync"); 1564 #endif 1565 1566 mp = NULL; 1567 error = 0; 1568 if (dq == NODQUOT) 1569 panic("dqsync: dquot"); 1570 if ((ump = dq->dq_ump) == NULL) 1571 return (0); 1572 UFS_LOCK(ump); 1573 if ((dqvp = ump->um_quotas[dq->dq_type]) == NULLVP) { 1574 if (vp == NULL) { 1575 UFS_UNLOCK(ump); 1576 return (0); 1577 } else 1578 panic("dqsync: file"); 1579 } 1580 vref(dqvp); 1581 UFS_UNLOCK(ump); 1582 1583 DQI_LOCK(dq); 1584 if ((dq->dq_flags & DQ_MOD) == 0) { 1585 DQI_UNLOCK(dq); 1586 vrele(dqvp); 1587 return (0); 1588 } 1589 DQI_UNLOCK(dq); 1590 1591 (void) vn_start_secondary_write(dqvp, &mp, V_WAIT); 1592 if (vp != dqvp) 1593 vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY); 1594 1595 DQI_LOCK(dq); 1596 DQI_WAIT(dq, PINOD+2, "dqsync"); 1597 if ((dq->dq_flags & DQ_MOD) == 0) 1598 goto out; 1599 dq->dq_flags |= DQ_LOCK; 1600 DQI_UNLOCK(dq); 1601 1602 /* 1603 * Write the quota record to the quota file, performing any 1604 * necessary conversions. See dqget() for additional details. 1605 */ 1606 if (ump->um_qflags[dq->dq_type] & QTF_64BIT) { 1607 dq_dqb64(dq, (struct dqblk64 *)buf); 1608 recsize = sizeof(struct dqblk64); 1609 base = sizeof(struct dqhdr64); 1610 } else { 1611 dq_dqb32(dq, (struct dqblk32 *)buf); 1612 recsize = sizeof(struct dqblk32); 1613 base = 0; 1614 } 1615 1616 auio.uio_iov = &aiov; 1617 auio.uio_iovcnt = 1; 1618 aiov.iov_base = buf; 1619 aiov.iov_len = recsize; 1620 auio.uio_resid = recsize; 1621 auio.uio_offset = base + dq->dq_id * recsize; 1622 auio.uio_segflg = UIO_SYSSPACE; 1623 auio.uio_rw = UIO_WRITE; 1624 auio.uio_td = (struct thread *)0; 1625 error = VOP_WRITE(dqvp, &auio, 0, dq->dq_ump->um_cred[dq->dq_type]); 1626 if (auio.uio_resid && error == 0) 1627 error = EIO; 1628 1629 DQI_LOCK(dq); 1630 DQI_WAKEUP(dq); 1631 dq->dq_flags &= ~DQ_MOD; 1632 out: 1633 DQI_UNLOCK(dq); 1634 if (vp != dqvp) 1635 vput(dqvp); 1636 else 1637 vrele(dqvp); 1638 vn_finished_secondary_write(mp); 1639 return (error); 1640 } 1641 1642 /* 1643 * Flush all entries from the cache for a particular vnode. 1644 */ 1645 static int 1646 dqflush(struct vnode *vp) 1647 { 1648 struct dquot *dq, *nextdq; 1649 struct dqhash *dqh; 1650 int error; 1651 1652 /* 1653 * Move all dquot's that used to refer to this quota 1654 * file off their hash chains (they will eventually 1655 * fall off the head of the free list and be re-used). 1656 */ 1657 error = 0; 1658 DQH_LOCK(); 1659 for (dqh = &dqhashtbl[dqhash]; dqh >= dqhashtbl; dqh--) { 1660 for (dq = LIST_FIRST(dqh); dq; dq = nextdq) { 1661 nextdq = LIST_NEXT(dq, dq_hash); 1662 if (dq->dq_ump->um_quotas[dq->dq_type] != vp) 1663 continue; 1664 if (dq->dq_cnt) 1665 error = EBUSY; 1666 else { 1667 LIST_REMOVE(dq, dq_hash); 1668 dq->dq_ump = NULL; 1669 } 1670 } 1671 } 1672 DQH_UNLOCK(); 1673 return (error); 1674 } 1675 1676 /* 1677 * The following three functions are provided for the adjustment of 1678 * quotas by the soft updates code. 1679 */ 1680 #ifdef SOFTUPDATES 1681 /* 1682 * Acquire a reference to the quota structures associated with a vnode. 1683 * Return count of number of quota structures found. 1684 */ 1685 int 1686 quotaref(vp, qrp) 1687 struct vnode *vp; 1688 struct dquot **qrp; 1689 { 1690 struct inode *ip; 1691 struct dquot *dq; 1692 int i, found; 1693 1694 for (i = 0; i < MAXQUOTAS; i++) 1695 qrp[i] = NODQUOT; 1696 /* 1697 * Disk quotas must be turned off for system files. Currently 1698 * snapshot and quota files. 1699 */ 1700 if ((vp->v_vflag & VV_SYSTEM) != 0) 1701 return (0); 1702 /* 1703 * Iterate through and copy active quotas. 1704 */ 1705 found = 0; 1706 ip = VTOI(vp); 1707 mtx_lock(&dqhlock); 1708 for (i = 0; i < MAXQUOTAS; i++) { 1709 if ((dq = ip->i_dquot[i]) == NODQUOT) 1710 continue; 1711 DQREF(dq); 1712 qrp[i] = dq; 1713 found++; 1714 } 1715 mtx_unlock(&dqhlock); 1716 return (found); 1717 } 1718 1719 /* 1720 * Release a set of quota structures obtained from a vnode. 1721 */ 1722 void 1723 quotarele(qrp) 1724 struct dquot **qrp; 1725 { 1726 struct dquot *dq; 1727 int i; 1728 1729 for (i = 0; i < MAXQUOTAS; i++) { 1730 if ((dq = qrp[i]) == NODQUOT) 1731 continue; 1732 dqrele(NULL, dq); 1733 } 1734 } 1735 1736 /* 1737 * Adjust the number of blocks associated with a quota. 1738 * Positive numbers when adding blocks; negative numbers when freeing blocks. 1739 */ 1740 void 1741 quotaadj(qrp, ump, blkcount) 1742 struct dquot **qrp; 1743 struct ufsmount *ump; 1744 int64_t blkcount; 1745 { 1746 struct dquot *dq; 1747 ufs2_daddr_t ncurblocks; 1748 int i; 1749 1750 if (blkcount == 0) 1751 return; 1752 for (i = 0; i < MAXQUOTAS; i++) { 1753 if ((dq = qrp[i]) == NODQUOT) 1754 continue; 1755 DQI_LOCK(dq); 1756 DQI_WAIT(dq, PINOD+1, "adjqta"); 1757 ncurblocks = dq->dq_curblocks + blkcount; 1758 if (ncurblocks >= 0) 1759 dq->dq_curblocks = ncurblocks; 1760 else 1761 dq->dq_curblocks = 0; 1762 if (blkcount < 0) 1763 dq->dq_flags &= ~DQ_BLKS; 1764 else if (dq->dq_curblocks + blkcount >= dq->dq_bsoftlimit && 1765 dq->dq_curblocks < dq->dq_bsoftlimit) 1766 dq->dq_btime = time_second + ump->um_btime[i]; 1767 dq->dq_flags |= DQ_MOD; 1768 DQI_UNLOCK(dq); 1769 } 1770 } 1771 #endif /* SOFTUPDATES */ 1772 1773 /* 1774 * 32-bit / 64-bit conversion functions. 1775 * 1776 * 32-bit quota records are stored in native byte order. Attention must 1777 * be paid to overflow issues. 1778 * 1779 * 64-bit quota records are stored in network byte order. 1780 */ 1781 1782 #define CLIP32(u64) (u64 > UINT32_MAX ? UINT32_MAX : (uint32_t)u64) 1783 1784 /* 1785 * Convert 32-bit host-order structure to dquot. 1786 */ 1787 static void 1788 dqb32_dq(const struct dqblk32 *dqb32, struct dquot *dq) 1789 { 1790 1791 dq->dq_bhardlimit = dqb32->dqb_bhardlimit; 1792 dq->dq_bsoftlimit = dqb32->dqb_bsoftlimit; 1793 dq->dq_curblocks = dqb32->dqb_curblocks; 1794 dq->dq_ihardlimit = dqb32->dqb_ihardlimit; 1795 dq->dq_isoftlimit = dqb32->dqb_isoftlimit; 1796 dq->dq_curinodes = dqb32->dqb_curinodes; 1797 dq->dq_btime = dqb32->dqb_btime; 1798 dq->dq_itime = dqb32->dqb_itime; 1799 } 1800 1801 /* 1802 * Convert 64-bit network-order structure to dquot. 1803 */ 1804 static void 1805 dqb64_dq(const struct dqblk64 *dqb64, struct dquot *dq) 1806 { 1807 1808 dq->dq_bhardlimit = be64toh(dqb64->dqb_bhardlimit); 1809 dq->dq_bsoftlimit = be64toh(dqb64->dqb_bsoftlimit); 1810 dq->dq_curblocks = be64toh(dqb64->dqb_curblocks); 1811 dq->dq_ihardlimit = be64toh(dqb64->dqb_ihardlimit); 1812 dq->dq_isoftlimit = be64toh(dqb64->dqb_isoftlimit); 1813 dq->dq_curinodes = be64toh(dqb64->dqb_curinodes); 1814 dq->dq_btime = be64toh(dqb64->dqb_btime); 1815 dq->dq_itime = be64toh(dqb64->dqb_itime); 1816 } 1817 1818 /* 1819 * Convert dquot to 32-bit host-order structure. 1820 */ 1821 static void 1822 dq_dqb32(const struct dquot *dq, struct dqblk32 *dqb32) 1823 { 1824 1825 dqb32->dqb_bhardlimit = CLIP32(dq->dq_bhardlimit); 1826 dqb32->dqb_bsoftlimit = CLIP32(dq->dq_bsoftlimit); 1827 dqb32->dqb_curblocks = CLIP32(dq->dq_curblocks); 1828 dqb32->dqb_ihardlimit = CLIP32(dq->dq_ihardlimit); 1829 dqb32->dqb_isoftlimit = CLIP32(dq->dq_isoftlimit); 1830 dqb32->dqb_curinodes = CLIP32(dq->dq_curinodes); 1831 dqb32->dqb_btime = CLIP32(dq->dq_btime); 1832 dqb32->dqb_itime = CLIP32(dq->dq_itime); 1833 } 1834 1835 /* 1836 * Convert dquot to 64-bit network-order structure. 1837 */ 1838 static void 1839 dq_dqb64(const struct dquot *dq, struct dqblk64 *dqb64) 1840 { 1841 1842 dqb64->dqb_bhardlimit = htobe64(dq->dq_bhardlimit); 1843 dqb64->dqb_bsoftlimit = htobe64(dq->dq_bsoftlimit); 1844 dqb64->dqb_curblocks = htobe64(dq->dq_curblocks); 1845 dqb64->dqb_ihardlimit = htobe64(dq->dq_ihardlimit); 1846 dqb64->dqb_isoftlimit = htobe64(dq->dq_isoftlimit); 1847 dqb64->dqb_curinodes = htobe64(dq->dq_curinodes); 1848 dqb64->dqb_btime = htobe64(dq->dq_btime); 1849 dqb64->dqb_itime = htobe64(dq->dq_itime); 1850 } 1851 1852 /* 1853 * Convert 64-bit host-order structure to 32-bit host-order structure. 1854 */ 1855 static void 1856 dqb64_dqb32(const struct dqblk64 *dqb64, struct dqblk32 *dqb32) 1857 { 1858 1859 dqb32->dqb_bhardlimit = CLIP32(dqb64->dqb_bhardlimit); 1860 dqb32->dqb_bsoftlimit = CLIP32(dqb64->dqb_bsoftlimit); 1861 dqb32->dqb_curblocks = CLIP32(dqb64->dqb_curblocks); 1862 dqb32->dqb_ihardlimit = CLIP32(dqb64->dqb_ihardlimit); 1863 dqb32->dqb_isoftlimit = CLIP32(dqb64->dqb_isoftlimit); 1864 dqb32->dqb_curinodes = CLIP32(dqb64->dqb_curinodes); 1865 dqb32->dqb_btime = CLIP32(dqb64->dqb_btime); 1866 dqb32->dqb_itime = CLIP32(dqb64->dqb_itime); 1867 } 1868 1869 /* 1870 * Convert 32-bit host-order structure to 64-bit host-order structure. 1871 */ 1872 static void 1873 dqb32_dqb64(const struct dqblk32 *dqb32, struct dqblk64 *dqb64) 1874 { 1875 1876 dqb64->dqb_bhardlimit = dqb32->dqb_bhardlimit; 1877 dqb64->dqb_bsoftlimit = dqb32->dqb_bsoftlimit; 1878 dqb64->dqb_curblocks = dqb32->dqb_curblocks; 1879 dqb64->dqb_ihardlimit = dqb32->dqb_ihardlimit; 1880 dqb64->dqb_isoftlimit = dqb32->dqb_isoftlimit; 1881 dqb64->dqb_curinodes = dqb32->dqb_curinodes; 1882 dqb64->dqb_btime = dqb32->dqb_btime; 1883 dqb64->dqb_itime = dqb32->dqb_itime; 1884 } 1885