xref: /netbsd-src/sys/ufs/lfs/ulfs_quota2.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
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 					 &quota2_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