Sun Jan 29 07:04:22 2012 UTC ()
Teach quota2 QUOTACTL_GETALL to start in the middle, step 2.


(dholland)
diff -r1.19 -r1.20 src/sys/ufs/ufs/ufs_quota2.c

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

--- src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 07:03:47 1.19
+++ src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 07:04:21 1.20
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ufs_quota2.c,v 1.19 2012/01/29 07:03:47 dholland Exp $ */ 1/* $NetBSD: ufs_quota2.c,v 1.20 2012/01/29 07:04:21 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.19 2012/01/29 07:03:47 dholland Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.20 2012/01/29 07:04:21 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>
@@ -951,90 +951,121 @@ quota2_handle_cmd_get(struct ufsmount *u @@ -951,90 +951,121 @@ quota2_handle_cmd_get(struct ufsmount *u
951 (void)id2; 951 (void)id2;
952 } else 952 } else
953 error = quota2_fetch_q2e(ump, qk, ret); 953 error = quota2_fetch_q2e(ump, qk, ret);
954  954
955 return error; 955 return error;
956} 956}
957 957
958struct ufsq2_cursor { 958struct ufsq2_cursor {
959 uint32_t q2c_magic; /* magic number */ 959 uint32_t q2c_magic; /* magic number */
960 int q2c_hashsize; /* size of hash table at last go */ 960 int q2c_hashsize; /* size of hash table at last go */
961 961
962 int q2c_defaults_done; /* true if we've returned the default values */ 962 int q2c_defaults_done; /* true if we've returned the default values */
963 int q2c_hashpos; /* slot to start at in hash table */ 963 int q2c_hashpos; /* slot to start at in hash table */
 964 int q2c_uidpos; /* number of ids we've handled */
964 int q2c_blocks_done; /* true if we've returned the blocks value */ 965 int q2c_blocks_done; /* true if we've returned the blocks value */
965}; 966};
966 967
967#define Q2C_MAGIC (0xbeebe111) 968#define Q2C_MAGIC (0xbeebe111)
968 969
969#define Q2CURSOR(qkc) ((struct ufsq2_cursor *)&qkc->u.qkc_space[0]) 970#define Q2CURSOR(qkc) ((struct ufsq2_cursor *)&qkc->u.qkc_space[0])
970 971
 972static int
 973q2cursor_check(struct ufsq2_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_defaults_done != 0 && cursor->q2c_defaults_done != 1) {
 983 return EINVAL;
 984 }
 985 if (cursor->q2c_hashpos < 0 || cursor->q2c_uidpos < 0) {
 986 return EINVAL;
 987 }
 988 if (cursor->q2c_blocks_done != 0 && cursor->q2c_blocks_done != 1) {
 989 return EINVAL;
 990 }
 991 return 0;
 992}
