Sun Jan 29 06:52:39 2012 UTC ()
The handling of QUOTACTL_CLEAR does not use the proplib data
dictionary, so don't pass it.

Note: this change requires a kernel version bump.


(dholland)
diff -r1.16 -r1.17 src/sys/kern/vfs_quotactl.c
diff -r1.14 -r1.15 src/sys/sys/quotactl.h
diff -r1.88 -r1.89 src/sys/ufs/ufs/ufs_quota.c
diff -r1.10 -r1.11 src/sys/ufs/ufs/ufs_quota.h
diff -r1.11 -r1.12 src/sys/ufs/ufs/ufs_quota2.c

cvs diff -r1.16 -r1.17 src/sys/kern/vfs_quotactl.c (switch to unified diff)

--- src/sys/kern/vfs_quotactl.c 2012/01/29 06:51:42 1.16
+++ src/sys/kern/vfs_quotactl.c 2012/01/29 06:52:38 1.17
@@ -1,603 +1,602 @@ @@ -1,603 +1,602 @@
1/* $NetBSD: vfs_quotactl.c,v 1.16 2012/01/29 06:51:42 dholland Exp $ */ 1/* $NetBSD: vfs_quotactl.c,v 1.17 2012/01/29 06:52:38 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:
15 * 1. Redistributions of source code must retain the above copyright 15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer. 16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright 17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the 18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution. 19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors 20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 22 * without specific prior written permission.
23 * 23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE. 34 * SUCH DAMAGE.
35 * 35 *
36 * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95 36 * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95
37 * From NetBSD: ufs_vfsops.c,v 1.42 2011/03/24 17:05:46 bouyer Exp 37 * From NetBSD: ufs_vfsops.c,v 1.42 2011/03/24 17:05:46 bouyer Exp
38 */ 38 */
39 39
40/* 40/*
41 * Copyright (c) 1982, 1986, 1990, 1993, 1995 41 * Copyright (c) 1982, 1986, 1990, 1993, 1995
42 * The Regents of the University of California. All rights reserved. 42 * The Regents of the University of California. All rights reserved.
43 * 43 *
44 * This code is derived from software contributed to Berkeley by 44 * This code is derived from software contributed to Berkeley by
45 * Robert Elz at The University of Melbourne. 45 * Robert Elz at The University of Melbourne.
46 * 46 *
47 * Redistribution and use in source and binary forms, with or without 47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions 48 * modification, are permitted provided that the following conditions
49 * are met: 49 * are met:
50 * 1. Redistributions of source code must retain the above copyright 50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer. 51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright 52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the 53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution. 54 * documentation and/or other materials provided with the distribution.
55 * 3. Neither the name of the University nor the names of its contributors 55 * 3. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software 56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission. 57 * without specific prior written permission.
58 * 58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE. 69 * SUCH DAMAGE.
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.16 2012/01/29 06:51:42 dholland Exp $"); 83__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.17 2012/01/29 06:52:38 dholland Exp $");
84 84
85#include <sys/mount.h> 85#include <sys/mount.h>
86#include <sys/quota.h> 86#include <sys/quota.h>
87#include <sys/quotactl.h> 87#include <sys/quotactl.h>
88#include <quota/quotaprop.h> 88#include <quota/quotaprop.h>
89 89
90static int 90static int
91vfs_quotactl_getversion(struct mount *mp, 91vfs_quotactl_getversion(struct mount *mp,
92 prop_dictionary_t cmddict, int q2type, 92 prop_dictionary_t cmddict, int q2type,
93 prop_array_t datas) 93 prop_array_t datas)
94{ 94{
95 prop_array_t replies; 95 prop_array_t replies;
96 prop_dictionary_t data; 96 prop_dictionary_t data;
97 int q2version; 97 int q2version;
98 struct vfs_quotactl_args args; 98 struct vfs_quotactl_args args;
99 int error; 99 int error;
100 100
101 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 101 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
102 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 102 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
103 103
104 args.qc_type = QCT_GETVERSION; 104 args.qc_type = QCT_GETVERSION;
105 args.u.getversion.qc_version_ret = &q2version; 105 args.u.getversion.qc_version_ret = &q2version;
106 error = VFS_QUOTACTL(mp, QUOTACTL_GETVERSION, &args); 106 error = VFS_QUOTACTL(mp, QUOTACTL_GETVERSION, &args);
107 if (error) { 107 if (error) {
108 return error; 108 return error;
109 } 109 }
110 110
111 data = prop_dictionary_create(); 111 data = prop_dictionary_create();
112 if (data == NULL) { 112 if (data == NULL) {
113 return ENOMEM; 113 return ENOMEM;
114 } 114 }
115 115
116 if (!prop_dictionary_set_int8(data, "version", q2version)) { 116 if (!prop_dictionary_set_int8(data, "version", q2version)) {
117 prop_object_release(data); 117 prop_object_release(data);
118 return ENOMEM; 118 return ENOMEM;
119 } 119 }
120 120
121 replies = prop_array_create(); 121 replies = prop_array_create();
122 if (replies == NULL) { 122 if (replies == NULL) {
123 prop_object_release(data); 123 prop_object_release(data);
124 return ENOMEM; 124 return ENOMEM;
125 } 125 }
126 126
127 if (!prop_array_add_and_rel(replies, data)) { 127 if (!prop_array_add_and_rel(replies, data)) {
128 prop_object_release(data); 128 prop_object_release(data);
129 prop_object_release(replies); 129 prop_object_release(replies);
130 return ENOMEM; 130 return ENOMEM;
131 } 131 }
132 132
133 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 133 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
134 prop_object_release(replies); 134 prop_object_release(replies);
135 return ENOMEM; 135 return ENOMEM;
136 } 136 }
137 137
138 return error; 138 return error;
139} 139}
140 140
141static int 141static int
142vfs_quotactl_quotaon(struct mount *mp, 142vfs_quotactl_quotaon(struct mount *mp,
143 prop_dictionary_t cmddict, int q2type, 143 prop_dictionary_t cmddict, int q2type,
144 prop_array_t datas) 144 prop_array_t datas)
145{ 145{
146 struct vfs_quotactl_args args; 146 struct vfs_quotactl_args args;
147 147
148 args.qc_type = QCT_PROPLIB; 148 args.qc_type = QCT_PROPLIB;
149 args.u.proplib.qc_cmddict = cmddict; 149 args.u.proplib.qc_cmddict = cmddict;
150 args.u.proplib.qc_q2type = q2type; 150 args.u.proplib.qc_q2type = q2type;
151 args.u.proplib.qc_datas = datas; 151 args.u.proplib.qc_datas = datas;
152 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAON, &args); 152 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAON, &args);
153} 153}
154 154
155static int 155static int
156vfs_quotactl_quotaoff(struct mount *mp, 156vfs_quotactl_quotaoff(struct mount *mp,
157 prop_dictionary_t cmddict, int q2type, 157 prop_dictionary_t cmddict, int q2type,
158 prop_array_t datas) 158 prop_array_t datas)
159{ 159{
160 struct vfs_quotactl_args args; 160 struct vfs_quotactl_args args;
161 161
162 args.qc_type = QCT_PROPLIB; 162 args.qc_type = QCT_PROPLIB;
163 args.u.proplib.qc_cmddict = cmddict; 163 args.u.proplib.qc_cmddict = cmddict;
164 args.u.proplib.qc_q2type = q2type; 164 args.u.proplib.qc_q2type = q2type;
165 args.u.proplib.qc_datas = datas; 165 args.u.proplib.qc_datas = datas;
166 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAOFF, &args); 166 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAOFF, &args);
167} 167}
168 168
169static int 169static int
170vfs_quotactl_get_addreply(const struct quotakey *qk, 170vfs_quotactl_get_addreply(const struct quotakey *qk,
171 const struct quotaval *blocks, 171 const struct quotaval *blocks,
172 const struct quotaval *files, 172 const struct quotaval *files,
173 prop_array_t replies) 173 prop_array_t replies)
174{ 174{
175 prop_dictionary_t dict; 175 prop_dictionary_t dict;
176 id_t id; 176 id_t id;
177 int defaultq; 177 int defaultq;
178 uint64_t *valuesp[QUOTA_NLIMITS]; 178 uint64_t *valuesp[QUOTA_NLIMITS];
179 179
180 /* XXX illegal casts */ 180 /* XXX illegal casts */
181 valuesp[QUOTA_LIMIT_BLOCK] = (void *)(intptr_t)&blocks->qv_hardlimit; 181 valuesp[QUOTA_LIMIT_BLOCK] = (void *)(intptr_t)&blocks->qv_hardlimit;
182 valuesp[QUOTA_LIMIT_FILE] = (void *)(intptr_t)&files->qv_hardlimit; 182 valuesp[QUOTA_LIMIT_FILE] = (void *)(intptr_t)&files->qv_hardlimit;
183 183
184 if (qk->qk_id == QUOTA_DEFAULTID) { 184 if (qk->qk_id == QUOTA_DEFAULTID) {
185 id = 0; 185 id = 0;
186 defaultq = 1; 186 defaultq = 1;
187 } else { 187 } else {
188 id = qk->qk_id; 188 id = qk->qk_id;
189 defaultq = 0; 189 defaultq = 0;
190 } 190 }
191 191
192 dict = quota64toprop(id, defaultq, valuesp, 192 dict = quota64toprop(id, defaultq, valuesp,
193 ufs_quota_entry_names, UFS_QUOTA_NENTRIES, 193 ufs_quota_entry_names, UFS_QUOTA_NENTRIES,
194 ufs_quota_limit_names, QUOTA_NLIMITS); 194 ufs_quota_limit_names, QUOTA_NLIMITS);
195 if (dict == NULL) 195 if (dict == NULL)
196 return ENOMEM; 196 return ENOMEM;
197 if (!prop_array_add_and_rel(replies, dict)) { 197 if (!prop_array_add_and_rel(replies, dict)) {
198 prop_object_release(dict); 198 prop_object_release(dict);
199 return ENOMEM; 199 return ENOMEM;
200 } 200 }
201 201
202 return 0; 202 return 0;
203} 203}
204 204
205static int 205static int
206vfs_quotactl_get(struct mount *mp, 206vfs_quotactl_get(struct mount *mp,
207 prop_dictionary_t cmddict, int idtype, 207 prop_dictionary_t cmddict, int idtype,
208 prop_array_t datas) 208 prop_array_t datas)
209{ 209{
210 prop_object_iterator_t iter; 210 prop_object_iterator_t iter;
211 prop_dictionary_t data; 211 prop_dictionary_t data;
212 prop_array_t replies; 212 prop_array_t replies;
213 uint32_t id; 213 uint32_t id;
214 const char *idstr; 214 const char *idstr;
215 struct vfs_quotactl_args args; 215 struct vfs_quotactl_args args;
216 struct quotakey qk; 216 struct quotakey qk;
217 struct quotaval blocks, files; 217 struct quotaval blocks, files;
218 int error; 218 int error;
219 219
220 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 220 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
221 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 221 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
222 222
223 replies = prop_array_create(); 223 replies = prop_array_create();
224 if (replies == NULL) { 224 if (replies == NULL) {
225 return ENOMEM; 225 return ENOMEM;
226 } 226 }
227 227
228 iter = prop_array_iterator(datas); 228 iter = prop_array_iterator(datas);
229 if (iter == NULL) { 229 if (iter == NULL) {
230 prop_object_release(replies); 230 prop_object_release(replies);
231 return ENOMEM; 231 return ENOMEM;
232 } 232 }
233 233
234 while ((data = prop_object_iterator_next(iter)) != NULL) { 234 while ((data = prop_object_iterator_next(iter)) != NULL) {
235 qk.qk_idtype = idtype; 235 qk.qk_idtype = idtype;
236 236
237 if (!prop_dictionary_get_uint32(data, "id", &id)) { 237 if (!prop_dictionary_get_uint32(data, "id", &id)) {
238 if (!prop_dictionary_get_cstring_nocopy(data, "id", 238 if (!prop_dictionary_get_cstring_nocopy(data, "id",
239 &idstr)) 239 &idstr))
240 continue; 240 continue;
241 if (strcmp(idstr, "default")) { 241 if (strcmp(idstr, "default")) {
242 error = EINVAL; 242 error = EINVAL;
243 goto fail; 243 goto fail;
244 } 244 }
245 qk.qk_id = QUOTA_DEFAULTID; 245 qk.qk_id = QUOTA_DEFAULTID;
246 } else { 246 } else {
247 qk.qk_id = id; 247 qk.qk_id = id;
248 } 248 }
249 249
250 qk.qk_objtype = QUOTA_OBJTYPE_BLOCKS; 250 qk.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
251 251
252 args.qc_type = QCT_GET; 252 args.qc_type = QCT_GET;
253 args.u.get.qc_key = &qk; 253 args.u.get.qc_key = &qk;
254 args.u.get.qc_ret = &blocks; 254 args.u.get.qc_ret = &blocks;
255 error = VFS_QUOTACTL(mp, QUOTACTL_GET, &args); 255 error = VFS_QUOTACTL(mp, QUOTACTL_GET, &args);
256 if (error == EPERM) { 256 if (error == EPERM) {
257 /* XXX does this make sense? */ 257 /* XXX does this make sense? */
258 continue; 258 continue;
259 } else if (error == ENOENT) { 259 } else if (error == ENOENT) {
260 /* XXX does *this* make sense? */ 260 /* XXX does *this* make sense? */
261 continue; 261 continue;
262 } else if (error) { 262 } else if (error) {
263 goto fail; 263 goto fail;
264 } 264 }
265 265
266 qk.qk_objtype = QUOTA_OBJTYPE_FILES; 266 qk.qk_objtype = QUOTA_OBJTYPE_FILES;
267 267
268 args.qc_type = QCT_GET; 268 args.qc_type = QCT_GET;
269 args.u.get.qc_key = &qk; 269 args.u.get.qc_key = &qk;
270 args.u.get.qc_ret = &files; 270 args.u.get.qc_ret = &files;
271 error = VFS_QUOTACTL(mp, QUOTACTL_GET, &args); 271 error = VFS_QUOTACTL(mp, QUOTACTL_GET, &args);
272 if (error == EPERM) { 272 if (error == EPERM) {
273 /* XXX does this make sense? */ 273 /* XXX does this make sense? */
274 continue; 274 continue;
275 } else if (error == ENOENT) { 275 } else if (error == ENOENT) {
276 /* XXX does *this* make sense? */ 276 /* XXX does *this* make sense? */
277 continue; 277 continue;
278 } else if (error) { 278 } else if (error) {
279 goto fail; 279 goto fail;
280 } 280 }
281 281
282 error = vfs_quotactl_get_addreply(&qk, &blocks, &files, 282 error = vfs_quotactl_get_addreply(&qk, &blocks, &files,
283 replies); 283 replies);
284 } 284 }
285 285
286 prop_object_iterator_release(iter); 286 prop_object_iterator_release(iter);
287 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 287 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
288 error = ENOMEM; 288 error = ENOMEM;
289 } else { 289 } else {
290 error = 0; 290 error = 0;
291 } 291 }
292 292
293 return error; 293 return error;
294 294
295 fail: 295 fail:
296 prop_object_iterator_release(iter); 296 prop_object_iterator_release(iter);
297 prop_object_release(replies); 297 prop_object_release(replies);
298 return error; 298 return error;
299} 299}
300 300
301static int 301static int
302vfs_quotactl_put_extractinfo(prop_dictionary_t data, 302vfs_quotactl_put_extractinfo(prop_dictionary_t data,
303 struct quotaval *blocks, struct quotaval *files) 303 struct quotaval *blocks, struct quotaval *files)
304{ 304{
305 /* 305 /*
306 * So, the way proptoquota64 works is that you pass it an 306 * So, the way proptoquota64 works is that you pass it an
307 * array of pointers to uint64. Each of these pointers is 307 * array of pointers to uint64. Each of these pointers is
308 * supposed to point to 5 (UFS_QUOTA_NENTRIES) uint64s. This 308 * supposed to point to 5 (UFS_QUOTA_NENTRIES) uint64s. This
309 * array of pointers is the second argument. The third and 309 * array of pointers is the second argument. The third and
310 * forth argument are the names of the five values to extract, 310 * forth argument are the names of the five values to extract,
311 * and UFS_QUOTA_NENTRIES. The last two arguments are the 311 * and UFS_QUOTA_NENTRIES. The last two arguments are the
312 * names assocated with the pointers (QUOTATYPE_LDICT_BLOCK, 312 * names assocated with the pointers (QUOTATYPE_LDICT_BLOCK,
313 * QUOTADICT_LTYPE_FILE) and the number of pointers. Most of 313 * QUOTADICT_LTYPE_FILE) and the number of pointers. Most of
314 * the existing code was unsafely casting struct quotaval 314 * the existing code was unsafely casting struct quotaval
315 * (formerly struct ufs_quota_entry) to (uint64_t *) and using 315 * (formerly struct ufs_quota_entry) to (uint64_t *) and using
316 * that as the block of 5 uint64s. Or worse, pointing to 316 * that as the block of 5 uint64s. Or worse, pointing to
317 * subregions of that and reducing the number of uint64s to 317 * subregions of that and reducing the number of uint64s to
318 * pull "adjacent" values. Demons fly out of your nose! 318 * pull "adjacent" values. Demons fly out of your nose!
319 */ 319 */
320 320
321 uint64_t bvals[UFS_QUOTA_NENTRIES]; 321 uint64_t bvals[UFS_QUOTA_NENTRIES];
322 uint64_t fvals[UFS_QUOTA_NENTRIES]; 322 uint64_t fvals[UFS_QUOTA_NENTRIES];
323 uint64_t *valptrs[QUOTA_NLIMITS]; 323 uint64_t *valptrs[QUOTA_NLIMITS];
324 int error; 324 int error;
325 325
326 valptrs[QUOTA_LIMIT_BLOCK] = bvals; 326 valptrs[QUOTA_LIMIT_BLOCK] = bvals;
327 valptrs[QUOTA_LIMIT_FILE] = fvals; 327 valptrs[QUOTA_LIMIT_FILE] = fvals;
328 error = proptoquota64(data, valptrs, 328 error = proptoquota64(data, valptrs,
329 ufs_quota_entry_names, UFS_QUOTA_NENTRIES, 329 ufs_quota_entry_names, UFS_QUOTA_NENTRIES,
330 ufs_quota_limit_names, QUOTA_NLIMITS); 330 ufs_quota_limit_names, QUOTA_NLIMITS);
331 if (error) { 331 if (error) {
332 return error; 332 return error;
333 } 333 }
334 334
335 /* 335 /*
336 * There are no symbolic constants for these indexes! 336 * There are no symbolic constants for these indexes!
337 */ 337 */
338 338
339 blocks->qv_hardlimit = bvals[0]; 339 blocks->qv_hardlimit = bvals[0];
340 blocks->qv_softlimit = bvals[1]; 340 blocks->qv_softlimit = bvals[1];
341 blocks->qv_usage = bvals[2]; 341 blocks->qv_usage = bvals[2];
342 blocks->qv_expiretime = bvals[3]; 342 blocks->qv_expiretime = bvals[3];
343 blocks->qv_grace = bvals[4]; 343 blocks->qv_grace = bvals[4];
344 files->qv_hardlimit = fvals[0]; 344 files->qv_hardlimit = fvals[0];
345 files->qv_softlimit = fvals[1]; 345 files->qv_softlimit = fvals[1];
346 files->qv_usage = fvals[2]; 346 files->qv_usage = fvals[2];
347 files->qv_expiretime = fvals[3]; 347 files->qv_expiretime = fvals[3];
348 files->qv_grace = fvals[4]; 348 files->qv_grace = fvals[4];
349 349
350 return 0; 350 return 0;
351} 351}
352 352
353static int 353static int
354vfs_quotactl_put(struct mount *mp, 354vfs_quotactl_put(struct mount *mp,
355 prop_dictionary_t cmddict, int q2type, 355 prop_dictionary_t cmddict, int q2type,
356 prop_array_t datas) 356 prop_array_t datas)
357{ 357{
358 prop_array_t replies; 358 prop_array_t replies;
359 prop_object_iterator_t iter; 359 prop_object_iterator_t iter;
360 prop_dictionary_t data; 360 prop_dictionary_t data;
361 int defaultq; 361 int defaultq;
362 uint32_t id; 362 uint32_t id;
363 const char *idstr; 363 const char *idstr;
364 struct quotakey qk; 364 struct quotakey qk;
365 struct quotaval blocks, files; 365 struct quotaval blocks, files;
366 struct vfs_quotactl_args args; 366 struct vfs_quotactl_args args;
367 int error; 367 int error;
368 368
369 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 369 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
370 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 370 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
371 371
372 replies = prop_array_create(); 372 replies = prop_array_create();
373 if (replies == NULL) 373 if (replies == NULL)
374 return ENOMEM; 374 return ENOMEM;
375 375
376 iter = prop_array_iterator(datas); 376 iter = prop_array_iterator(datas);
377 if (iter == NULL) { 377 if (iter == NULL) {
378 prop_object_release(replies); 378 prop_object_release(replies);
379 return ENOMEM; 379 return ENOMEM;
380 } 380 }
381 381
382 while ((data = prop_object_iterator_next(iter)) != NULL) { 382 while ((data = prop_object_iterator_next(iter)) != NULL) {
383 383
384 KASSERT(prop_object_type(data) == PROP_TYPE_DICTIONARY); 384 KASSERT(prop_object_type(data) == PROP_TYPE_DICTIONARY);
385 385
386 if (!prop_dictionary_get_uint32(data, "id", &id)) { 386 if (!prop_dictionary_get_uint32(data, "id", &id)) {
387 if (!prop_dictionary_get_cstring_nocopy(data, "id", 387 if (!prop_dictionary_get_cstring_nocopy(data, "id",
388 &idstr)) 388 &idstr))
389 continue; 389 continue;
390 if (strcmp(idstr, "default")) 390 if (strcmp(idstr, "default"))
391 continue; 391 continue;
392 id = 0; 392 id = 0;
393 defaultq = 1; 393 defaultq = 1;
394 } else { 394 } else {
395 defaultq = 0; 395 defaultq = 0;
396 } 396 }
397 397
398 error = vfs_quotactl_put_extractinfo(data, &blocks, &files); 398 error = vfs_quotactl_put_extractinfo(data, &blocks, &files);
399 if (error) { 399 if (error) {
400 goto err; 400 goto err;
401 } 401 }
402 402
403 qk.qk_idtype = q2type; 403 qk.qk_idtype = q2type;
404 qk.qk_id = defaultq ? QUOTA_DEFAULTID : id; 404 qk.qk_id = defaultq ? QUOTA_DEFAULTID : id;
405 qk.qk_objtype = QUOTA_OBJTYPE_BLOCKS; 405 qk.qk_objtype = QUOTA_OBJTYPE_BLOCKS;
406 406
407 args.qc_type = QCT_PUT; 407 args.qc_type = QCT_PUT;
408 args.u.put.qc_key = &qk; 408 args.u.put.qc_key = &qk;
409 args.u.put.qc_val = &blocks; 409 args.u.put.qc_val = &blocks;
410 error = VFS_QUOTACTL(mp, QUOTACTL_PUT, &args); 410 error = VFS_QUOTACTL(mp, QUOTACTL_PUT, &args);
411 if (error) { 411 if (error) {
412 goto err; 412 goto err;
413 } 413 }
414 414
415 qk.qk_idtype = q2type; 415 qk.qk_idtype = q2type;
416 qk.qk_id = defaultq ? QUOTA_DEFAULTID : id; 416 qk.qk_id = defaultq ? QUOTA_DEFAULTID : id;
417 qk.qk_objtype = QUOTA_OBJTYPE_FILES; 417 qk.qk_objtype = QUOTA_OBJTYPE_FILES;
418 418
419 args.qc_type = QCT_PUT; 419 args.qc_type = QCT_PUT;
420 args.u.put.qc_key = &qk; 420 args.u.put.qc_key = &qk;
421 args.u.put.qc_val = &files; 421 args.u.put.qc_val = &files;
422 error = VFS_QUOTACTL(mp, QUOTACTL_PUT, &args); 422 error = VFS_QUOTACTL(mp, QUOTACTL_PUT, &args);
423 if (error) { 423 if (error) {
424 goto err; 424 goto err;
425 } 425 }
426 } 426 }
427 prop_object_iterator_release(iter); 427 prop_object_iterator_release(iter);
428 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 428 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
429 error = ENOMEM; 429 error = ENOMEM;
430 } else { 430 } else {
431 error = 0; 431 error = 0;
432 } 432 }
433 return error; 433 return error;
434err: 434err:
435 prop_object_iterator_release(iter); 435 prop_object_iterator_release(iter);
436 prop_object_release(replies); 436 prop_object_release(replies);
437 return error; 437 return error;
438} 438}
439 439
440static int 440static int
441vfs_quotactl_getall(struct mount *mp, 441vfs_quotactl_getall(struct mount *mp,
442 prop_dictionary_t cmddict, int q2type, 442 prop_dictionary_t cmddict, int q2type,
443 prop_array_t datas) 443 prop_array_t datas)
444{ 444{
445 struct vfs_quotactl_args args; 445 struct vfs_quotactl_args args;
446 446
447 args.qc_type = QCT_PROPLIB; 447 args.qc_type = QCT_PROPLIB;
448 args.u.proplib.qc_cmddict = cmddict; 448 args.u.proplib.qc_cmddict = cmddict;
449 args.u.proplib.qc_q2type = q2type; 449 args.u.proplib.qc_q2type = q2type;
450 args.u.proplib.qc_datas = datas; 450 args.u.proplib.qc_datas = datas;
451 return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args); 451 return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args);
452} 452}
453 453
454static int 454static int
455vfs_quotactl_clear(struct mount *mp, 455vfs_quotactl_clear(struct mount *mp,
456 prop_dictionary_t cmddict, int q2type, 456 prop_dictionary_t cmddict, int q2type,
457 prop_array_t datas) 457 prop_array_t datas)
458{ 458{
459 prop_array_t replies; 459 prop_array_t replies;
460 prop_object_iterator_t iter; 460 prop_object_iterator_t iter;
461 prop_dictionary_t data; 461 prop_dictionary_t data;
462 uint32_t id; 462 uint32_t id;
463 int defaultq; 463 int defaultq;
464 const char *idstr; 464 const char *idstr;
465 struct vfs_quotactl_args args; 465 struct vfs_quotactl_args args;
466 int error; 466 int error;
467 467
468 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 468 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
469 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 469 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
470 470
471 replies = prop_array_create(); 471 replies = prop_array_create();
472 if (replies == NULL) 472 if (replies == NULL)
473 return ENOMEM; 473 return ENOMEM;
474 474
475 iter = prop_array_iterator(datas); 475 iter = prop_array_iterator(datas);
476 if (iter == NULL) { 476 if (iter == NULL) {
477 prop_object_release(replies); 477 prop_object_release(replies);
478 return ENOMEM; 478 return ENOMEM;
479 } 479 }
480 480
481 while ((data = prop_object_iterator_next(iter)) != NULL) { 481 while ((data = prop_object_iterator_next(iter)) != NULL) {
482 if (!prop_dictionary_get_uint32(data, "id", &id)) { 482 if (!prop_dictionary_get_uint32(data, "id", &id)) {
483 if (!prop_dictionary_get_cstring_nocopy(data, "id", 483 if (!prop_dictionary_get_cstring_nocopy(data, "id",
484 &idstr)) 484 &idstr))
485 continue; 485 continue;
486 if (strcmp(idstr, "default")) 486 if (strcmp(idstr, "default"))
487 continue; 487 continue;
488 id = 0; 488 id = 0;
489 defaultq = 1; 489 defaultq = 1;
490 } else { 490 } else {
491 defaultq = 0; 491 defaultq = 0;
492 } 492 }
493 493
494 args.qc_type = QCT_CLEAR; 494 args.qc_type = QCT_CLEAR;
495 args.u.clear.qc_idtype = q2type; 495 args.u.clear.qc_idtype = q2type;
496 args.u.clear.qc_id = id; 496 args.u.clear.qc_id = id;
497 args.u.clear.qc_defaultq = defaultq; 497 args.u.clear.qc_defaultq = defaultq;
498 args.u.clear.qc_data = data; 
499 error = VFS_QUOTACTL(mp, QUOTACTL_CLEAR, &args); 498 error = VFS_QUOTACTL(mp, QUOTACTL_CLEAR, &args);
500 if (error) { 499 if (error) {
501 goto err; 500 goto err;
502 } 501 }
503 } 502 }
504 503
505 prop_object_iterator_release(iter); 504 prop_object_iterator_release(iter);
506 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 505 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
507 error = ENOMEM; 506 error = ENOMEM;
508 } else { 507 } else {
509 error = 0; 508 error = 0;
510 } 509 }
511 return error; 510 return error;
512err: 511err:
513 prop_object_iterator_release(iter); 512 prop_object_iterator_release(iter);
514 prop_object_release(replies); 513 prop_object_release(replies);
515 return error; 514 return error;
516} 515}
517 516
518static int 517static int
519vfs_quotactl_cmd(struct mount *mp, prop_dictionary_t cmddict) 518vfs_quotactl_cmd(struct mount *mp, prop_dictionary_t cmddict)
520{ 519{
521 int error; 520 int error;
522 const char *cmd, *type; 521 const char *cmd, *type;
523 prop_array_t datas; 522 prop_array_t datas;
524 int q2type; 523 int q2type;
525 524
526 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd)) 525 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd))
527 return EINVAL; 526 return EINVAL;
528 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type)) 527 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type))
529 return EINVAL; 528 return EINVAL;
530 529
531 if (!strcmp(type, QUOTADICT_CLASS_USER)) { 530 if (!strcmp(type, QUOTADICT_CLASS_USER)) {
532 q2type = QUOTA_CLASS_USER; 531 q2type = QUOTA_CLASS_USER;
533 } else if (!strcmp(type, QUOTADICT_CLASS_GROUP)) { 532 } else if (!strcmp(type, QUOTADICT_CLASS_GROUP)) {
534 q2type = QUOTA_CLASS_GROUP; 533 q2type = QUOTA_CLASS_GROUP;
535 } else { 534 } else {
536 /* XXX this is a bad errno for this case */ 535 /* XXX this is a bad errno for this case */
537 return EOPNOTSUPP; 536 return EOPNOTSUPP;
538 } 537 }
539 538
540 datas = prop_dictionary_get(cmddict, "data"); 539 datas = prop_dictionary_get(cmddict, "data");
541 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY) 540 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY)
542 return EINVAL; 541 return EINVAL;
543 542
544 prop_object_retain(datas); 543 prop_object_retain(datas);
545 prop_dictionary_remove(cmddict, "data"); /* prepare for return */ 544 prop_dictionary_remove(cmddict, "data"); /* prepare for return */
546 545
547 if (strcmp(cmd, "get version") == 0) { 546 if (strcmp(cmd, "get version") == 0) {
548 error = vfs_quotactl_getversion(mp, cmddict, q2type, datas); 547 error = vfs_quotactl_getversion(mp, cmddict, q2type, datas);
549 } else if (strcmp(cmd, "quotaon") == 0) { 548 } else if (strcmp(cmd, "quotaon") == 0) {
550 error = vfs_quotactl_quotaon(mp, cmddict, q2type, datas); 549 error = vfs_quotactl_quotaon(mp, cmddict, q2type, datas);
551 } else if (strcmp(cmd, "quotaoff") == 0) { 550 } else if (strcmp(cmd, "quotaoff") == 0) {
552 error = vfs_quotactl_quotaoff(mp, cmddict, q2type, datas); 551 error = vfs_quotactl_quotaoff(mp, cmddict, q2type, datas);
553 } else if (strcmp(cmd, "get") == 0) { 552 } else if (strcmp(cmd, "get") == 0) {
554 error = vfs_quotactl_get(mp, cmddict, q2type, datas); 553 error = vfs_quotactl_get(mp, cmddict, q2type, datas);
555 } else if (strcmp(cmd, "set") == 0) { 554 } else if (strcmp(cmd, "set") == 0) {
556 error = vfs_quotactl_put(mp, cmddict, q2type, datas); 555 error = vfs_quotactl_put(mp, cmddict, q2type, datas);
557 } else if (strcmp(cmd, "getall") == 0) { 556 } else if (strcmp(cmd, "getall") == 0) {
558 error = vfs_quotactl_getall(mp, cmddict, q2type, datas); 557 error = vfs_quotactl_getall(mp, cmddict, q2type, datas);
559 } else if (strcmp(cmd, "clear") == 0) { 558 } else if (strcmp(cmd, "clear") == 0) {
560 error = vfs_quotactl_clear(mp, cmddict, q2type, datas); 559 error = vfs_quotactl_clear(mp, cmddict, q2type, datas);
561 } else { 560 } else {
562 /* XXX this a bad errno for this case */ 561 /* XXX this a bad errno for this case */
563 error = EOPNOTSUPP; 562 error = EOPNOTSUPP;
564 } 563 }
565 564
566 error = (prop_dictionary_set_int8(cmddict, "return", 565 error = (prop_dictionary_set_int8(cmddict, "return",
567 error) ? 0 : ENOMEM); 566 error) ? 0 : ENOMEM);
568 prop_object_release(datas); 567 prop_object_release(datas);
569 568
570 return error; 569 return error;
571} 570}
572 571
573int 572int
574vfs_quotactl(struct mount *mp, prop_dictionary_t dict) 573vfs_quotactl(struct mount *mp, prop_dictionary_t dict)
575{ 574{
576 prop_dictionary_t cmddict; 575 prop_dictionary_t cmddict;
577 prop_array_t commands; 576 prop_array_t commands;
578 prop_object_iterator_t iter; 577 prop_object_iterator_t iter;
579 int error; 578 int error;
580 579
581 error = quota_get_cmds(dict, &commands); 580 error = quota_get_cmds(dict, &commands);
582 if (error) { 581 if (error) {
583 return error; 582 return error;
584 } 583 }
585 584
586 iter = prop_array_iterator(commands); 585 iter = prop_array_iterator(commands);
587 if (iter == NULL) { 586 if (iter == NULL) {
588 return ENOMEM; 587 return ENOMEM;
589 } 588 }
590 589
591 while ((cmddict = prop_object_iterator_next(iter)) != NULL) { 590 while ((cmddict = prop_object_iterator_next(iter)) != NULL) {
592 if (prop_object_type(cmddict) != PROP_TYPE_DICTIONARY) { 591 if (prop_object_type(cmddict) != PROP_TYPE_DICTIONARY) {
593 /* XXX shouldn't this be an error? */ 592 /* XXX shouldn't this be an error? */
594 continue; 593 continue;
595 } 594 }
596 error = vfs_quotactl_cmd(mp, cmddict); 595 error = vfs_quotactl_cmd(mp, cmddict);
597 if (error) { 596 if (error) {
598 break; 597 break;
599 } 598 }
600 } 599 }
601 prop_object_iterator_release(iter); 600 prop_object_iterator_release(iter);
602 return error; 601 return error;
603} 602}

