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