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 * 4. 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 void 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 + ip->i_ump->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 ITOV(ip)->v_mount->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 ITOV(ip)->v_mount->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 + ip->i_ump->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 ITOV(ip)->v_mount->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 ino_t ncurinodes; 311 int i, error, warn, do_check; 312 313 #ifdef DIAGNOSTIC 314 if ((flags & CHOWN) == 0) 315 chkdquot(ip); 316 #endif 317 if (change == 0) 318 return (0); 319 if (change < 0) { 320 for (i = 0; i < MAXQUOTAS; i++) { 321 if ((dq = ip->i_dquot[i]) == NODQUOT) 322 continue; 323 DQI_LOCK(dq); 324 DQI_WAIT(dq, PINOD+1, "chkiq1"); 325 ncurinodes = dq->dq_curinodes + change; 326 /* XXX: ncurinodes is unsigned */ 327 if (dq->dq_curinodes != 0 && ncurinodes >= 0) 328 dq->dq_curinodes = ncurinodes; 329 else 330 dq->dq_curinodes = 0; 331 dq->dq_flags &= ~DQ_INODS; 332 dq->dq_flags |= DQ_MOD; 333 DQI_UNLOCK(dq); 334 } 335 return (0); 336 } 337 if ((flags & FORCE) == 0 && 338 priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0)) 339 do_check = 1; 340 else 341 do_check = 0; 342 for (i = 0; i < MAXQUOTAS; i++) { 343 if ((dq = ip->i_dquot[i]) == NODQUOT) 344 continue; 345 warn = 0; 346 DQI_LOCK(dq); 347 DQI_WAIT(dq, PINOD+1, "chkiq2"); 348 if (do_check) { 349 error = chkiqchg(ip, change, cred, i, &warn); 350 if (error) { 351 /* 352 * Roll back user quota changes when 353 * group quota failed. 354 */ 355 while (i > 0) { 356 --i; 357 dq = ip->i_dquot[i]; 358 if (dq == NODQUOT) 359 continue; 360 DQI_LOCK(dq); 361 DQI_WAIT(dq, PINOD+1, "chkiq3"); 362 ncurinodes = dq->dq_curinodes - change; 363 /* XXX: ncurinodes is unsigned */ 364 if (dq->dq_curinodes != 0 && 365 ncurinodes >= 0) 366 dq->dq_curinodes = ncurinodes; 367 else 368 dq->dq_curinodes = 0; 369 dq->dq_flags &= ~DQ_INODS; 370 dq->dq_flags |= DQ_MOD; 371 DQI_UNLOCK(dq); 372 } 373 return (error); 374 } 375 } 376 /* Reset timer when crossing soft limit */ 377 if (dq->dq_curinodes + change >= dq->dq_isoftlimit && 378 dq->dq_curinodes < dq->dq_isoftlimit) 379 dq->dq_itime = time_second + ip->i_ump->um_itime[i]; 380 dq->dq_curinodes += change; 381 dq->dq_flags |= DQ_MOD; 382 DQI_UNLOCK(dq); 383 if (warn) 384 uprintf("\n%s: warning, %s inode quota exceeded\n", 385 ITOV(ip)->v_mount->mnt_stat.f_mntonname, 386 quotatypes[i]); 387 } 388 return (0); 389 } 390 391 /* 392 * Check for a valid change to a users allocation. 393 * Issue an error message if appropriate. 394 */ 395 static int 396 chkiqchg(struct inode *ip, int change, struct ucred *cred, int type, int *warn) 397 { 398 struct dquot *dq = ip->i_dquot[type]; 399 ino_t ncurinodes = dq->dq_curinodes + change; 400 401 /* 402 * If user would exceed their hard limit, disallow inode allocation. 403 */ 404 if (ncurinodes >= dq->dq_ihardlimit && dq->dq_ihardlimit) { 405 if ((dq->dq_flags & DQ_INODS) == 0 && 406 ip->i_uid == cred->cr_uid) { 407 dq->dq_flags |= DQ_INODS; 408 DQI_UNLOCK(dq); 409 uprintf("\n%s: write failed, %s inode limit reached\n", 410 ITOV(ip)->v_mount->mnt_stat.f_mntonname, 411 quotatypes[type]); 412 return (EDQUOT); 413 } 414 DQI_UNLOCK(dq); 415 return (EDQUOT); 416 } 417 /* 418 * If user is over their soft limit for too long, disallow inode 419 * allocation. Reset time limit as they cross their soft limit. 420 */ 421 if (ncurinodes >= dq->dq_isoftlimit && dq->dq_isoftlimit) { 422 if (dq->dq_curinodes < dq->dq_isoftlimit) { 423 dq->dq_itime = time_second + ip->i_ump->um_itime[type]; 424 if (ip->i_uid == cred->cr_uid) 425 *warn = 1; 426 return (0); 427 } 428 if (time_second > dq->dq_itime) { 429 if ((dq->dq_flags & DQ_INODS) == 0 && 430 ip->i_uid == cred->cr_uid) { 431 dq->dq_flags |= DQ_INODS; 432 DQI_UNLOCK(dq); 433 uprintf("\n%s: write failed, %s " 434 "inode quota exceeded for too long\n", 435 ITOV(ip)->v_mount->mnt_stat.f_mntonname, 436 quotatypes[type]); 437 return (EDQUOT); 438 } 439 DQI_UNLOCK(dq); 440 return (EDQUOT); 441 } 442 } 443 return (0); 444 } 445 446 #ifdef DIAGNOSTIC 447 /* 448 * On filesystems with quotas enabled, it is an error for a file to change 449 * size and not to have a dquot structure associated with it. 450 */ 451 static void 452 chkdquot(struct inode *ip) 453 { 454 struct ufsmount *ump = ip->i_ump; 455 struct vnode *vp = ITOV(ip); 456 int i; 457 458 /* 459 * Disk quotas must be turned off for system files. Currently 460 * these are snapshots and quota files. 461 */ 462 if ((vp->v_vflag & VV_SYSTEM) != 0) 463 return; 464 /* 465 * XXX: Turn off quotas for files with a negative UID or GID. 466 * This prevents the creation of 100GB+ quota files. 467 */ 468 if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0) 469 return; 470 471 UFS_LOCK(ump); 472 for (i = 0; i < MAXQUOTAS; i++) { 473 if (ump->um_quotas[i] == NULLVP || 474 (ump->um_qflags[i] & (QTF_OPENING|QTF_CLOSING))) 475 continue; 476 if (ip->i_dquot[i] == NODQUOT) { 477 UFS_UNLOCK(ump); 478 vprint("chkdquot: missing dquot", ITOV(ip)); 479 panic("chkdquot: missing dquot"); 480 } 481 } 482 UFS_UNLOCK(ump); 483 } 484 #endif 485 486 /* 487 * Code to process quotactl commands. 488 */ 489 490 /* 491 * Q_QUOTAON - set up a quota file for a particular filesystem. 492 */ 493 int 494 quotaon(struct thread *td, struct mount *mp, int type, void *fname) 495 { 496 struct ufsmount *ump; 497 struct vnode *vp, **vpp; 498 struct vnode *mvp; 499 struct dquot *dq; 500 int error, flags, vfslocked; 501 struct nameidata nd; 502 503 error = priv_check(td, PRIV_UFS_QUOTAON); 504 if (error) 505 return (error); 506 507 if (mp->mnt_flag & MNT_RDONLY) 508 return (EROFS); 509 510 ump = VFSTOUFS(mp); 511 dq = NODQUOT; 512 513 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_USERSPACE, fname, td); 514 flags = FREAD | FWRITE; 515 error = vn_open(&nd, &flags, 0, NULL); 516 if (error) 517 return (error); 518 vfslocked = NDHASGIANT(&nd); 519 NDFREE(&nd, NDF_ONLY_PNBUF); 520 vp = nd.ni_vp; 521 if (vp->v_type != VREG) { 522 VOP_UNLOCK(vp, 0); 523 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); 524 VFS_UNLOCK_GIANT(vfslocked); 525 return (EACCES); 526 } 527 528 UFS_LOCK(ump); 529 if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) { 530 UFS_UNLOCK(ump); 531 VOP_UNLOCK(vp, 0); 532 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); 533 VFS_UNLOCK_GIANT(vfslocked); 534 return (EALREADY); 535 } 536 ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING; 537 UFS_UNLOCK(ump); 538 if ((error = dqopen(vp, ump, type)) != 0) { 539 VOP_UNLOCK(vp, 0); 540 UFS_LOCK(ump); 541 ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING); 542 UFS_UNLOCK(ump); 543 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); 544 VFS_UNLOCK_GIANT(vfslocked); 545 return (error); 546 } 547 VOP_UNLOCK(vp, 0); 548 MNT_ILOCK(mp); 549 mp->mnt_flag |= MNT_QUOTA; 550 MNT_IUNLOCK(mp); 551 552 vpp = &ump->um_quotas[type]; 553 if (*vpp != vp) 554 quotaoff1(td, mp, type); 555 556 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 557 vp->v_vflag |= VV_SYSTEM; 558 VOP_UNLOCK(vp, 0); 559 *vpp = vp; 560 VFS_UNLOCK_GIANT(vfslocked); 561 /* 562 * Save the credential of the process that turned on quotas. 563 * Set up the time limits for this quota. 564 */ 565 ump->um_cred[type] = crhold(td->td_ucred); 566 ump->um_btime[type] = MAX_DQ_TIME; 567 ump->um_itime[type] = MAX_IQ_TIME; 568 if (dqget(NULLVP, 0, ump, type, &dq) == 0) { 569 if (dq->dq_btime > 0) 570 ump->um_btime[type] = dq->dq_btime; 571 if (dq->dq_itime > 0) 572 ump->um_itime[type] = dq->dq_itime; 573 dqrele(NULLVP, dq); 574 } 575 /* 576 * Allow the getdq from getinoquota below to read the quota 577 * from file. 578 */ 579 UFS_LOCK(ump); 580 ump->um_qflags[type] &= ~QTF_CLOSING; 581 UFS_UNLOCK(ump); 582 /* 583 * Search vnodes associated with this mount point, 584 * adding references to quota file being opened. 585 * NB: only need to add dquot's for inodes being modified. 586 */ 587 MNT_ILOCK(mp); 588 again: 589 MNT_VNODE_FOREACH(vp, mp, mvp) { 590 VI_LOCK(vp); 591 MNT_IUNLOCK(mp); 592 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { 593 MNT_ILOCK(mp); 594 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); 595 goto again; 596 } 597 if (vp->v_type == VNON || vp->v_writecount == 0) { 598 VOP_UNLOCK(vp, 0); 599 vrele(vp); 600 MNT_ILOCK(mp); 601 continue; 602 } 603 error = getinoquota(VTOI(vp)); 604 VOP_UNLOCK(vp, 0); 605 vrele(vp); 606 MNT_ILOCK(mp); 607 if (error) { 608 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); 609 break; 610 } 611 } 612 MNT_IUNLOCK(mp); 613 614 if (error) 615 quotaoff_inchange(td, mp, type); 616 UFS_LOCK(ump); 617 ump->um_qflags[type] &= ~QTF_OPENING; 618 KASSERT((ump->um_qflags[type] & QTF_CLOSING) == 0, 619 ("quotaon: leaking flags")); 620 UFS_UNLOCK(ump); 621 622 return (error); 623 } 624 625 /* 626 * Main code to turn off disk quotas for a filesystem. Does not change 627 * flags. 628 */ 629 static int 630 quotaoff1(struct thread *td, struct mount *mp, int type) 631 { 632 struct vnode *vp; 633 struct vnode *qvp, *mvp; 634 struct ufsmount *ump; 635 struct dquot *dq; 636 struct inode *ip; 637 struct ucred *cr; 638 int vfslocked; 639 int error; 640 641 ump = VFSTOUFS(mp); 642 643 UFS_LOCK(ump); 644 KASSERT((ump->um_qflags[type] & QTF_CLOSING) != 0, 645 ("quotaoff1: flags are invalid")); 646 if ((qvp = ump->um_quotas[type]) == NULLVP) { 647 UFS_UNLOCK(ump); 648 return (0); 649 } 650 cr = ump->um_cred[type]; 651 UFS_UNLOCK(ump); 652 653 /* 654 * Search vnodes associated with this mount point, 655 * deleting any references to quota file being closed. 656 */ 657 MNT_ILOCK(mp); 658 again: 659 MNT_VNODE_FOREACH(vp, mp, mvp) { 660 VI_LOCK(vp); 661 MNT_IUNLOCK(mp); 662 if (vp->v_type == VNON) { 663 VI_UNLOCK(vp); 664 MNT_ILOCK(mp); 665 continue; 666 } 667 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { 668 MNT_ILOCK(mp); 669 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); 670 goto again; 671 } 672 ip = VTOI(vp); 673 dq = ip->i_dquot[type]; 674 ip->i_dquot[type] = NODQUOT; 675 dqrele(vp, dq); 676 VOP_UNLOCK(vp, 0); 677 vrele(vp); 678 MNT_ILOCK(mp); 679 } 680 MNT_IUNLOCK(mp); 681 682 dqflush(qvp); 683 /* Clear um_quotas before closing the quota vnode to prevent 684 * access to the closed vnode from dqget/dqsync 685 */ 686 UFS_LOCK(ump); 687 ump->um_quotas[type] = NULLVP; 688 ump->um_cred[type] = NOCRED; 689 UFS_UNLOCK(ump); 690 691 vfslocked = VFS_LOCK_GIANT(qvp->v_mount); 692 vn_lock(qvp, LK_EXCLUSIVE | LK_RETRY); 693 qvp->v_vflag &= ~VV_SYSTEM; 694 VOP_UNLOCK(qvp, 0); 695 error = vn_close(qvp, FREAD|FWRITE, td->td_ucred, td); 696 VFS_UNLOCK_GIANT(vfslocked); 697 crfree(cr); 698 699 return (error); 700 } 701 702 /* 703 * Turns off quotas, assumes that ump->um_qflags are already checked 704 * and QTF_CLOSING is set to indicate operation in progress. Fixes 705 * ump->um_qflags and mp->mnt_flag after. 706 */ 707 int 708 quotaoff_inchange(struct thread *td, struct mount *mp, int type) 709 { 710 struct ufsmount *ump; 711 int i; 712 int error; 713 714 error = quotaoff1(td, mp, type); 715 716 ump = VFSTOUFS(mp); 717 UFS_LOCK(ump); 718 ump->um_qflags[type] &= ~QTF_CLOSING; 719 for (i = 0; i < MAXQUOTAS; i++) 720 if (ump->um_quotas[i] != NULLVP) 721 break; 722 if (i == MAXQUOTAS) { 723 MNT_ILOCK(mp); 724 mp->mnt_flag &= ~MNT_QUOTA; 725 MNT_IUNLOCK(mp); 726 } 727 UFS_UNLOCK(ump); 728 return (error); 729 } 730 731 /* 732 * Q_QUOTAOFF - turn off disk quotas for a filesystem. 733 */ 734 int 735 quotaoff(struct thread *td, struct mount *mp, int type) 736 { 737 struct ufsmount *ump; 738 int error; 739 740 error = priv_check(td, PRIV_UFS_QUOTAOFF); 741 if (error) 742 return (error); 743 744 ump = VFSTOUFS(mp); 745 UFS_LOCK(ump); 746 if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) { 747 UFS_UNLOCK(ump); 748 return (EALREADY); 749 } 750 ump->um_qflags[type] |= QTF_CLOSING; 751 UFS_UNLOCK(ump); 752 753 return (quotaoff_inchange(td, mp, type)); 754 } 755 756 /* 757 * Q_GETQUOTA - return current values in a dqblk structure. 758 */ 759 static int 760 _getquota(struct thread *td, struct mount *mp, u_long id, int type, 761 struct dqblk64 *dqb) 762 { 763 struct dquot *dq; 764 int error; 765 766 switch (type) { 767 case USRQUOTA: 768 if ((td->td_ucred->cr_uid != id) && !unprivileged_get_quota) { 769 error = priv_check(td, PRIV_VFS_GETQUOTA); 770 if (error) 771 return (error); 772 } 773 break; 774 775 case GRPQUOTA: 776 if (!groupmember(id, td->td_ucred) && 777 !unprivileged_get_quota) { 778 error = priv_check(td, PRIV_VFS_GETQUOTA); 779 if (error) 780 return (error); 781 } 782 break; 783 784 default: 785 return (EINVAL); 786 } 787 788 dq = NODQUOT; 789 error = dqget(NULLVP, id, VFSTOUFS(mp), type, &dq); 790 if (error) 791 return (error); 792 *dqb = dq->dq_dqb; 793 dqrele(NULLVP, dq); 794 return (error); 795 } 796 797 /* 798 * Q_SETQUOTA - assign an entire dqblk structure. 799 */ 800 static int 801 _setquota(struct thread *td, struct mount *mp, u_long id, int type, 802 struct dqblk64 *dqb) 803 { 804 struct dquot *dq; 805 struct dquot *ndq; 806 struct ufsmount *ump; 807 struct dqblk64 newlim; 808 int error; 809 810 error = priv_check(td, PRIV_VFS_SETQUOTA); 811 if (error) 812 return (error); 813 814 newlim = *dqb; 815 816 ndq = NODQUOT; 817 ump = VFSTOUFS(mp); 818 819 error = dqget(NULLVP, id, ump, type, &ndq); 820 if (error) 821 return (error); 822 dq = ndq; 823 DQI_LOCK(dq); 824 DQI_WAIT(dq, PINOD+1, "setqta"); 825 /* 826 * Copy all but the current values. 827 * Reset time limit if previously had no soft limit or were 828 * under it, but now have a soft limit and are over it. 829 */ 830 newlim.dqb_curblocks = dq->dq_curblocks; 831 newlim.dqb_curinodes = dq->dq_curinodes; 832 if (dq->dq_id != 0) { 833 newlim.dqb_btime = dq->dq_btime; 834 newlim.dqb_itime = dq->dq_itime; 835 } 836 if (newlim.dqb_bsoftlimit && 837 dq->dq_curblocks >= newlim.dqb_bsoftlimit && 838 (dq->dq_bsoftlimit == 0 || dq->dq_curblocks < dq->dq_bsoftlimit)) 839 newlim.dqb_btime = time_second + ump->um_btime[type]; 840 if (newlim.dqb_isoftlimit && 841 dq->dq_curinodes >= newlim.dqb_isoftlimit && 842 (dq->dq_isoftlimit == 0 || dq->dq_curinodes < dq->dq_isoftlimit)) 843 newlim.dqb_itime = time_second + ump->um_itime[type]; 844 dq->dq_dqb = newlim; 845 if (dq->dq_curblocks < dq->dq_bsoftlimit) 846 dq->dq_flags &= ~DQ_BLKS; 847 if (dq->dq_curinodes < dq->dq_isoftlimit) 848 dq->dq_flags &= ~DQ_INODS; 849 if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 && 850 dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0) 851 dq->dq_flags |= DQ_FAKE; 852 else 853 dq->dq_flags &= ~DQ_FAKE; 854 dq->dq_flags |= DQ_MOD; 855 DQI_UNLOCK(dq); 856 dqrele(NULLVP, dq); 857 return (0); 858 } 859 860 /* 861 * Q_SETUSE - set current inode and block usage. 862 */ 863 static int 864 _setuse(struct thread *td, struct mount *mp, u_long id, int type, 865 struct dqblk64 *dqb) 866 { 867 struct dquot *dq; 868 struct ufsmount *ump; 869 struct dquot *ndq; 870 struct dqblk64 usage; 871 int error; 872 873 error = priv_check(td, PRIV_UFS_SETUSE); 874 if (error) 875 return (error); 876 877 usage = *dqb; 878 879 ump = VFSTOUFS(mp); 880 ndq = NODQUOT; 881 882 error = dqget(NULLVP, id, ump, type, &ndq); 883 if (error) 884 return (error); 885 dq = ndq; 886 DQI_LOCK(dq); 887 DQI_WAIT(dq, PINOD+1, "setuse"); 888 /* 889 * Reset time limit if have a soft limit and were 890 * previously under it, but are now over it. 891 */ 892 if (dq->dq_bsoftlimit && dq->dq_curblocks < dq->dq_bsoftlimit && 893 usage.dqb_curblocks >= dq->dq_bsoftlimit) 894 dq->dq_btime = time_second + ump->um_btime[type]; 895 if (dq->dq_isoftlimit && dq->dq_curinodes < dq->dq_isoftlimit && 896 usage.dqb_curinodes >= dq->dq_isoftlimit) 897 dq->dq_itime = time_second + ump->um_itime[type]; 898 dq->dq_curblocks = usage.dqb_curblocks; 899 dq->dq_curinodes = usage.dqb_curinodes; 900 if (dq->dq_curblocks < dq->dq_bsoftlimit) 901 dq->dq_flags &= ~DQ_BLKS; 902 if (dq->dq_curinodes < dq->dq_isoftlimit) 903 dq->dq_flags &= ~DQ_INODS; 904 dq->dq_flags |= DQ_MOD; 905 DQI_UNLOCK(dq); 906 dqrele(NULLVP, dq); 907 return (0); 908 } 909 910 int 911 getquota32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 912 { 913 struct dqblk32 dqb32; 914 struct dqblk64 dqb64; 915 int error; 916 917 error = _getquota(td, mp, id, type, &dqb64); 918 if (error) 919 return (error); 920 dqb64_dqb32(&dqb64, &dqb32); 921 error = copyout(&dqb32, addr, sizeof(dqb32)); 922 return (error); 923 } 924 925 int 926 setquota32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 927 { 928 struct dqblk32 dqb32; 929 struct dqblk64 dqb64; 930 int error; 931 932 error = copyin(addr, &dqb32, sizeof(dqb32)); 933 if (error) 934 return (error); 935 dqb32_dqb64(&dqb32, &dqb64); 936 error = _setquota(td, mp, id, type, &dqb64); 937 return (error); 938 } 939 940 int 941 setuse32(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 942 { 943 struct dqblk32 dqb32; 944 struct dqblk64 dqb64; 945 int error; 946 947 error = copyin(addr, &dqb32, sizeof(dqb32)); 948 if (error) 949 return (error); 950 dqb32_dqb64(&dqb32, &dqb64); 951 error = _setuse(td, mp, id, type, &dqb64); 952 return (error); 953 } 954 955 int 956 getquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 957 { 958 struct dqblk64 dqb64; 959 int error; 960 961 error = _getquota(td, mp, id, type, &dqb64); 962 if (error) 963 return (error); 964 error = copyout(&dqb64, addr, sizeof(dqb64)); 965 return (error); 966 } 967 968 int 969 setquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 970 { 971 struct dqblk64 dqb64; 972 int error; 973 974 error = copyin(addr, &dqb64, sizeof(dqb64)); 975 if (error) 976 return (error); 977 error = _setquota(td, mp, id, type, &dqb64); 978 return (error); 979 } 980 981 int 982 setuse(struct thread *td, struct mount *mp, u_long id, int type, void *addr) 983 { 984 struct dqblk64 dqb64; 985 int error; 986 987 error = copyin(addr, &dqb64, sizeof(dqb64)); 988 if (error) 989 return (error); 990 error = _setuse(td, mp, id, type, &dqb64); 991 return (error); 992 } 993 994 /* 995 * Q_GETQUOTASIZE - get bit-size of quota file fields 996 */ 997 int 998 getquotasize(struct thread *td, struct mount *mp, u_long id, int type, 999 void *sizep) 1000 { 1001 struct ufsmount *ump = VFSTOUFS(mp); 1002 int bitsize; 1003 1004 UFS_LOCK(ump); 1005 if (ump->um_quotas[type] == NULLVP || 1006 (ump->um_qflags[type] & QTF_CLOSING)) { 1007 UFS_UNLOCK(ump); 1008 return (EINVAL); 1009 } 1010 if ((ump->um_qflags[type] & QTF_64BIT) != 0) 1011 bitsize = 64; 1012 else 1013 bitsize = 32; 1014 UFS_UNLOCK(ump); 1015 return (copyout(&bitsize, sizep, sizeof(int))); 1016 } 1017 1018 /* 1019 * Q_SYNC - sync quota files to disk. 1020 */ 1021 int 1022 qsync(struct mount *mp) 1023 { 1024 struct ufsmount *ump = VFSTOUFS(mp); 1025 struct thread *td = curthread; /* XXX */ 1026 struct vnode *vp, *mvp; 1027 struct dquot *dq; 1028 int i, error; 1029 1030 /* 1031 * Check if the mount point has any quotas. 1032 * If not, simply return. 1033 */ 1034 UFS_LOCK(ump); 1035 for (i = 0; i < MAXQUOTAS; i++) 1036 if (ump->um_quotas[i] != NULLVP) 1037 break; 1038 UFS_UNLOCK(ump); 1039 if (i == MAXQUOTAS) 1040 return (0); 1041 /* 1042 * Search vnodes associated with this mount point, 1043 * synchronizing any modified dquot structures. 1044 */ 1045 MNT_ILOCK(mp); 1046 again: 1047 MNT_VNODE_FOREACH(vp, mp, mvp) { 1048 VI_LOCK(vp); 1049 MNT_IUNLOCK(mp); 1050 if (vp->v_type == VNON) { 1051 VI_UNLOCK(vp); 1052 MNT_ILOCK(mp); 1053 continue; 1054 } 1055 error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td); 1056 if (error) { 1057 MNT_ILOCK(mp); 1058 if (error == ENOENT) { 1059 MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); 1060 goto again; 1061 } 1062 continue; 1063 } 1064 for (i = 0; i < MAXQUOTAS; i++) { 1065 dq = VTOI(vp)->i_dquot[i]; 1066 if (dq != NODQUOT) 1067 dqsync(vp, dq); 1068 } 1069 vput(vp); 1070 MNT_ILOCK(mp); 1071 } 1072 MNT_IUNLOCK(mp); 1073 return (0); 1074 } 1075 1076 /* 1077 * Code pertaining to management of the in-core dquot data structures. 1078 */ 1079 #define DQHASH(dqvp, id) \ 1080 (&dqhashtbl[((((intptr_t)(dqvp)) >> 8) + id) & dqhash]) 1081 static LIST_HEAD(dqhash, dquot) *dqhashtbl; 1082 static u_long dqhash; 1083 1084 /* 1085 * Dquot free list. 1086 */ 1087 #define DQUOTINC 5 /* minimum free dquots desired */ 1088 static TAILQ_HEAD(dqfreelist, dquot) dqfreelist; 1089 static long numdquot, desireddquot = DQUOTINC; 1090 1091 /* 1092 * Lock to protect quota hash, dq free list and dq_cnt ref counters of 1093 * _all_ dqs. 1094 */ 1095 struct mtx dqhlock; 1096 1097 #define DQH_LOCK() mtx_lock(&dqhlock) 1098 #define DQH_UNLOCK() mtx_unlock(&dqhlock) 1099 1100 static struct dquot *dqhashfind(struct dqhash *dqh, u_long id, 1101 struct vnode *dqvp); 1102 1103 /* 1104 * Initialize the quota system. 1105 */ 1106 void 1107 dqinit(void) 1108 { 1109 1110 mtx_init(&dqhlock, "dqhlock", NULL, MTX_DEF); 1111 dqhashtbl = hashinit(desiredvnodes, M_DQUOT, &dqhash); 1112 TAILQ_INIT(&dqfreelist); 1113 } 1114 1115 /* 1116 * Shut down the quota system. 1117 */ 1118 void 1119 dquninit(void) 1120 { 1121 struct dquot *dq; 1122 1123 hashdestroy(dqhashtbl, M_DQUOT, dqhash); 1124 while ((dq = TAILQ_FIRST(&dqfreelist)) != NULL) { 1125 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); 1126 mtx_destroy(&dq->dq_lock); 1127 free(dq, M_DQUOT); 1128 } 1129 mtx_destroy(&dqhlock); 1130 } 1131 1132 static struct dquot * 1133 dqhashfind(struct dqhash *dqh, u_long id, struct vnode *dqvp) 1134 { 1135 struct dquot *dq; 1136 1137 mtx_assert(&dqhlock, MA_OWNED); 1138 LIST_FOREACH(dq, dqh, dq_hash) { 1139 if (dq->dq_id != id || 1140 dq->dq_ump->um_quotas[dq->dq_type] != dqvp) 1141 continue; 1142 /* 1143 * Cache hit with no references. Take 1144 * the structure off the free list. 1145 */ 1146 if (dq->dq_cnt == 0) 1147 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); 1148 DQREF(dq); 1149 return (dq); 1150 } 1151 return (NODQUOT); 1152 } 1153 1154 /* 1155 * Determine the quota file type. 1156 * 1157 * A 32-bit quota file is simply an array of struct dqblk32. 1158 * 1159 * A 64-bit quota file is a struct dqhdr64 followed by an array of struct 1160 * dqblk64. The header contains various magic bits which allow us to be 1161 * reasonably confident that it is indeeda 64-bit quota file and not just 1162 * a 32-bit quota file that just happens to "look right". 1163 * 1164 */ 1165 static int 1166 dqopen(struct vnode *vp, struct ufsmount *ump, int type) 1167 { 1168 struct dqhdr64 dqh; 1169 struct iovec aiov; 1170 struct uio auio; 1171 int error; 1172 1173 ASSERT_VOP_LOCKED(vp, "dqopen"); 1174 auio.uio_iov = &aiov; 1175 auio.uio_iovcnt = 1; 1176 aiov.iov_base = &dqh; 1177 aiov.iov_len = sizeof(dqh); 1178 auio.uio_resid = sizeof(dqh); 1179 auio.uio_offset = 0; 1180 auio.uio_segflg = UIO_SYSSPACE; 1181 auio.uio_rw = UIO_READ; 1182 auio.uio_td = (struct thread *)0; 1183 error = VOP_READ(vp, &auio, 0, ump->um_cred[type]); 1184 1185 if (error != 0) 1186 return (error); 1187 if (auio.uio_resid > 0) { 1188 /* assume 32 bits */ 1189 return (0); 1190 } 1191 1192 UFS_LOCK(ump); 1193 if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) == 0 && 1194 be32toh(dqh.dqh_version) == Q_DQHDR64_VERSION && 1195 be32toh(dqh.dqh_hdrlen) == (uint32_t)sizeof(struct dqhdr64) && 1196 be32toh(dqh.dqh_reclen) == (uint32_t)sizeof(struct dqblk64)) { 1197 /* XXX: what if the magic matches, but the sizes are wrong? */ 1198 ump->um_qflags[type] |= QTF_64BIT; 1199 } else { 1200 ump->um_qflags[type] &= ~QTF_64BIT; 1201 } 1202 UFS_UNLOCK(ump); 1203 1204 return (0); 1205 } 1206 1207 /* 1208 * Obtain a dquot structure for the specified identifier and quota file 1209 * reading the information from the file if necessary. 1210 */ 1211 static int 1212 dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, 1213 struct dquot **dqp) 1214 { 1215 uint8_t buf[sizeof(struct dqblk64)]; 1216 off_t base, recsize; 1217 struct dquot *dq, *dq1; 1218 struct dqhash *dqh; 1219 struct vnode *dqvp; 1220 struct iovec aiov; 1221 struct uio auio; 1222 int vfslocked, dqvplocked, error; 1223 1224 #ifdef DEBUG_VFS_LOCKS 1225 if (vp != NULLVP) 1226 ASSERT_VOP_ELOCKED(vp, "dqget"); 1227 #endif 1228 1229 if (vp != NULLVP && *dqp != NODQUOT) { 1230 return (0); 1231 } 1232 1233 /* XXX: Disallow negative id values to prevent the 1234 * creation of 100GB+ quota data files. 1235 */ 1236 if ((int)id < 0) 1237 return (EINVAL); 1238 1239 UFS_LOCK(ump); 1240 dqvp = ump->um_quotas[type]; 1241 if (dqvp == NULLVP || (ump->um_qflags[type] & QTF_CLOSING)) { 1242 *dqp = NODQUOT; 1243 UFS_UNLOCK(ump); 1244 return (EINVAL); 1245 } 1246 vref(dqvp); 1247 UFS_UNLOCK(ump); 1248 error = 0; 1249 dqvplocked = 0; 1250 1251 /* 1252 * Check the cache first. 1253 */ 1254 dqh = DQHASH(dqvp, id); 1255 DQH_LOCK(); 1256 dq = dqhashfind(dqh, id, dqvp); 1257 if (dq != NULL) { 1258 DQH_UNLOCK(); 1259 hfound: DQI_LOCK(dq); 1260 DQI_WAIT(dq, PINOD+1, "dqget"); 1261 DQI_UNLOCK(dq); 1262 if (dq->dq_ump == NULL) { 1263 dqrele(vp, dq); 1264 dq = NODQUOT; 1265 error = EIO; 1266 } 1267 *dqp = dq; 1268 vfslocked = VFS_LOCK_GIANT(dqvp->v_mount); 1269 if (dqvplocked) 1270 vput(dqvp); 1271 else 1272 vrele(dqvp); 1273 VFS_UNLOCK_GIANT(vfslocked); 1274 return (error); 1275 } 1276 1277 /* 1278 * Quota vnode lock is before DQ_LOCK. Acquire dqvp lock there 1279 * since new dq will appear on the hash chain DQ_LOCKed. 1280 */ 1281 if (vp != dqvp) { 1282 DQH_UNLOCK(); 1283 vn_lock(dqvp, LK_SHARED | LK_RETRY); 1284 dqvplocked = 1; 1285 DQH_LOCK(); 1286 /* 1287 * Recheck the cache after sleep for quota vnode lock. 1288 */ 1289 dq = dqhashfind(dqh, id, dqvp); 1290 if (dq != NULL) { 1291 DQH_UNLOCK(); 1292 goto hfound; 1293 } 1294 } 1295 1296 /* 1297 * Not in cache, allocate a new one or take it from the 1298 * free list. 1299 */ 1300 if (TAILQ_FIRST(&dqfreelist) == NODQUOT && 1301 numdquot < MAXQUOTAS * desiredvnodes) 1302 desireddquot += DQUOTINC; 1303 if (numdquot < desireddquot) { 1304 numdquot++; 1305 DQH_UNLOCK(); 1306 dq1 = malloc(sizeof *dq1, M_DQUOT, M_WAITOK | M_ZERO); 1307 mtx_init(&dq1->dq_lock, "dqlock", NULL, MTX_DEF); 1308 DQH_LOCK(); 1309 /* 1310 * Recheck the cache after sleep for memory. 1311 */ 1312 dq = dqhashfind(dqh, id, dqvp); 1313 if (dq != NULL) { 1314 numdquot--; 1315 DQH_UNLOCK(); 1316 mtx_destroy(&dq1->dq_lock); 1317 free(dq1, M_DQUOT); 1318 goto hfound; 1319 } 1320 dq = dq1; 1321 } else { 1322 if ((dq = TAILQ_FIRST(&dqfreelist)) == NULL) { 1323 DQH_UNLOCK(); 1324 tablefull("dquot"); 1325 *dqp = NODQUOT; 1326 vfslocked = VFS_LOCK_GIANT(dqvp->v_mount); 1327 if (dqvplocked) 1328 vput(dqvp); 1329 else 1330 vrele(dqvp); 1331 VFS_UNLOCK_GIANT(vfslocked); 1332 return (EUSERS); 1333 } 1334 if (dq->dq_cnt || (dq->dq_flags & DQ_MOD)) 1335 panic("dqget: free dquot isn't %p", dq); 1336 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); 1337 if (dq->dq_ump != NULL) 1338 LIST_REMOVE(dq, dq_hash); 1339 } 1340 1341 /* 1342 * Dq is put into hash already locked to prevent parallel 1343 * usage while it is being read from file. 1344 */ 1345 dq->dq_flags = DQ_LOCK; 1346 dq->dq_id = id; 1347 dq->dq_type = type; 1348 dq->dq_ump = ump; 1349 LIST_INSERT_HEAD(dqh, dq, dq_hash); 1350 DQREF(dq); 1351 DQH_UNLOCK(); 1352 1353 /* 1354 * Read the requested quota record from the quota file, performing 1355 * any necessary conversions. 1356 */ 1357 if (ump->um_qflags[type] & QTF_64BIT) { 1358 recsize = sizeof(struct dqblk64); 1359 base = sizeof(struct dqhdr64); 1360 } else { 1361 recsize = sizeof(struct dqblk32); 1362 base = 0; 1363 } 1364 auio.uio_iov = &aiov; 1365 auio.uio_iovcnt = 1; 1366 aiov.iov_base = buf; 1367 aiov.iov_len = recsize; 1368 auio.uio_resid = recsize; 1369 auio.uio_offset = base + id * recsize; 1370 auio.uio_segflg = UIO_SYSSPACE; 1371 auio.uio_rw = UIO_READ; 1372 auio.uio_td = (struct thread *)0; 1373 1374 vfslocked = VFS_LOCK_GIANT(dqvp->v_mount); 1375 error = VOP_READ(dqvp, &auio, 0, ump->um_cred[type]); 1376 if (auio.uio_resid == recsize && error == 0) { 1377 bzero(&dq->dq_dqb, sizeof(dq->dq_dqb)); 1378 } else { 1379 if (ump->um_qflags[type] & QTF_64BIT) 1380 dqb64_dq((struct dqblk64 *)buf, dq); 1381 else 1382 dqb32_dq((struct dqblk32 *)buf, dq); 1383 } 1384 if (dqvplocked) 1385 vput(dqvp); 1386 else 1387 vrele(dqvp); 1388 VFS_UNLOCK_GIANT(vfslocked); 1389 /* 1390 * I/O error in reading quota file, release 1391 * quota structure and reflect problem to caller. 1392 */ 1393 if (error) { 1394 DQH_LOCK(); 1395 dq->dq_ump = NULL; 1396 LIST_REMOVE(dq, dq_hash); 1397 DQH_UNLOCK(); 1398 DQI_LOCK(dq); 1399 if (dq->dq_flags & DQ_WANT) 1400 wakeup(dq); 1401 dq->dq_flags = 0; 1402 DQI_UNLOCK(dq); 1403 dqrele(vp, dq); 1404 *dqp = NODQUOT; 1405 return (error); 1406 } 1407 DQI_LOCK(dq); 1408 /* 1409 * Check for no limit to enforce. 1410 * Initialize time values if necessary. 1411 */ 1412 if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 && 1413 dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0) 1414 dq->dq_flags |= DQ_FAKE; 1415 if (dq->dq_id != 0) { 1416 if (dq->dq_btime == 0) { 1417 dq->dq_btime = time_second + ump->um_btime[type]; 1418 if (dq->dq_bsoftlimit && 1419 dq->dq_curblocks >= dq->dq_bsoftlimit) 1420 dq->dq_flags |= DQ_MOD; 1421 } 1422 if (dq->dq_itime == 0) { 1423 dq->dq_itime = time_second + ump->um_itime[type]; 1424 if (dq->dq_isoftlimit && 1425 dq->dq_curinodes >= dq->dq_isoftlimit) 1426 dq->dq_flags |= DQ_MOD; 1427 } 1428 } 1429 DQI_WAKEUP(dq); 1430 DQI_UNLOCK(dq); 1431 *dqp = dq; 1432 return (0); 1433 } 1434 1435 #ifdef DIAGNOSTIC 1436 /* 1437 * Obtain a reference to a dquot. 1438 */ 1439 static void 1440 dqref(struct dquot *dq) 1441 { 1442 1443 dq->dq_cnt++; 1444 } 1445 #endif 1446 1447 /* 1448 * Release a reference to a dquot. 1449 */ 1450 void 1451 dqrele(struct vnode *vp, struct dquot *dq) 1452 { 1453 1454 if (dq == NODQUOT) 1455 return; 1456 DQH_LOCK(); 1457 if (dq->dq_cnt > 1) { 1458 dq->dq_cnt--; 1459 DQH_UNLOCK(); 1460 return; 1461 } 1462 DQH_UNLOCK(); 1463 sync: 1464 (void) dqsync(vp, dq); 1465 1466 DQH_LOCK(); 1467 if (--dq->dq_cnt > 0) 1468 { 1469 DQH_UNLOCK(); 1470 return; 1471 } 1472 1473 /* 1474 * The dq may become dirty after it is synced but before it is 1475 * put to the free list. Checking the DQ_MOD there without 1476 * locking dq should be safe since no other references to the 1477 * dq exist. 1478 */ 1479 if ((dq->dq_flags & DQ_MOD) != 0) { 1480 dq->dq_cnt++; 1481 DQH_UNLOCK(); 1482 goto sync; 1483 } 1484 TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist); 1485 DQH_UNLOCK(); 1486 } 1487 1488 /* 1489 * Update the disk quota in the quota file. 1490 */ 1491 static int 1492 dqsync(struct vnode *vp, struct dquot *dq) 1493 { 1494 uint8_t buf[sizeof(struct dqblk64)]; 1495 off_t base, recsize; 1496 struct vnode *dqvp; 1497 struct iovec aiov; 1498 struct uio auio; 1499 int vfslocked, error; 1500 struct mount *mp; 1501 struct ufsmount *ump; 1502 1503 #ifdef DEBUG_VFS_LOCKS 1504 if (vp != NULL) 1505 ASSERT_VOP_ELOCKED(vp, "dqsync"); 1506 #endif 1507 1508 mp = NULL; 1509 error = 0; 1510 if (dq == NODQUOT) 1511 panic("dqsync: dquot"); 1512 if ((ump = dq->dq_ump) == NULL) 1513 return (0); 1514 UFS_LOCK(ump); 1515 if ((dqvp = ump->um_quotas[dq->dq_type]) == NULLVP) 1516 panic("dqsync: file"); 1517 vref(dqvp); 1518 UFS_UNLOCK(ump); 1519 1520 vfslocked = VFS_LOCK_GIANT(dqvp->v_mount); 1521 DQI_LOCK(dq); 1522 if ((dq->dq_flags & DQ_MOD) == 0) { 1523 DQI_UNLOCK(dq); 1524 vrele(dqvp); 1525 VFS_UNLOCK_GIANT(vfslocked); 1526 return (0); 1527 } 1528 DQI_UNLOCK(dq); 1529 1530 (void) vn_start_secondary_write(dqvp, &mp, V_WAIT); 1531 if (vp != dqvp) 1532 vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY); 1533 1534 VFS_UNLOCK_GIANT(vfslocked); 1535 DQI_LOCK(dq); 1536 DQI_WAIT(dq, PINOD+2, "dqsync"); 1537 if ((dq->dq_flags & DQ_MOD) == 0) 1538 goto out; 1539 dq->dq_flags |= DQ_LOCK; 1540 DQI_UNLOCK(dq); 1541 1542 /* 1543 * Write the quota record to the quota file, performing any 1544 * necessary conversions. See dqget() for additional details. 1545 */ 1546 if (ump->um_qflags[dq->dq_type] & QTF_64BIT) { 1547 dq_dqb64(dq, (struct dqblk64 *)buf); 1548 recsize = sizeof(struct dqblk64); 1549 base = sizeof(struct dqhdr64); 1550 } else { 1551 dq_dqb32(dq, (struct dqblk32 *)buf); 1552 recsize = sizeof(struct dqblk32); 1553 base = 0; 1554 } 1555 1556 auio.uio_iov = &aiov; 1557 auio.uio_iovcnt = 1; 1558 aiov.iov_base = buf; 1559 aiov.iov_len = recsize; 1560 auio.uio_resid = recsize; 1561 auio.uio_offset = base + dq->dq_id * recsize; 1562 auio.uio_segflg = UIO_SYSSPACE; 1563 auio.uio_rw = UIO_WRITE; 1564 auio.uio_td = (struct thread *)0; 1565 vfslocked = VFS_LOCK_GIANT(dqvp->v_mount); 1566 error = VOP_WRITE(dqvp, &auio, 0, dq->dq_ump->um_cred[dq->dq_type]); 1567 VFS_UNLOCK_GIANT(vfslocked); 1568 if (auio.uio_resid && error == 0) 1569 error = EIO; 1570 1571 DQI_LOCK(dq); 1572 DQI_WAKEUP(dq); 1573 dq->dq_flags &= ~DQ_MOD; 1574 out: 1575 DQI_UNLOCK(dq); 1576 vfslocked = VFS_LOCK_GIANT(dqvp->v_mount); 1577 if (vp != dqvp) 1578 vput(dqvp); 1579 else 1580 vrele(dqvp); 1581 vn_finished_secondary_write(mp); 1582 VFS_UNLOCK_GIANT(vfslocked); 1583 return (error); 1584 } 1585 1586 /* 1587 * Flush all entries from the cache for a particular vnode. 1588 */ 1589 static void 1590 dqflush(struct vnode *vp) 1591 { 1592 struct dquot *dq, *nextdq; 1593 struct dqhash *dqh; 1594 1595 /* 1596 * Move all dquot's that used to refer to this quota 1597 * file off their hash chains (they will eventually 1598 * fall off the head of the free list and be re-used). 1599 */ 1600 DQH_LOCK(); 1601 for (dqh = &dqhashtbl[dqhash]; dqh >= dqhashtbl; dqh--) { 1602 for (dq = LIST_FIRST(dqh); dq; dq = nextdq) { 1603 nextdq = LIST_NEXT(dq, dq_hash); 1604 if (dq->dq_ump->um_quotas[dq->dq_type] != vp) 1605 continue; 1606 if (dq->dq_cnt) 1607 panic("dqflush: stray dquot"); 1608 LIST_REMOVE(dq, dq_hash); 1609 dq->dq_ump = (struct ufsmount *)0; 1610 } 1611 } 1612 DQH_UNLOCK(); 1613 } 1614 1615 /* 1616 * 32-bit / 64-bit conversion functions. 1617 * 1618 * 32-bit quota records are stored in native byte order. Attention must 1619 * be paid to overflow issues. 1620 * 1621 * 64-bit quota records are stored in network byte order. 1622 */ 1623 1624 #define CLIP32(u64) (u64 > UINT32_MAX ? UINT32_MAX : (uint32_t)u64) 1625 1626 /* 1627 * Convert 32-bit host-order structure to dquot. 1628 */ 1629 static void 1630 dqb32_dq(const struct dqblk32 *dqb32, struct dquot *dq) 1631 { 1632 1633 dq->dq_bhardlimit = dqb32->dqb_bhardlimit; 1634 dq->dq_bsoftlimit = dqb32->dqb_bsoftlimit; 1635 dq->dq_curblocks = dqb32->dqb_curblocks; 1636 dq->dq_ihardlimit = dqb32->dqb_ihardlimit; 1637 dq->dq_isoftlimit = dqb32->dqb_isoftlimit; 1638 dq->dq_curinodes = dqb32->dqb_curinodes; 1639 dq->dq_btime = dqb32->dqb_btime; 1640 dq->dq_itime = dqb32->dqb_itime; 1641 } 1642 1643 /* 1644 * Convert 64-bit network-order structure to dquot. 1645 */ 1646 static void 1647 dqb64_dq(const struct dqblk64 *dqb64, struct dquot *dq) 1648 { 1649 1650 dq->dq_bhardlimit = be64toh(dqb64->dqb_bhardlimit); 1651 dq->dq_bsoftlimit = be64toh(dqb64->dqb_bsoftlimit); 1652 dq->dq_curblocks = be64toh(dqb64->dqb_curblocks); 1653 dq->dq_ihardlimit = be64toh(dqb64->dqb_ihardlimit); 1654 dq->dq_isoftlimit = be64toh(dqb64->dqb_isoftlimit); 1655 dq->dq_curinodes = be64toh(dqb64->dqb_curinodes); 1656 dq->dq_btime = be64toh(dqb64->dqb_btime); 1657 dq->dq_itime = be64toh(dqb64->dqb_itime); 1658 } 1659 1660 /* 1661 * Convert dquot to 32-bit host-order structure. 1662 */ 1663 static void 1664 dq_dqb32(const struct dquot *dq, struct dqblk32 *dqb32) 1665 { 1666 1667 dqb32->dqb_bhardlimit = CLIP32(dq->dq_bhardlimit); 1668 dqb32->dqb_bsoftlimit = CLIP32(dq->dq_bsoftlimit); 1669 dqb32->dqb_curblocks = CLIP32(dq->dq_curblocks); 1670 dqb32->dqb_ihardlimit = CLIP32(dq->dq_ihardlimit); 1671 dqb32->dqb_isoftlimit = CLIP32(dq->dq_isoftlimit); 1672 dqb32->dqb_curinodes = CLIP32(dq->dq_curinodes); 1673 dqb32->dqb_btime = CLIP32(dq->dq_btime); 1674 dqb32->dqb_itime = CLIP32(dq->dq_itime); 1675 } 1676 1677 /* 1678 * Convert dquot to 64-bit network-order structure. 1679 */ 1680 static void 1681 dq_dqb64(const struct dquot *dq, struct dqblk64 *dqb64) 1682 { 1683 1684 dqb64->dqb_bhardlimit = htobe64(dq->dq_bhardlimit); 1685 dqb64->dqb_bsoftlimit = htobe64(dq->dq_bsoftlimit); 1686 dqb64->dqb_curblocks = htobe64(dq->dq_curblocks); 1687 dqb64->dqb_ihardlimit = htobe64(dq->dq_ihardlimit); 1688 dqb64->dqb_isoftlimit = htobe64(dq->dq_isoftlimit); 1689 dqb64->dqb_curinodes = htobe64(dq->dq_curinodes); 1690 dqb64->dqb_btime = htobe64(dq->dq_btime); 1691 dqb64->dqb_itime = htobe64(dq->dq_itime); 1692 } 1693 1694 /* 1695 * Convert 64-bit host-order structure to 32-bit host-order structure. 1696 */ 1697 static void 1698 dqb64_dqb32(const struct dqblk64 *dqb64, struct dqblk32 *dqb32) 1699 { 1700 1701 dqb32->dqb_bhardlimit = CLIP32(dqb64->dqb_bhardlimit); 1702 dqb32->dqb_bsoftlimit = CLIP32(dqb64->dqb_bsoftlimit); 1703 dqb32->dqb_curblocks = CLIP32(dqb64->dqb_curblocks); 1704 dqb32->dqb_ihardlimit = CLIP32(dqb64->dqb_ihardlimit); 1705 dqb32->dqb_isoftlimit = CLIP32(dqb64->dqb_isoftlimit); 1706 dqb32->dqb_curinodes = CLIP32(dqb64->dqb_curinodes); 1707 dqb32->dqb_btime = CLIP32(dqb64->dqb_btime); 1708 dqb32->dqb_itime = CLIP32(dqb64->dqb_itime); 1709 } 1710 1711 /* 1712 * Convert 32-bit host-order structure to 64-bit host-order structure. 1713 */ 1714 static void 1715 dqb32_dqb64(const struct dqblk32 *dqb32, struct dqblk64 *dqb64) 1716 { 1717 1718 dqb64->dqb_bhardlimit = dqb32->dqb_bhardlimit; 1719 dqb64->dqb_bsoftlimit = dqb32->dqb_bsoftlimit; 1720 dqb64->dqb_curblocks = dqb32->dqb_curblocks; 1721 dqb64->dqb_ihardlimit = dqb32->dqb_ihardlimit; 1722 dqb64->dqb_isoftlimit = dqb32->dqb_isoftlimit; 1723 dqb64->dqb_curinodes = dqb32->dqb_curinodes; 1724 dqb64->dqb_btime = dqb32->dqb_btime; 1725 dqb64->dqb_itime = dqb32->dqb_itime; 1726 } 1727