cvs diff -r1.14 -r1.15 src/sys/sys/quotactl.h (switch to unified diff)

--- src/sys/sys/quotactl.h 2012/01/29 06:51:43 1.14
+++ src/sys/sys/quotactl.h 2012/01/29 06:52:39 1.15
@@ -1,85 +1,84 @@ @@ -1,85 +1,84 @@
1/* $NetBSD: quotactl.h,v 1.14 2012/01/29 06:51:43 dholland Exp $ */ 1/* $NetBSD: quotactl.h,v 1.15 2012/01/29 06:52:39 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
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE. 28 * POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31#ifndef _SYS_QUOTACTL_H_ 31#ifndef _SYS_QUOTACTL_H_
32#define _SYS_QUOTACTL_H_ 32#define _SYS_QUOTACTL_H_
33 33
34/* 34/*
35 * Note - this is an internal interface. Application code (and, 35 * Note - this is an internal interface. Application code (and,
36 * really, anything that isn't libquota or inside the kernel) should 36 * really, anything that isn't libquota or inside the kernel) should
37 * use the <quota.h> API instead. 37 * use the <quota.h> API instead.
38 */ 38 */
39 39
40/* Command codes. */ 40/* Command codes. */
41#define QUOTACTL_GETVERSION 0 41#define QUOTACTL_GETVERSION 0
42#define QUOTACTL_QUOTAON 1 42#define QUOTACTL_QUOTAON 1
43#define QUOTACTL_QUOTAOFF 2 43#define QUOTACTL_QUOTAOFF 2
44#define QUOTACTL_GET 3 44#define QUOTACTL_GET 3
45#define QUOTACTL_PUT 4 45#define QUOTACTL_PUT 4
46#define QUOTACTL_GETALL 5 46#define QUOTACTL_GETALL 5
47#define QUOTACTL_CLEAR 6 47#define QUOTACTL_CLEAR 6
48 48
49/* Argument encoding. */ 49/* Argument encoding. */
50enum vfs_quotactl_argtypes { 50enum vfs_quotactl_argtypes {
51 QCT_PROPLIB, /* quotaon/off, get, set, getall, clear */ 51 QCT_PROPLIB, /* quotaon/off, get, set, getall, clear */
52 QCT_GETVERSION, /* getversion */ 52 QCT_GETVERSION, /* getversion */
53 QCT_GET, /* get */ 53 QCT_GET, /* get */
54 QCT_PUT, /* put */ 54 QCT_PUT, /* put */
55 QCT_CLEAR, /* clear */ 55 QCT_CLEAR, /* clear */
56}; 56};
57struct vfs_quotactl_args { 57struct vfs_quotactl_args {
58 enum vfs_quotactl_argtypes qc_type; 58 enum vfs_quotactl_argtypes qc_type;
59 union { 59 union {
60 struct { 60 struct {
61 prop_dictionary_t qc_cmddict; 61 prop_dictionary_t qc_cmddict;
62 int qc_q2type; 62 int qc_q2type;
63 prop_array_t qc_datas; 63 prop_array_t qc_datas;
64 } proplib; 64 } proplib;
65 struct { 65 struct {
66 int *qc_version_ret; 66 int *qc_version_ret;
67 } getversion; 67 } getversion;
68 struct { 68 struct {
69 const struct quotakey *qc_key; 69 const struct quotakey *qc_key;
70 struct quotaval *qc_ret; 70 struct quotaval *qc_ret;
71 } get; 71 } get;
72 struct { 72 struct {
73 const struct quotakey *qc_key; 73 const struct quotakey *qc_key;
74 const struct quotaval *qc_val; 74 const struct quotaval *qc_val;
75 } put; 75 } put;
76 struct { 76 struct {
77 int qc_idtype; 77 int qc_idtype;
78 id_t qc_id; 78 id_t qc_id;
79 int qc_defaultq; 79 int qc_defaultq;
80 prop_dictionary_t qc_data; 
81 } clear; 80 } clear;
82 } u; 81 } u;
83}; 82};
84 83
85#endif /* _SYS_QUOTACTL_H_ */ 84#endif /* _SYS_QUOTACTL_H_ */

cvs diff -r1.88 -r1.89 src/sys/ufs/ufs/ufs_quota.c (switch to unified diff)