971 993
972struct getuids { 994struct getuids {
973 long nuids; /* number of uids in array */ 995 long nuids; /* number of uids in array */
974 long size; /* size of array */ 996 long size; /* size of array */
975 uid_t *uids; /* array of uids, dynamically allocated */ 997 uid_t *uids; /* array of uids, dynamically allocated */
 998 long skip;
 999 long seen;
976}; 1000};
977 1001
978static int 1002static int
979quota2_getuids_callback(struct ufsmount *ump, uint64_t *offp, 1003quota2_getuids_callback(struct ufsmount *ump, uint64_t *offp,
980 struct quota2_entry *q2ep, uint64_t off, void *v) 1004 struct quota2_entry *q2ep, uint64_t off, void *v)
981{ 1005{
982 struct getuids *gu = v; 1006 struct getuids *gu = v;
983 uid_t *newuids; 1007 uid_t *newuids;
984#ifdef FFS_EI 1008#ifdef FFS_EI
985 const int needswap = UFS_MPNEEDSWAP(ump); 1009 const int needswap = UFS_MPNEEDSWAP(ump);
986#endif 1010#endif
987 1011
 1012 if (gu->skip > 0) {
 1013 gu->skip--;
 1014 return 0;
 1015 }
988 if (gu->nuids == gu->size) { 1016 if (gu->nuids == gu->size) {
989 newuids = realloc(gu->uids, gu->size + PAGE_SIZE, M_TEMP, 1017 newuids = realloc(gu->uids, gu->size + PAGE_SIZE, M_TEMP,
990 M_WAITOK); 1018 M_WAITOK);
991 if (newuids == NULL) { 1019 if (newuids == NULL) {
992 free(gu->uids, M_TEMP); 1020 free(gu->uids, M_TEMP);
993 return ENOMEM; 1021 return ENOMEM;
994 } 1022 }
995 gu->uids = newuids; 1023 gu->uids = newuids;
996 gu->size += (PAGE_SIZE / sizeof(uid_t)); 1024 gu->size += (PAGE_SIZE / sizeof(uid_t));
997 } 1025 }
998 gu->uids[gu->nuids] = ufs_rw32(q2ep->q2e_uid, needswap); 1026 gu->uids[gu->nuids] = ufs_rw32(q2ep->q2e_uid, needswap);
999 gu->nuids++; 1027 gu->nuids++;
 1028 gu->seen++;
1000 return 0; 1029 return 0;
1001} 1030}
1002 1031
1003int 1032int
1004quota2_handle_cmd_getall(struct ufsmount *ump, struct quotakcursor *qkc, 1033quota2_handle_cmd_getall(struct ufsmount *ump, struct quotakcursor *qkc,
1005 int idtype, struct quota_getall_result *result) 1034 int idtype, struct quota_getall_result *result)
1006{ 1035{
1007 int error; 1036 int error;
1008 struct ufsq2_cursor *cursor; 1037 struct ufsq2_cursor *cursor;
1009 struct quota2_header *q2h; 1038 struct quota2_header *q2h;
1010 struct quota2_entry q2e; 1039 struct quota2_entry q2e;
1011 struct buf *hbp; 1040 struct buf *hbp;
1012 uint64_t offset; 1041 uint64_t offset;
1013 int i, j; 1042 int i, j;
1014 int quota2_hash_size; 1043 int quota2_hash_size;
1015 const int needswap = UFS_MPNEEDSWAP(ump); 1044 const int needswap = UFS_MPNEEDSWAP(ump);
1016 struct getuids gu; 1045 struct getuids gu;
1017 id_t junkid; 1046 id_t junkid;
1018 struct quotaval qv; 1047 struct quotaval qv;
1019 unsigned num, maxnum; 1048 unsigned num, maxnum;
1020 1049
1021 cursor = Q2CURSOR(qkc); 1050 cursor = Q2CURSOR(qkc);
1022 if (cursor->q2c_magic != Q2C_MAGIC) { 1051 error = q2cursor_check(cursor);
1023 return EINVAL; 1052 if (error) {
 1053 return error;
1024 } 1054 }
1025 1055
1026 if (ump->um_quotas[idtype] == NULLVP) 1056 if (ump->um_quotas[idtype] == NULLVP) {
1027 return ENODEV; 1057 return ENODEV;
 1058 }
1028 1059
1029 mutex_enter(&dqlock); 1060 mutex_enter(&dqlock);
1030 error = getq2h(ump, idtype, &hbp, &q2h, 0); 1061 error = getq2h(ump, idtype, &hbp, &q2h, 0);
1031 if (error) { 1062 if (error) {
1032 mutex_exit(&dqlock); 1063 mutex_exit(&dqlock);
1033 return error; 1064 return error;
1034 } 1065 }
1035 1066
1036 if (cursor->q2c_defaults_done == 0) { 1067 if (cursor->q2c_defaults_done == 0) {
1037 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); 1068 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap);
1038 if (cursor->q2c_blocks_done == 0) { 1069 if (cursor->q2c_blocks_done == 0) {
1039 q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &qv); 1070 q2e_to_quotaval(&q2e, 1, &junkid, QL_BLOCK, &qv);
1040 result->qr_defblocks = qv; 1071 result->qr_defblocks = qv;
@@ -1055,43 +1086,41 @@ quota2_handle_cmd_getall(struct ufsmount @@ -1055,43 +1086,41 @@ quota2_handle_cmd_getall(struct ufsmount
1055 * and then read entries for these uids 1086 * and then read entries for these uids
1056 */ 1087 */
1057 memset(&gu, 0, sizeof(gu)); 1088 memset(&gu, 0, sizeof(gu));
1058 quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap); 1089 quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap);
1059 1090
1060 /* if the table size has changed, make the caller start over */ 1091 /* if the table size has changed, make the caller start over */
1061 if (cursor->q2c_hashsize == 0) { 1092 if (cursor->q2c_hashsize == 0) {
1062 cursor->q2c_hashsize = quota2_hash_size; 1093 cursor->q2c_hashsize = quota2_hash_size;
1063 } else if (cursor->q2c_hashsize != quota2_hash_size) { 1094 } else if (cursor->q2c_hashsize != quota2_hash_size) {
1064 error = EDEADLK; 1095 error = EDEADLK;
1065 goto fail; 1096 goto fail;
1066 } 1097 }
1067 1098
1068 /* why are these variables signed? */ 1099 gu.skip = cursor->q2c_uidpos;
1069 if (cursor->q2c_hashpos < 0) { 1100 gu.seen = 0;
1070 error = EINVAL; 
1071 goto fail; 
1072 } 
1073 
1074 for (i = cursor->q2c_hashpos; i < quota2_hash_size ; i++) { 1101 for (i = cursor->q2c_hashpos; i < quota2_hash_size ; i++) {
1075 offset = q2h->q2h_entries[i]; 1102 offset = q2h->q2h_entries[i];
 1103 gu.seen = 0;
1076 error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gu, 1104 error = quota2_walk_list(ump, hbp, idtype, &offset, 0, &gu,
1077 quota2_getuids_callback); 1105 quota2_getuids_callback);
1078 if (error) { 1106 if (error) {
1079 if (gu.uids != NULL) 1107 if (gu.uids != NULL)
1080 free(gu.uids, M_TEMP); 1108 free(gu.uids, M_TEMP);
1081 break; 1109 break;
1082 } 1110 }
1083 } 1111 }
1084 cursor->q2c_hashpos = i; 1112 cursor->q2c_hashpos = i;
 1113 cursor->q2c_uidpos = gu.seen;
1085 1114
1086fail: 1115fail:
1087 mutex_exit(&dqlock); 1116 mutex_exit(&dqlock);
1088 brelse(hbp, 0); 1117 brelse(hbp, 0);
1089 if (error) 1118 if (error)
1090 return error; 1119 return error;
1091 1120
1092 maxnum = gu.nuids*2; 1121 maxnum = gu.nuids*2;
1093 result->qr_keys = malloc(maxnum * sizeof(result->qr_keys[0]), 1122 result->qr_keys = malloc(maxnum * sizeof(result->qr_keys[0]),
1094 M_TEMP, M_WAITOK); 1123 M_TEMP, M_WAITOK);
1095 result->qr_vals = malloc(maxnum * sizeof(result->qr_vals[0]), 1124 result->qr_vals = malloc(maxnum * sizeof(result->qr_vals[0]),
1096 M_TEMP, M_WAITOK); 1125 M_TEMP, M_WAITOK);
1097 1126
@@ -1111,40 +1140,44 @@ fail: @@ -1111,40 +1140,44 @@ fail:
1111 return error; 1140 return error;
1112} 1141}
1113 1142
1114int 1143int
1115quota2_handle_cmd_cursoropen(struct ufsmount *ump, struct quotakcursor *qkc) 1144quota2_handle_cmd_cursoropen(struct ufsmount *ump, struct quotakcursor *qkc)
1116{ 1145{
1117 struct ufsq2_cursor *cursor; 1146 struct ufsq2_cursor *cursor;
1118 1147
1119 CTASSERT(sizeof(*cursor) <= sizeof(qkc->u.qkc_space)); 1148 CTASSERT(sizeof(*cursor) <= sizeof(qkc->u.qkc_space));
1120 cursor = Q2CURSOR(qkc); 1149 cursor = Q2CURSOR(qkc);
1121 1150
1122 cursor->q2c_magic = Q2C_MAGIC; 1151 cursor->q2c_magic = Q2C_MAGIC;
1123 cursor->q2c_hashsize = 0; 1152 cursor->q2c_hashsize = 0;
1124 cursor->q2c_hashpos = 0; 1153
1125 cursor->q2c_defaults_done = 0; 1154 cursor->q2c_defaults_done = 0;
 1155 cursor->q2c_hashpos = 0;
 1156 cursor->q2c_uidpos = 0;
1126 cursor->q2c_blocks_done = 0; 1157 cursor->q2c_blocks_done = 0;
1127 return 0; 1158 return 0;
1128} 1159}
1129 1160
1130int 1161int
1131quota2_handle_cmd_cursorclose(struct ufsmount *ump, struct quotakcursor *qkc) 1162quota2_handle_cmd_cursorclose(struct ufsmount *ump, struct quotakcursor *qkc)
1132{ 1163{
1133 struct ufsq2_cursor *cursor; 1164 struct ufsq2_cursor *cursor;
 1165 int error;
1134 1166
1135 cursor = Q2CURSOR(qkc); 1167 cursor = Q2CURSOR(qkc);
1136 if (cursor->q2c_magic != Q2C_MAGIC) { 1168 error = q2cursor_check(cursor);
1137 return EINVAL; 1169 if (error) {
 1170 return error;
1138 } 1171 }
1139 1172
1140 /* nothing to do */ 1173 /* nothing to do */
1141 1174
1142 return 0; 1175 return 0;
1143} 1176}
1144 1177
1145int 1178int
1146q2sync(struct mount *mp) 1179q2sync(struct mount *mp)
1147{ 1180{
1148 return 0; 1181 return 0;
1149} 1182}
1150 1183