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