--- src/sys/ufs/ufs/ufs_quota.c 2012/01/29 06:51:43 1.88
+++ src/sys/ufs/ufs/ufs_quota.c 2012/01/29 06:52:39 1.89
@@ -1,787 +1,783 @@ @@ -1,787 +1,783 @@
1/* $NetBSD: ufs_quota.c,v 1.88 2012/01/29 06:51:43 dholland Exp $ */ 1/* $NetBSD: ufs_quota.c,v 1.89 2012/01/29 06:52:39 dholland Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1990, 1993, 1995 4 * Copyright (c) 1982, 1986, 1990, 1993, 1995
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Robert Elz at The University of Melbourne. 8 * Robert Elz at The University of Melbourne.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 * 33 *
34 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 34 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.88 2012/01/29 06:51:43 dholland Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.89 2012/01/29 06:52:39 dholland Exp $");
39 39
40#if defined(_KERNEL_OPT) 40#if defined(_KERNEL_OPT)
41#include "opt_quota.h" 41#include "opt_quota.h"
42#endif  42#endif
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/kernel.h> 44#include <sys/kernel.h>
45#include <sys/systm.h> 45#include <sys/systm.h>
46#include <sys/namei.h> 46#include <sys/namei.h>
47#include <sys/file.h> 47#include <sys/file.h>
48#include <sys/proc.h> 48#include <sys/proc.h>
49#include <sys/vnode.h> 49#include <sys/vnode.h>
50#include <sys/mount.h> 50#include <sys/mount.h>
51#include <sys/kauth.h> 51#include <sys/kauth.h>
52 52
53#include <sys/quotactl.h> 53#include <sys/quotactl.h>
54#include <ufs/ufs/quota.h> 54#include <ufs/ufs/quota.h>
55#include <ufs/ufs/inode.h> 55#include <ufs/ufs/inode.h>
56#include <ufs/ufs/ufsmount.h> 56#include <ufs/ufs/ufsmount.h>
57#include <ufs/ufs/ufs_extern.h> 57#include <ufs/ufs/ufs_extern.h>
58#include <ufs/ufs/ufs_quota.h> 58#include <ufs/ufs/ufs_quota.h>
59#include <quota/quotaprop.h> 59#include <quota/quotaprop.h>
60 60
61kmutex_t dqlock; 61kmutex_t dqlock;
62kcondvar_t dqcv; 62kcondvar_t dqcv;
63 63
64/* 64/*
65 * Code pertaining to management of the in-core dquot data structures. 65 * Code pertaining to management of the in-core dquot data structures.
66 */ 66 */
67#define DQHASH(dqvp, id) \ 67#define DQHASH(dqvp, id) \
68 (((((long)(dqvp)) >> 8) + id) & dqhash) 68 (((((long)(dqvp)) >> 8) + id) & dqhash)
69static LIST_HEAD(dqhashhead, dquot) *dqhashtbl; 69static LIST_HEAD(dqhashhead, dquot) *dqhashtbl;
70static u_long dqhash; 70static u_long dqhash;
71static pool_cache_t dquot_cache; 71static pool_cache_t dquot_cache;
72 72
73 73
74static int quota_handle_cmd_get_version(struct mount *, struct lwp *, 74static int quota_handle_cmd_get_version(struct mount *, struct lwp *,
75 struct vfs_quotactl_args *args); 75 struct vfs_quotactl_args *args);
76static int quota_handle_cmd_get(struct mount *, struct lwp *, 76static int quota_handle_cmd_get(struct mount *, struct lwp *,
77 struct vfs_quotactl_args *args); 77 struct vfs_quotactl_args *args);
78static int quota_handle_cmd_put(struct mount *, struct lwp *, 78static int quota_handle_cmd_put(struct mount *, struct lwp *,
79 struct vfs_quotactl_args *args); 79 struct vfs_quotactl_args *args);
80static int quota_handle_cmd_getall(struct mount *, struct lwp *, 80static int quota_handle_cmd_getall(struct mount *, struct lwp *,
81 struct vfs_quotactl_args *args); 81 struct vfs_quotactl_args *args);
82static int quota_handle_cmd_clear(struct mount *, struct lwp *, 82static int quota_handle_cmd_clear(struct mount *, struct lwp *,
83 struct vfs_quotactl_args *args); 83 struct vfs_quotactl_args *args);
84static int quota_handle_cmd_quotaon(struct mount *, struct lwp *,  84static int quota_handle_cmd_quotaon(struct mount *, struct lwp *,
85 struct vfs_quotactl_args *args); 85 struct vfs_quotactl_args *args);
86static int quota_handle_cmd_quotaoff(struct mount *, struct lwp *,  86static int quota_handle_cmd_quotaoff(struct mount *, struct lwp *,
87 struct vfs_quotactl_args *args); 87 struct vfs_quotactl_args *args);
88 88
89/* 89/*
90 * Initialize the quota fields of an inode. 90 * Initialize the quota fields of an inode.
91 */ 91 */
92void 92void
93ufsquota_init(struct inode *ip) 93ufsquota_init(struct inode *ip)
94{ 94{
95 int i; 95 int i;
96 96
97 for (i = 0; i < MAXQUOTAS; i++) 97 for (i = 0; i < MAXQUOTAS; i++)
98 ip->i_dquot[i] = NODQUOT; 98 ip->i_dquot[i] = NODQUOT;
99} 99}
100 100
101/* 101/*
102 * Release the quota fields from an inode. 102 * Release the quota fields from an inode.
103 */ 103 */
104void 104void
105ufsquota_free(struct inode *ip) 105ufsquota_free(struct inode *ip)
106{ 106{
107 int i; 107 int i;
108 108
109 for (i = 0; i < MAXQUOTAS; i++) { 109 for (i = 0; i < MAXQUOTAS; i++) {
110 dqrele(ITOV(ip), ip->i_dquot[i]); 110 dqrele(ITOV(ip), ip->i_dquot[i]);
111 ip->i_dquot[i] = NODQUOT; 111 ip->i_dquot[i] = NODQUOT;
112 } 112 }
113} 113}
114 114
115/* 115/*
116 * Update disk usage, and take corrective action. 116 * Update disk usage, and take corrective action.
117 */ 117 */
118int 118int
119chkdq(struct inode *ip, int64_t change, kauth_cred_t cred, int flags) 119chkdq(struct inode *ip, int64_t change, kauth_cred_t cred, int flags)
120{ 120{
121 /* do not track snapshot usage, or we will deadlock */ 121 /* do not track snapshot usage, or we will deadlock */
122 if ((ip->i_flags & SF_SNAPSHOT) != 0) 122 if ((ip->i_flags & SF_SNAPSHOT) != 0)
123 return 0; 123 return 0;
124 124
125#ifdef QUOTA 125#ifdef QUOTA
126 if (ip->i_ump->um_flags & UFS_QUOTA) 126 if (ip->i_ump->um_flags & UFS_QUOTA)
127 return chkdq1(ip, change, cred, flags); 127 return chkdq1(ip, change, cred, flags);
128#endif 128#endif
129#ifdef QUOTA2 129#ifdef QUOTA2
130 if (ip->i_ump->um_flags & UFS_QUOTA2) 130 if (ip->i_ump->um_flags & UFS_QUOTA2)
131 return chkdq2(ip, change, cred, flags); 131 return chkdq2(ip, change, cred, flags);
132#endif 132#endif
133 return 0; 133 return 0;
134} 134}
135 135
136/* 136/*
137 * Check the inode limit, applying corrective action. 137 * Check the inode limit, applying corrective action.
138 */ 138 */
139int 139int
140chkiq(struct inode *ip, int32_t change, kauth_cred_t cred, int flags) 140chkiq(struct inode *ip, int32_t change, kauth_cred_t cred, int flags)
141{ 141{
142 /* do not track snapshot usage, or we will deadlock */ 142 /* do not track snapshot usage, or we will deadlock */
143 if ((ip->i_flags & SF_SNAPSHOT) != 0) 143 if ((ip->i_flags & SF_SNAPSHOT) != 0)
144 return 0; 144 return 0;
145#ifdef QUOTA 145#ifdef QUOTA
146 if (ip->i_ump->um_flags & UFS_QUOTA) 146 if (ip->i_ump->um_flags & UFS_QUOTA)
147 return chkiq1(ip, change, cred, flags); 147 return chkiq1(ip, change, cred, flags);
148#endif 148#endif
149#ifdef QUOTA2 149#ifdef QUOTA2
150 if (ip->i_ump->um_flags & UFS_QUOTA2) 150 if (ip->i_ump->um_flags & UFS_QUOTA2)
151 return chkiq2(ip, change, cred, flags); 151 return chkiq2(ip, change, cred, flags);
152#endif 152#endif
153 return 0; 153 return 0;
154} 154}
155 155
156int 156int
157quota_handle_cmd(struct mount *mp, struct lwp *l, int op, 157quota_handle_cmd(struct mount *mp, struct lwp *l, int op,
158 struct vfs_quotactl_args *args) 158 struct vfs_quotactl_args *args)
159{ 159{
160 int error = 0; 160 int error = 0;
161 161
162 switch (op) { 162 switch (op) {
163 case QUOTACTL_GETVERSION: 163 case QUOTACTL_GETVERSION:
164 error = quota_handle_cmd_get_version(mp, l, args); 164 error = quota_handle_cmd_get_version(mp, l, args);
165 break; 165 break;
166 case QUOTACTL_QUOTAON: 166 case QUOTACTL_QUOTAON:
167 error = quota_handle_cmd_quotaon(mp, l, args); 167 error = quota_handle_cmd_quotaon(mp, l, args);
168 break; 168 break;
169 case QUOTACTL_QUOTAOFF: 169 case QUOTACTL_QUOTAOFF:
170 error = quota_handle_cmd_quotaoff(mp, l, args); 170 error = quota_handle_cmd_quotaoff(mp, l, args);
171 break; 171 break;
172 case QUOTACTL_GET: 172 case QUOTACTL_GET:
173 error = quota_handle_cmd_get(mp, l, args); 173 error = quota_handle_cmd_get(mp, l, args);
174 break; 174 break;
175 case QUOTACTL_PUT: 175 case QUOTACTL_PUT:
176 error = quota_handle_cmd_put(mp, l, args); 176 error = quota_handle_cmd_put(mp, l, args);
177 break; 177 break;
178 case QUOTACTL_GETALL: 178 case QUOTACTL_GETALL:
179 error = quota_handle_cmd_getall(mp, l, args); 179 error = quota_handle_cmd_getall(mp, l, args);
180 break; 180 break;
181 case QUOTACTL_CLEAR: 181 case QUOTACTL_CLEAR:
182 error = quota_handle_cmd_clear(mp, l, args); 182 error = quota_handle_cmd_clear(mp, l, args);
183 break; 183 break;
184 default: 184 default:
185 panic("Invalid quotactl operation %d\n", op); 185 panic("Invalid quotactl operation %d\n", op);
186 } 186 }
187 187
188 return error; 188 return error;
189} 189}
190 190
191static int  191static int
192quota_handle_cmd_get_version(struct mount *mp, struct lwp *l,  192quota_handle_cmd_get_version(struct mount *mp, struct lwp *l,
193 struct vfs_quotactl_args *args) 193 struct vfs_quotactl_args *args)
194{ 194{
195 struct ufsmount *ump = VFSTOUFS(mp); 195 struct ufsmount *ump = VFSTOUFS(mp);
196 int *version_ret; 196 int *version_ret;
197 197
198 KASSERT(args->qc_type == QCT_GETVERSION); 198 KASSERT(args->qc_type == QCT_GETVERSION);
199 version_ret = args->u.getversion.qc_version_ret; 199 version_ret = args->u.getversion.qc_version_ret;
200 200
201 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 201 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0)
202 return EOPNOTSUPP; 202 return EOPNOTSUPP;
203 203
204#ifdef QUOTA 204#ifdef QUOTA
205 if (ump->um_flags & UFS_QUOTA) { 205 if (ump->um_flags & UFS_QUOTA) {
206 *version_ret = 1; 206 *version_ret = 1;
207 } else 207 } else
208#endif 208#endif
209#ifdef QUOTA2 209#ifdef QUOTA2
210 if (ump->um_flags & UFS_QUOTA2) { 210 if (ump->um_flags & UFS_QUOTA2) {
211 *version_ret = 2; 211 *version_ret = 2;
212 } else 212 } else
213#endif 213#endif
214 return EOPNOTSUPP; 214 return EOPNOTSUPP;
215 215
216 return 0; 216 return 0;
217} 217}
218 218
219/* XXX shouldn't all this be in kauth ? */ 219/* XXX shouldn't all this be in kauth ? */
220static int 220static int
221quota_get_auth(struct mount *mp, struct lwp *l, uid_t id) { 221quota_get_auth(struct mount *mp, struct lwp *l, uid_t id) {
222 /* The user can always query about his own quota. */ 222 /* The user can always query about his own quota. */
223 if (id == kauth_cred_getuid(l->l_cred)) 223 if (id == kauth_cred_getuid(l->l_cred))
224 return 0; 224 return 0;
225 return kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 225 return kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
226 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(id), NULL); 226 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(id), NULL);
227} 227}
228 228
229static int  229static int
230quota_handle_cmd_get(struct mount *mp, struct lwp *l,  230quota_handle_cmd_get(struct mount *mp, struct lwp *l,
231 struct vfs_quotactl_args *args) 231 struct vfs_quotactl_args *args)
232{ 232{
233 struct ufsmount *ump = VFSTOUFS(mp); 233 struct ufsmount *ump = VFSTOUFS(mp);
234 int error; 234 int error;
235 const struct quotakey *qk; 235 const struct quotakey *qk;
236 struct quotaval *ret; 236 struct quotaval *ret;
237 237
238 KASSERT(args->qc_type == QCT_GET); 238 KASSERT(args->qc_type == QCT_GET);
239 qk = args->u.get.qc_key; 239 qk = args->u.get.qc_key;
240 ret = args->u.get.qc_ret; 240 ret = args->u.get.qc_ret;
241 241
242 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 242 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0)
243 return EOPNOTSUPP; 243 return EOPNOTSUPP;
244  244
245 error = quota_get_auth(mp, l, qk->qk_id); 245 error = quota_get_auth(mp, l, qk->qk_id);
246 if (error != 0)  246 if (error != 0)
247 return error; 247 return error;
248#ifdef QUOTA 248#ifdef QUOTA
249 if (ump->um_flags & UFS_QUOTA) { 249 if (ump->um_flags & UFS_QUOTA) {
250 error = quota1_handle_cmd_get(ump, qk, ret); 250 error = quota1_handle_cmd_get(ump, qk, ret);
251 } else 251 } else
252#endif 252#endif
253#ifdef QUOTA2 253#ifdef QUOTA2
254 if (ump->um_flags & UFS_QUOTA2) { 254 if (ump->um_flags & UFS_QUOTA2) {
255 error = quota2_handle_cmd_get(ump, qk, ret); 255 error = quota2_handle_cmd_get(ump, qk, ret);
256 } else 256 } else
257#endif 257#endif
258 panic("quota_handle_cmd_get: no support ?"); 258 panic("quota_handle_cmd_get: no support ?");
259  259
260 if (error != 0) 260 if (error != 0)
261 return error; 261 return error;
262 262
263 return error; 263 return error;
264} 264}
265 265
266static int  266static int
267quota_handle_cmd_put(struct mount *mp, struct lwp *l,  267quota_handle_cmd_put(struct mount *mp, struct lwp *l,
268 struct vfs_quotactl_args *args) 268 struct vfs_quotactl_args *args)
269{ 269{
270 struct ufsmount *ump = VFSTOUFS(mp); 270 struct ufsmount *ump = VFSTOUFS(mp);
271 const struct quotakey *qk; 271 const struct quotakey *qk;
272 const struct quotaval *qv; 272 const struct quotaval *qv;
273 id_t kauth_id; 273 id_t kauth_id;
274 int error; 274 int error;
275 275
276 KASSERT(args->qc_type == QCT_PUT); 276 KASSERT(args->qc_type == QCT_PUT);
277 qk = args->u.put.qc_key; 277 qk = args->u.put.qc_key;
278 qv = args->u.put.qc_val; 278 qv = args->u.put.qc_val;
279 279
280 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 280 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0)
281 return EOPNOTSUPP; 281 return EOPNOTSUPP;
282 282
283 kauth_id = qk->qk_id; 283 kauth_id = qk->qk_id;
284 if (kauth_id == QUOTA_DEFAULTID) { 284 if (kauth_id == QUOTA_DEFAULTID) {
285 kauth_id = 0; 285 kauth_id = 0;
286 } 286 }
287 287
288 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 288 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
289 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(kauth_id), 289 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(kauth_id),
290 NULL); 290 NULL);
291 if (error != 0) { 291 if (error != 0) {
292 return error; 292 return error;
293 } 293 }
294 294
295#ifdef QUOTA 295#ifdef QUOTA
296 if (ump->um_flags & UFS_QUOTA) 296 if (ump->um_flags & UFS_QUOTA)
297 error = quota1_handle_cmd_put(ump, qk, qv); 297 error = quota1_handle_cmd_put(ump, qk, qv);
298 else 298 else
299#endif 299#endif
300#ifdef QUOTA2 300#ifdef QUOTA2
301 if (ump->um_flags & UFS_QUOTA2) { 301 if (ump->um_flags & UFS_QUOTA2) {
302 error = quota2_handle_cmd_put(ump, qk, qv); 302 error = quota2_handle_cmd_put(ump, qk, qv);
303 } else 303 } else
304#endif 304#endif
305 panic("quota_handle_cmd_get: no support ?"); 305 panic("quota_handle_cmd_get: no support ?");
306  306
307 if (error == ENOENT) { 307 if (error == ENOENT) {
308 error = 0; 308 error = 0;
309 } 309 }
310 310
311 return error; 311 return error;
312} 312}
313 313
314static int  314static int
315quota_handle_cmd_clear(struct mount *mp, struct lwp *l,  315quota_handle_cmd_clear(struct mount *mp, struct lwp *l,
316 struct vfs_quotactl_args *args) 316 struct vfs_quotactl_args *args)
317{ 317{
318 struct ufsmount *ump = VFSTOUFS(mp); 318 struct ufsmount *ump = VFSTOUFS(mp);
319 int idtype; 319 int idtype;
320 id_t id; 320 id_t id;
321 int defaultq; 321 int defaultq;
322 prop_dictionary_t data; 
323 int error; 322 int error;
324 323
325 KASSERT(args->qc_type == QCT_CLEAR); 324 KASSERT(args->qc_type == QCT_CLEAR);
326 idtype = args->u.clear.qc_idtype; 325 idtype = args->u.clear.qc_idtype;
327 id = args->u.clear.qc_id; 326 id = args->u.clear.qc_id;
328 defaultq = args->u.clear.qc_defaultq; 327 defaultq = args->u.clear.qc_defaultq;
329 data = args->u.clear.qc_data; 
330 
331 KASSERT(prop_object_type(data) == PROP_TYPE_DICTIONARY); 
332 328
333 if ((ump->um_flags & UFS_QUOTA2) == 0) 329 if ((ump->um_flags & UFS_QUOTA2) == 0)
334 return EOPNOTSUPP; 330 return EOPNOTSUPP;
335 331
336 /* avoid whitespace changes */ 332 /* avoid whitespace changes */
337 { 333 {
338 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 334 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
339 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(id), NULL); 335 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(id), NULL);
340 if (error != 0) 336 if (error != 0)
341 goto err; 337 goto err;
342#ifdef QUOTA2 338#ifdef QUOTA2
343 if (ump->um_flags & UFS_QUOTA2) { 339 if (ump->um_flags & UFS_QUOTA2) {
344 error = quota2_handle_cmd_clear(ump, idtype, id, defaultq, 340 error = quota2_handle_cmd_clear(ump, idtype, id,
345 data); 341 defaultq);
346 } else 342 } else
347#endif 343#endif
348 panic("quota_handle_cmd_get: no support ?"); 344 panic("quota_handle_cmd_get: no support ?");
349  345
350 if (error && error != ENOENT) 346 if (error && error != ENOENT)
351 goto err; 347 goto err;
352 } 348 }
353 349
354 return 0; 350 return 0;
355 err: 351 err:
356 return error; 352 return error;
357} 353}
358 354
359static int  355static int
360quota_handle_cmd_getall(struct mount *mp, struct lwp *l,  356quota_handle_cmd_getall(struct mount *mp, struct lwp *l,
361 struct vfs_quotactl_args *args) 357 struct vfs_quotactl_args *args)
362{ 358{
363 prop_array_t replies; 359 prop_array_t replies;
364 struct ufsmount *ump = VFSTOUFS(mp); 360 struct ufsmount *ump = VFSTOUFS(mp);
365 int error; 361 int error;
366 prop_dictionary_t cmddict; 362 prop_dictionary_t cmddict;
367 int q2type; 363 int q2type;
368 prop_array_t datas; 364 prop_array_t datas;
369 365
370 KASSERT(args->qc_type == QCT_PROPLIB); 366 KASSERT(args->qc_type == QCT_PROPLIB);
371 cmddict = args->u.proplib.qc_cmddict; 367 cmddict = args->u.proplib.qc_cmddict;
372 q2type = args->u.proplib.qc_q2type; 368 q2type = args->u.proplib.qc_q2type;
373 datas = args->u.proplib.qc_datas; 369 datas = args->u.proplib.qc_datas;
374 370
375 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 371 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
376 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 372 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
377 373
378 if ((ump->um_flags & UFS_QUOTA2) == 0) 374 if ((ump->um_flags & UFS_QUOTA2) == 0)
379 return EOPNOTSUPP; 375 return EOPNOTSUPP;
380  376
381 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 377 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
382 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL); 378 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL);
383 if (error) 379 if (error)
384 return error; 380 return error;
385  381
386 replies = prop_array_create(); 382 replies = prop_array_create();
387 if (replies == NULL) 383 if (replies == NULL)
388 return ENOMEM; 384 return ENOMEM;
389 385
390#ifdef QUOTA2 386#ifdef QUOTA2
391 if (ump->um_flags & UFS_QUOTA2) { 387 if (ump->um_flags & UFS_QUOTA2) {
392 error = quota2_handle_cmd_getall(ump, q2type, replies); 388 error = quota2_handle_cmd_getall(ump, q2type, replies);
393 } else 389 } else
394#endif 390#endif
395 panic("quota_handle_cmd_getall: no support ?"); 391 panic("quota_handle_cmd_getall: no support ?");
396 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 392 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
397 error = ENOMEM; 393 error = ENOMEM;
398 } else { 394 } else {
399 error = 0; 395 error = 0;
400 } 396 }
401 return error; 397 return error;
402} 398}
403 399
404static int  400static int
405quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l,  401quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l,
406 struct vfs_quotactl_args *args) 402 struct vfs_quotactl_args *args)
407{ 403{
408 prop_dictionary_t data; 404 prop_dictionary_t data;
409 struct ufsmount *ump = VFSTOUFS(mp); 405 struct ufsmount *ump = VFSTOUFS(mp);
410 int error; 406 int error;
411 const char *qfile; 407 const char *qfile;
412 prop_dictionary_t cmddict; 408 prop_dictionary_t cmddict;
413 int q2type; 409 int q2type;
414 prop_array_t datas; 410 prop_array_t datas;
415 411
416 KASSERT(args->qc_type == QCT_PROPLIB); 412 KASSERT(args->qc_type == QCT_PROPLIB);
417 cmddict = args->u.proplib.qc_cmddict; 413 cmddict = args->u.proplib.qc_cmddict;
418 q2type = args->u.proplib.qc_q2type; 414 q2type = args->u.proplib.qc_q2type;
419 datas = args->u.proplib.qc_datas; 415 datas = args->u.proplib.qc_datas;
420 416
421 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 417 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
422 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 418 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
423 419
424 if ((ump->um_flags & UFS_QUOTA2) != 0) 420 if ((ump->um_flags & UFS_QUOTA2) != 0)
425 return EBUSY; 421 return EBUSY;
426  422
427 if (prop_array_count(datas) != 1) 423 if (prop_array_count(datas) != 1)
428 return EINVAL; 424 return EINVAL;
429 425
430 data = prop_array_get(datas, 0); 426 data = prop_array_get(datas, 0);
431 if (data == NULL) 427 if (data == NULL)
432 return ENOMEM; 428 return ENOMEM;
433 if (!prop_dictionary_get_cstring_nocopy(data, "quotafile", 429 if (!prop_dictionary_get_cstring_nocopy(data, "quotafile",
434 &qfile)) 430 &qfile))
435 return EINVAL; 431 return EINVAL;
436 432
437 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 433 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
438 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL); 434 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
439 if (error != 0) { 435 if (error != 0) {
440 return error; 436 return error;
441 } 437 }
442#ifdef QUOTA 438#ifdef QUOTA
443 error = quota1_handle_cmd_quotaon(l, ump, q2type, qfile); 439 error = quota1_handle_cmd_quotaon(l, ump, q2type, qfile);
444#else 440#else
445 error = EOPNOTSUPP; 441 error = EOPNOTSUPP;
446#endif 442#endif
447  443
448 return error; 444 return error;
449} 445}
450 446
451static int  447static int
452quota_handle_cmd_quotaoff(struct mount *mp, struct lwp *l,  448quota_handle_cmd_quotaoff(struct mount *mp, struct lwp *l,
453 struct vfs_quotactl_args *args) 449 struct vfs_quotactl_args *args)
454{ 450{
455 struct ufsmount *ump = VFSTOUFS(mp); 451 struct ufsmount *ump = VFSTOUFS(mp);
456 int error; 452 int error;
457 prop_dictionary_t cmddict; 453 prop_dictionary_t cmddict;
458 int q2type; 454 int q2type;
459 prop_array_t datas; 455 prop_array_t datas;
460 456
461 KASSERT(args->qc_type == QCT_PROPLIB); 457 KASSERT(args->qc_type == QCT_PROPLIB);
462 cmddict = args->u.proplib.qc_cmddict; 458 cmddict = args->u.proplib.qc_cmddict;
463 q2type = args->u.proplib.qc_q2type; 459 q2type = args->u.proplib.qc_q2type;
464 datas = args->u.proplib.qc_datas; 460 datas = args->u.proplib.qc_datas;
465 461
466 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 462 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
467 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 463 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
468 464
469 if ((ump->um_flags & UFS_QUOTA2) != 0) 465 if ((ump->um_flags & UFS_QUOTA2) != 0)
470 return EOPNOTSUPP; 466 return EOPNOTSUPP;
471  467
472 if (prop_array_count(datas) != 0) 468 if (prop_array_count(datas) != 0)
473 return EINVAL; 469 return EINVAL;
474 470
475 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 471 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
476 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL); 472 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
477 if (error != 0) { 473 if (error != 0) {
478 return error; 474 return error;
479 } 475 }
480#ifdef QUOTA 476#ifdef QUOTA
481 error = quota1_handle_cmd_quotaoff(l, ump, q2type); 477 error = quota1_handle_cmd_quotaoff(l, ump, q2type);
482#else 478#else
483 error = EOPNOTSUPP; 479 error = EOPNOTSUPP;
484#endif 480#endif
485  481
486 return error; 482 return error;
487} 483}
488 484
489/* 485/*
490 * Initialize the quota system. 486 * Initialize the quota system.
491 */ 487 */
492void 488void
493dqinit(void) 489dqinit(void)
494{ 490{
495 491
496 mutex_init(&dqlock, MUTEX_DEFAULT, IPL_NONE); 492 mutex_init(&dqlock, MUTEX_DEFAULT, IPL_NONE);
497 cv_init(&dqcv, "quota"); 493 cv_init(&dqcv, "quota");
498 dqhashtbl = hashinit(desiredvnodes, HASH_LIST, true, &dqhash); 494 dqhashtbl = hashinit(desiredvnodes, HASH_LIST, true, &dqhash);
499 dquot_cache = pool_cache_init(sizeof(struct dquot), 0, 0, 0, "ufsdq", 495 dquot_cache = pool_cache_init(sizeof(struct dquot), 0, 0, 0, "ufsdq",
500 NULL, IPL_NONE, NULL, NULL, NULL); 496 NULL, IPL_NONE, NULL, NULL, NULL);
501} 497}
502 498
503void 499void
504dqreinit(void) 500dqreinit(void)
505{ 501{
506 struct dquot *dq; 502 struct dquot *dq;
507 struct dqhashhead *oldhash, *hash; 503 struct dqhashhead *oldhash, *hash;
508 struct vnode *dqvp; 504 struct vnode *dqvp;
509 u_long oldmask, mask, hashval; 505 u_long oldmask, mask, hashval;
510 int i; 506 int i;
511 507
512 hash = hashinit(desiredvnodes, HASH_LIST, true, &mask); 508 hash = hashinit(desiredvnodes, HASH_LIST, true, &mask);
513 mutex_enter(&dqlock); 509 mutex_enter(&dqlock);
514 oldhash = dqhashtbl; 510 oldhash = dqhashtbl;
515 oldmask = dqhash; 511 oldmask = dqhash;
516 dqhashtbl = hash; 512 dqhashtbl = hash;
517 dqhash = mask; 513 dqhash = mask;
518 for (i = 0; i <= oldmask; i++) { 514 for (i = 0; i <= oldmask; i++) {
519 while ((dq = LIST_FIRST(&oldhash[i])) != NULL) { 515 while ((dq = LIST_FIRST(&oldhash[i])) != NULL) {
520 dqvp = dq->dq_ump->um_quotas[dq->dq_type]; 516 dqvp = dq->dq_ump->um_quotas[dq->dq_type];
521 LIST_REMOVE(dq, dq_hash); 517 LIST_REMOVE(dq, dq_hash);
522 hashval = DQHASH(dqvp, dq->dq_id); 518 hashval = DQHASH(dqvp, dq->dq_id);
523 LIST_INSERT_HEAD(&dqhashtbl[hashval], dq, dq_hash); 519 LIST_INSERT_HEAD(&dqhashtbl[hashval], dq, dq_hash);
524 } 520 }
525 } 521 }
526 mutex_exit(&dqlock); 522 mutex_exit(&dqlock);
527 hashdone(oldhash, HASH_LIST, oldmask); 523 hashdone(oldhash, HASH_LIST, oldmask);
528} 524}
529 525
530/* 526/*
531 * Free resources held by quota system. 527 * Free resources held by quota system.
532 */ 528 */
533void 529void
534dqdone(void) 530dqdone(void)
535{ 531{
536 532
537 pool_cache_destroy(dquot_cache); 533 pool_cache_destroy(dquot_cache);
538 hashdone(dqhashtbl, HASH_LIST, dqhash); 534 hashdone(dqhashtbl, HASH_LIST, dqhash);
539 cv_destroy(&dqcv); 535 cv_destroy(&dqcv);
540 mutex_destroy(&dqlock); 536 mutex_destroy(&dqlock);
541} 537}
542 538
543/* 539/*
544 * Set up the quotas for an inode. 540 * Set up the quotas for an inode.
545 * 541 *
546 * This routine completely defines the semantics of quotas. 542 * This routine completely defines the semantics of quotas.
547 * If other criterion want to be used to establish quotas, the 543 * If other criterion want to be used to establish quotas, the
548 * MAXQUOTAS value in quotas.h should be increased, and the 544 * MAXQUOTAS value in quotas.h should be increased, and the
549 * additional dquots set up here. 545 * additional dquots set up here.
550 */ 546 */
551int 547int
552getinoquota(struct inode *ip) 548getinoquota(struct inode *ip)
553{ 549{
554 struct ufsmount *ump = ip->i_ump; 550 struct ufsmount *ump = ip->i_ump;
555 struct vnode *vp = ITOV(ip); 551 struct vnode *vp = ITOV(ip);
556 int i, error; 552 int i, error;
557 u_int32_t ino_ids[MAXQUOTAS]; 553 u_int32_t ino_ids[MAXQUOTAS];
558 554
559 /* 555 /*
560 * To avoid deadlocks never update quotas for quota files 556 * To avoid deadlocks never update quotas for quota files
561 * on the same file system 557 * on the same file system
562 */ 558 */
563 for (i = 0; i < MAXQUOTAS; i++) 559 for (i = 0; i < MAXQUOTAS; i++)
564 if (vp == ump->um_quotas[i]) 560 if (vp == ump->um_quotas[i])
565 return 0; 561 return 0;
566 562
567 ino_ids[USRQUOTA] = ip->i_uid; 563 ino_ids[USRQUOTA] = ip->i_uid;
568 ino_ids[GRPQUOTA] = ip->i_gid; 564 ino_ids[GRPQUOTA] = ip->i_gid;
569 for (i = 0; i < MAXQUOTAS; i++) { 565 for (i = 0; i < MAXQUOTAS; i++) {
570 /* 566 /*
571 * If the file id changed the quota needs update. 567 * If the file id changed the quota needs update.
572 */ 568 */
573 if (ip->i_dquot[i] != NODQUOT && 569 if (ip->i_dquot[i] != NODQUOT &&
574 ip->i_dquot[i]->dq_id != ino_ids[i]) { 570 ip->i_dquot[i]->dq_id != ino_ids[i]) {
575 dqrele(ITOV(ip), ip->i_dquot[i]); 571 dqrele(ITOV(ip), ip->i_dquot[i]);
576 ip->i_dquot[i] = NODQUOT; 572 ip->i_dquot[i] = NODQUOT;
577 } 573 }
578 /* 574 /*
579 * Set up the quota based on file id. 575 * Set up the quota based on file id.
580 * ENODEV means that quotas are not enabled. 576 * ENODEV means that quotas are not enabled.
581 */ 577 */
582 if (ip->i_dquot[i] == NODQUOT && 578 if (ip->i_dquot[i] == NODQUOT &&
583 (error = dqget(vp, ino_ids[i], ump, i, &ip->i_dquot[i])) && 579 (error = dqget(vp, ino_ids[i], ump, i, &ip->i_dquot[i])) &&
584 error != ENODEV) 580 error != ENODEV)
585 return (error); 581 return (error);
586 } 582 }
587 return 0; 583 return 0;
588} 584}
589 585
590/* 586/*
591 * Obtain a dquot structure for the specified identifier and quota file 587 * Obtain a dquot structure for the specified identifier and quota file
592 * reading the information from the file if necessary. 588 * reading the information from the file if necessary.
593 */ 589 */
594int 590int
595dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, 591dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type,
596 struct dquot **dqp) 592 struct dquot **dqp)
597{ 593{
598 struct dquot *dq, *ndq; 594 struct dquot *dq, *ndq;
599 struct dqhashhead *dqh; 595 struct dqhashhead *dqh;
600 struct vnode *dqvp; 596 struct vnode *dqvp;
601 int error = 0; /* XXX gcc */ 597 int error = 0; /* XXX gcc */
602 598
603 /* Lock to see an up to date value for QTF_CLOSING. */ 599 /* Lock to see an up to date value for QTF_CLOSING. */
604 mutex_enter(&dqlock); 600 mutex_enter(&dqlock);
605 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) { 601 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) {
606 mutex_exit(&dqlock); 602 mutex_exit(&dqlock);
607 *dqp = NODQUOT; 603 *dqp = NODQUOT;
608 return (ENODEV); 604 return (ENODEV);
609 } 605 }
610 dqvp = ump->um_quotas[type]; 606 dqvp = ump->um_quotas[type];
611#ifdef QUOTA 607#ifdef QUOTA
612 if (ump->um_flags & UFS_QUOTA) { 608 if (ump->um_flags & UFS_QUOTA) {
613 if (dqvp == NULLVP || (ump->umq1_qflags[type] & QTF_CLOSING)) { 609 if (dqvp == NULLVP || (ump->umq1_qflags[type] & QTF_CLOSING)) {
614 mutex_exit(&dqlock); 610 mutex_exit(&dqlock);
615 *dqp = NODQUOT; 611 *dqp = NODQUOT;
616 return (ENODEV); 612 return (ENODEV);
617 } 613 }
618 } 614 }
619#endif 615#endif
620#ifdef QUOTA2 616#ifdef QUOTA2
621 if (ump->um_flags & UFS_QUOTA2) { 617 if (ump->um_flags & UFS_QUOTA2) {
622 if (dqvp == NULLVP) { 618 if (dqvp == NULLVP) {
623 mutex_exit(&dqlock); 619 mutex_exit(&dqlock);
624 *dqp = NODQUOT; 620 *dqp = NODQUOT;
625 return (ENODEV); 621 return (ENODEV);
626 } 622 }
627 } 623 }
628#endif 624#endif
629 KASSERT(dqvp != vp); 625 KASSERT(dqvp != vp);
630 /* 626 /*
631 * Check the cache first. 627 * Check the cache first.
632 */ 628 */
633 dqh = &dqhashtbl[DQHASH(dqvp, id)]; 629 dqh = &dqhashtbl[DQHASH(dqvp, id)];
634 LIST_FOREACH(dq, dqh, dq_hash) { 630 LIST_FOREACH(dq, dqh, dq_hash) {
635 if (dq->dq_id != id || 631 if (dq->dq_id != id ||
636 dq->dq_ump->um_quotas[dq->dq_type] != dqvp) 632 dq->dq_ump->um_quotas[dq->dq_type] != dqvp)
637 continue; 633 continue;
638 KASSERT(dq->dq_cnt > 0); 634 KASSERT(dq->dq_cnt > 0);
639 dqref(dq); 635 dqref(dq);
640 mutex_exit(&dqlock); 636 mutex_exit(&dqlock);
641 *dqp = dq; 637 *dqp = dq;
642 return (0); 638 return (0);
643 } 639 }
644 /* 640 /*
645 * Not in cache, allocate a new one. 641 * Not in cache, allocate a new one.
646 */ 642 */
647 mutex_exit(&dqlock); 643 mutex_exit(&dqlock);
648 ndq = pool_cache_get(dquot_cache, PR_WAITOK); 644 ndq = pool_cache_get(dquot_cache, PR_WAITOK);
649 /* 645 /*
650 * Initialize the contents of the dquot structure. 646 * Initialize the contents of the dquot structure.
651 */ 647 */
652 memset((char *)ndq, 0, sizeof *ndq); 648 memset((char *)ndq, 0, sizeof *ndq);
653 ndq->dq_flags = 0; 649 ndq->dq_flags = 0;
654 ndq->dq_id = id; 650 ndq->dq_id = id;
655 ndq->dq_ump = ump; 651 ndq->dq_ump = ump;
656 ndq->dq_type = type; 652 ndq->dq_type = type;
657 mutex_init(&ndq->dq_interlock, MUTEX_DEFAULT, IPL_NONE); 653 mutex_init(&ndq->dq_interlock, MUTEX_DEFAULT, IPL_NONE);
658 mutex_enter(&dqlock); 654 mutex_enter(&dqlock);
659 dqh = &dqhashtbl[DQHASH(dqvp, id)]; 655 dqh = &dqhashtbl[DQHASH(dqvp, id)];
660 LIST_FOREACH(dq, dqh, dq_hash) { 656 LIST_FOREACH(dq, dqh, dq_hash) {
661 if (dq->dq_id != id || 657 if (dq->dq_id != id ||
662 dq->dq_ump->um_quotas[dq->dq_type] != dqvp) 658 dq->dq_ump->um_quotas[dq->dq_type] != dqvp)
663 continue; 659 continue;
664 /* 660 /*
665 * Another thread beat us allocating this dquot. 661 * Another thread beat us allocating this dquot.
666 */ 662 */
667 KASSERT(dq->dq_cnt > 0); 663 KASSERT(dq->dq_cnt > 0);
668 dqref(dq); 664 dqref(dq);
669 mutex_exit(&dqlock); 665 mutex_exit(&dqlock);
670 mutex_destroy(&ndq->dq_interlock); 666 mutex_destroy(&ndq->dq_interlock);
671 pool_cache_put(dquot_cache, ndq); 667 pool_cache_put(dquot_cache, ndq);
672 *dqp = dq; 668 *dqp = dq;
673 return 0; 669 return 0;
674 } 670 }
675 dq = ndq; 671 dq = ndq;
676 LIST_INSERT_HEAD(dqh, dq, dq_hash); 672 LIST_INSERT_HEAD(dqh, dq, dq_hash);
677 dqref(dq); 673 dqref(dq);
678 mutex_enter(&dq->dq_interlock); 674 mutex_enter(&dq->dq_interlock);
679 mutex_exit(&dqlock); 675 mutex_exit(&dqlock);
680#ifdef QUOTA 676#ifdef QUOTA
681 if (ump->um_flags & UFS_QUOTA) 677 if (ump->um_flags & UFS_QUOTA)
682 error = dq1get(dqvp, id, ump, type, dq); 678 error = dq1get(dqvp, id, ump, type, dq);
683#endif 679#endif
684#ifdef QUOTA2 680#ifdef QUOTA2
685 if (ump->um_flags & UFS_QUOTA2) 681 if (ump->um_flags & UFS_QUOTA2)
686 error = dq2get(dqvp, id, ump, type, dq); 682 error = dq2get(dqvp, id, ump, type, dq);
687#endif 683#endif
688 /* 684 /*
689 * I/O error in reading quota file, release 685 * I/O error in reading quota file, release
690 * quota structure and reflect problem to caller. 686 * quota structure and reflect problem to caller.
691 */ 687 */
692 if (error) { 688 if (error) {
693 mutex_enter(&dqlock); 689 mutex_enter(&dqlock);
694 LIST_REMOVE(dq, dq_hash); 690 LIST_REMOVE(dq, dq_hash);
695 mutex_exit(&dqlock); 691 mutex_exit(&dqlock);
696 mutex_exit(&dq->dq_interlock); 692 mutex_exit(&dq->dq_interlock);
697 dqrele(vp, dq); 693 dqrele(vp, dq);
698 *dqp = NODQUOT; 694 *dqp = NODQUOT;
699 return (error); 695 return (error);
700 } 696 }
701 mutex_exit(&dq->dq_interlock); 697 mutex_exit(&dq->dq_interlock);
702 *dqp = dq; 698 *dqp = dq;
703 return (0); 699 return (0);
704} 700}
705 701
706/* 702/*
707 * Obtain a reference to a dquot. 703 * Obtain a reference to a dquot.
708 */ 704 */
709void 705void
710dqref(struct dquot *dq) 706dqref(struct dquot *dq)
711{ 707{
712 708
713 KASSERT(mutex_owned(&dqlock)); 709 KASSERT(mutex_owned(&dqlock));
714 dq->dq_cnt++; 710 dq->dq_cnt++;
715 KASSERT(dq->dq_cnt > 0); 711 KASSERT(dq->dq_cnt > 0);
716} 712}
717 713
718/* 714/*
719 * Release a reference to a dquot. 715 * Release a reference to a dquot.
720 */ 716 */
721void 717void
722dqrele(struct vnode *vp, struct dquot *dq) 718dqrele(struct vnode *vp, struct dquot *dq)
723{ 719{
724 720
725 if (dq == NODQUOT) 721 if (dq == NODQUOT)
726 return; 722 return;
727 mutex_enter(&dq->dq_interlock); 723 mutex_enter(&dq->dq_interlock);
728 for (;;) { 724 for (;;) {
729 mutex_enter(&dqlock); 725 mutex_enter(&dqlock);
730 if (dq->dq_cnt > 1) { 726 if (dq->dq_cnt > 1) {
731 dq->dq_cnt--; 727 dq->dq_cnt--;
732 mutex_exit(&dqlock); 728 mutex_exit(&dqlock);
733 mutex_exit(&dq->dq_interlock); 729 mutex_exit(&dq->dq_interlock);
734 return; 730 return;
735 } 731 }
736 if ((dq->dq_flags & DQ_MOD) == 0) 732 if ((dq->dq_flags & DQ_MOD) == 0)
737 break; 733 break;
738 mutex_exit(&dqlock); 734 mutex_exit(&dqlock);
739#ifdef QUOTA 735#ifdef QUOTA
740 if (dq->dq_ump->um_flags & UFS_QUOTA) 736 if (dq->dq_ump->um_flags & UFS_QUOTA)
741 (void) dq1sync(vp, dq); 737 (void) dq1sync(vp, dq);
742#endif 738#endif
743#ifdef QUOTA2 739#ifdef QUOTA2
744 if (dq->dq_ump->um_flags & UFS_QUOTA2) 740 if (dq->dq_ump->um_flags & UFS_QUOTA2)
745 (void) dq2sync(vp, dq); 741 (void) dq2sync(vp, dq);
746#endif 742#endif
747 } 743 }
748 KASSERT(dq->dq_cnt == 1 && (dq->dq_flags & DQ_MOD) == 0); 744 KASSERT(dq->dq_cnt == 1 && (dq->dq_flags & DQ_MOD) == 0);
749 LIST_REMOVE(dq, dq_hash); 745 LIST_REMOVE(dq, dq_hash);
750 mutex_exit(&dqlock); 746 mutex_exit(&dqlock);
751 mutex_exit(&dq->dq_interlock); 747 mutex_exit(&dq->dq_interlock);
752 mutex_destroy(&dq->dq_interlock); 748 mutex_destroy(&dq->dq_interlock);
753 pool_cache_put(dquot_cache, dq); 749 pool_cache_put(dquot_cache, dq);
754} 750}
755 751
756int 752int
757qsync(struct mount *mp) 753qsync(struct mount *mp)
758{ 754{
759 struct ufsmount *ump = VFSTOUFS(mp); 755 struct ufsmount *ump = VFSTOUFS(mp);
760#ifdef QUOTA 756#ifdef QUOTA
761 if (ump->um_flags & UFS_QUOTA) 757 if (ump->um_flags & UFS_QUOTA)
762 return q1sync(mp); 758 return q1sync(mp);
763#endif 759#endif
764#ifdef QUOTA2 760#ifdef QUOTA2
765 if (ump->um_flags & UFS_QUOTA2) 761 if (ump->um_flags & UFS_QUOTA2)
766 return q2sync(mp); 762 return q2sync(mp);
767#endif 763#endif
768 return 0; 764 return 0;
769} 765}
770 766
771#ifdef DIAGNOSTIC 767#ifdef DIAGNOSTIC
772/* 768/*
773 * Check the hash chains for stray dquot's. 769 * Check the hash chains for stray dquot's.
774 */ 770 */
775void 771void
776dqflush(struct vnode *vp) 772dqflush(struct vnode *vp)
777{ 773{
778 struct dquot *dq; 774 struct dquot *dq;
779 int i; 775 int i;
780 776
781 mutex_enter(&dqlock); 777 mutex_enter(&dqlock);
782 for (i = 0; i <= dqhash; i++) 778 for (i = 0; i <= dqhash; i++)
783 LIST_FOREACH(dq, &dqhashtbl[i], dq_hash) 779 LIST_FOREACH(dq, &dqhashtbl[i], dq_hash)
784 KASSERT(dq->dq_ump->um_quotas[dq->dq_type] != vp); 780 KASSERT(dq->dq_ump->um_quotas[dq->dq_type] != vp);
785 mutex_exit(&dqlock); 781 mutex_exit(&dqlock);
786} 782}
787#endif 783#endif

