1 /* $NetBSD: ufs_quota2.c,v 1.40 2015/03/28 19:24:05 maxv Exp $ */ 2 /*- 3 * Copyright (c) 2010 Manuel Bouyer 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.40 2015/03/28 19:24:05 maxv Exp $"); 30 31 #include <sys/buf.h> 32 #include <sys/param.h> 33 #include <sys/kernel.h> 34 #include <sys/systm.h> 35 #include <sys/namei.h> 36 #include <sys/file.h> 37 #include <sys/proc.h> 38 #include <sys/vnode.h> 39 #include <sys/mount.h> 40 #include <sys/fstrans.h> 41 #include <sys/kauth.h> 42 #include <sys/wapbl.h> 43 #include <sys/quota.h> 44 #include <sys/quotactl.h> 45 #include <sys/timevar.h> 46 47 #include <ufs/ufs/quota2.h> 48 #include <ufs/ufs/inode.h> 49 #include <ufs/ufs/ufsmount.h> 50 #include <ufs/ufs/ufs_bswap.h> 51 #include <ufs/ufs/ufs_extern.h> 52 #include <ufs/ufs/ufs_quota.h> 53 #include <ufs/ufs/ufs_wapbl.h> 54 55 /* 56 * LOCKING: 57 * Data in the entries are protected by the associated struct dquot's 58 * dq_interlock (this means we can't read or change a quota entry without 59 * grabing a dquot for it). 60 * The header and lists (including pointers in the data entries, and q2e_uid) 61 * are protected by the global dqlock. 62 * the locking order is dq_interlock -> dqlock 63 */ 64 65 static int quota2_bwrite(struct mount *, struct buf *); 66 static int getinoquota2(struct inode *, bool, bool, struct buf **, 67 struct quota2_entry **); 68 static int getq2h(struct ufsmount *, int, struct buf **, 69 struct quota2_header **, int); 70 static int getq2e(struct ufsmount *, int, daddr_t, int, struct buf **, 71 struct quota2_entry **, int); 72 static int quota2_walk_list(struct ufsmount *, struct buf *, int, 73 uint64_t *, int, void *, 74 int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, 75 uint64_t, void *)); 76 77 static const char *limnames[] = INITQLNAMES; 78 79 static void 80 quota2_dict_update_q2e_limits(int objtype, const struct quotaval *val, 81 struct quota2_entry *q2e) 82 { 83 /* make sure we can index q2e_val[] by the fs-independent objtype */ 84 CTASSERT(QUOTA_OBJTYPE_BLOCKS == QL_BLOCK); 85 CTASSERT(QUOTA_OBJTYPE_FILES == QL_FILE); 86 87 q2e->q2e_val[objtype].q2v_hardlimit = val->qv_hardlimit; 88 q2e->q2e_val[objtype].q2v_softlimit = val->qv_softlimit; 89 q2e->q2e_val[objtype].q2v_grace = val->qv_grace; 90 } 91 92 /* 93 * Convert internal representation to FS-independent representation. 94 * (Note that while the two types are currently identical, the 95 * internal representation is an on-disk struct and the FS-independent 96 * representation is not, and they might diverge in the future.) 97 */ 98 static void 99 q2val_to_quotaval(struct quota2_val *q2v, struct quotaval *qv) 100 { 101 qv->qv_softlimit = q2v->q2v_softlimit; 102 qv->qv_hardlimit = q2v->q2v_hardlimit; 103 qv->qv_usage = q2v->q2v_cur; 104 qv->qv_expiretime = q2v->q2v_time; 105 qv->qv_grace = q2v->q2v_grace; 106 } 107 108 /* 109 * Convert a quota2entry and default-flag to the FS-independent 110 * representation. 111 */ 112 static void 113 q2e_to_quotaval(struct quota2_entry *q2e, int def, 114 id_t *id, int objtype, struct quotaval *ret) 115 { 116 if (def) { 117 *id = QUOTA_DEFAULTID; 118 } else { 119 *id = q2e->q2e_uid; 120 } 121 122 KASSERT(objtype >= 0 && objtype < N_QL); 123 q2val_to_quotaval(&q2e->q2e_val[objtype], ret); 124 } 125 126 127 static int 128 quota2_bwrite(struct mount *mp, struct buf *bp) 129 { 130 if (mp->mnt_flag & MNT_SYNCHRONOUS) 131 return bwrite(bp); 132 else { 133 bdwrite(bp); 134 return 0; 135 } 136 } 137 138 static int 139 getq2h(struct ufsmount *ump, int type, 140 struct buf **bpp, struct quota2_header **q2hp, int flags) 141 { 142 const int needswap = UFS_MPNEEDSWAP(ump); 143 int error; 144 struct buf *bp; 145 struct quota2_header *q2h; 146 147 KASSERT(mutex_owned(&dqlock)); 148 error = bread(ump->um_quotas[type], 0, ump->umq2_bsize, 149 flags, &bp); 150 if (error) 151 return error; 152 if (bp->b_resid != 0) 153 panic("dq2get: %s quota file truncated", quotatypes[type]); 154 155 q2h = (void *)bp->b_data; 156 if (ufs_rw32(q2h->q2h_magic_number, needswap) != Q2_HEAD_MAGIC || 157 q2h->q2h_type != type) 158 panic("dq2get: corrupted %s quota header", quotatypes[type]); 159 *bpp = bp; 160 *q2hp = q2h; 161 return 0; 162 } 163 164 static int 165 getq2e(struct ufsmount *ump, int type, daddr_t lblkno, int blkoffset, 166 struct buf **bpp, struct quota2_entry **q2ep, int flags) 167 { 168 int error; 169 struct buf *bp; 170 171 if (blkoffset & (sizeof(uint64_t) - 1)) { 172 panic("dq2get: %s quota file corrupted", 173 quotatypes[type]); 174 } 175 error = bread(ump->um_quotas[type], lblkno, ump->umq2_bsize, 176 flags, &bp); 177 if (error) 178 return error; 179 if (bp->b_resid != 0) { 180 panic("dq2get: %s quota file corrupted", 181 quotatypes[type]); 182 } 183 *q2ep = (void *)((char *)bp->b_data + blkoffset); 184 *bpp = bp; 185 return 0; 186 } 187 188 /* walk a quota entry list, calling the callback for each entry */ 189 #define Q2WL_ABORT 0x10000000 190 191 static int 192 quota2_walk_list(struct ufsmount *ump, struct buf *hbp, int type, 193 uint64_t *offp, int flags, void *a, 194 int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, uint64_t, void *)) 195 { 196 const int needswap = UFS_MPNEEDSWAP(ump); 197 daddr_t off = ufs_rw64(*offp, needswap); 198 struct buf *bp, *obp = hbp; 199 int ret = 0, ret2 = 0; 200 struct quota2_entry *q2e; 201 daddr_t lblkno, blkoff, olblkno = 0; 202 203 KASSERT(mutex_owner(&dqlock)); 204 205 while (off != 0) { 206 lblkno = (off >> ump->um_mountp->mnt_fs_bshift); 207 blkoff = (off & ump->umq2_bmask); 208 if (lblkno == 0) { 209 /* in the header block */ 210 bp = hbp; 211 } else if (lblkno == olblkno) { 212 /* still in the same buf */ 213 bp = obp; 214 } else { 215 ret = bread(ump->um_quotas[type], lblkno, 216 ump->umq2_bsize, flags, &bp); 217 if (ret) 218 return ret; 219 if (bp->b_resid != 0) { 220 panic("quota2_walk_list: %s quota file corrupted", 221 quotatypes[type]); 222 } 223 } 224 q2e = (void *)((char *)(bp->b_data) + blkoff); 225 ret = (*func)(ump, offp, q2e, off, a); 226 if (off != ufs_rw64(*offp, needswap)) { 227 /* callback changed parent's pointer, redo */ 228 off = ufs_rw64(*offp, needswap); 229 if (bp != hbp && bp != obp) 230 ret2 = bwrite(bp); 231 } else { 232 /* parent if now current */ 233 if (obp != bp && obp != hbp) { 234 if (flags & B_MODIFY) 235 ret2 = bwrite(obp); 236 else 237 brelse(obp, 0); 238 } 239 obp = bp; 240 olblkno = lblkno; 241 offp = &(q2e->q2e_next); 242 off = ufs_rw64(*offp, needswap); 243 } 244 if (ret) 245 break; 246 if (ret2) { 247 ret = ret2; 248 break; 249 } 250 } 251 if (obp != hbp) { 252 if (flags & B_MODIFY) 253 ret2 = bwrite(obp); 254 else 255 brelse(obp, 0); 256 } 257 if (ret & Q2WL_ABORT) 258 return 0; 259 if (ret == 0) 260 return ret2; 261 return ret; 262 } 263 264 int 265 quota2_umount(struct mount *mp, int flags) 266 { 267 int i, error; 268 struct ufsmount *ump = VFSTOUFS(mp); 269 270 if ((ump->um_flags & UFS_QUOTA2) == 0) 271 return 0; 272 273 for (i = 0; i < MAXQUOTAS; i++) { 274 if (ump->um_quotas[i] != NULLVP) { 275 error = vn_close(ump->um_quotas[i], FREAD|FWRITE, 276 ump->um_cred[i]); 277 if (error) { 278 printf("quota2_umount failed: close(%p) %d\n", 279 ump->um_quotas[i], error); 280 return error; 281 } 282 } 283 ump->um_quotas[i] = NULLVP; 284 } 285 return 0; 286 } 287 288 static int 289 quota2_q2ealloc(struct ufsmount *ump, int type, uid_t uid, struct dquot *dq) 290 { 291 int error, error2; 292 struct buf *hbp, *bp; 293 struct quota2_header *q2h; 294 struct quota2_entry *q2e; 295 daddr_t offset; 296 u_long hash_mask; 297 const int needswap = UFS_MPNEEDSWAP(ump); 298 299 KASSERT(mutex_owned(&dq->dq_interlock)); 300 KASSERT(mutex_owned(&dqlock)); 301 error = getq2h(ump, type, &hbp, &q2h, B_MODIFY); 302 if (error) 303 return error; 304 offset = ufs_rw64(q2h->q2h_free, needswap); 305 if (offset == 0) { 306 struct vnode *vp = ump->um_quotas[type]; 307 struct inode *ip = VTOI(vp); 308 uint64_t size = ip->i_size; 309 /* need to alocate a new disk block */ 310 error = UFS_BALLOC(vp, size, ump->umq2_bsize, 311 ump->um_cred[type], B_CLRBUF | B_SYNC, &bp); 312 if (error) { 313 brelse(hbp, 0); 314 return error; 315 } 316 KASSERT((ip->i_size % ump->umq2_bsize) == 0); 317 ip->i_size += ump->umq2_bsize; 318 DIP_ASSIGN(ip, size, ip->i_size); 319 ip->i_flag |= IN_CHANGE | IN_UPDATE; 320 uvm_vnp_setsize(vp, ip->i_size); 321 quota2_addfreeq2e(q2h, bp->b_data, size, ump->umq2_bsize, 322 needswap); 323 error = bwrite(bp); 324 error2 = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT); 325 if (error || error2) { 326 brelse(hbp, 0); 327 if (error) 328 return error; 329 return error2; 330 } 331 offset = ufs_rw64(q2h->q2h_free, needswap); 332 KASSERT(offset != 0); 333 } 334 dq->dq2_lblkno = (offset >> ump->um_mountp->mnt_fs_bshift); 335 dq->dq2_blkoff = (offset & ump->umq2_bmask); 336 if (dq->dq2_lblkno == 0) { 337 bp = hbp; 338 q2e = (void *)((char *)bp->b_data + dq->dq2_blkoff); 339 } else { 340 error = getq2e(ump, type, dq->dq2_lblkno, 341 dq->dq2_blkoff, &bp, &q2e, B_MODIFY); 342 if (error) { 343 brelse(hbp, 0); 344 return error; 345 } 346 } 347 hash_mask = ((1 << q2h->q2h_hash_shift) - 1); 348 /* remove from free list */ 349 q2h->q2h_free = q2e->q2e_next; 350 351 memcpy(q2e, &q2h->q2h_defentry, sizeof(*q2e)); 352 q2e->q2e_uid = ufs_rw32(uid, needswap); 353 /* insert in hash list */ 354 q2e->q2e_next = q2h->q2h_entries[uid & hash_mask]; 355 q2h->q2h_entries[uid & hash_mask] = ufs_rw64(offset, needswap); 356 if (hbp != bp) { 357 bwrite(hbp); 358 } 359 bwrite(bp); 360 return 0; 361 } 362 363 static int 364 getinoquota2(struct inode *ip, bool alloc, bool modify, struct buf **bpp, 365 struct quota2_entry **q2ep) 366 { 367 int error; 368 int i; 369 struct dquot *dq; 370 struct ufsmount *ump = ip->i_ump; 371 u_int32_t ino_ids[MAXQUOTAS]; 372 373 error = getinoquota(ip); 374 if (error) 375 return error; 376 377 if (alloc) { 378 UFS_WAPBL_JLOCK_ASSERT(ump->um_mountp); 379 } 380 ino_ids[USRQUOTA] = ip->i_uid; 381 ino_ids[GRPQUOTA] = ip->i_gid; 382 /* first get the interlock for all dquot */ 383 for (i = 0; i < MAXQUOTAS; i++) { 384 dq = ip->i_dquot[i]; 385 if (dq == NODQUOT) 386 continue; 387 mutex_enter(&dq->dq_interlock); 388 } 389 /* now get the corresponding quota entry */ 390 for (i = 0; i < MAXQUOTAS; i++) { 391 bpp[i] = NULL; 392 q2ep[i] = NULL; 393 dq = ip->i_dquot[i]; 394 if (dq == NODQUOT) 395 continue; 396 if (__predict_false(ump->um_quotas[i] == NULL)) { 397 /* 398 * quotas have been turned off. This can happen 399 * at umount time. 400 */ 401 mutex_exit(&dq->dq_interlock); 402 dqrele(NULLVP, dq); 403 ip->i_dquot[i] = NULL; 404 continue; 405 } 406 407 if ((dq->dq2_lblkno | dq->dq2_blkoff) == 0) { 408 if (!alloc) { 409 continue; 410 } 411 /* need to alloc a new on-disk quot */ 412 mutex_enter(&dqlock); 413 error = quota2_q2ealloc(ump, i, ino_ids[i], dq); 414 mutex_exit(&dqlock); 415 if (error) 416 return error; 417 } 418 KASSERT(dq->dq2_lblkno != 0 || dq->dq2_blkoff != 0); 419 error = getq2e(ump, i, dq->dq2_lblkno, 420 dq->dq2_blkoff, &bpp[i], &q2ep[i], 421 modify ? B_MODIFY : 0); 422 if (error) 423 return error; 424 } 425 return 0; 426 } 427 428 __inline static int __unused 429 quota2_check_limit(struct quota2_val *q2v, uint64_t change, time_t now) 430 { 431 return quota_check_limit(q2v->q2v_cur, change, q2v->q2v_softlimit, 432 q2v->q2v_hardlimit, q2v->q2v_time, now); 433 } 434 435 static int 436 quota2_check(struct inode *ip, int vtype, int64_t change, kauth_cred_t cred, 437 int flags) 438 { 439 int error; 440 struct buf *bp[MAXQUOTAS]; 441 struct quota2_entry *q2e[MAXQUOTAS]; 442 struct quota2_val *q2vp; 443 struct dquot *dq; 444 uint64_t ncurblks; 445 struct ufsmount *ump = ip->i_ump; 446 struct mount *mp = ump->um_mountp; 447 const int needswap = UFS_MPNEEDSWAP(ump); 448 int i; 449 450 if ((error = getinoquota2(ip, change > 0, change != 0, bp, q2e)) != 0) 451 return error; 452 if (change == 0) { 453 for (i = 0; i < MAXQUOTAS; i++) { 454 dq = ip->i_dquot[i]; 455 if (dq == NODQUOT) 456 continue; 457 if (bp[i]) 458 brelse(bp[i], 0); 459 mutex_exit(&dq->dq_interlock); 460 } 461 return 0; 462 } 463 if (change < 0) { 464 for (i = 0; i < MAXQUOTAS; i++) { 465 dq = ip->i_dquot[i]; 466 if (dq == NODQUOT) 467 continue; 468 if (q2e[i] == NULL) { 469 mutex_exit(&dq->dq_interlock); 470 continue; 471 } 472 q2vp = &q2e[i]->q2e_val[vtype]; 473 ncurblks = ufs_rw64(q2vp->q2v_cur, needswap); 474 if (ncurblks < -change) 475 ncurblks = 0; 476 else 477 ncurblks += change; 478 q2vp->q2v_cur = ufs_rw64(ncurblks, needswap); 479 quota2_bwrite(mp, bp[i]); 480 mutex_exit(&dq->dq_interlock); 481 } 482 return 0; 483 } 484 /* see if the allocation is allowed */ 485 for (i = 0; i < MAXQUOTAS; i++) { 486 struct quota2_val q2v; 487 int ql_stat; 488 dq = ip->i_dquot[i]; 489 if (dq == NODQUOT) 490 continue; 491 KASSERT(q2e[i] != NULL); 492 quota2_ufs_rwq2v(&q2e[i]->q2e_val[vtype], &q2v, needswap); 493 ql_stat = quota2_check_limit(&q2v, change, time_second); 494 495 if ((flags & FORCE) == 0 && 496 kauth_authorize_system(cred, KAUTH_SYSTEM_FS_QUOTA, 497 KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT, 498 KAUTH_ARG(i), KAUTH_ARG(vtype), NULL) != 0) { 499 /* enforce this limit */ 500 switch(QL_STATUS(ql_stat)) { 501 case QL_S_DENY_HARD: 502 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) { 503 uprintf("\n%s: write failed, %s %s " 504 "limit reached\n", 505 mp->mnt_stat.f_mntonname, 506 quotatypes[i], limnames[vtype]); 507 dq->dq_flags |= DQ_WARN(vtype); 508 } 509 error = EDQUOT; 510 break; 511 case QL_S_DENY_GRACE: 512 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) { 513 uprintf("\n%s: write failed, %s %s " 514 "limit reached\n", 515 mp->mnt_stat.f_mntonname, 516 quotatypes[i], limnames[vtype]); 517 dq->dq_flags |= DQ_WARN(vtype); 518 } 519 error = EDQUOT; 520 break; 521 case QL_S_ALLOW_SOFT: 522 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) { 523 uprintf("\n%s: warning, %s %s " 524 "quota exceeded\n", 525 mp->mnt_stat.f_mntonname, 526 quotatypes[i], limnames[vtype]); 527 dq->dq_flags |= DQ_WARN(vtype); 528 } 529 break; 530 } 531 } 532 /* 533 * always do this; we don't know if the allocation will 534 * succed or not in the end. if we don't do the allocation 535 * q2v_time will be ignored anyway 536 */ 537 if (ql_stat & QL_F_CROSS) { 538 q2v.q2v_time = time_second + q2v.q2v_grace; 539 quota2_ufs_rwq2v(&q2v, &q2e[i]->q2e_val[vtype], 540 needswap); 541 } 542 } 543 544 /* now do the allocation if allowed */ 545 for (i = 0; i < MAXQUOTAS; i++) { 546 dq = ip->i_dquot[i]; 547 if (dq == NODQUOT) 548 continue; 549 KASSERT(q2e[i] != NULL); 550 if (error == 0) { 551 q2vp = &q2e[i]->q2e_val[vtype]; 552 ncurblks = ufs_rw64(q2vp->q2v_cur, needswap); 553 q2vp->q2v_cur = ufs_rw64(ncurblks + change, needswap); 554 quota2_bwrite(mp, bp[i]); 555 } else 556 brelse(bp[i], 0); 557 mutex_exit(&dq->dq_interlock); 558 } 559 return error; 560 } 561 562 int 563 chkdq2(struct inode *ip, int64_t change, kauth_cred_t cred, int flags) 564 { 565 return quota2_check(ip, QL_BLOCK, change, cred, flags); 566 } 567 568 int 569 chkiq2(struct inode *ip, int32_t change, kauth_cred_t cred, int flags) 570 { 571 return quota2_check(ip, QL_FILE, change, cred, flags); 572 } 573 574 int 575 quota2_handle_cmd_put(struct ufsmount *ump, const struct quotakey *key, 576 const struct quotaval *val) 577 { 578 int error; 579 struct dquot *dq; 580 struct quota2_header *q2h; 581 struct quota2_entry q2e, *q2ep; 582 struct buf *bp; 583 const int needswap = UFS_MPNEEDSWAP(ump); 584 585 /* make sure we can index by the fs-independent idtype */ 586 CTASSERT(QUOTA_IDTYPE_USER == USRQUOTA); 587 CTASSERT(QUOTA_IDTYPE_GROUP == GRPQUOTA); 588 589 if (ump->um_quotas[key->qk_idtype] == NULLVP) 590 return ENODEV; 591 error = UFS_WAPBL_BEGIN(ump->um_mountp); 592 if (error) 593 return error; 594 595 if (key->qk_id == QUOTA_DEFAULTID) { 596 mutex_enter(&dqlock); 597 error = getq2h(ump, key->qk_idtype, &bp, &q2h, B_MODIFY); 598 if (error) { 599 mutex_exit(&dqlock); 600 goto out_wapbl; 601 } 602 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); 603 quota2_dict_update_q2e_limits(key->qk_objtype, val, &q2e); 604 quota2_ufs_rwq2e(&q2e, &q2h->q2h_defentry, needswap); 605 mutex_exit(&dqlock); 606 quota2_bwrite(ump->um_mountp, bp); 607 goto out_wapbl; 608 } 609 610 error = dqget(NULLVP, key->qk_id, ump, key->qk_idtype, &dq); 611 if (error) 612 goto out_wapbl; 613 614 mutex_enter(&dq->dq_interlock); 615 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 616 /* need to alloc a new on-disk quot */ 617 mutex_enter(&dqlock); 618 error = quota2_q2ealloc(ump, key->qk_idtype, key->qk_id, dq); 619 mutex_exit(&dqlock); 620 if (error) 621 goto out_il; 622 } 623 KASSERT(dq->dq2_lblkno != 0 || dq->dq2_blkoff != 0); 624 error = getq2e(ump, key->qk_idtype, dq->dq2_lblkno, 625 dq->dq2_blkoff, &bp, &q2ep, B_MODIFY); 626 if (error) 627 goto out_il; 628 629 quota2_ufs_rwq2e(q2ep, &q2e, needswap); 630 /* 631 * Reset time limit if previously had no soft limit or were 632 * under it, but now have a soft limit and are over it. 633 */ 634 if (val->qv_softlimit && 635 q2e.q2e_val[key->qk_objtype].q2v_cur >= val->qv_softlimit && 636 (q2e.q2e_val[key->qk_objtype].q2v_softlimit == 0 || 637 q2e.q2e_val[key->qk_objtype].q2v_cur < q2e.q2e_val[key->qk_objtype].q2v_softlimit)) 638 q2e.q2e_val[key->qk_objtype].q2v_time = time_second + val->qv_grace; 639 quota2_dict_update_q2e_limits(key->qk_objtype, val, &q2e); 640 quota2_ufs_rwq2e(&q2e, q2ep, needswap); 641 quota2_bwrite(ump->um_mountp, bp); 642 643 out_il: 644 mutex_exit(&dq->dq_interlock); 645 dqrele(NULLVP, dq); 646 out_wapbl: 647 UFS_WAPBL_END(ump->um_mountp); 648 return error; 649 } 650 651 struct dq2clear_callback { 652 uid_t id; 653 struct dquot *dq; 654 struct quota2_header *q2h; 655 }; 656 657 static int 658 dq2clear_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e, 659 uint64_t off, void *v) 660 { 661 struct dq2clear_callback *c = v; 662 const int needswap = UFS_MPNEEDSWAP(ump); 663 uint64_t myoff; 664 665 if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) { 666 KASSERT(mutex_owned(&c->dq->dq_interlock)); 667 c->dq->dq2_lblkno = 0; 668 c->dq->dq2_blkoff = 0; 669 myoff = *offp; 670 /* remove from hash list */ 671 *offp = q2e->q2e_next; 672 /* add to free list */ 673 q2e->q2e_next = c->q2h->q2h_free; 674 c->q2h->q2h_free = myoff; 675 return Q2WL_ABORT; 676 } 677 return 0; 678 } 679 int 680 quota2_handle_cmd_del(struct ufsmount *ump, const struct quotakey *qk) 681 { 682 int idtype; 683 id_t id; 684 int objtype; 685 int error, i, canfree; 686 struct dquot *dq; 687 struct quota2_header *q2h; 688 struct quota2_entry q2e, *q2ep; 689 struct buf *hbp, *bp; 690 u_long hash_mask; 691 struct dq2clear_callback c; 692 693 idtype = qk->qk_idtype; 694 id = qk->qk_id; 695 objtype = qk->qk_objtype; 696 697 if (ump->um_quotas[idtype] == NULLVP) 698 return ENODEV; 699 if (id == QUOTA_DEFAULTID) 700 return EOPNOTSUPP; 701 702 /* get the default entry before locking the entry's buffer */ 703 mutex_enter(&dqlock); 704 error = getq2h(ump, idtype, &hbp, &q2h, 0); 705 if (error) { 706 mutex_exit(&dqlock); 707 return error; 708 } 709 /* we'll copy to another disk entry, so no need to swap */ 710 memcpy(&q2e, &q2h->q2h_defentry, sizeof(q2e)); 711 mutex_exit(&dqlock); 712 brelse(hbp, 0); 713 714 error = dqget(NULLVP, id, ump, idtype, &dq); 715 if (error) 716 return error; 717 718 mutex_enter(&dq->dq_interlock); 719 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 720 /* already clear, nothing to do */ 721 error = ENOENT; 722 goto out_il; 723 } 724 error = UFS_WAPBL_BEGIN(ump->um_mountp); 725 if (error) 726 goto out_dq; 727 728 error = getq2e(ump, idtype, dq->dq2_lblkno, dq->dq2_blkoff, 729 &bp, &q2ep, B_MODIFY); 730 if (error) 731 goto out_wapbl; 732 733 /* make sure we can index by the objtype passed in */ 734 CTASSERT(QUOTA_OBJTYPE_BLOCKS == QL_BLOCK); 735 CTASSERT(QUOTA_OBJTYPE_FILES == QL_FILE); 736 737 /* clear the requested objtype by copying from the default entry */ 738 q2ep->q2e_val[objtype].q2v_softlimit = 739 q2e.q2e_val[objtype].q2v_softlimit; 740 q2ep->q2e_val[objtype].q2v_hardlimit = 741 q2e.q2e_val[objtype].q2v_hardlimit; 742 q2ep->q2e_val[objtype].q2v_grace = 743 q2e.q2e_val[objtype].q2v_grace; 744 q2ep->q2e_val[objtype].q2v_time = 0; 745 746 /* if this entry now contains no information, we can free it */ 747 canfree = 1; 748 for (i = 0; i < N_QL; i++) { 749 if (q2ep->q2e_val[i].q2v_cur != 0 || 750 (q2ep->q2e_val[i].q2v_softlimit != 751 q2e.q2e_val[i].q2v_softlimit) || 752 (q2ep->q2e_val[i].q2v_hardlimit != 753 q2e.q2e_val[i].q2v_hardlimit) || 754 (q2ep->q2e_val[i].q2v_grace != 755 q2e.q2e_val[i].q2v_grace)) { 756 canfree = 0; 757 break; 758 } 759 /* note: do not need to check q2v_time */ 760 } 761 762 if (canfree == 0) { 763 quota2_bwrite(ump->um_mountp, bp); 764 goto out_wapbl; 765 } 766 /* we can free it. release bp so we can walk the list */ 767 brelse(bp, 0); 768 mutex_enter(&dqlock); 769 error = getq2h(ump, idtype, &hbp, &q2h, 0); 770 if (error) 771 goto out_dqlock; 772 773 hash_mask = ((1 << q2h->q2h_hash_shift) - 1); 774 c.dq = dq; 775 c.id = id; 776 c.q2h = q2h; 777 error = quota2_walk_list(ump, hbp, idtype, 778 &q2h->q2h_entries[id & hash_mask], B_MODIFY, &c, 779 dq2clear_callback); 780 781 bwrite(hbp); 782 783 out_dqlock: 784 mutex_exit(&dqlock); 785 out_wapbl: 786 UFS_WAPBL_END(ump->um_mountp); 787 out_il: 788 mutex_exit(&dq->dq_interlock); 789 out_dq: 790 dqrele(NULLVP, dq); 791 return error; 792 } 793 794 static int 795 quota2_fetch_q2e(struct ufsmount *ump, const struct quotakey *qk, 796 struct quota2_entry *ret) 797 { 798 struct dquot *dq; 799 int error; 800 struct quota2_entry *q2ep; 801 struct buf *bp; 802 const int needswap = UFS_MPNEEDSWAP(ump); 803 804 error = dqget(NULLVP, qk->qk_id, ump, qk->qk_idtype, &dq); 805 if (error) 806 return error; 807 808 mutex_enter(&dq->dq_interlock); 809 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 810 mutex_exit(&dq->dq_interlock); 811 dqrele(NULLVP, dq); 812 return ENOENT; 813 } 814 error = getq2e(ump, qk->qk_idtype, dq->dq2_lblkno, dq->dq2_blkoff, 815 &bp, &q2ep, 0); 816 if (error) { 817 mutex_exit(&dq->dq_interlock); 818 dqrele(NULLVP, dq); 819 return error; 820 } 821 quota2_ufs_rwq2e(q2ep, ret, needswap); 822 brelse(bp, 0); 823 mutex_exit(&dq->dq_interlock); 824 dqrele(NULLVP, dq); 825 826 return 0; 827 } 828 829 static int 830 quota2_fetch_quotaval(struct ufsmount *ump, const struct quotakey *qk, 831 struct quotaval *ret) 832 { 833 struct dquot *dq; 834 int error; 835 struct quota2_entry *q2ep, q2e; 836 struct buf *bp; 837 const int needswap = UFS_MPNEEDSWAP(ump); 838 id_t id2; 839 840 error = dqget(NULLVP, qk->qk_id, ump, qk->qk_idtype, &dq); 841 if (error) 842 return error; 843 844 mutex_enter(&dq->dq_interlock); 845 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 846 mutex_exit(&dq->dq_interlock); 847 dqrele(NULLVP, dq); 848 return ENOENT; 849 } 850 error = getq2e(ump, qk->qk_idtype, dq->dq2_lblkno, dq->dq2_blkoff, 851 &bp, &q2ep, 0); 852 if (error) { 853 mutex_exit(&dq->dq_interlock); 854 dqrele(NULLVP, dq); 855 return error; 856 } 857 quota2_ufs_rwq2e(q2ep, &q2e, needswap); 858 brelse(bp, 0); 859 mutex_exit(&dq->dq_interlock); 860 dqrele(NULLVP, dq); 861 862 q2e_to_quotaval(&q2e, 0, &id2, qk->qk_objtype, ret); 863 KASSERT(id2 == qk->qk_id); 864 return 0; 865 } 866 867 int 868 quota2_handle_cmd_get(struct ufsmount *ump, const struct quotakey *qk, 869 struct quotaval *qv) 870 { 871 int error; 872 struct quota2_header *q2h; 873 struct quota2_entry q2e; 874 struct buf *bp; 875 const int needswap = UFS_MPNEEDSWAP(ump); 876 id_t id2; 877 878 /* 879 * Make sure the FS-independent codes match the internal ones, 880 * so we can use the passed-in objtype without having to 881 * convert it explicitly to QL_BLOCK/QL_FILE. 882 */ 883 CTASSERT(QL_BLOCK == QUOTA_OBJTYPE_BLOCKS); 884 CTASSERT(QL_FILE == QUOTA_OBJTYPE_FILES); 885 CTASSERT(N_QL == 2); 886 887 if (qk->qk_objtype < 0 || qk->qk_objtype >= N_QL) { 888 return EINVAL; 889 } 890 891 if (ump->um_quotas[qk->qk_idtype] == NULLVP) 892 return ENODEV; 893 if (qk->qk_id == QUOTA_DEFAULTID) { 894 mutex_enter(&dqlock); 895 error = getq2h(ump, qk->qk_idtype, &bp, &q2h, 0); 896 if (error) { 897 mutex_exit(&dqlock); 898 return error; 899 } 900 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); 901 mutex_exit(&dqlock); 902 brelse(bp, 0); 903 q2e_to_quotaval(&q2e, qk->qk_id == QUOTA_DEFAULTID, &id2, 904 qk->qk_objtype, qv); 905 (void)id2; 906 } else 907 error = quota2_fetch_quotaval(ump, qk, qv); 908 909 return error; 910 } 911 912 /* 913 * Cursor structure we used. 914 * 915 * This will get stored in userland between calls so we must not assume 916 * it isn't arbitrarily corrupted. 917 */ 918 struct ufsq2_cursor { 919 uint32_t q2c_magic; /* magic number */ 920 int q2c_hashsize; /* size of hash table at last go */ 921 922 int q2c_users_done; /* true if we've returned all user data */ 923 int q2c_groups_done; /* true if we've returned all group data */ 924 int q2c_defaults_done; /* true if we've returned the default values */ 925 int q2c_hashpos; /* slot to start at in hash table */ 926 int q2c_uidpos; /* number of ids we've handled */ 927 int q2c_blocks_done; /* true if we've returned the blocks value */ 928 }; 929 930 /* 931 * State of a single cursorget call, or at least the part of it that 932 * needs to be passed around. 933 */ 934 struct q2cursor_state { 935 /* data return pointers */ 936 struct quotakey *keys; 937 struct quotaval *vals; 938 939 /* key/value counters */ 940 unsigned maxkeyvals; 941 unsigned numkeys; /* number of keys assigned */ 942 943 /* ID to key/value conversion state */ 944 int skipfirst; /* if true skip first key/value */ 945 int skiplast; /* if true skip last key/value */ 946 947 /* ID counters */ 948 unsigned maxids; /* maximum number of IDs to handle */ 949 unsigned numids; /* number of IDs handled */ 950 }; 951 952 /* 953 * Additional structure for getids callback. 954 */ 955 struct q2cursor_getids { 956 struct q2cursor_state *state; 957 int idtype; 958 unsigned skip; /* number of ids to skip over */ 959 unsigned new_skip; /* number of ids to skip over next time */ 960 unsigned skipped; /* number skipped so far */ 961 int stopped; /* true if we stopped quota_walk_list early */ 962 }; 963 964 /* 965 * Cursor-related functions 966 */ 967 968 /* magic number */ 969 #define Q2C_MAGIC (0xbeebe111) 970 971 /* extract cursor from caller form */ 972 #define Q2CURSOR(qkc) ((struct ufsq2_cursor *)&qkc->u.qkc_space[0]) 973 974 /* 975 * Check that a cursor we're handed is something like valid. If 976 * someone munges it and it still passes these checks, they'll get 977 * partial or odd results back but won't break anything. 978 */ 979 static int 980 q2cursor_check(struct ufsq2_cursor *cursor) 981 { 982 if (cursor->q2c_magic != Q2C_MAGIC) { 983 return EINVAL; 984 } 985 if (cursor->q2c_hashsize < 0) { 986 return EINVAL; 987 } 988 989 if (cursor->q2c_users_done != 0 && cursor->q2c_users_done != 1) { 990 return EINVAL; 991 } 992 if (cursor->q2c_groups_done != 0 && cursor->q2c_groups_done != 1) { 993 return EINVAL; 994 } 995 if (cursor->q2c_defaults_done != 0 && cursor->q2c_defaults_done != 1) { 996 return EINVAL; 997 } 998 if (cursor->q2c_hashpos < 0 || cursor->q2c_uidpos < 0) { 999 return EINVAL; 1000 } 1001 if (cursor->q2c_blocks_done != 0 && cursor->q2c_blocks_done != 1) { 1002 return EINVAL; 1003 } 1004 return 0; 1005 } 1006 1007 /* 1008 * Set up the q2cursor state. 1009 */ 1010 static void 1011 q2cursor_initstate(struct q2cursor_state *state, struct quotakey *keys, 1012 struct quotaval *vals, unsigned maxkeyvals, int blocks_done) 1013 { 1014 state->keys = keys; 1015 state->vals = vals; 1016 1017 state->maxkeyvals = maxkeyvals; 1018 state->numkeys = 0; 1019 1020 /* 1021 * For each ID there are two quotavals to return. If the 1022 * maximum number of entries to return is odd, we might want 1023 * to skip the first quotaval of the first ID, or the last 1024 * quotaval of the last ID, but not both. So the number of IDs 1025 * we want is (up to) half the number of return slots we have, 1026 * rounded up. 1027 */ 1028 1029 state->maxids = (state->maxkeyvals + 1) / 2; 1030 state->numids = 0; 1031 if (state->maxkeyvals % 2) { 1032 if (blocks_done) { 1033 state->skipfirst = 1; 1034 state->skiplast = 0; 1035 } else { 1036 state->skipfirst = 0; 1037 state->skiplast = 1; 1038 } 1039 } else { 1040 state->skipfirst = 0; 1041 state->skiplast = 0; 1042 } 1043 } 1044 1045 /* 1046 * Choose which idtype we're going to work on. If doing a full 1047 * iteration, we do users first, then groups, but either might be 1048 * disabled or marked to skip via cursorsetidtype(), so don't make 1049 * silly assumptions. 1050 */ 1051 static int 1052 q2cursor_pickidtype(struct ufsq2_cursor *cursor, int *idtype_ret) 1053 { 1054 if (cursor->q2c_users_done == 0) { 1055 *idtype_ret = QUOTA_IDTYPE_USER; 1056 } else if (cursor->q2c_groups_done == 0) { 1057 *idtype_ret = QUOTA_IDTYPE_GROUP; 1058 } else { 1059 return EAGAIN; 1060 } 1061 return 0; 1062 } 1063 1064 /* 1065 * Add an ID to the current state. Sets up either one or two keys to 1066 * refer to it, depending on whether it's first/last and the setting 1067 * of skipfirst. (skiplast does not need to be explicitly tested) 1068 */ 1069 static void 1070 q2cursor_addid(struct q2cursor_state *state, int idtype, id_t id) 1071 { 1072 KASSERT(state->numids < state->maxids); 1073 KASSERT(state->numkeys < state->maxkeyvals); 1074 1075 if (!state->skipfirst || state->numkeys > 0) { 1076 state->keys[state->numkeys].qk_idtype = idtype; 1077 state->keys[state->numkeys].qk_id = id; 1078 state->keys[state->numkeys].qk_objtype = QUOTA_OBJTYPE_BLOCKS; 1079 state->numkeys++; 1080 } 1081 if (state->numkeys < state->maxkeyvals) { 1082 state->keys[state->numkeys].qk_idtype = idtype; 1083 state->keys[state->numkeys].qk_id = id; 1084 state->keys[state->numkeys].qk_objtype = QUOTA_OBJTYPE_FILES; 1085 state->numkeys++; 1086 } else { 1087 KASSERT(state->skiplast); 1088 } 1089 state->numids++; 1090 } 1091 1092 /* 1093 * Callback function for getting IDs. Update counting and call addid. 1094 */ 1095 static int 1096 q2cursor_getids_callback(struct ufsmount *ump, uint64_t *offp, 1097 struct quota2_entry *q2ep, uint64_t off, void *v) 1098 { 1099 struct q2cursor_getids *gi = v; 1100 id_t id; 1101 const int needswap = UFS_MPNEEDSWAP(ump); 1102 1103 if (gi->skipped < gi->skip) { 1104 gi->skipped++; 1105 return 0; 1106 } 1107 id = ufs_rw32(q2ep->q2e_uid, needswap); 1108 q2cursor_addid(gi->state, gi->idtype, id); 1109 gi->new_skip++; 1110 if (gi->state->numids >= gi->state->maxids) { 1111 /* got enough ids, stop now */ 1112 gi->stopped = 1; 1113 return Q2WL_ABORT; 1114 } 1115 return 0; 1116 } 1117 1118 /* 1119 * Fill in a batch of quotakeys by scanning one or more hash chains. 1120 */ 1121 static int 1122 q2cursor_getkeys(struct ufsmount *ump, int idtype, struct ufsq2_cursor *cursor, 1123 struct q2cursor_state *state, 1124 int *hashsize_ret, struct quota2_entry *default_q2e_ret) 1125 { 1126 const int needswap = UFS_MPNEEDSWAP(ump); 1127 struct buf *hbp; 1128 struct quota2_header *q2h; 1129 int quota2_hash_size; 1130 struct q2cursor_getids gi; 1131 uint64_t offset; 1132 int error; 1133 1134 /* 1135 * Read the header block. 1136 */ 1137 1138 mutex_enter(&dqlock); 1139 error = getq2h(ump, idtype, &hbp, &q2h, 0); 1140 if (error) { 1141 mutex_exit(&dqlock); 1142 return error; 1143 } 1144 1145 /* if the table size has changed, make the caller start over */ 1146 quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap); 1147 if (cursor->q2c_hashsize == 0) { 1148 cursor->q2c_hashsize = quota2_hash_size; 1149 } else if (cursor->q2c_hashsize != quota2_hash_size) { 1150 error = EDEADLK; 1151 goto scanfail; 1152 } 1153 1154 /* grab the entry with the default values out of the header */ 1155 quota2_ufs_rwq2e(&q2h->q2h_defentry, default_q2e_ret, needswap); 1156 1157 /* If we haven't done the defaults yet, that goes first. */ 1158 if (cursor->q2c_defaults_done == 0) { 1159 q2cursor_addid(state, idtype, QUOTA_DEFAULTID); 1160 /* if we read both halves, mark it done */ 1161 if (state->numids < state->maxids || !state->skiplast) { 1162 cursor->q2c_defaults_done = 1; 1163 } 1164 } 1165 1166 gi.state = state; 1167 gi.idtype = idtype; 1168 1169 while (state->numids < state->maxids) { 1170 if (cursor->q2c_hashpos >= quota2_hash_size) { 1171 /* nothing more left */ 1172 break; 1173 } 1174 1175 /* scan this hash chain */ 1176 gi.skip = cursor->q2c_uidpos; 1177 gi.new_skip = gi.skip; 1178 gi.skipped = 0; 1179 gi.stopped = 0; 1180 offset = q2h->q2h_entries[cursor->q2c_hashpos]; 1181 1182 error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gi, 1183 q2cursor_getids_callback); 1184 KASSERT(error != Q2WL_ABORT); 1185 if (error) { 1186 break; 1187 } 1188 if (gi.stopped) { 1189 /* callback stopped before reading whole chain */ 1190 cursor->q2c_uidpos = gi.new_skip; 1191 /* if we didn't get both halves, back up */ 1192 if (state->numids == state->maxids && state->skiplast){ 1193 KASSERT(cursor->q2c_uidpos > 0); 1194 cursor->q2c_uidpos--; 1195 } 1196 } else { 1197 /* read whole chain */ 1198 /* if we got both halves of the last id, advance */ 1199 if (state->numids < state->maxids || !state->skiplast){ 1200 cursor->q2c_uidpos = 0; 1201 cursor->q2c_hashpos++; 1202 } 1203 } 1204 } 1205 1206 scanfail: 1207 mutex_exit(&dqlock); 1208 brelse(hbp, 0); 1209 if (error) 1210 return error; 1211 1212 *hashsize_ret = quota2_hash_size; 1213 return 0; 1214 } 1215 1216 /* 1217 * Fetch the quotavals for the quotakeys. 1218 */ 1219 static int 1220 q2cursor_getvals(struct ufsmount *ump, struct q2cursor_state *state, 1221 const struct quota2_entry *default_q2e) 1222 { 1223 int hasid; 1224 id_t loadedid, id; 1225 unsigned pos; 1226 struct quota2_entry q2e; 1227 int objtype; 1228 int error; 1229 1230 hasid = 0; 1231 loadedid = 0; 1232 for (pos = 0; pos < state->numkeys; pos++) { 1233 id = state->keys[pos].qk_id; 1234 if (!hasid || id != loadedid) { 1235 hasid = 1; 1236 loadedid = id; 1237 if (id == QUOTA_DEFAULTID) { 1238 q2e = *default_q2e; 1239 } else { 1240 error = quota2_fetch_q2e(ump, 1241 &state->keys[pos], 1242 &q2e); 1243 if (error == ENOENT) { 1244 /* something changed - start over */ 1245 error = EDEADLK; 1246 } 1247 if (error) { 1248 return error; 1249 } 1250 } 1251 } 1252 1253 1254 objtype = state->keys[pos].qk_objtype; 1255 KASSERT(objtype >= 0 && objtype < N_QL); 1256 q2val_to_quotaval(&q2e.q2e_val[objtype], &state->vals[pos]); 1257 } 1258 1259 return 0; 1260 } 1261 1262 /* 1263 * Handle cursorget. 1264 * 1265 * We can't just read keys and values directly, because we can't walk 1266 * the list with qdlock and grab dq_interlock to read the entries at 1267 * the same time. So we're going to do two passes: one to figure out 1268 * which IDs we want and fill in the keys, and then a second to use 1269 * the keys to fetch the values. 1270 */ 1271 int 1272 quota2_handle_cmd_cursorget(struct ufsmount *ump, struct quotakcursor *qkc, 1273 struct quotakey *keys, struct quotaval *vals, unsigned maxreturn, 1274 unsigned *ret) 1275 { 1276 int error; 1277 struct ufsq2_cursor *cursor; 1278 struct ufsq2_cursor newcursor; 1279 struct q2cursor_state state; 1280 struct quota2_entry default_q2e; 1281 int idtype; 1282 int quota2_hash_size = 0; /* XXX: sh3 gcc 4.8 -Wuninitialized */ 1283 1284 /* 1285 * Convert and validate the cursor. 1286 */ 1287 cursor = Q2CURSOR(qkc); 1288 error = q2cursor_check(cursor); 1289 if (error) { 1290 return error; 1291 } 1292 1293 /* 1294 * Make sure our on-disk codes match the values of the 1295 * FS-independent ones. This avoids the need for explicit 1296 * conversion (which would be a NOP anyway and thus easily 1297 * left out or called in the wrong places...) 1298 */ 1299 CTASSERT(QUOTA_IDTYPE_USER == USRQUOTA); 1300 CTASSERT(QUOTA_IDTYPE_GROUP == GRPQUOTA); 1301 CTASSERT(QUOTA_OBJTYPE_BLOCKS == QL_BLOCK); 1302 CTASSERT(QUOTA_OBJTYPE_FILES == QL_FILE); 1303 1304 /* 1305 * If some of the idtypes aren't configured/enabled, arrange 1306 * to skip over them. 1307 */ 1308 if (cursor->q2c_users_done == 0 && 1309 ump->um_quotas[USRQUOTA] == NULLVP) { 1310 cursor->q2c_users_done = 1; 1311 } 1312 if (cursor->q2c_groups_done == 0 && 1313 ump->um_quotas[GRPQUOTA] == NULLVP) { 1314 cursor->q2c_groups_done = 1; 1315 } 1316 1317 /* Loop over, potentially, both idtypes */ 1318 while (1) { 1319 1320 /* Choose id type */ 1321 error = q2cursor_pickidtype(cursor, &idtype); 1322 if (error == EAGAIN) { 1323 /* nothing more to do, return 0 */ 1324 *ret = 0; 1325 return 0; 1326 } 1327 KASSERT(ump->um_quotas[idtype] != NULLVP); 1328 1329 /* 1330 * Initialize the per-call iteration state. Copy the 1331 * cursor state so we can update it in place but back 1332 * out on error. 1333 */ 1334 q2cursor_initstate(&state, keys, vals, maxreturn, 1335 cursor->q2c_blocks_done); 1336 newcursor = *cursor; 1337 1338 /* Assign keys */ 1339 error = q2cursor_getkeys(ump, idtype, &newcursor, &state, 1340 "a2_hash_size, &default_q2e); 1341 if (error) { 1342 return error; 1343 } 1344 1345 /* Now fill in the values. */ 1346 error = q2cursor_getvals(ump, &state, &default_q2e); 1347 if (error) { 1348 return error; 1349 } 1350 1351 /* 1352 * Now that we aren't going to fail and lose what we 1353 * did so far, we can update the cursor state. 1354 */ 1355 1356 if (newcursor.q2c_hashpos >= quota2_hash_size) { 1357 if (idtype == QUOTA_IDTYPE_USER) 1358 cursor->q2c_users_done = 1; 1359 else 1360 cursor->q2c_groups_done = 1; 1361 1362 /* start over on another id type */ 1363 cursor->q2c_hashsize = 0; 1364 cursor->q2c_defaults_done = 0; 1365 cursor->q2c_hashpos = 0; 1366 cursor->q2c_uidpos = 0; 1367 cursor->q2c_blocks_done = 0; 1368 } else { 1369 *cursor = newcursor; 1370 cursor->q2c_blocks_done = state.skiplast; 1371 } 1372 1373 /* 1374 * If we have something to return, return it. 1375 * Otherwise, continue to the other idtype, if any, 1376 * and only return zero at end of iteration. 1377 */ 1378 if (state.numkeys > 0) { 1379 break; 1380 } 1381 } 1382 1383 *ret = state.numkeys; 1384 return 0; 1385 } 1386 1387 int 1388 quota2_handle_cmd_cursoropen(struct ufsmount *ump, struct quotakcursor *qkc) 1389 { 1390 struct ufsq2_cursor *cursor; 1391 1392 CTASSERT(sizeof(*cursor) <= sizeof(qkc->u.qkc_space)); 1393 cursor = Q2CURSOR(qkc); 1394 1395 cursor->q2c_magic = Q2C_MAGIC; 1396 cursor->q2c_hashsize = 0; 1397 1398 cursor->q2c_users_done = 0; 1399 cursor->q2c_groups_done = 0; 1400 cursor->q2c_defaults_done = 0; 1401 cursor->q2c_hashpos = 0; 1402 cursor->q2c_uidpos = 0; 1403 cursor->q2c_blocks_done = 0; 1404 return 0; 1405 } 1406 1407 int 1408 quota2_handle_cmd_cursorclose(struct ufsmount *ump, struct quotakcursor *qkc) 1409 { 1410 struct ufsq2_cursor *cursor; 1411 int error; 1412 1413 cursor = Q2CURSOR(qkc); 1414 error = q2cursor_check(cursor); 1415 if (error) { 1416 return error; 1417 } 1418 1419 /* nothing to do */ 1420 1421 return 0; 1422 } 1423 1424 int 1425 quota2_handle_cmd_cursorskipidtype(struct ufsmount *ump, 1426 struct quotakcursor *qkc, int idtype) 1427 { 1428 struct ufsq2_cursor *cursor; 1429 int error; 1430 1431 cursor = Q2CURSOR(qkc); 1432 error = q2cursor_check(cursor); 1433 if (error) { 1434 return error; 1435 } 1436 1437 switch (idtype) { 1438 case QUOTA_IDTYPE_USER: 1439 cursor->q2c_users_done = 1; 1440 break; 1441 case QUOTA_IDTYPE_GROUP: 1442 cursor->q2c_groups_done = 1; 1443 break; 1444 default: 1445 return EINVAL; 1446 } 1447 1448 return 0; 1449 } 1450 1451 int 1452 quota2_handle_cmd_cursoratend(struct ufsmount *ump, struct quotakcursor *qkc, 1453 int *ret) 1454 { 1455 struct ufsq2_cursor *cursor; 1456 int error; 1457 1458 cursor = Q2CURSOR(qkc); 1459 error = q2cursor_check(cursor); 1460 if (error) { 1461 return error; 1462 } 1463 1464 *ret = (cursor->q2c_users_done && cursor->q2c_groups_done); 1465 return 0; 1466 } 1467 1468 int 1469 quota2_handle_cmd_cursorrewind(struct ufsmount *ump, struct quotakcursor *qkc) 1470 { 1471 struct ufsq2_cursor *cursor; 1472 int error; 1473 1474 cursor = Q2CURSOR(qkc); 1475 error = q2cursor_check(cursor); 1476 if (error) { 1477 return error; 1478 } 1479 1480 cursor->q2c_hashsize = 0; 1481 1482 cursor->q2c_users_done = 0; 1483 cursor->q2c_groups_done = 0; 1484 cursor->q2c_defaults_done = 0; 1485 cursor->q2c_hashpos = 0; 1486 cursor->q2c_uidpos = 0; 1487 cursor->q2c_blocks_done = 0; 1488 1489 return 0; 1490 } 1491 1492 int 1493 q2sync(struct mount *mp) 1494 { 1495 return 0; 1496 } 1497 1498 struct dq2get_callback { 1499 uid_t id; 1500 struct dquot *dq; 1501 }; 1502 1503 static int 1504 dq2get_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e, 1505 uint64_t off, void *v) 1506 { 1507 struct dq2get_callback *c = v; 1508 daddr_t lblkno; 1509 int blkoff; 1510 const int needswap = UFS_MPNEEDSWAP(ump); 1511 1512 if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) { 1513 KASSERT(mutex_owned(&c->dq->dq_interlock)); 1514 lblkno = (off >> ump->um_mountp->mnt_fs_bshift); 1515 blkoff = (off & ump->umq2_bmask); 1516 c->dq->dq2_lblkno = lblkno; 1517 c->dq->dq2_blkoff = blkoff; 1518 return Q2WL_ABORT; 1519 } 1520 return 0; 1521 } 1522 1523 int 1524 dq2get(struct vnode *dqvp, u_long id, struct ufsmount *ump, int type, 1525 struct dquot *dq) 1526 { 1527 struct buf *bp; 1528 struct quota2_header *q2h; 1529 int error; 1530 daddr_t offset; 1531 u_long hash_mask; 1532 struct dq2get_callback c = { 1533 .id = id, 1534 .dq = dq 1535 }; 1536 1537 KASSERT(mutex_owned(&dq->dq_interlock)); 1538 mutex_enter(&dqlock); 1539 error = getq2h(ump, type, &bp, &q2h, 0); 1540 if (error) 1541 goto out_mutex; 1542 /* look for our entry */ 1543 hash_mask = ((1 << q2h->q2h_hash_shift) - 1); 1544 offset = q2h->q2h_entries[id & hash_mask]; 1545 error = quota2_walk_list(ump, bp, type, &offset, 0, (void *)&c, 1546 dq2get_callback); 1547 brelse(bp, 0); 1548 out_mutex: 1549 mutex_exit(&dqlock); 1550 return error; 1551 } 1552 1553 int 1554 dq2sync(struct vnode *vp, struct dquot *dq) 1555 { 1556 return 0; 1557 } 1558