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