cvs diff -r1.10 -r1.11 src/sys/ufs/ufs/ufs_quota.h (switch to unified diff)

--- src/sys/ufs/ufs/ufs_quota.h 2012/01/29 06:49:44 1.10
+++ src/sys/ufs/ufs/ufs_quota.h 2012/01/29 06:52:39 1.11
@@ -1,134 +1,134 @@ @@ -1,134 +1,134 @@
1/* $NetBSD: ufs_quota.h,v 1.10 2012/01/29 06:49:44 dholland Exp $ */ 1/* $NetBSD: ufs_quota.h,v 1.11 2012/01/29 06:52:39 dholland Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1990, 1993, 1995 4 * Copyright (c) 1982, 1986, 1990, 1993, 1995
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Robert Elz at The University of Melbourne. 8 * Robert Elz at The University of Melbourne.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 * 33 *
34 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 34 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
35 */ 35 */
36#include <ufs/ufs/quota1.h> 36#include <ufs/ufs/quota1.h>
37#include <ufs/ufs/quota2.h> 37#include <ufs/ufs/quota2.h>
38 38
39/* link to this quota in the quota inode (for QUOTA2) */ 39/* link to this quota in the quota inode (for QUOTA2) */
40struct dq2_desc { 40struct dq2_desc {
41 uint64_t dq2_lblkno; /* logical disk block holding this quota */ 41 uint64_t dq2_lblkno; /* logical disk block holding this quota */
42 u_int dq2_blkoff; /* offset in disk block holding this quota */ 42 u_int dq2_blkoff; /* offset in disk block holding this quota */
43}; 43};
44 44
45/* 45/*
46 * The following structure records disk usage for a user or group on a 46 * The following structure records disk usage for a user or group on a
47 * filesystem. There is one allocated for each quota that exists on any 47 * filesystem. There is one allocated for each quota that exists on any
48 * filesystem for the current user or group. A cache is kept of recently 48 * filesystem for the current user or group. A cache is kept of recently
49 * used entries. 49 * used entries.
50 * Field markings and the corresponding locks: 50 * Field markings and the corresponding locks:
51 * h: dqlock 51 * h: dqlock
52 * d: dq_interlock 52 * d: dq_interlock
53 * 53 *
54 * Lock order is: dq_interlock -> dqlock 54 * Lock order is: dq_interlock -> dqlock
55 * dq_interlock -> dqvp 55 * dq_interlock -> dqvp
56 */ 56 */
57struct dquot { 57struct dquot {
58 LIST_ENTRY(dquot) dq_hash; /* h: hash list */ 58 LIST_ENTRY(dquot) dq_hash; /* h: hash list */
59 u_int16_t dq_flags; /* d: flags, see below */ 59 u_int16_t dq_flags; /* d: flags, see below */
60 u_int16_t dq_type; /* d: quota type of this dquot */ 60 u_int16_t dq_type; /* d: quota type of this dquot */
61 u_int32_t dq_cnt; /* h: count of active references */ 61 u_int32_t dq_cnt; /* h: count of active references */
62 u_int32_t dq_id; /* d: identifier this applies to */ 62 u_int32_t dq_id; /* d: identifier this applies to */
63 struct ufsmount *dq_ump; /* d: filesystem this is taken from */ 63 struct ufsmount *dq_ump; /* d: filesystem this is taken from */
64 kmutex_t dq_interlock; /* d: lock this dquot */ 64 kmutex_t dq_interlock; /* d: lock this dquot */
65 union { 65 union {
66 struct dqblk dq1_dqb; /* d: actual usage & quotas */ 66 struct dqblk dq1_dqb; /* d: actual usage & quotas */
67 struct dq2_desc dq2_desc; /* d: pointer to quota data */ 67 struct dq2_desc dq2_desc; /* d: pointer to quota data */
68 } dq_un; 68 } dq_un;
69}; 69};
70 70
71/* 71/*
72 * Flag values. 72 * Flag values.
73 */ 73 */
74#define DQ_MOD 0x04 /* this quota modified since read */ 74#define DQ_MOD 0x04 /* this quota modified since read */
75#define DQ_FAKE 0x08 /* no limits here, just usage */ 75#define DQ_FAKE 0x08 /* no limits here, just usage */
76#define DQ_WARN(ltype) (0x10 << ltype) /* has been warned about "type" limit */ 76#define DQ_WARN(ltype) (0x10 << ltype) /* has been warned about "type" limit */
77/* 77/*
78 * Shorthand notation. 78 * Shorthand notation.
79 */ 79 */
80#define dq_bhardlimit dq_un.dq1_dqb.dqb_bhardlimit 80#define dq_bhardlimit dq_un.dq1_dqb.dqb_bhardlimit
81#define dq_bsoftlimit dq_un.dq1_dqb.dqb_bsoftlimit 81#define dq_bsoftlimit dq_un.dq1_dqb.dqb_bsoftlimit
82#define dq_curblocks dq_un.dq1_dqb.dqb_curblocks 82#define dq_curblocks dq_un.dq1_dqb.dqb_curblocks
83#define dq_ihardlimit dq_un.dq1_dqb.dqb_ihardlimit 83#define dq_ihardlimit dq_un.dq1_dqb.dqb_ihardlimit
84#define dq_isoftlimit dq_un.dq1_dqb.dqb_isoftlimit 84#define dq_isoftlimit dq_un.dq1_dqb.dqb_isoftlimit
85#define dq_curinodes dq_un.dq1_dqb.dqb_curinodes 85#define dq_curinodes dq_un.dq1_dqb.dqb_curinodes
86#define dq_btime dq_un.dq1_dqb.dqb_btime 86#define dq_btime dq_un.dq1_dqb.dqb_btime
87#define dq_itime dq_un.dq1_dqb.dqb_itime 87#define dq_itime dq_un.dq1_dqb.dqb_itime
88 88
89#define dq2_lblkno dq_un.dq2_desc.dq2_lblkno 89#define dq2_lblkno dq_un.dq2_desc.dq2_lblkno
90#define dq2_blkoff dq_un.dq2_desc.dq2_blkoff 90#define dq2_blkoff dq_un.dq2_desc.dq2_blkoff
91/* 91/*
92 * If the system has never checked for a quota for this file, then it is 92 * If the system has never checked for a quota for this file, then it is
93 * set to NODQUOT. Once a write attempt is made the inode pointer is set 93 * set to NODQUOT. Once a write attempt is made the inode pointer is set
94 * to reference a dquot structure. 94 * to reference a dquot structure.
95 */ 95 */
96#define NODQUOT NULL 96#define NODQUOT NULL
97 97
98extern kmutex_t dqlock; 98extern kmutex_t dqlock;
99extern kcondvar_t dqcv; 99extern kcondvar_t dqcv;
100/* 100/*
101 * Quota name to error message mapping. 101 * Quota name to error message mapping.
102 */ 102 */
103const char *quotatypes[MAXQUOTAS]; 103const char *quotatypes[MAXQUOTAS];
104 104
105int getinoquota(struct inode *); 105int getinoquota(struct inode *);
106int dqget(struct vnode *, u_long, struct ufsmount *, int, struct dquot **); 106int dqget(struct vnode *, u_long, struct ufsmount *, int, struct dquot **);
107void dqref(struct dquot *); 107void dqref(struct dquot *);
108void dqrele(struct vnode *, struct dquot *); 108void dqrele(struct vnode *, struct dquot *);
109void dqflush(struct vnode *); 109void dqflush(struct vnode *);
110 110
111int chkdq1(struct inode *, int64_t, kauth_cred_t, int); 111int chkdq1(struct inode *, int64_t, kauth_cred_t, int);
112int chkiq1(struct inode *, int32_t, kauth_cred_t, int); 112int chkiq1(struct inode *, int32_t, kauth_cred_t, int);
113int q1sync(struct mount *); 113int q1sync(struct mount *);
114int dq1get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *); 114int dq1get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *);
115int dq1sync(struct vnode *, struct dquot *); 115int dq1sync(struct vnode *, struct dquot *);
116int quota1_handle_cmd_get(struct ufsmount *, const struct quotakey *, 116int quota1_handle_cmd_get(struct ufsmount *, const struct quotakey *,
117 struct quotaval *); 117 struct quotaval *);
118int quota1_handle_cmd_put(struct ufsmount *, const struct quotakey *, 118int quota1_handle_cmd_put(struct ufsmount *, const struct quotakey *,
119 const struct quotaval *); 119 const struct quotaval *);
120int quota1_handle_cmd_quotaon(struct lwp *, struct ufsmount *, int, 120int quota1_handle_cmd_quotaon(struct lwp *, struct ufsmount *, int,
121 const char *); 121 const char *);
122int quota1_handle_cmd_quotaoff(struct lwp *, struct ufsmount *, int); 122int quota1_handle_cmd_quotaoff(struct lwp *, struct ufsmount *, int);
123 123
124int chkdq2(struct inode *, int64_t, kauth_cred_t, int); 124int chkdq2(struct inode *, int64_t, kauth_cred_t, int);
125int chkiq2(struct inode *, int32_t, kauth_cred_t, int); 125int chkiq2(struct inode *, int32_t, kauth_cred_t, int);
126int quota2_handle_cmd_get(struct ufsmount *, const struct quotakey *, 126int quota2_handle_cmd_get(struct ufsmount *, const struct quotakey *,
127 struct quotaval *); 127 struct quotaval *);
128int quota2_handle_cmd_put(struct ufsmount *, const struct quotakey *, 128int quota2_handle_cmd_put(struct ufsmount *, const struct quotakey *,
129 const struct quotaval *); 129 const struct quotaval *);
130int quota2_handle_cmd_clear(struct ufsmount *, int, int, int, prop_dictionary_t); 130int quota2_handle_cmd_clear(struct ufsmount *, int, int, int);
131int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t); 131int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t);
132int q2sync(struct mount *); 132int q2sync(struct mount *);
133int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *); 133int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *);
134int dq2sync(struct vnode *, struct dquot *); 134int dq2sync(struct vnode *, struct dquot *);

