Sun Jan 29 07:06:02 2012 UTC ()
Stop treating the default values specially in QUOTACTL_GETALL.

Note: this change requires a kernel version bump.


(dholland)
diff -r1.24 -r1.25 src/sys/kern/vfs_quotactl.c
diff -r1.22 -r1.23 src/sys/sys/quotactl.h
diff -r1.21 -r1.22 src/sys/ufs/ufs/ufs_quota2.c

cvs diff -r1.24 -r1.25 src/sys/kern/vfs_quotactl.c (expand / switch to unified diff)

--- src/sys/kern/vfs_quotactl.c 2012/01/29 07:05:12 1.24
+++ src/sys/kern/vfs_quotactl.c 2012/01/29 07:06:01 1.25
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: vfs_quotactl.c,v 1.24 2012/01/29 07:05:12 dholland Exp $ */ 1/* $NetBSD: vfs_quotactl.c,v 1.25 2012/01/29 07:06:01 dholland Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1991, 1993, 1994 4 * Copyright (c) 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc. 6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed 7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph 8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc. 10 * the permission of UNIX System Laboratories, Inc.
11 * 11 *
12 * Redistribution and use in source and binary forms, with or without 12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions 13 * modification, are permitted provided that the following conditions
14 * are met: 14 * are met:
@@ -70,27 +70,27 @@ @@ -70,27 +70,27 @@
70 * 70 *
71 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 71 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
72 * From NetBSD: ufs_quota.c,v 1.70 2011/03/24 17:05:46 bouyer Exp 72 * From NetBSD: ufs_quota.c,v 1.70 2011/03/24 17:05:46 bouyer Exp
73 */ 73 */
74 74
75/* 75/*
76 * Note that both of the copyrights above are moderately spurious; 76 * Note that both of the copyrights above are moderately spurious;
77 * this code should almost certainly have the Copyright 2010 Manuel 77 * this code should almost certainly have the Copyright 2010 Manuel
78 * Bouyer notice and license found in e.g. sys/ufs/ufs/quota2_subr.c. 78 * Bouyer notice and license found in e.g. sys/ufs/ufs/quota2_subr.c.
79 * However, they're what was on the files this code was sliced out of. 79 * However, they're what was on the files this code was sliced out of.
80 */ 80 */
81 81
82#include <sys/cdefs.h> 82#include <sys/cdefs.h>
83__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.24 2012/01/29 07:05:12 dholland Exp $"); 83__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.25 2012/01/29 07:06:01 dholland Exp $");
84 84
85#include <sys/malloc.h> /* XXX: temporary */ 85#include <sys/malloc.h> /* XXX: temporary */
86#include <sys/mount.h> 86#include <sys/mount.h>
87#include <sys/quota.h> 87#include <sys/quota.h>
88#include <sys/quotactl.h> 88#include <sys/quotactl.h>
89#include <quota/quotaprop.h> 89#include <quota/quotaprop.h>
90 90
91static int 91static int
92vfs_quotactl_getversion(struct mount *mp, 92vfs_quotactl_getversion(struct mount *mp,
93 prop_dictionary_t cmddict, int q2type, 93 prop_dictionary_t cmddict, int q2type,
94 prop_array_t datas) 94 prop_array_t datas)
95{ 95{
96 prop_array_t replies; 96 prop_array_t replies;
@@ -502,26 +502,28 @@ err: @@ -502,26 +502,28 @@ err:
502} 502}
503 503
504static int 504static int
505vfs_quotactl_getall(struct mount *mp, 505vfs_quotactl_getall(struct mount *mp,
506 prop_dictionary_t cmddict, int q2type, 506 prop_dictionary_t cmddict, int q2type,
507 prop_array_t datas) 507 prop_array_t datas)
508{ 508{
509 struct quotakcursor cursor; 509 struct quotakcursor cursor;
510 struct quota_getall_result result; 510 struct quota_getall_result result;
511 struct vfs_quotactl_args args; 511 struct vfs_quotactl_args args;
512 prop_array_t replies; 512 prop_array_t replies;
513 prop_dictionary_t dict; 513 prop_dictionary_t dict;
514 unsigned i; 514 unsigned i;
 515 id_t id;
 516 int defaultq;
515 int error, error2; 517 int error, error2;
516 int skip = 0; 518 int skip = 0;
517 519
518 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 520 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
519 521
520 args.qc_type = QCT_CURSOROPEN; 522 args.qc_type = QCT_CURSOROPEN;
521 args.u.cursoropen.qc_cursor = &cursor; 523 args.u.cursoropen.qc_cursor = &cursor;
522 error = VFS_QUOTACTL(mp, QUOTACTL_CURSOROPEN, &args); 524 error = VFS_QUOTACTL(mp, QUOTACTL_CURSOROPEN, &args);
523 if (error) { 525 if (error) {
524 return error; 526 return error;
525 } 527 }
526 528
527 result.qr_keys = NULL; 529 result.qr_keys = NULL;
@@ -549,35 +551,35 @@ vfs_quotactl_getall(struct mount *mp, @@ -549,35 +551,35 @@ vfs_quotactl_getall(struct mount *mp,
549 goto err; 551 goto err;
550 } 552 }
551 553
552 replies = prop_array_create(); 554 replies = prop_array_create();
553 if (replies == NULL) { 555 if (replies == NULL) {
554 error = ENOMEM; 556 error = ENOMEM;
555 goto err; 557 goto err;
556 } 558 }
557 559
558 if (skip) { 560 if (skip) {
559 goto skip; 561 goto skip;
560 } 562 }
561 563
562 dict = vfs_quotactl_getall_makereply(0, 1, &result.qr_defblocks, 
563 &result.qr_deffiles); 
564 if (!prop_array_add_and_rel(replies, dict)) { 
565 error = ENOMEM; 
566 goto err; 
567 } 
568 
569 for (i = 0; i < result.qr_num; i += 2) { 564 for (i = 0; i < result.qr_num; i += 2) {
570 dict = vfs_quotactl_getall_makereply(result.qr_keys[i].qk_id,0, 565 id = result.qr_keys[i].qk_id;
 566 if (id == QUOTA_DEFAULTID) {
 567 id = 0;
 568 defaultq = 1;
 569 } else {
 570 defaultq = 0;
 571 }
 572 dict = vfs_quotactl_getall_makereply(id, defaultq,
571 &result.qr_vals[i], 573 &result.qr_vals[i],
572 &result.qr_vals[i+1]); 574 &result.qr_vals[i+1]);
573 if (dict == NULL) { 575 if (dict == NULL) {
574 error = ENOMEM; 576 error = ENOMEM;
575 goto err; 577 goto err;
576 } 578 }
577 if (!prop_array_add_and_rel(replies, dict)) { 579 if (!prop_array_add_and_rel(replies, dict)) {
578 error = ENOMEM; 580 error = ENOMEM;
579 goto err; 581 goto err;
580 } 582 }
581 } 583 }
582 584
583skip: 585skip:

cvs diff -r1.22 -r1.23 src/sys/sys/quotactl.h (expand / switch to unified diff)

--- src/sys/sys/quotactl.h 2012/01/29 07:05:12 1.22
+++ src/sys/sys/quotactl.h 2012/01/29 07:06:01 1.23
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: quotactl.h,v 1.22 2012/01/29 07:05:12 dholland Exp $ */ 1/* $NetBSD: quotactl.h,v 1.23 2012/01/29 07:06:01 dholland Exp $ */
2/*- 2/*-
3 * Copyright (c) 2011 The NetBSD Foundation, Inc. 3 * Copyright (c) 2011 The NetBSD Foundation, Inc.
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by David A. Holland. 7 * by David A. Holland.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -97,25 +97,23 @@ struct vfs_quotactl_args { @@ -97,25 +97,23 @@ struct vfs_quotactl_args {
97 struct { 97 struct {
98 const struct quotakey *qc_key; 98 const struct quotakey *qc_key;
99 } delete; 99 } delete;
100 struct { 100 struct {
101 struct quotakcursor *qc_cursor; 101 struct quotakcursor *qc_cursor;
102 } cursoropen; 102 } cursoropen;
103 struct { 103 struct {
104 struct quotakcursor *qc_cursor; 104 struct quotakcursor *qc_cursor;
105 } cursorclose; 105 } cursorclose;
106 struct { 106 struct {
107 struct quotakcursor *qc_cursor; 107 struct quotakcursor *qc_cursor;
108 int qc_idtype; 108 int qc_idtype;
109 struct quota_getall_result { 109 struct quota_getall_result {
110 struct quotaval qr_defblocks; 
111 struct quotaval qr_deffiles; 
112 struct quotakey *qr_keys; 110 struct quotakey *qr_keys;
113 struct quotaval *qr_vals; 111 struct quotaval *qr_vals;
114 unsigned qr_num; 112 unsigned qr_num;
115 unsigned qr_max; 113 unsigned qr_max;
116 } *qc_result; 114 } *qc_result;
117 } getall; 115 } getall;
118 } u; 116 } u;
119}; 117};
120 118
121#endif /* _SYS_QUOTACTL_H_ */ 119#endif /* _SYS_QUOTACTL_H_ */

cvs diff -r1.21 -r1.22 src/sys/ufs/ufs/ufs_quota2.c (expand / switch to unified diff)

--- src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 07:05:12 1.21
+++ src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 07:06:02 1.22
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ufs_quota2.c,v 1.21 2012/01/29 07:05:12 dholland Exp $ */ 1/* $NetBSD: ufs_quota2.c,v 1.22 2012/01/29 07:06:02 dholland Exp $ */
2/*- 2/*-
3 * Copyright (c) 2010 Manuel Bouyer 3 * Copyright (c) 2010 Manuel Bouyer
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -16,27 +16,27 @@ @@ -16,27 +16,27 @@
16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE. 25 * POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.21 2012/01/29 07:05:12 dholland Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.22 2012/01/29 07:06:02 dholland Exp $");
30 30
31#include <sys/buf.h> 31#include <sys/buf.h>
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/kernel.h> 33#include <sys/kernel.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/malloc.h> 35#include <sys/malloc.h>
36#include <sys/namei.h> 36#include <sys/namei.h>
37#include <sys/file.h> 37#include <sys/file.h>
38#include <sys/proc.h> 38#include <sys/proc.h>
39#include <sys/vnode.h> 39#include <sys/vnode.h>
40#include <sys/mount.h> 40#include <sys/mount.h>
41#include <sys/fstrans.h> 41#include <sys/fstrans.h>
42#include <sys/kauth.h> 42#include <sys/kauth.h>
@@ -1045,139 +1045,178 @@ quota2_handle_cmd_getall(struct ufsmount @@ -1045,139 +1045,178 @@ quota2_handle_cmd_getall(struct ufsmount
1045 int idtype, struct quota_getall_result *result) 1045 int idtype, struct quota_getall_result *result)
1046{ 1046{
1047 int error; 1047 int error;
1048 struct ufsq2_cursor *cursor; 1048 struct ufsq2_cursor *cursor;
1049 struct quota2_header *q2h; 1049 struct quota2_header *q2h;
1050 struct quota2_entry q2e; 1050 struct quota2_entry q2e;
1051 struct buf *hbp; 1051 struct buf *hbp;
1052 uint64_t offset; 1052 uint64_t offset;
1053 int i, j; 1053 int i, j;
1054 int quota2_hash_size; 1054 int quota2_hash_size;
1055 const int needswap = UFS_MPNEEDSWAP(ump); 1055 const int needswap = UFS_MPNEEDSWAP(ump);
1056 struct getuids gu; 1056 struct getuids gu;
1057 id_t junkid; 1057 id_t junkid;
1058 struct quotaval qv; 1058 struct quotakey bkey, fkey;
 1059 struct quotaval bval, fval;
 1060 int dobval = 0, dofval = 0;
1059 unsigned num, maxnum; 1061 unsigned num, maxnum;
1060 int skipfirst, skiplast; 1062 int skipfirst, skiplast;
 1063 int maxreturn, numreturn;
1061 1064
1062 cursor = Q2CURSOR(qkc); 1065 cursor = Q2CURSOR(qkc);
1063 error = q2cursor_check(cursor); 1066 error = q2cursor_check(cursor);
1064 if (error) { 1067 if (error) {
1065 return error; 1068 return error;
1066 } 1069 }
1067 1070
1068 if (ump->um_quotas[idtype] == NULLVP) { 1071 if (ump->um_quotas[idtype] == NULLVP) {
1069 return ENODEV; 1072 return ENODEV;
1070 } 1073 }
1071 1074
 1075 maxreturn = result->qr_max;
 1076 numreturn = 0;
 1077
1072 mutex_enter(&dqlock); 1078 mutex_enter(&dqlock);
1073 error = getq2h(ump, idtype, &hbp, &q2h, 0); 1079 error = getq2h(ump, idtype, &hbp, &q2h, 0);
1074 if (error) { 1080 if (error) {
1075 mutex_exit(&dqlock); 1081 mutex_exit(&dqlock);
1076 return error; 1082 return error;
1077 } 1083 }
1078 1084
1079 if (cursor->q2c_defaults_done == 0) { 1085 if (cursor->q2c_defaults_done == 0) {
1080 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); 1086 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap);
1081 if (cursor->q2c_blocks_done == 0) { 1087 if (cursor->q2c_blocks_done == 0) {
1082 q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &qv); 1088 q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &bval);
1083 result->qr_defblocks = qv; 1089 bkey.qk_idtype = idtype;
 1090 bkey.qk_id = QUOTA_DEFAULTID;
 1091 bkey.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
 1092 dobval = 1;
1084 cursor->q2c_blocks_done = 1; 1093 cursor->q2c_blocks_done = 1;
1085 } 1094 }
1086 if (cursor->q2c_blocks_done == 1) { 1095 if (cursor->q2c_blocks_done == 1) {
1087 q2e_to_quotaval(&q2e, 1, &junkid, QL_FILE, &qv); 1096 q2e_to_quotaval(&q2e, 1, &junkid, QL_FILE, &fval);
1088 result->qr_deffiles = qv; 1097 fkey.qk_idtype = idtype;
 1098 fkey.qk_id = QUOTA_DEFAULTID;
 1099 fkey.qk_objtype = QUOTA_OBJTYPE_FILES;
 1100 dofval = 1;
1089 cursor->q2c_blocks_done = 0; 1101 cursor->q2c_blocks_done = 0;
1090 cursor->q2c_defaults_done = 1; 1102 cursor->q2c_defaults_done = 1;
1091 } 1103 }
1092 } 1104 }
1093 1105
1094 /* 1106 /*
1095 * we can't directly get entries as we can't walk the list 1107 * we can't directly get entries as we can't walk the list
1096 * with qdlock and grab dq_interlock to read the entries 1108 * with qdlock and grab dq_interlock to read the entries
1097 * at the same time. So just walk the lists to build a list of uid, 1109 * at the same time. So just walk the lists to build a list of uid,
1098 * and then read entries for these uids 1110 * and then read entries for these uids
1099 */ 1111 */
1100 memset(&gu, 0, sizeof(gu)); 1112 memset(&gu, 0, sizeof(gu));
1101 quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap); 1113 quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap);
1102 1114
1103 /* if the table size has changed, make the caller start over */ 1115 /* if the table size has changed, make the caller start over */
1104 if (cursor->q2c_hashsize == 0) { 1116 if (cursor->q2c_hashsize == 0) {
1105 cursor->q2c_hashsize = quota2_hash_size; 1117 cursor->q2c_hashsize = quota2_hash_size;
1106 } else if (cursor->q2c_hashsize != quota2_hash_size) { 1118 } else if (cursor->q2c_hashsize != quota2_hash_size) {
1107 error = EDEADLK; 1119 error = EDEADLK;
1108 goto fail; 1120 goto fail;
1109 } 1121 }
1110 1122
1111 gu.skip = cursor->q2c_uidpos; 1123 gu.skip = cursor->q2c_uidpos;
1112 gu.seen = 0; 1124 gu.seen = 0;
1113 gu.limit = result->qr_max / 2; 1125 gu.limit = (maxreturn - numreturn) / 2;
1114 if (gu.limit == 0 && result->qr_max > 0) { 1126 if (gu.limit == 0 && (maxreturn - numreturn) > 0) {
1115 gu.limit = 1; 1127 gu.limit = 1;
1116 } 1128 }
 1129 if (dobval && gu.limit > 0)
 1130 gu.limit--;
 1131 if (dofval && gu.limit > 0)
 1132 gu.limit--;
1117 for (i = cursor->q2c_hashpos; i < quota2_hash_size ; i++) { 1133 for (i = cursor->q2c_hashpos; i < quota2_hash_size ; i++) {
1118 offset = q2h->q2h_entries[i]; 1134 offset = q2h->q2h_entries[i];
1119 gu.seen = 0; 1135 gu.seen = 0;
1120 error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gu, 1136 error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gu,
1121 quota2_getuids_callback); 1137 quota2_getuids_callback);
1122 if (error == Q2WL_ABORT) { 1138 if (error == Q2WL_ABORT) {
1123 /* got enough uids for now */ 1139 /* got enough uids for now */
1124 error = 0; 1140 error = 0;
1125 break; 1141 break;
1126 } 1142 }
1127 if (error) { 1143 if (error) {
1128 if (gu.uids != NULL) 1144 if (gu.uids != NULL)
1129 free(gu.uids, M_TEMP); 1145 free(gu.uids, M_TEMP);
1130 break; 1146 break;
1131 } 1147 }
1132 } 1148 }
1133 cursor->q2c_hashpos = i; 1149 cursor->q2c_hashpos = i;
1134 cursor->q2c_uidpos = gu.seen; 1150 cursor->q2c_uidpos = gu.seen;
1135 1151
1136fail: 1152fail:
1137 mutex_exit(&dqlock); 1153 mutex_exit(&dqlock);
1138 brelse(hbp, 0); 1154 brelse(hbp, 0);
1139 if (error) 1155 if (error)
1140 return error; 1156 return error;
1141 1157
1142 maxnum = gu.nuids*2; 1158 maxnum = gu.nuids*2;
 1159 if (dobval)
 1160 maxnum++;
 1161 if (dofval)
 1162 maxnum++;