cvs diff -r1.11 -r1.12 src/sys/ufs/ufs/ufs_quota2.c (switch to unified diff)

--- src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 06:49:44 1.11
+++ src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 06:52:39 1.12
@@ -1,1084 +1,1084 @@ @@ -1,1084 +1,1084 @@
1/* $NetBSD: ufs_quota2.c,v 1.11 2012/01/29 06:49:44 dholland Exp $ */ 1/* $NetBSD: ufs_quota2.c,v 1.12 2012/01/29 06:52:39 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
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.11 2012/01/29 06:49:44 dholland Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.12 2012/01/29 06:52:39 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>
43#include <sys/wapbl.h> 43#include <sys/wapbl.h>
44#include <sys/quota.h> 44#include <sys/quota.h>
45 45
46#include <ufs/ufs/quota2.h> 46#include <ufs/ufs/quota2.h>
47#include <ufs/ufs/inode.h> 47#include <ufs/ufs/inode.h>
48#include <ufs/ufs/ufsmount.h> 48#include <ufs/ufs/ufsmount.h>
49#include <ufs/ufs/ufs_bswap.h> 49#include <ufs/ufs/ufs_bswap.h>
50#include <ufs/ufs/ufs_extern.h> 50#include <ufs/ufs/ufs_extern.h>
51#include <ufs/ufs/ufs_quota.h> 51#include <ufs/ufs/ufs_quota.h>
52#include <ufs/ufs/ufs_wapbl.h> 52#include <ufs/ufs/ufs_wapbl.h>
53#include <quota/quotaprop.h> 53#include <quota/quotaprop.h>
54 54
55/* 55/*
56 * LOCKING: 56 * LOCKING:
57 * Data in the entries are protected by the associated struct dquot's 57 * Data in the entries are protected by the associated struct dquot's
58 * dq_interlock (this means we can't read or change a quota entry without 58 * dq_interlock (this means we can't read or change a quota entry without
59 * grabing a dquot for it). 59 * grabing a dquot for it).
60 * The header and lists (including pointers in the data entries, and q2e_uid) 60 * The header and lists (including pointers in the data entries, and q2e_uid)
61 * are protected by the global dqlock. 61 * are protected by the global dqlock.
62 * the locking order is dq_interlock -> dqlock 62 * the locking order is dq_interlock -> dqlock
63 */ 63 */
64 64
65static int quota2_bwrite(struct mount *, struct buf *); 65static int quota2_bwrite(struct mount *, struct buf *);
66static int getinoquota2(struct inode *, bool, bool, struct buf **, 66static int getinoquota2(struct inode *, bool, bool, struct buf **,
67 struct quota2_entry **); 67 struct quota2_entry **);
68static int getq2h(struct ufsmount *, int, struct buf **, 68static int getq2h(struct ufsmount *, int, struct buf **,
69 struct quota2_header **, int); 69 struct quota2_header **, int);
70static int getq2e(struct ufsmount *, int, daddr_t, int, struct buf **, 70static int getq2e(struct ufsmount *, int, daddr_t, int, struct buf **,
71 struct quota2_entry **, int); 71 struct quota2_entry **, int);
72static int quota2_walk_list(struct ufsmount *, struct buf *, int, 72static int quota2_walk_list(struct ufsmount *, struct buf *, int,
73 uint64_t *, int, void *, 73 uint64_t *, int, void *,
74 int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, 74 int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *,
75 uint64_t, void *)); 75 uint64_t, void *));
76 76
77static prop_dictionary_t q2etoprop(struct quota2_entry *, int); 77static prop_dictionary_t q2etoprop(struct quota2_entry *, int);
78 78
79static const char *limnames[] = INITQLNAMES; 79static const char *limnames[] = INITQLNAMES;
80 80
81static void 81static void
82quota2_dict_update_q2e_limits(int objtype, const struct quotaval *val, 82quota2_dict_update_q2e_limits(int objtype, const struct quotaval *val,
83 struct quota2_entry *q2e) 83 struct quota2_entry *q2e)
84{ 84{
85 /* make sure we can index q2e_val[] by the fs-independent objtype */ 85 /* make sure we can index q2e_val[] by the fs-independent objtype */
86 CTASSERT(QUOTA_OBJTYPE_BLOCKS == QL_BLOCK); 86 CTASSERT(QUOTA_OBJTYPE_BLOCKS == QL_BLOCK);
87 CTASSERT(QUOTA_OBJTYPE_FILES == QL_FILE); 87 CTASSERT(QUOTA_OBJTYPE_FILES == QL_FILE);
88 88
89 q2e->q2e_val[objtype].q2v_hardlimit = val->qv_hardlimit; 89 q2e->q2e_val[objtype].q2v_hardlimit = val->qv_hardlimit;
90 q2e->q2e_val[objtype].q2v_softlimit = val->qv_softlimit; 90 q2e->q2e_val[objtype].q2v_softlimit = val->qv_softlimit;
91 q2e->q2e_val[objtype].q2v_grace = val->qv_grace; 91 q2e->q2e_val[objtype].q2v_grace = val->qv_grace;
92} 92}
93 93
94static prop_dictionary_t 94static prop_dictionary_t
95q2etoprop(struct quota2_entry *q2e, int def) 95q2etoprop(struct quota2_entry *q2e, int def)
96{ 96{
97 const char *val_names[] = INITQVNAMES_ALL; 97 const char *val_names[] = INITQVNAMES_ALL;
98 prop_dictionary_t dict1 = prop_dictionary_create(); 98 prop_dictionary_t dict1 = prop_dictionary_create();
99 prop_dictionary_t dict2; 99 prop_dictionary_t dict2;
100 int i; 100 int i;
101 101
102 if (dict1 == NULL) 102 if (dict1 == NULL)
103 return NULL; 103 return NULL;
104 104
105 if (def) { 105 if (def) {
106 if (!prop_dictionary_set_cstring_nocopy(dict1, "id", 106 if (!prop_dictionary_set_cstring_nocopy(dict1, "id",
107 "default")) { 107 "default")) {
108 goto err; 108 goto err;
109 } 109 }
110 } else { 110 } else {
111 if (!prop_dictionary_set_uint32(dict1, "id", q2e->q2e_uid)) { 111 if (!prop_dictionary_set_uint32(dict1, "id", q2e->q2e_uid)) {
112 goto err; 112 goto err;
113 } 113 }
114 } 114 }
115 for (i = 0; i < N_QL; i++) { 115 for (i = 0; i < N_QL; i++) {
116 dict2 = limits64toprop(&q2e->q2e_val[i].q2v_hardlimit, 116 dict2 = limits64toprop(&q2e->q2e_val[i].q2v_hardlimit,
117 val_names, N_QV); 117 val_names, N_QV);
118 if (dict2 == NULL) 118 if (dict2 == NULL)
119 goto err; 119 goto err;
120 if (!prop_dictionary_set_and_rel(dict1, limnames[i], dict2)) 120 if (!prop_dictionary_set_and_rel(dict1, limnames[i], dict2))
121 goto err; 121 goto err;
122 } 122 }
123 return dict1; 123 return dict1;
124 124
125err: 125err:
126 prop_object_release(dict1); 126 prop_object_release(dict1);
127 return NULL; 127 return NULL;
128} 128}
129 129
130/* 130/*
131 * Convert internal representation to FS-independent representation. 131 * Convert internal representation to FS-independent representation.
132 * (Note that while the two types are currently identical, the 132 * (Note that while the two types are currently identical, the
133 * internal representation is an on-disk struct and the FS-independent 133 * internal representation is an on-disk struct and the FS-independent
134 * representation is not, and they might diverge in the future.) 134 * representation is not, and they might diverge in the future.)
135 */ 135 */
136static void 136static void
137q2val_to_quotaval(struct quota2_val *q2v, struct quotaval *qv) 137q2val_to_quotaval(struct quota2_val *q2v, struct quotaval *qv)
138{ 138{
139 qv->qv_softlimit = q2v->q2v_softlimit; 139 qv->qv_softlimit = q2v->q2v_softlimit;
140 qv->qv_hardlimit = q2v->q2v_hardlimit; 140 qv->qv_hardlimit = q2v->q2v_hardlimit;
141 qv->qv_usage = q2v->q2v_cur; 141 qv->qv_usage = q2v->q2v_cur;
142 qv->qv_expiretime = q2v->q2v_time; 142 qv->qv_expiretime = q2v->q2v_time;
143 qv->qv_grace = q2v->q2v_grace; 143 qv->qv_grace = q2v->q2v_grace;
144} 144}
145 145
146/* 146/*
147 * Convert a quota2entry and default-flag to the FS-independent 147 * Convert a quota2entry and default-flag to the FS-independent
148 * representation. 148 * representation.
149 */ 149 */
150static void 150static void
151q2e_to_quotaval(struct quota2_entry *q2e, int def, 151q2e_to_quotaval(struct quota2_entry *q2e, int def,
152 id_t *id, int objtype, struct quotaval *ret) 152 id_t *id, int objtype, struct quotaval *ret)
153{ 153{
154 if (def) { 154 if (def) {
155 *id = QUOTA_DEFAULTID; 155 *id = QUOTA_DEFAULTID;
156 } else { 156 } else {
157 *id = q2e->q2e_uid; 157 *id = q2e->q2e_uid;
158 } 158 }
159 159
160 KASSERT(objtype >= 0 && objtype < N_QL); 160 KASSERT(objtype >= 0 && objtype < N_QL);
161 q2val_to_quotaval(&q2e->q2e_val[objtype], ret); 161 q2val_to_quotaval(&q2e->q2e_val[objtype], ret);
162} 162}
163 163
164 164
165static int 165static int
166quota2_bwrite(struct mount *mp, struct buf *bp) 166quota2_bwrite(struct mount *mp, struct buf *bp)
167{ 167{
168 if (mp->mnt_flag & MNT_SYNCHRONOUS) 168 if (mp->mnt_flag & MNT_SYNCHRONOUS)
169 return bwrite(bp); 169 return bwrite(bp);
170 else { 170 else {
171 bdwrite(bp); 171 bdwrite(bp);
172 return 0; 172 return 0;
173 } 173 }
174} 174}
175 175
176static int 176static int
177getq2h(struct ufsmount *ump, int type, 177getq2h(struct ufsmount *ump, int type,
178 struct buf **bpp, struct quota2_header **q2hp, int flags) 178 struct buf **bpp, struct quota2_header **q2hp, int flags)
179{ 179{
180#ifdef FFS_EI 180#ifdef FFS_EI
181 const int needswap = UFS_MPNEEDSWAP(ump); 181 const int needswap = UFS_MPNEEDSWAP(ump);
182#endif 182#endif
183 int error; 183 int error;
184 struct buf *bp; 184 struct buf *bp;
185 struct quota2_header *q2h; 185 struct quota2_header *q2h;
186 186
187 KASSERT(mutex_owned(&dqlock)); 187 KASSERT(mutex_owned(&dqlock));
188 error = bread(ump->um_quotas[type], 0, ump->umq2_bsize, 188 error = bread(ump->um_quotas[type], 0, ump->umq2_bsize,
189 ump->um_cred[type], flags, &bp); 189 ump->um_cred[type], flags, &bp);
190 if (error) 190 if (error)
191 return error; 191 return error;
192 if (bp->b_resid != 0)  192 if (bp->b_resid != 0)
193 panic("dq2get: %s quota file truncated", quotatypes[type]); 193 panic("dq2get: %s quota file truncated", quotatypes[type]);
194 194
195 q2h = (void *)bp->b_data; 195 q2h = (void *)bp->b_data;
196 if (ufs_rw32(q2h->q2h_magic_number, needswap) != Q2_HEAD_MAGIC || 196 if (ufs_rw32(q2h->q2h_magic_number, needswap) != Q2_HEAD_MAGIC ||
197 q2h->q2h_type != type) 197 q2h->q2h_type != type)
198 panic("dq2get: corrupted %s quota header", quotatypes[type]); 198 panic("dq2get: corrupted %s quota header", quotatypes[type]);
199 *bpp = bp; 199 *bpp = bp;
200 *q2hp = q2h; 200 *q2hp = q2h;
201 return 0; 201 return 0;
202} 202}
203 203
204static int 204static int
205getq2e(struct ufsmount *ump, int type, daddr_t lblkno, int blkoffset, 205getq2e(struct ufsmount *ump, int type, daddr_t lblkno, int blkoffset,
206 struct buf **bpp, struct quota2_entry **q2ep, int flags) 206 struct buf **bpp, struct quota2_entry **q2ep, int flags)
207{ 207{
208 int error; 208 int error;
209 struct buf *bp; 209 struct buf *bp;
210 210
211 if (blkoffset & (sizeof(uint64_t) - 1)) { 211 if (blkoffset & (sizeof(uint64_t) - 1)) {
212 panic("dq2get: %s quota file corrupted", 212 panic("dq2get: %s quota file corrupted",
213 quotatypes[type]); 213 quotatypes[type]);
214 } 214 }
215 error = bread(ump->um_quotas[type], lblkno, ump->umq2_bsize, 215 error = bread(ump->um_quotas[type], lblkno, ump->umq2_bsize,
216 ump->um_cred[type], flags, &bp); 216 ump->um_cred[type], flags, &bp);
217 if (error) 217 if (error)
218 return error; 218 return error;
219 if (bp->b_resid != 0) { 219 if (bp->b_resid != 0) {
220 panic("dq2get: %s quota file corrupted", 220 panic("dq2get: %s quota file corrupted",
221 quotatypes[type]); 221 quotatypes[type]);
222 } 222 }
223 *q2ep = (void *)((char *)bp->b_data + blkoffset); 223 *q2ep = (void *)((char *)bp->b_data + blkoffset);
224 *bpp = bp; 224 *bpp = bp;
225 return 0; 225 return 0;
226} 226}
227 227
228/* walk a quota entry list, calling the callback for each entry */ 228/* walk a quota entry list, calling the callback for each entry */
229#define Q2WL_ABORT 0x10000000 229#define Q2WL_ABORT 0x10000000
230 230
231static int 231static int
232quota2_walk_list(struct ufsmount *ump, struct buf *hbp, int type, 232quota2_walk_list(struct ufsmount *ump, struct buf *hbp, int type,
233 uint64_t *offp, int flags, void *a, 233 uint64_t *offp, int flags, void *a,
234 int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, uint64_t, void *)) 234 int (*func)(struct ufsmount *, uint64_t *, struct quota2_entry *, uint64_t, void *))
235{ 235{
236#ifdef FFS_EI 236#ifdef FFS_EI
237 const int needswap = UFS_MPNEEDSWAP(ump); 237 const int needswap = UFS_MPNEEDSWAP(ump);
238#endif 238#endif
239 daddr_t off = ufs_rw64(*offp, needswap); 239 daddr_t off = ufs_rw64(*offp, needswap);
240 struct buf *bp, *obp = hbp; 240 struct buf *bp, *obp = hbp;
241 int ret = 0, ret2 = 0; 241 int ret = 0, ret2 = 0;
242 struct quota2_entry *q2e; 242 struct quota2_entry *q2e;
243 daddr_t lblkno, blkoff, olblkno = 0; 243 daddr_t lblkno, blkoff, olblkno = 0;
244 244
245 KASSERT(mutex_owner(&dqlock)); 245 KASSERT(mutex_owner(&dqlock));
246 246
247 while (off != 0) { 247 while (off != 0) {
248 lblkno = (off >> ump->um_mountp->mnt_fs_bshift); 248 lblkno = (off >> ump->um_mountp->mnt_fs_bshift);
249 blkoff = (off & ump->umq2_bmask); 249 blkoff = (off & ump->umq2_bmask);
250 if (lblkno == 0) { 250 if (lblkno == 0) {
251 /* in the header block */ 251 /* in the header block */
252 bp = hbp; 252 bp = hbp;
253 } else if (lblkno == olblkno) { 253 } else if (lblkno == olblkno) {
254 /* still in the same buf */ 254 /* still in the same buf */
255 bp = obp; 255 bp = obp;
256 } else { 256 } else {
257 ret = bread(ump->um_quotas[type], lblkno,  257 ret = bread(ump->um_quotas[type], lblkno,
258 ump->umq2_bsize, 258 ump->umq2_bsize,
259 ump->um_cred[type], flags, &bp); 259 ump->um_cred[type], flags, &bp);
260 if (ret) 260 if (ret)
261 return ret; 261 return ret;
262 if (bp->b_resid != 0) { 262 if (bp->b_resid != 0) {
263 panic("quota2_walk_list: %s quota file corrupted", 263 panic("quota2_walk_list: %s quota file corrupted",
264 quotatypes[type]); 264 quotatypes[type]);
265 } 265 }
266 } 266 }
267 q2e = (void *)((char *)(bp->b_data) + blkoff); 267 q2e = (void *)((char *)(bp->b_data) + blkoff);
268 ret = (*func)(ump, offp, q2e, off, a); 268 ret = (*func)(ump, offp, q2e, off, a);
269 if (off != ufs_rw64(*offp, needswap)) { 269 if (off != ufs_rw64(*offp, needswap)) {
270 /* callback changed parent's pointer, redo */ 270 /* callback changed parent's pointer, redo */
271 off = ufs_rw64(*offp, needswap); 271 off = ufs_rw64(*offp, needswap);
272 if (bp != hbp && bp != obp) 272 if (bp != hbp && bp != obp)
273 ret2 = bwrite(bp); 273 ret2 = bwrite(bp);
274 } else { 274 } else {
275 /* parent if now current */ 275 /* parent if now current */
276 if (obp != bp && obp != hbp) { 276 if (obp != bp && obp != hbp) {
277 if (flags & B_MODIFY) 277 if (flags & B_MODIFY)
278 ret2 = bwrite(obp); 278 ret2 = bwrite(obp);
279 else 279 else
280 brelse(obp, 0); 280 brelse(obp, 0);
281 } 281 }
282 obp = bp; 282 obp = bp;
283 olblkno = lblkno; 283 olblkno = lblkno;
284 offp = &(q2e->q2e_next); 284 offp = &(q2e->q2e_next);
285 off = ufs_rw64(*offp, needswap); 285 off = ufs_rw64(*offp, needswap);
286 } 286 }
287 if (ret) 287 if (ret)
288 break; 288 break;
289 if (ret2) { 289 if (ret2) {
290 ret = ret2; 290 ret = ret2;
291 break; 291 break;
292 } 292 }
293 } 293 }
294 if (obp != hbp) { 294 if (obp != hbp) {
295 if (flags & B_MODIFY) 295 if (flags & B_MODIFY)
296 ret2 = bwrite(obp); 296 ret2 = bwrite(obp);
297 else 297 else
298 brelse(obp, 0); 298 brelse(obp, 0);
299 } 299 }
300 if (ret & Q2WL_ABORT) 300 if (ret & Q2WL_ABORT)
301 return 0; 301 return 0;
302 if (ret == 0) 302 if (ret == 0)
303 return ret2; 303 return ret2;
304 return ret; 304 return ret;
305} 305}
306 306
307int 307int
308quota2_umount(struct mount *mp, int flags) 308quota2_umount(struct mount *mp, int flags)
309{ 309{
310 int i, error; 310 int i, error;
311 struct ufsmount *ump = VFSTOUFS(mp); 311 struct ufsmount *ump = VFSTOUFS(mp);
312 312
313 if ((ump->um_flags & UFS_QUOTA2) == 0) 313 if ((ump->um_flags & UFS_QUOTA2) == 0)
314 return 0; 314 return 0;
315 315
316 for (i = 0; i < MAXQUOTAS; i++) { 316 for (i = 0; i < MAXQUOTAS; i++) {
317 if (ump->um_quotas[i] != NULLVP) { 317 if (ump->um_quotas[i] != NULLVP) {
318 error = vn_close(ump->um_quotas[i], FREAD|FWRITE, 318 error = vn_close(ump->um_quotas[i], FREAD|FWRITE,
319 ump->um_cred[i]); 319 ump->um_cred[i]);
320 if (error) { 320 if (error) {
321 printf("quota2_umount failed: close(%p) %d\n", 321 printf("quota2_umount failed: close(%p) %d\n",
322 ump->um_quotas[i], error); 322 ump->um_quotas[i], error);
323 return error; 323 return error;
324 } 324 }
325 } 325 }
326 ump->um_quotas[i] = NULLVP; 326 ump->um_quotas[i] = NULLVP;
327 } 327 }
328 return 0; 328 return 0;
329} 329}
330 330
331static int  331static int
332quota2_q2ealloc(struct ufsmount *ump, int type, uid_t uid, struct dquot *dq, 332quota2_q2ealloc(struct ufsmount *ump, int type, uid_t uid, struct dquot *dq,
333 struct buf **bpp, struct quota2_entry **q2ep) 333 struct buf **bpp, struct quota2_entry **q2ep)
334{ 334{
335 int error, error2; 335 int error, error2;
336 struct buf *hbp, *bp; 336 struct buf *hbp, *bp;
337 struct quota2_header *q2h; 337 struct quota2_header *q2h;
338 struct quota2_entry *q2e; 338 struct quota2_entry *q2e;
339 daddr_t offset; 339 daddr_t offset;
340 u_long hash_mask; 340 u_long hash_mask;
341 const int needswap = UFS_MPNEEDSWAP(ump); 341 const int needswap = UFS_MPNEEDSWAP(ump);
342 342
343 KASSERT(mutex_owned(&dq->dq_interlock)); 343 KASSERT(mutex_owned(&dq->dq_interlock));
344 KASSERT(mutex_owned(&dqlock)); 344 KASSERT(mutex_owned(&dqlock));
345 error = getq2h(ump, type, &hbp, &q2h, B_MODIFY); 345 error = getq2h(ump, type, &hbp, &q2h, B_MODIFY);
346 if (error) 346 if (error)
347 return error; 347 return error;
348 offset = ufs_rw64(q2h->q2h_free, needswap); 348 offset = ufs_rw64(q2h->q2h_free, needswap);
349 if (offset == 0) { 349 if (offset == 0) {
350 struct vnode *vp = ump->um_quotas[type]; 350 struct vnode *vp = ump->um_quotas[type];
351 struct inode *ip = VTOI(vp); 351 struct inode *ip = VTOI(vp);
352 uint64_t size = ip->i_size; 352 uint64_t size = ip->i_size;
353 /* need to alocate a new disk block */ 353 /* need to alocate a new disk block */
354 error = UFS_BALLOC(vp, size, ump->umq2_bsize, 354 error = UFS_BALLOC(vp, size, ump->umq2_bsize,
355 ump->um_cred[type], B_CLRBUF | B_SYNC, &bp); 355 ump->um_cred[type], B_CLRBUF | B_SYNC, &bp);
356 if (error) { 356 if (error) {
357 brelse(hbp, 0); 357 brelse(hbp, 0);
358 return error; 358 return error;
359 } 359 }
360 KASSERT((ip->i_size % ump->umq2_bsize) == 0); 360 KASSERT((ip->i_size % ump->umq2_bsize) == 0);
361 ip->i_size += ump->umq2_bsize; 361 ip->i_size += ump->umq2_bsize;
362 DIP_ASSIGN(ip, size, ip->i_size); 362 DIP_ASSIGN(ip, size, ip->i_size);
363 ip->i_flag |= IN_CHANGE | IN_UPDATE; 363 ip->i_flag |= IN_CHANGE | IN_UPDATE;
364 uvm_vnp_setsize(vp, ip->i_size); 364 uvm_vnp_setsize(vp, ip->i_size);
365 quota2_addfreeq2e(q2h, bp->b_data, size, ump->umq2_bsize, 365 quota2_addfreeq2e(q2h, bp->b_data, size, ump->umq2_bsize,
366 needswap); 366 needswap);
367 error = bwrite(bp); 367 error = bwrite(bp);
368 error2 = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT); 368 error2 = UFS_UPDATE(vp, NULL, NULL, UPDATE_WAIT);
369 if (error || error2) { 369 if (error || error2) {
370 brelse(hbp, 0); 370 brelse(hbp, 0);
371 if (error) 371 if (error)
372 return error; 372 return error;
373 return error2; 373 return error2;
374 } 374 }
375 offset = ufs_rw64(q2h->q2h_free, needswap); 375 offset = ufs_rw64(q2h->q2h_free, needswap);
376 KASSERT(offset != 0); 376 KASSERT(offset != 0);
377 } 377 }
378 dq->dq2_lblkno = (offset >> ump->um_mountp->mnt_fs_bshift); 378 dq->dq2_lblkno = (offset >> ump->um_mountp->mnt_fs_bshift);
379 dq->dq2_blkoff = (offset & ump->umq2_bmask); 379 dq->dq2_blkoff = (offset & ump->umq2_bmask);
380 if (dq->dq2_lblkno == 0) { 380 if (dq->dq2_lblkno == 0) {
381 bp = hbp; 381 bp = hbp;
382 q2e = (void *)((char *)bp->b_data + dq->dq2_blkoff); 382 q2e = (void *)((char *)bp->b_data + dq->dq2_blkoff);
383 } else { 383 } else {
384 error = getq2e(ump, type, dq->dq2_lblkno, 384 error = getq2e(ump, type, dq->dq2_lblkno,
385 dq->dq2_blkoff, &bp, &q2e, B_MODIFY); 385 dq->dq2_blkoff, &bp, &q2e, B_MODIFY);
386 if (error) { 386 if (error) {
387 brelse(hbp, 0); 387 brelse(hbp, 0);
388 return error; 388 return error;
389 } 389 }
390 } 390 }
391 hash_mask = ((1 << q2h->q2h_hash_shift) - 1); 391 hash_mask = ((1 << q2h->q2h_hash_shift) - 1);
392 /* remove from free list */ 392 /* remove from free list */
393 q2h->q2h_free = q2e->q2e_next; 393 q2h->q2h_free = q2e->q2e_next;
394 394
395 memcpy(q2e, &q2h->q2h_defentry, sizeof(*q2e)); 395 memcpy(q2e, &q2h->q2h_defentry, sizeof(*q2e));
396 q2e->q2e_uid = ufs_rw32(uid, needswap); 396 q2e->q2e_uid = ufs_rw32(uid, needswap);
397 /* insert in hash list */  397 /* insert in hash list */
398 q2e->q2e_next = q2h->q2h_entries[uid & hash_mask]; 398 q2e->q2e_next = q2h->q2h_entries[uid & hash_mask];
399 q2h->q2h_entries[uid & hash_mask] = ufs_rw64(offset, needswap); 399 q2h->q2h_entries[uid & hash_mask] = ufs_rw64(offset, needswap);
400 if (hbp != bp) { 400 if (hbp != bp) {
401 bwrite(hbp); 401 bwrite(hbp);
402 } 402 }
403 *q2ep = q2e; 403 *q2ep = q2e;
404 *bpp = bp; 404 *bpp = bp;
405 return 0; 405 return 0;
406} 406}
407 407
408static int 408static int
409getinoquota2(struct inode *ip, bool alloc, bool modify, struct buf **bpp, 409getinoquota2(struct inode *ip, bool alloc, bool modify, struct buf **bpp,
410 struct quota2_entry **q2ep) 410 struct quota2_entry **q2ep)
411{ 411{
412 int error; 412 int error;
413 int i; 413 int i;
414 struct dquot *dq; 414 struct dquot *dq;
415 struct ufsmount *ump = ip->i_ump; 415 struct ufsmount *ump = ip->i_ump;
416 u_int32_t ino_ids[MAXQUOTAS]; 416 u_int32_t ino_ids[MAXQUOTAS];
417 417
418 error = getinoquota(ip); 418 error = getinoquota(ip);
419 if (error) 419 if (error)
420 return error; 420 return error;
421 421
422 if (alloc) { 422 if (alloc) {
423 UFS_WAPBL_JLOCK_ASSERT(ump->um_mountp); 423 UFS_WAPBL_JLOCK_ASSERT(ump->um_mountp);
424 } 424 }
425 ino_ids[USRQUOTA] = ip->i_uid; 425 ino_ids[USRQUOTA] = ip->i_uid;
426 ino_ids[GRPQUOTA] = ip->i_gid; 426 ino_ids[GRPQUOTA] = ip->i_gid;
427 /* first get the interlock for all dquot */ 427 /* first get the interlock for all dquot */
428 for (i = 0; i < MAXQUOTAS; i++) { 428 for (i = 0; i < MAXQUOTAS; i++) {
429 dq = ip->i_dquot[i]; 429 dq = ip->i_dquot[i];
430 if (dq == NODQUOT) 430 if (dq == NODQUOT)
431 continue; 431 continue;
432 mutex_enter(&dq->dq_interlock); 432 mutex_enter(&dq->dq_interlock);
433 } 433 }
434 /* now get the corresponding quota entry */ 434 /* now get the corresponding quota entry */
435 for (i = 0; i < MAXQUOTAS; i++) { 435 for (i = 0; i < MAXQUOTAS; i++) {
436 bpp[i] = NULL; 436 bpp[i] = NULL;
437 q2ep[i] = NULL; 437 q2ep[i] = NULL;
438 dq = ip->i_dquot[i]; 438 dq = ip->i_dquot[i];
439 if (dq == NODQUOT) 439 if (dq == NODQUOT)
440 continue; 440 continue;
441 if (__predict_false(ump->um_quotas[i] == NULL)) { 441 if (__predict_false(ump->um_quotas[i] == NULL)) {
442 /* 442 /*
443 * quotas have been turned off. This can happen 443 * quotas have been turned off. This can happen
444 * at umount time. 444 * at umount time.
445 */ 445 */
446 mutex_exit(&dq->dq_interlock); 446 mutex_exit(&dq->dq_interlock);
447 dqrele(NULLVP, dq); 447 dqrele(NULLVP, dq);
448 ip->i_dquot[i] = NULL; 448 ip->i_dquot[i] = NULL;
449 continue; 449 continue;
450 } 450 }
451 451
452 if ((dq->dq2_lblkno | dq->dq2_blkoff) == 0) { 452 if ((dq->dq2_lblkno | dq->dq2_blkoff) == 0) {
453 if (!alloc) { 453 if (!alloc) {
454 continue; 454 continue;
455 } 455 }
456 /* need to alloc a new on-disk quot */ 456 /* need to alloc a new on-disk quot */
457 mutex_enter(&dqlock); 457 mutex_enter(&dqlock);
458 error = quota2_q2ealloc(ump, i, ino_ids[i], dq, 458 error = quota2_q2ealloc(ump, i, ino_ids[i], dq,
459 &bpp[i], &q2ep[i]); 459 &bpp[i], &q2ep[i]);
460 mutex_exit(&dqlock); 460 mutex_exit(&dqlock);
461 if (error) 461 if (error)
462 return error; 462 return error;
463 } else { 463 } else {
464 error = getq2e(ump, i, dq->dq2_lblkno, 464 error = getq2e(ump, i, dq->dq2_lblkno,
465 dq->dq2_blkoff, &bpp[i], &q2ep[i], 465 dq->dq2_blkoff, &bpp[i], &q2ep[i],
466 modify ? B_MODIFY : 0); 466 modify ? B_MODIFY : 0);
467 if (error) 467 if (error)
468 return error; 468 return error;
469 } 469 }
470 } 470 }
471 return 0; 471 return 0;
472} 472}
473 473
474static int 474static int
475quota2_check(struct inode *ip, int vtype, int64_t change, kauth_cred_t cred, 475quota2_check(struct inode *ip, int vtype, int64_t change, kauth_cred_t cred,
476 int flags) 476 int flags)
477{ 477{
478 int error; 478 int error;
479 struct buf *bp[MAXQUOTAS]; 479 struct buf *bp[MAXQUOTAS];
480 struct quota2_entry *q2e[MAXQUOTAS]; 480 struct quota2_entry *q2e[MAXQUOTAS];
481 struct quota2_val *q2vp; 481 struct quota2_val *q2vp;
482 struct dquot *dq; 482 struct dquot *dq;
483 uint64_t ncurblks; 483 uint64_t ncurblks;
484 struct ufsmount *ump = ip->i_ump; 484 struct ufsmount *ump = ip->i_ump;
485 struct mount *mp = ump->um_mountp; 485 struct mount *mp = ump->um_mountp;
486 const int needswap = UFS_MPNEEDSWAP(ump); 486 const int needswap = UFS_MPNEEDSWAP(ump);
487 int i; 487 int i;
488 488
489 if ((error = getinoquota2(ip, change > 0, change != 0, bp, q2e)) != 0) 489 if ((error = getinoquota2(ip, change > 0, change != 0, bp, q2e)) != 0)
490 return error; 490 return error;
491 if (change == 0) { 491 if (change == 0) {
492 for (i = 0; i < MAXQUOTAS; i++) { 492 for (i = 0; i < MAXQUOTAS; i++) {
493 dq = ip->i_dquot[i]; 493 dq = ip->i_dquot[i];
494 if (dq == NODQUOT) 494 if (dq == NODQUOT)
495 continue; 495 continue;
496 if (bp[i]) 496 if (bp[i])
497 brelse(bp[i], 0); 497 brelse(bp[i], 0);
498 mutex_exit(&dq->dq_interlock); 498 mutex_exit(&dq->dq_interlock);
499 } 499 }
500 return 0; 500 return 0;
501 } 501 }
502 if (change < 0) { 502 if (change < 0) {
503 for (i = 0; i < MAXQUOTAS; i++) { 503 for (i = 0; i < MAXQUOTAS; i++) {
504 dq = ip->i_dquot[i]; 504 dq = ip->i_dquot[i];
505 if (dq == NODQUOT) 505 if (dq == NODQUOT)
506 continue; 506 continue;
507 if (q2e[i] == NULL) { 507 if (q2e[i] == NULL) {
508 mutex_exit(&dq->dq_interlock); 508 mutex_exit(&dq->dq_interlock);
509 continue; 509 continue;
510 } 510 }
511 q2vp = &q2e[i]->q2e_val[vtype]; 511 q2vp = &q2e[i]->q2e_val[vtype];
512 ncurblks = ufs_rw64(q2vp->q2v_cur, needswap); 512 ncurblks = ufs_rw64(q2vp->q2v_cur, needswap);
513 if (ncurblks < -change) 513 if (ncurblks < -change)
514 ncurblks = 0; 514 ncurblks = 0;
515 else 515 else
516 ncurblks += change; 516 ncurblks += change;
517 q2vp->q2v_cur = ufs_rw64(ncurblks, needswap); 517 q2vp->q2v_cur = ufs_rw64(ncurblks, needswap);
518 quota2_bwrite(mp, bp[i]); 518 quota2_bwrite(mp, bp[i]);
519 mutex_exit(&dq->dq_interlock); 519 mutex_exit(&dq->dq_interlock);
520 } 520 }
521 return 0; 521 return 0;
522 } 522 }
523 /* see if the allocation is allowed */ 523 /* see if the allocation is allowed */
524 for (i = 0; i < MAXQUOTAS; i++) { 524 for (i = 0; i < MAXQUOTAS; i++) {
525 struct quota2_val q2v; 525 struct quota2_val q2v;
526 int ql_stat; 526 int ql_stat;
527 dq = ip->i_dquot[i]; 527 dq = ip->i_dquot[i];
528 if (dq == NODQUOT) 528 if (dq == NODQUOT)
529 continue; 529 continue;
530 KASSERT(q2e[i] != NULL); 530 KASSERT(q2e[i] != NULL);
531 quota2_ufs_rwq2v(&q2e[i]->q2e_val[vtype], &q2v, needswap); 531 quota2_ufs_rwq2v(&q2e[i]->q2e_val[vtype], &q2v, needswap);
532 ql_stat = quota2_check_limit(&q2v, change, time_second); 532 ql_stat = quota2_check_limit(&q2v, change, time_second);
533 533
534 if ((flags & FORCE) == 0 && 534 if ((flags & FORCE) == 0 &&
535 kauth_authorize_system(cred, KAUTH_SYSTEM_FS_QUOTA, 535 kauth_authorize_system(cred, KAUTH_SYSTEM_FS_QUOTA,
536 KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT, 536 KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT,
537 KAUTH_ARG(i), KAUTH_ARG(vtype), NULL) != 0) { 537 KAUTH_ARG(i), KAUTH_ARG(vtype), NULL) != 0) {
538 /* enforce this limit */ 538 /* enforce this limit */
539 switch(QL_STATUS(ql_stat)) { 539 switch(QL_STATUS(ql_stat)) {
540 case QL_S_DENY_HARD: 540 case QL_S_DENY_HARD:
541 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) { 541 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) {
542 uprintf("\n%s: write failed, %s %s " 542 uprintf("\n%s: write failed, %s %s "
543 "limit reached\n", 543 "limit reached\n",
544 mp->mnt_stat.f_mntonname, 544 mp->mnt_stat.f_mntonname,
545 quotatypes[i], limnames[vtype]); 545 quotatypes[i], limnames[vtype]);
546 dq->dq_flags |= DQ_WARN(vtype); 546 dq->dq_flags |= DQ_WARN(vtype);
547 } 547 }
548 error = EDQUOT; 548 error = EDQUOT;
549 break; 549 break;
550 case QL_S_DENY_GRACE: 550 case QL_S_DENY_GRACE:
551 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) { 551 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) {
552 uprintf("\n%s: write failed, %s %s " 552 uprintf("\n%s: write failed, %s %s "
553 "limit reached\n", 553 "limit reached\n",
554 mp->mnt_stat.f_mntonname, 554 mp->mnt_stat.f_mntonname,
555 quotatypes[i], limnames[vtype]); 555 quotatypes[i], limnames[vtype]);
556 dq->dq_flags |= DQ_WARN(vtype); 556 dq->dq_flags |= DQ_WARN(vtype);
557 } 557 }
558 error = EDQUOT; 558 error = EDQUOT;
559 break; 559 break;
560 case QL_S_ALLOW_SOFT: 560 case QL_S_ALLOW_SOFT:
561 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) { 561 if ((dq->dq_flags & DQ_WARN(vtype)) == 0) {
562 uprintf("\n%s: warning, %s %s " 562 uprintf("\n%s: warning, %s %s "
563 "quota exceeded\n", 563 "quota exceeded\n",
564 mp->mnt_stat.f_mntonname, 564 mp->mnt_stat.f_mntonname,
565 quotatypes[i], limnames[vtype]); 565 quotatypes[i], limnames[vtype]);
566 dq->dq_flags |= DQ_WARN(vtype); 566 dq->dq_flags |= DQ_WARN(vtype);
567 } 567 }
568 break; 568 break;
569 } 569 }
570 } 570 }
571 /* 571 /*
572 * always do this; we don't know if the allocation will 572 * always do this; we don't know if the allocation will
573 * succed or not in the end. if we don't do the allocation 573 * succed or not in the end. if we don't do the allocation
574 * q2v_time will be ignored anyway 574 * q2v_time will be ignored anyway
575 */ 575 */
576 if (ql_stat & QL_F_CROSS) { 576 if (ql_stat & QL_F_CROSS) {
577 q2v.q2v_time = time_second + q2v.q2v_grace; 577 q2v.q2v_time = time_second + q2v.q2v_grace;
578 quota2_ufs_rwq2v(&q2v, &q2e[i]->q2e_val[vtype], 578 quota2_ufs_rwq2v(&q2v, &q2e[i]->q2e_val[vtype],
579 needswap); 579 needswap);
580 } 580 }
581 } 581 }
582 582
583 /* now do the allocation if allowed */ 583 /* now do the allocation if allowed */
584 for (i = 0; i < MAXQUOTAS; i++) { 584 for (i = 0; i < MAXQUOTAS; i++) {
585 dq = ip->i_dquot[i]; 585 dq = ip->i_dquot[i];
586 if (dq == NODQUOT) 586 if (dq == NODQUOT)
587 continue; 587 continue;
588 KASSERT(q2e[i] != NULL); 588 KASSERT(q2e[i] != NULL);
589 if (error == 0) { 589 if (error == 0) {
590 q2vp = &q2e[i]->q2e_val[vtype]; 590 q2vp = &q2e[i]->q2e_val[vtype];
591 ncurblks = ufs_rw64(q2vp->q2v_cur, needswap); 591 ncurblks = ufs_rw64(q2vp->q2v_cur, needswap);
592 q2vp->q2v_cur = ufs_rw64(ncurblks + change, needswap); 592 q2vp->q2v_cur = ufs_rw64(ncurblks + change, needswap);
593 quota2_bwrite(mp, bp[i]); 593 quota2_bwrite(mp, bp[i]);
594 } else 594 } else
595 brelse(bp[i], 0); 595 brelse(bp[i], 0);
596 mutex_exit(&dq->dq_interlock); 596 mutex_exit(&dq->dq_interlock);
597 } 597 }
598 return error; 598 return error;
599} 599}
600 600
601int 601int
602chkdq2(struct inode *ip, int64_t change, kauth_cred_t cred, int flags) 602chkdq2(struct inode *ip, int64_t change, kauth_cred_t cred, int flags)
603{ 603{
604 return quota2_check(ip, QL_BLOCK, change, cred, flags); 604 return quota2_check(ip, QL_BLOCK, change, cred, flags);
605} 605}
606 606
607int 607int
608chkiq2(struct inode *ip, int32_t change, kauth_cred_t cred, int flags) 608chkiq2(struct inode *ip, int32_t change, kauth_cred_t cred, int flags)
609{ 609{
610 return quota2_check(ip, QL_FILE, change, cred, flags); 610 return quota2_check(ip, QL_FILE, change, cred, flags);
611} 611}
612 612
613int 613int
614quota2_handle_cmd_put(struct ufsmount *ump, const struct quotakey *key, 614quota2_handle_cmd_put(struct ufsmount *ump, const struct quotakey *key,
615 const struct quotaval *val) 615 const struct quotaval *val)
616{ 616{
617 int error; 617 int error;
618 struct dquot *dq; 618 struct dquot *dq;
619 struct quota2_header *q2h; 619 struct quota2_header *q2h;
620 struct quota2_entry q2e, *q2ep; 620 struct quota2_entry q2e, *q2ep;
621 struct buf *bp; 621 struct buf *bp;
622 const int needswap = UFS_MPNEEDSWAP(ump); 622 const int needswap = UFS_MPNEEDSWAP(ump);
623 623
624 /* make sure we can index by the fs-independent idtype */ 624 /* make sure we can index by the fs-independent idtype */
625 CTASSERT(QUOTA_IDTYPE_USER == USRQUOTA); 625 CTASSERT(QUOTA_IDTYPE_USER == USRQUOTA);
626 CTASSERT(QUOTA_IDTYPE_GROUP == GRPQUOTA); 626 CTASSERT(QUOTA_IDTYPE_GROUP == GRPQUOTA);
627 627
628 if (ump->um_quotas[key->qk_idtype] == NULLVP) 628 if (ump->um_quotas[key->qk_idtype] == NULLVP)
629 return ENODEV; 629 return ENODEV;
630 error = UFS_WAPBL_BEGIN(ump->um_mountp); 630 error = UFS_WAPBL_BEGIN(ump->um_mountp);
631 if (error) 631 if (error)
632 return error; 632 return error;
633  633
634 if (key->qk_id == QUOTA_DEFAULTID) { 634 if (key->qk_id == QUOTA_DEFAULTID) {
635 mutex_enter(&dqlock); 635 mutex_enter(&dqlock);
636 error = getq2h(ump, key->qk_idtype, &bp, &q2h, B_MODIFY); 636 error = getq2h(ump, key->qk_idtype, &bp, &q2h, B_MODIFY);
637 if (error) { 637 if (error) {
638 mutex_exit(&dqlock); 638 mutex_exit(&dqlock);
639 goto out_wapbl; 639 goto out_wapbl;
640 } 640 }
641 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); 641 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap);
642 quota2_dict_update_q2e_limits(key->qk_objtype, val, &q2e); 642 quota2_dict_update_q2e_limits(key->qk_objtype, val, &q2e);
643 quota2_ufs_rwq2e(&q2e, &q2h->q2h_defentry, needswap); 643 quota2_ufs_rwq2e(&q2e, &q2h->q2h_defentry, needswap);
644 mutex_exit(&dqlock); 644 mutex_exit(&dqlock);
645 quota2_bwrite(ump->um_mountp, bp); 645 quota2_bwrite(ump->um_mountp, bp);
646 goto out_wapbl; 646 goto out_wapbl;
647 } 647 }
648 648
649 error = dqget(NULLVP, key->qk_id, ump, key->qk_idtype, &dq); 649 error = dqget(NULLVP, key->qk_id, ump, key->qk_idtype, &dq);
650 if (error) 650 if (error)
651 goto out_wapbl; 651 goto out_wapbl;
652 652
653 mutex_enter(&dq->dq_interlock); 653 mutex_enter(&dq->dq_interlock);
654 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 654 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) {
655 /* need to alloc a new on-disk quot */ 655 /* need to alloc a new on-disk quot */
656 mutex_enter(&dqlock); 656 mutex_enter(&dqlock);
657 error = quota2_q2ealloc(ump, key->qk_idtype, key->qk_id, dq, 657 error = quota2_q2ealloc(ump, key->qk_idtype, key->qk_id, dq,
658 &bp, &q2ep); 658 &bp, &q2ep);
659 mutex_exit(&dqlock); 659 mutex_exit(&dqlock);
660 } else { 660 } else {
661 error = getq2e(ump, key->qk_idtype, dq->dq2_lblkno, 661 error = getq2e(ump, key->qk_idtype, dq->dq2_lblkno,
662 dq->dq2_blkoff, &bp, &q2ep, B_MODIFY); 662 dq->dq2_blkoff, &bp, &q2ep, B_MODIFY);
663 } 663 }
664 if (error) 664 if (error)
665 goto out_il; 665 goto out_il;
666  666
667 quota2_ufs_rwq2e(q2ep, &q2e, needswap); 667 quota2_ufs_rwq2e(q2ep, &q2e, needswap);
668 quota2_dict_update_q2e_limits(key->qk_objtype, val, &q2e); 668 quota2_dict_update_q2e_limits(key->qk_objtype, val, &q2e);
669 quota2_ufs_rwq2e(&q2e, q2ep, needswap); 669 quota2_ufs_rwq2e(&q2e, q2ep, needswap);
670 quota2_bwrite(ump->um_mountp, bp); 670 quota2_bwrite(ump->um_mountp, bp);
671 671
672out_il: 672out_il:
673 mutex_exit(&dq->dq_interlock); 673 mutex_exit(&dq->dq_interlock);
674 dqrele(NULLVP, dq); 674 dqrele(NULLVP, dq);
675out_wapbl: 675out_wapbl:
676 UFS_WAPBL_END(ump->um_mountp); 676 UFS_WAPBL_END(ump->um_mountp);
677 return error; 677 return error;
678} 678}
679 679
680struct dq2clear_callback { 680struct dq2clear_callback {
681 uid_t id; 681 uid_t id;
682 struct dquot *dq; 682 struct dquot *dq;
683 struct quota2_header *q2h; 683 struct quota2_header *q2h;
684}; 684};
685 685
686static int 686static int
687dq2clear_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e, 687dq2clear_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e,
688 uint64_t off, void *v) 688 uint64_t off, void *v)
689{ 689{
690 struct dq2clear_callback *c = v; 690 struct dq2clear_callback *c = v;
691#ifdef FFS_EI 691#ifdef FFS_EI
692 const int needswap = UFS_MPNEEDSWAP(ump); 692 const int needswap = UFS_MPNEEDSWAP(ump);
693#endif 693#endif
694 uint64_t myoff; 694 uint64_t myoff;
695 695
696 if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) { 696 if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) {
697 KASSERT(mutex_owned(&c->dq->dq_interlock)); 697 KASSERT(mutex_owned(&c->dq->dq_interlock));
698 c->dq->dq2_lblkno = 0; 698 c->dq->dq2_lblkno = 0;
699 c->dq->dq2_blkoff = 0; 699 c->dq->dq2_blkoff = 0;
700 myoff = *offp; 700 myoff = *offp;
701 /* remove from hash list */ 701 /* remove from hash list */
702 *offp = q2e->q2e_next; 702 *offp = q2e->q2e_next;
703 /* add to free list */ 703 /* add to free list */
704 q2e->q2e_next = c->q2h->q2h_free; 704 q2e->q2e_next = c->q2h->q2h_free;
705 c->q2h->q2h_free = myoff; 705 c->q2h->q2h_free = myoff;
706 return Q2WL_ABORT; 706 return Q2WL_ABORT;
707 } 707 }
708 return 0; 708 return 0;
709} 709}
710int 710int
711quota2_handle_cmd_clear(struct ufsmount *ump, int type, int id, 711quota2_handle_cmd_clear(struct ufsmount *ump, int idtype, int id,
712 int defaultq, prop_dictionary_t data) 712 int defaultq)
713{ 713{
714 int error, i; 714 int error, i;
715 struct dquot *dq; 715 struct dquot *dq;
716 struct quota2_header *q2h; 716 struct quota2_header *q2h;
717 struct quota2_entry q2e, *q2ep; 717 struct quota2_entry q2e, *q2ep;
718 struct buf *hbp, *bp; 718 struct buf *hbp, *bp;
719 u_long hash_mask; 719 u_long hash_mask;
720 struct dq2clear_callback c; 720 struct dq2clear_callback c;
721 721
722 if (ump->um_quotas[type] == NULLVP) 722 if (ump->um_quotas[idtype] == NULLVP)
723 return ENODEV; 723 return ENODEV;
724 if (defaultq) 724 if (defaultq)
725 return EOPNOTSUPP; 725 return EOPNOTSUPP;
726 726
727 /* get the default entry before locking the entry's buffer */ 727 /* get the default entry before locking the entry's buffer */
728 mutex_enter(&dqlock); 728 mutex_enter(&dqlock);
729 error = getq2h(ump, type, &hbp, &q2h, 0); 729 error = getq2h(ump, idtype, &hbp, &q2h, 0);
730 if (error) { 730 if (error) {
731 mutex_exit(&dqlock); 731 mutex_exit(&dqlock);
732 return error; 732 return error;
733 } 733 }
734 /* we'll copy to another disk entry, so no need to swap */ 734 /* we'll copy to another disk entry, so no need to swap */
735 memcpy(&q2e, &q2h->q2h_defentry, sizeof(q2e)); 735 memcpy(&q2e, &q2h->q2h_defentry, sizeof(q2e));
736 mutex_exit(&dqlock); 736 mutex_exit(&dqlock);
737 brelse(hbp, 0); 737 brelse(hbp, 0);
738 738
739 error = dqget(NULLVP, id, ump, type, &dq); 739 error = dqget(NULLVP, id, ump, idtype, &dq);
740 if (error) 740 if (error)
741 return error; 741 return error;
742 742
743 mutex_enter(&dq->dq_interlock); 743 mutex_enter(&dq->dq_interlock);
744 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 744 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) {
745 /* already clear, nothing to do */ 745 /* already clear, nothing to do */
746 error = ENOENT; 746 error = ENOENT;
747 goto out_il; 747 goto out_il;
748 } 748 }
749 error = UFS_WAPBL_BEGIN(ump->um_mountp); 749 error = UFS_WAPBL_BEGIN(ump->um_mountp);
750 if (error) 750 if (error)
751 goto out_dq; 751 goto out_dq;
752  752
753 error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff, 753 error = getq2e(ump, idtype, dq->dq2_lblkno, dq->dq2_blkoff,
754 &bp, &q2ep, B_MODIFY); 754 &bp, &q2ep, B_MODIFY);
755 if (error) 755 if (error)
756 goto out_wapbl; 756 goto out_wapbl;
757 757
758 if (q2ep->q2e_val[QL_BLOCK].q2v_cur != 0 || 758 if (q2ep->q2e_val[QL_BLOCK].q2v_cur != 0 ||
759 q2ep->q2e_val[QL_FILE].q2v_cur != 0) { 759 q2ep->q2e_val[QL_FILE].q2v_cur != 0) {
760 /* can't free this entry; revert to default */ 760 /* can't free this entry; revert to default */
761 for (i = 0; i < N_QL; i++) { 761 for (i = 0; i < N_QL; i++) {
762 q2ep->q2e_val[i].q2v_softlimit = 762 q2ep->q2e_val[i].q2v_softlimit =
763 q2e.q2e_val[i].q2v_softlimit; 763 q2e.q2e_val[i].q2v_softlimit;
764 q2ep->q2e_val[i].q2v_hardlimit = 764 q2ep->q2e_val[i].q2v_hardlimit =
765 q2e.q2e_val[i].q2v_hardlimit; 765 q2e.q2e_val[i].q2v_hardlimit;
766 q2ep->q2e_val[i].q2v_grace = 766 q2ep->q2e_val[i].q2v_grace =
767 q2e.q2e_val[i].q2v_grace; 767 q2e.q2e_val[i].q2v_grace;
768 q2ep->q2e_val[i].q2v_time = 0; 768 q2ep->q2e_val[i].q2v_time = 0;
769 } 769 }
770 quota2_bwrite(ump->um_mountp, bp); 770 quota2_bwrite(ump->um_mountp, bp);
771 goto out_wapbl; 771 goto out_wapbl;
772 } 772 }
773 /* we can free it. release bp so we can walk the list */ 773 /* we can free it. release bp so we can walk the list */
774 brelse(bp, 0); 774 brelse(bp, 0);
775 mutex_enter(&dqlock); 775 mutex_enter(&dqlock);
776 error = getq2h(ump, type, &hbp, &q2h, 0); 776 error = getq2h(ump, idtype, &hbp, &q2h, 0);
777 if (error) 777 if (error)
778 goto out_dqlock; 778 goto out_dqlock;
779 779
780 hash_mask = ((1 << q2h->q2h_hash_shift) - 1); 780 hash_mask = ((1 << q2h->q2h_hash_shift) - 1);
781 c.dq = dq; 781 c.dq = dq;
782 c.id = id; 782 c.id = id;
783 c.q2h = q2h; 783 c.q2h = q2h;
784 error = quota2_walk_list(ump, hbp, type, 784 error = quota2_walk_list(ump, hbp, idtype,
785 &q2h->q2h_entries[id & hash_mask], B_MODIFY, &c, 785 &q2h->q2h_entries[id & hash_mask], B_MODIFY, &c,
786 dq2clear_callback); 786 dq2clear_callback);
787 787
788 bwrite(hbp); 788 bwrite(hbp);
789 789
790out_dqlock: 790out_dqlock:
791 mutex_exit(&dqlock); 791 mutex_exit(&dqlock);
792out_wapbl: 792out_wapbl:
793 UFS_WAPBL_END(ump->um_mountp); 793 UFS_WAPBL_END(ump->um_mountp);
794out_il: 794out_il:
795 mutex_exit(&dq->dq_interlock); 795 mutex_exit(&dq->dq_interlock);
796out_dq: 796out_dq:
797 dqrele(NULLVP, dq); 797 dqrele(NULLVP, dq);
798 return error; 798 return error;
799} 799}
800 800
801static int 801static int
802quota2_array_add_q2e(struct ufsmount *ump, int type, 802quota2_array_add_q2e(struct ufsmount *ump, int type,
803 int id, prop_array_t replies) 803 int id, prop_array_t replies)
804{ 804{
805 struct dquot *dq; 805 struct dquot *dq;
806 int error; 806 int error;
807 struct quota2_entry *q2ep, q2e; 807 struct quota2_entry *q2ep, q2e;
808 struct buf *bp; 808 struct buf *bp;
809 const int needswap = UFS_MPNEEDSWAP(ump); 809 const int needswap = UFS_MPNEEDSWAP(ump);
810 prop_dictionary_t dict; 810 prop_dictionary_t dict;
811 811
812 error = dqget(NULLVP, id, ump, type, &dq); 812 error = dqget(NULLVP, id, ump, type, &dq);
813 if (error) 813 if (error)
814 return error; 814 return error;
815 815
816 mutex_enter(&dq->dq_interlock); 816 mutex_enter(&dq->dq_interlock);
817 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 817 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) {
818 mutex_exit(&dq->dq_interlock); 818 mutex_exit(&dq->dq_interlock);
819 dqrele(NULLVP, dq); 819 dqrele(NULLVP, dq);
820 return ENOENT; 820 return ENOENT;
821 } 821 }
822 error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff, 822 error = getq2e(ump, type, dq->dq2_lblkno, dq->dq2_blkoff,
823 &bp, &q2ep, 0); 823 &bp, &q2ep, 0);
824 if (error) { 824 if (error) {
825 mutex_exit(&dq->dq_interlock); 825 mutex_exit(&dq->dq_interlock);
826 dqrele(NULLVP, dq); 826 dqrele(NULLVP, dq);
827 return error; 827 return error;
828 } 828 }
829 quota2_ufs_rwq2e(q2ep, &q2e, needswap); 829 quota2_ufs_rwq2e(q2ep, &q2e, needswap);
830 brelse(bp, 0); 830 brelse(bp, 0);
831 mutex_exit(&dq->dq_interlock); 831 mutex_exit(&dq->dq_interlock);
832 dqrele(NULLVP, dq); 832 dqrele(NULLVP, dq);
833 833
834 dict = q2etoprop(&q2e, 0); 834 dict = q2etoprop(&q2e, 0);
835 if (dict == NULL) 835 if (dict == NULL)
836 return ENOMEM; 836 return ENOMEM;
837 if (!prop_array_add_and_rel(replies, dict)) 837 if (!prop_array_add_and_rel(replies, dict))
838 return ENOMEM; 838 return ENOMEM;
839 return 0; 839 return 0;
840} 840}
841 841
842static int 842static int
843quota2_fetch_q2e(struct ufsmount *ump, const struct quotakey *qk, 843quota2_fetch_q2e(struct ufsmount *ump, const struct quotakey *qk,
844 struct quotaval *ret) 844 struct quotaval *ret)
845{ 845{
846 struct dquot *dq; 846 struct dquot *dq;
847 int error; 847 int error;
848 struct quota2_entry *q2ep, q2e; 848 struct quota2_entry *q2ep, q2e;
849 struct buf *bp; 849 struct buf *bp;
850 const int needswap = UFS_MPNEEDSWAP(ump); 850 const int needswap = UFS_MPNEEDSWAP(ump);
851 id_t id2; 851 id_t id2;
852 852
853 error = dqget(NULLVP, qk->qk_id, ump, qk->qk_idtype, &dq); 853 error = dqget(NULLVP, qk->qk_id, ump, qk->qk_idtype, &dq);
854 if (error) 854 if (error)
855 return error; 855 return error;
856 856
857 mutex_enter(&dq->dq_interlock); 857 mutex_enter(&dq->dq_interlock);
858 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) { 858 if (dq->dq2_lblkno == 0 && dq->dq2_blkoff == 0) {
859 mutex_exit(&dq->dq_interlock); 859 mutex_exit(&dq->dq_interlock);
860 dqrele(NULLVP, dq); 860 dqrele(NULLVP, dq);
861 return ENOENT; 861 return ENOENT;
862 } 862 }
863 error = getq2e(ump, qk->qk_idtype, dq->dq2_lblkno, dq->dq2_blkoff, 863 error = getq2e(ump, qk->qk_idtype, dq->dq2_lblkno, dq->dq2_blkoff,
864 &bp, &q2ep, 0); 864 &bp, &q2ep, 0);
865 if (error) { 865 if (error) {
866 mutex_exit(&dq->dq_interlock); 866 mutex_exit(&dq->dq_interlock);
867 dqrele(NULLVP, dq); 867 dqrele(NULLVP, dq);
868 return error; 868 return error;
869 } 869 }
870 quota2_ufs_rwq2e(q2ep, &q2e, needswap); 870 quota2_ufs_rwq2e(q2ep, &q2e, needswap);
871 brelse(bp, 0); 871 brelse(bp, 0);
872 mutex_exit(&dq->dq_interlock); 872 mutex_exit(&dq->dq_interlock);
873 dqrele(NULLVP, dq); 873 dqrele(NULLVP, dq);
874 874
875 q2e_to_quotaval(&q2e, 0, &id2, qk->qk_objtype, ret); 875 q2e_to_quotaval(&q2e, 0, &id2, qk->qk_objtype, ret);
876 KASSERT(id2 == qk->qk_id); 876 KASSERT(id2 == qk->qk_id);
877 return 0; 877 return 0;
878} 878}
879 879
880int 880int
881quota2_handle_cmd_get(struct ufsmount *ump, const struct quotakey *qk, 881quota2_handle_cmd_get(struct ufsmount *ump, const struct quotakey *qk,
882 struct quotaval *ret) 882 struct quotaval *ret)
883{ 883{
884 int error; 884 int error;
885 struct quota2_header *q2h; 885 struct quota2_header *q2h;
886 struct quota2_entry q2e; 886 struct quota2_entry q2e;
887 struct buf *bp; 887 struct buf *bp;
888 const int needswap = UFS_MPNEEDSWAP(ump); 888 const int needswap = UFS_MPNEEDSWAP(ump);
889 id_t id2; 889 id_t id2;
890 890
891 /* 891 /*
892 * Make sure the FS-independent codes match the internal ones, 892 * Make sure the FS-independent codes match the internal ones,
893 * so we can use the passed-in objtype without having to 893 * so we can use the passed-in objtype without having to
894 * convert it explicitly to QL_BLOCK/QL_FILE. 894 * convert it explicitly to QL_BLOCK/QL_FILE.
895 */ 895 */
896 CTASSERT(QL_BLOCK == QUOTA_OBJTYPE_BLOCKS); 896 CTASSERT(QL_BLOCK == QUOTA_OBJTYPE_BLOCKS);
897 CTASSERT(QL_FILE == QUOTA_OBJTYPE_FILES); 897 CTASSERT(QL_FILE == QUOTA_OBJTYPE_FILES);
898 CTASSERT(N_QL == 2); 898 CTASSERT(N_QL == 2);
899 899
900 if (qk->qk_objtype < 0 || qk->qk_objtype >= N_QL) { 900 if (qk->qk_objtype < 0 || qk->qk_objtype >= N_QL) {
901 return EINVAL; 901 return EINVAL;
902 } 902 }
903 903
904 if (ump->um_quotas[qk->qk_idtype] == NULLVP) 904 if (ump->um_quotas[qk->qk_idtype] == NULLVP)
905 return ENODEV; 905 return ENODEV;
906 if (qk->qk_id == QUOTA_DEFAULTID) { 906 if (qk->qk_id == QUOTA_DEFAULTID) {
907 mutex_enter(&dqlock); 907 mutex_enter(&dqlock);
908 error = getq2h(ump, qk->qk_idtype, &bp, &q2h, 0); 908 error = getq2h(ump, qk->qk_idtype, &bp, &q2h, 0);
909 if (error) { 909 if (error) {
910 mutex_exit(&dqlock); 910 mutex_exit(&dqlock);
911 return error; 911 return error;
912 } 912 }
913 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); 913 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap);
914 mutex_exit(&dqlock); 914 mutex_exit(&dqlock);
915 brelse(bp, 0); 915 brelse(bp, 0);
916 q2e_to_quotaval(&q2e, qk->qk_id == QUOTA_DEFAULTID, &id2, 916 q2e_to_quotaval(&q2e, qk->qk_id == QUOTA_DEFAULTID, &id2,
917 qk->qk_objtype, ret); 917 qk->qk_objtype, ret);
918 (void)id2; 918 (void)id2;
919 } else 919 } else
920 error = quota2_fetch_q2e(ump, qk, ret); 920 error = quota2_fetch_q2e(ump, qk, ret);
921  921
922 return error; 922 return error;
923} 923}
924 924
925struct getuids { 925struct getuids {
926 long nuids; /* number of uids in array */ 926 long nuids; /* number of uids in array */
927 long size; /* size of array */ 927 long size; /* size of array */
928 uid_t *uids; /* array of uids, dynamically allocated */ 928 uid_t *uids; /* array of uids, dynamically allocated */
929}; 929};
930 930
931static int 931static int
932quota2_getuids_callback(struct ufsmount *ump, uint64_t *offp, 932quota2_getuids_callback(struct ufsmount *ump, uint64_t *offp,
933 struct quota2_entry *q2ep, uint64_t off, void *v) 933 struct quota2_entry *q2ep, uint64_t off, void *v)
934{ 934{
935 struct getuids *gu = v; 935 struct getuids *gu = v;
936 uid_t *newuids; 936 uid_t *newuids;
937#ifdef FFS_EI 937#ifdef FFS_EI
938 const int needswap = UFS_MPNEEDSWAP(ump); 938 const int needswap = UFS_MPNEEDSWAP(ump);
939#endif 939#endif
940 940
941 if (gu->nuids == gu->size) { 941 if (gu->nuids == gu->size) {
942 newuids = realloc(gu->uids, gu->size + PAGE_SIZE, M_TEMP, 942 newuids = realloc(gu->uids, gu->size + PAGE_SIZE, M_TEMP,
943 M_WAITOK); 943 M_WAITOK);
944 if (newuids == NULL) { 944 if (newuids == NULL) {
945 free(gu->uids, M_TEMP); 945 free(gu->uids, M_TEMP);
946 return ENOMEM; 946 return ENOMEM;
947 } 947 }
948 gu->uids = newuids; 948 gu->uids = newuids;
949 gu->size += (PAGE_SIZE / sizeof(uid_t)); 949 gu->size += (PAGE_SIZE / sizeof(uid_t));
950 } 950 }
951 gu->uids[gu->nuids] = ufs_rw32(q2ep->q2e_uid, needswap); 951 gu->uids[gu->nuids] = ufs_rw32(q2ep->q2e_uid, needswap);
952 gu->nuids++; 952 gu->nuids++;
953 return 0; 953 return 0;
954} 954}
955 955
956int 956int
957quota2_handle_cmd_getall(struct ufsmount *ump, int type, prop_array_t replies) 957quota2_handle_cmd_getall(struct ufsmount *ump, int type, prop_array_t replies)
958{ 958{
959 int error; 959 int error;
960 struct quota2_header *q2h; 960 struct quota2_header *q2h;
961 struct quota2_entry q2e; 961 struct quota2_entry q2e;
962 struct buf *hbp; 962 struct buf *hbp;
963 prop_dictionary_t dict; 963 prop_dictionary_t dict;
964 uint64_t offset; 964 uint64_t offset;
965 int i, j; 965 int i, j;
966 int quota2_hash_size; 966 int quota2_hash_size;
967 const int needswap = UFS_MPNEEDSWAP(ump); 967 const int needswap = UFS_MPNEEDSWAP(ump);
968 struct getuids gu; 968 struct getuids gu;
969 969
970 if (ump->um_quotas[type] == NULLVP) 970 if (ump->um_quotas[type] == NULLVP)
971 return ENODEV; 971 return ENODEV;
972 mutex_enter(&dqlock); 972 mutex_enter(&dqlock);
973 error = getq2h(ump, type, &hbp, &q2h, 0); 973 error = getq2h(ump, type, &hbp, &q2h, 0);
974 if (error) { 974 if (error) {
975 mutex_exit(&dqlock); 975 mutex_exit(&dqlock);
976 return error; 976 return error;
977 } 977 }
978 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap); 978 quota2_ufs_rwq2e(&q2h->q2h_defentry, &q2e, needswap);
979 dict = q2etoprop(&q2e, 1); 979 dict = q2etoprop(&q2e, 1);
980 if (!prop_array_add_and_rel(replies, dict)) { 980 if (!prop_array_add_and_rel(replies, dict)) {
981 error = ENOMEM; 981 error = ENOMEM;
982 goto error_bp; 982 goto error_bp;
983 } 983 }
984 /* 984 /*
985 * we can't directly get entries as we can't walk the list 985 * we can't directly get entries as we can't walk the list
986 * with qdlock and grab dq_interlock to read the entries 986 * with qdlock and grab dq_interlock to read the entries
987 * at the same time. So just walk the lists to build a list of uid, 987 * at the same time. So just walk the lists to build a list of uid,
988 * and then read entries for these uids 988 * and then read entries for these uids
989 */ 989 */
990 memset(&gu, 0, sizeof(gu)); 990 memset(&gu, 0, sizeof(gu));
991 quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap); 991 quota2_hash_size = ufs_rw16(q2h->q2h_hash_size, needswap);
992 for (i = 0; i < quota2_hash_size ; i++) { 992 for (i = 0; i < quota2_hash_size ; i++) {
993 offset = q2h->q2h_entries[i]; 993 offset = q2h->q2h_entries[i];
994 error = quota2_walk_list(ump, hbp, type, &offset, 0, &gu, 994 error = quota2_walk_list(ump, hbp, type, &offset, 0, &gu,
995 quota2_getuids_callback); 995 quota2_getuids_callback);
996 if (error) { 996 if (error) {
997 if (gu.uids != NULL) 997 if (gu.uids != NULL)
998 free(gu.uids, M_TEMP); 998 free(gu.uids, M_TEMP);
999 break; 999 break;
1000 } 1000 }
1001 } 1001 }
1002error_bp: 1002error_bp:
1003 mutex_exit(&dqlock); 1003 mutex_exit(&dqlock);
1004 brelse(hbp, 0); 1004 brelse(hbp, 0);
1005 if (error) 1005 if (error)
1006 return error; 1006 return error;
1007 for (j = 0; j < gu.nuids; j++) { 1007 for (j = 0; j < gu.nuids; j++) {
1008 error = quota2_array_add_q2e(ump, type, 1008 error = quota2_array_add_q2e(ump, type,
1009 gu.uids[j], replies); 1009 gu.uids[j], replies);
1010 if (error && error != ENOENT) 1010 if (error && error != ENOENT)
1011 break; 1011 break;
1012 } 1012 }
1013 free(gu.uids, M_TEMP); 1013 free(gu.uids, M_TEMP);
1014 return error; 1014 return error;
1015} 1015}
1016 1016
1017int 1017int
1018q2sync(struct mount *mp) 1018q2sync(struct mount *mp)
1019{ 1019{
1020 return 0; 1020 return 0;
1021} 1021}
1022 1022
1023struct dq2get_callback { 1023struct dq2get_callback {
1024 uid_t id; 1024 uid_t id;
1025 struct dquot *dq; 1025 struct dquot *dq;
1026}; 1026};
1027 1027
1028static int 1028static int
1029dq2get_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e, 1029dq2get_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e,
1030 uint64_t off, void *v) 1030 uint64_t off, void *v)
1031{ 1031{
1032 struct dq2get_callback *c = v; 1032 struct dq2get_callback *c = v;
1033 daddr_t lblkno; 1033 daddr_t lblkno;
1034 int blkoff; 1034 int blkoff;
1035#ifdef FFS_EI 1035#ifdef FFS_EI
1036 const int needswap = UFS_MPNEEDSWAP(ump); 1036 const int needswap = UFS_MPNEEDSWAP(ump);
1037#endif 1037#endif
1038 1038
1039 if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) { 1039 if (ufs_rw32(q2e->q2e_uid, needswap) == c->id) {
1040 KASSERT(mutex_owned(&c->dq->dq_interlock)); 1040 KASSERT(mutex_owned(&c->dq->dq_interlock));
1041 lblkno = (off >> ump->um_mountp->mnt_fs_bshift); 1041 lblkno = (off >> ump->um_mountp->mnt_fs_bshift);
1042 blkoff = (off & ump->umq2_bmask); 1042 blkoff = (off & ump->umq2_bmask);
1043 c->dq->dq2_lblkno = lblkno; 1043 c->dq->dq2_lblkno = lblkno;
1044 c->dq->dq2_blkoff = blkoff; 1044 c->dq->dq2_blkoff = blkoff;
1045 return Q2WL_ABORT; 1045 return Q2WL_ABORT;
1046 } 1046 }
1047 return 0; 1047 return 0;
1048} 1048}
1049 1049
1050int 1050int
1051dq2get(struct vnode *dqvp, u_long id, struct ufsmount *ump, int type, 1051dq2get(struct vnode *dqvp, u_long id, struct ufsmount *ump, int type,
1052 struct dquot *dq) 1052 struct dquot *dq)
1053{ 1053{
1054 struct buf *bp; 1054 struct buf *bp;
1055 struct quota2_header *q2h; 1055 struct quota2_header *q2h;
1056 int error; 1056 int error;
1057 daddr_t offset; 1057 daddr_t offset;
1058 u_long hash_mask; 1058 u_long hash_mask;
1059 struct dq2get_callback c = { 1059 struct dq2get_callback c = {
1060 .id = id, 1060 .id = id,
1061 .dq = dq 1061 .dq = dq
1062 }; 1062 };
1063 1063
1064 KASSERT(mutex_owned(&dq->dq_interlock)); 1064 KASSERT(mutex_owned(&dq->dq_interlock));
1065 mutex_enter(&dqlock); 1065 mutex_enter(&dqlock);
1066 error = getq2h(ump, type, &bp, &q2h, 0); 1066 error = getq2h(ump, type, &bp, &q2h, 0);
1067 if (error) 1067 if (error)
1068 goto out_mutex; 1068 goto out_mutex;
1069 /* look for our entry */ 1069 /* look for our entry */
1070 hash_mask = ((1 << q2h->q2h_hash_shift) - 1); 1070 hash_mask = ((1 << q2h->q2h_hash_shift) - 1);
1071 offset = q2h->q2h_entries[id & hash_mask]; 1071 offset = q2h->q2h_entries[id & hash_mask];
1072 error = quota2_walk_list(ump, bp, type, &offset, 0, (void *)&c, 1072 error = quota2_walk_list(ump, bp, type, &offset, 0, (void *)&c,
1073 dq2get_callback); 1073 dq2get_callback);
1074 brelse(bp, 0); 1074 brelse(bp, 0);
1075out_mutex: 1075out_mutex:
1076 mutex_exit(&dqlock); 1076 mutex_exit(&dqlock);
1077 return error; 1077 return error;
1078} 1078}
1079 1079
1080int 1080int
1081dq2sync(struct vnode *vp, struct dquot *dq) 1081dq2sync(struct vnode *vp, struct dquot *dq)
1082{ 1082{
1083 return 0; 1083 return 0;
1084} 1084}