1143 result->qr_keys = malloc(maxnum * sizeof(result->qr_keys[0]), 1163 result->qr_keys = malloc(maxnum * sizeof(result->qr_keys[0]),
1144 M_TEMP, M_WAITOK); 1164 M_TEMP, M_WAITOK);
1145 result->qr_vals = malloc(maxnum * sizeof(result->qr_vals[0]), 1165 result->qr_vals = malloc(maxnum * sizeof(result->qr_vals[0]),
1146 M_TEMP, M_WAITOK); 1166 M_TEMP, M_WAITOK);
1147 1167
 1168 if (dobval && numreturn < maxreturn) {
 1169 result->qr_keys[numreturn] = bkey;
 1170 result->qr_vals[numreturn] = bval;
 1171 numreturn++;
 1172 }
 1173 if (dofval && numreturn < maxreturn) {
 1174 result->qr_keys[numreturn] = fkey;
 1175 result->qr_vals[numreturn] = fval;
 1176 numreturn++;
 1177 }
 1178 if (numreturn == maxreturn) {
 1179 return 0;
 1180 }
 1181
1148 /* 1182 /*
1149 * If we've already sent back the blocks value for the first id, 1183 * If we've already sent back the blocks value for the first id,
1150 * don't send it again (skipfirst). 1184 * don't send it again (skipfirst).
1151 * 1185 *
1152 * If we have an odd number of available result slots and we 1186 * If we have an odd number of available result slots and we
1153 * aren't going to skip the first result entry, we need to 1187 * aren't going to skip the first result entry, we need to
1154 * leave off the last result entry (skiplast). 1188 * leave off the last result entry (skiplast).
1155 */ 1189 */
1156 skipfirst = (cursor->q2c_blocks_done != 0); 1190 skipfirst = (cursor->q2c_blocks_done != 0);
1157 skiplast = skipfirst == 0 && (result->qr_max < maxnum); 1191 skiplast = skipfirst == 0 && (result->qr_max < maxnum);
1158 num = 0; 1192 num = 0;
1159 for (j = 0; j < gu.nuids; j++) { 1193 for (j = 0; j < gu.nuids; j++) {
1160 error = quota2_result_add_q2e(ump, idtype, 1194 error = quota2_result_add_q2e(ump, idtype,
1161 gu.uids[j], result, j*2, 1195 gu.uids[j], result, numreturn + j*2,
1162 j == 0 && skipfirst, 1196 j == 0 && skipfirst,
1163 j + 1 == gu.nuids && skiplast); 1197 j + 1 == gu.nuids && skiplast);
1164 if (error == ENOENT) 1198 if (error == ENOENT)
1165 continue; 1199 continue;
1166 if (error) 1200 if (error)
1167 break; 1201 break;
1168 num += 2; 1202 if ((j == 0 && skipfirst) || (j + 1 == gu.nuids && skiplast)) {
 1203 num += 1;
 1204 } else {
 1205 num += 2;
 1206 }
1169 } 1207 }
1170 result->qr_num = num; 1208 numreturn += num;
 1209 result->qr_num = numreturn;
1171 1210
1172 cursor->q2c_blocks_done = skiplast; 1211 cursor->q2c_blocks_done = skiplast;
1173 1212
1174 free(gu.uids, M_TEMP); 1213 free(gu.uids, M_TEMP);
1175 return error; 1214 return error;
1176} 1215}
1177 1216
1178int 1217int
1179quota2_handle_cmd_cursoropen(struct ufsmount *ump, struct quotakcursor *qkc) 1218quota2_handle_cmd_cursoropen(struct ufsmount *ump, struct quotakcursor *qkc)
1180{ 1219{
1181 struct ufsq2_cursor *cursor; 1220 struct ufsq2_cursor *cursor;
1182 1221
1183 CTASSERT(sizeof(*cursor) <= sizeof(qkc->u.qkc_space)); 1222 CTASSERT(sizeof(*cursor) <= sizeof(qkc->u.qkc_space));