Sun Jan 29 06:44:33 2012 UTC ()
Move the top level iteration for QUOTACTL_SET from ufs to vfs_quotactl.

Note: this change requires a kernel version bump.


(dholland)
diff -r1.10 -r1.11 src/sys/kern/vfs_quotactl.c
diff -r1.8 -r1.9 src/sys/sys/quotactl.h
diff -r1.79 -r1.80 src/sys/ufs/ufs/ufs_quota.c

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

--- src/sys/kern/vfs_quotactl.c 2012/01/29 06:41:41 1.10
+++ src/sys/kern/vfs_quotactl.c 2012/01/29 06:44:33 1.11
@@ -1,428 +1,477 @@ @@ -1,428 +1,477 @@
1/* $NetBSD: vfs_quotactl.c,v 1.10 2012/01/29 06:41:41 dholland Exp $ */ 1/* $NetBSD: vfs_quotactl.c,v 1.11 2012/01/29 06:44:33 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.10 2012/01/29 06:41:41 dholland Exp $"); 83__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.11 2012/01/29 06:44:33 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_set(struct mount *mp, 302vfs_quotactl_set(struct mount *mp,
303 prop_dictionary_t cmddict, int q2type, 303 prop_dictionary_t cmddict, int q2type,
304 prop_array_t datas) 304 prop_array_t datas)
305{ 305{
 306 prop_array_t replies;
 307 prop_object_iterator_t iter;
 308 prop_dictionary_t data;
 309 int defaultq;
 310 uint32_t id;
 311 const char *idstr;
306 struct vfs_quotactl_args args; 312 struct vfs_quotactl_args args;
 313 int error;
307 314
308 args.qc_type = QCT_PROPLIB; 315 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
309 args.u.proplib.qc_cmddict = cmddict; 316 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
310 args.u.proplib.qc_q2type = q2type; 317
311 args.u.proplib.qc_datas = datas; 318 replies = prop_array_create();
312 return VFS_QUOTACTL(mp, QUOTACTL_SET, &args); 319 if (replies == NULL)
 320 return ENOMEM;
 321
 322 iter = prop_array_iterator(datas);
 323 if (iter == NULL) {
 324 prop_object_release(replies);
 325 return ENOMEM;
 326 }
 327
 328 while ((data = prop_object_iterator_next(iter)) != NULL) {
 329 if (!prop_dictionary_get_uint32(data, "id", &id)) {
 330 if (!prop_dictionary_get_cstring_nocopy(data, "id",
 331 &idstr))
 332 continue;
 333 if (strcmp(idstr, "default"))
 334 continue;
 335 id = 0;
 336 defaultq = 1;
 337 } else {
 338 defaultq = 0;
 339 }
 340
 341 args.qc_type = QCT_SET;
 342 args.u.set.qc_id = id;
 343 args.u.set.qc_defaultq = defaultq;
 344 args.u.set.qc_q2type = q2type;
 345 args.u.set.qc_data = data;
 346 error = VFS_QUOTACTL(mp, QUOTACTL_SET, &args);
 347 if (error) {
 348 goto err;
 349 }
 350 }
 351 prop_object_iterator_release(iter);
 352 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
 353 error = ENOMEM;
 354 } else {
 355 error = 0;
 356 }
 357 return error;
 358err:
 359 prop_object_iterator_release(iter);
 360 prop_object_release(replies);
 361 return error;
313} 362}
314 363
315static int 364static int
316vfs_quotactl_getall(struct mount *mp, 365vfs_quotactl_getall(struct mount *mp,
317 prop_dictionary_t cmddict, int q2type, 366 prop_dictionary_t cmddict, int q2type,
318 prop_array_t datas) 367 prop_array_t datas)
319{ 368{
320 struct vfs_quotactl_args args; 369 struct vfs_quotactl_args args;
321 370
322 args.qc_type = QCT_PROPLIB; 371 args.qc_type = QCT_PROPLIB;
323 args.u.proplib.qc_cmddict = cmddict; 372 args.u.proplib.qc_cmddict = cmddict;
324 args.u.proplib.qc_q2type = q2type; 373 args.u.proplib.qc_q2type = q2type;
325 args.u.proplib.qc_datas = datas; 374 args.u.proplib.qc_datas = datas;
326 return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args); 375 return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args);
327} 376}
328 377
329static int 378static int
330vfs_quotactl_clear(struct mount *mp, 379vfs_quotactl_clear(struct mount *mp,
331 prop_dictionary_t cmddict, int q2type, 380 prop_dictionary_t cmddict, int q2type,
332 prop_array_t datas) 381 prop_array_t datas)
333{ 382{
334 struct vfs_quotactl_args args; 383 struct vfs_quotactl_args args;
335 384
336 args.qc_type = QCT_PROPLIB; 385 args.qc_type = QCT_PROPLIB;
337 args.u.proplib.qc_cmddict = cmddict; 386 args.u.proplib.qc_cmddict = cmddict;
338 args.u.proplib.qc_q2type = q2type; 387 args.u.proplib.qc_q2type = q2type;
339 args.u.proplib.qc_datas = datas; 388 args.u.proplib.qc_datas = datas;
340 return VFS_QUOTACTL(mp, QUOTACTL_CLEAR, &args); 389 return VFS_QUOTACTL(mp, QUOTACTL_CLEAR, &args);
341} 390}
342 391
343static int 392static int
344vfs_quotactl_cmd(struct mount *mp, prop_dictionary_t cmddict) 393vfs_quotactl_cmd(struct mount *mp, prop_dictionary_t cmddict)
345{ 394{
346 int error; 395 int error;
347 const char *cmd, *type; 396 const char *cmd, *type;
348 prop_array_t datas; 397 prop_array_t datas;
349 int q2type; 398 int q2type;
350 399
351 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd)) 400 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd))
352 return EINVAL; 401 return EINVAL;
353 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type)) 402 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type))
354 return EINVAL; 403 return EINVAL;
355 404
356 if (!strcmp(type, QUOTADICT_CLASS_USER)) { 405 if (!strcmp(type, QUOTADICT_CLASS_USER)) {
357 q2type = QUOTA_CLASS_USER; 406 q2type = QUOTA_CLASS_USER;
358 } else if (!strcmp(type, QUOTADICT_CLASS_GROUP)) { 407 } else if (!strcmp(type, QUOTADICT_CLASS_GROUP)) {
359 q2type = QUOTA_CLASS_GROUP; 408 q2type = QUOTA_CLASS_GROUP;
360 } else { 409 } else {
361 /* XXX this is a bad errno for this case */ 410 /* XXX this is a bad errno for this case */
362 return EOPNOTSUPP; 411 return EOPNOTSUPP;
363 } 412 }
364 413
365 datas = prop_dictionary_get(cmddict, "data"); 414 datas = prop_dictionary_get(cmddict, "data");
366 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY) 415 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY)
367 return EINVAL; 416 return EINVAL;
368 417
369 prop_object_retain(datas); 418 prop_object_retain(datas);
370 prop_dictionary_remove(cmddict, "data"); /* prepare for return */ 419 prop_dictionary_remove(cmddict, "data"); /* prepare for return */
371 420
372 if (strcmp(cmd, "get version") == 0) { 421 if (strcmp(cmd, "get version") == 0) {
373 error = vfs_quotactl_getversion(mp, cmddict, q2type, datas); 422 error = vfs_quotactl_getversion(mp, cmddict, q2type, datas);
374 } else if (strcmp(cmd, "quotaon") == 0) { 423 } else if (strcmp(cmd, "quotaon") == 0) {
375 error = vfs_quotactl_quotaon(mp, cmddict, q2type, datas); 424 error = vfs_quotactl_quotaon(mp, cmddict, q2type, datas);
376 } else if (strcmp(cmd, "quotaoff") == 0) { 425 } else if (strcmp(cmd, "quotaoff") == 0) {
377 error = vfs_quotactl_quotaoff(mp, cmddict, q2type, datas); 426 error = vfs_quotactl_quotaoff(mp, cmddict, q2type, datas);
378 } else if (strcmp(cmd, "get") == 0) { 427 } else if (strcmp(cmd, "get") == 0) {
379 error = vfs_quotactl_get(mp, cmddict, q2type, datas); 428 error = vfs_quotactl_get(mp, cmddict, q2type, datas);
380 } else if (strcmp(cmd, "set") == 0) { 429 } else if (strcmp(cmd, "set") == 0) {
381 error = vfs_quotactl_set(mp, cmddict, q2type, datas); 430 error = vfs_quotactl_set(mp, cmddict, q2type, datas);
382 } else if (strcmp(cmd, "getall") == 0) { 431 } else if (strcmp(cmd, "getall") == 0) {
383 error = vfs_quotactl_getall(mp, cmddict, q2type, datas); 432 error = vfs_quotactl_getall(mp, cmddict, q2type, datas);
384 } else if (strcmp(cmd, "clear") == 0) { 433 } else if (strcmp(cmd, "clear") == 0) {
385 error = vfs_quotactl_clear(mp, cmddict, q2type, datas); 434 error = vfs_quotactl_clear(mp, cmddict, q2type, datas);
386 } else { 435 } else {
387 /* XXX this a bad errno for this case */ 436 /* XXX this a bad errno for this case */
388 error = EOPNOTSUPP; 437 error = EOPNOTSUPP;
389 } 438 }
390 439
391 error = (prop_dictionary_set_int8(cmddict, "return", 440 error = (prop_dictionary_set_int8(cmddict, "return",
392 error) ? 0 : ENOMEM); 441 error) ? 0 : ENOMEM);
393 prop_object_release(datas); 442 prop_object_release(datas);
394 443
395 return error; 444 return error;
396} 445}
397 446
398int 447int
399vfs_quotactl(struct mount *mp, prop_dictionary_t dict) 448vfs_quotactl(struct mount *mp, prop_dictionary_t dict)
400{ 449{
401 prop_dictionary_t cmddict; 450 prop_dictionary_t cmddict;
402 prop_array_t commands; 451 prop_array_t commands;
403 prop_object_iterator_t iter; 452 prop_object_iterator_t iter;
404 int error; 453 int error;
405 454
406 error = quota_get_cmds(dict, &commands); 455 error = quota_get_cmds(dict, &commands);
407 if (error) { 456 if (error) {
408 return error; 457 return error;
409 } 458 }
410 459
411 iter = prop_array_iterator(commands); 460 iter = prop_array_iterator(commands);
412 if (iter == NULL) { 461 if (iter == NULL) {
413 return ENOMEM; 462 return ENOMEM;
414 } 463 }
415 464
416 while ((cmddict = prop_object_iterator_next(iter)) != NULL) { 465 while ((cmddict = prop_object_iterator_next(iter)) != NULL) {
417 if (prop_object_type(cmddict) != PROP_TYPE_DICTIONARY) { 466 if (prop_object_type(cmddict) != PROP_TYPE_DICTIONARY) {
418 /* XXX shouldn't this be an error? */ 467 /* XXX shouldn't this be an error? */
419 continue; 468 continue;
420 } 469 }
421 error = vfs_quotactl_cmd(mp, cmddict); 470 error = vfs_quotactl_cmd(mp, cmddict);
422 if (error) { 471 if (error) {
423 break; 472 break;
424 } 473 }
425 } 474 }
426 prop_object_iterator_release(iter); 475 prop_object_iterator_release(iter);
427 return error; 476 return error;
428} 477}

cvs diff -r1.8 -r1.9 src/sys/sys/quotactl.h (switch to unified diff)

--- src/sys/sys/quotactl.h 2012/01/29 06:41:41 1.8
+++ src/sys/sys/quotactl.h 2012/01/29 06:44:33 1.9
@@ -1,73 +1,80 @@ @@ -1,73 +1,80 @@
1/* $NetBSD: quotactl.h,v 1.8 2012/01/29 06:41:41 dholland Exp $ */ 1/* $NetBSD: quotactl.h,v 1.9 2012/01/29 06:44:33 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_SET 4 45#define QUOTACTL_SET 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_SET, /* set */
54}; 55};
55struct vfs_quotactl_args { 56struct vfs_quotactl_args {
56 enum vfs_quotactl_argtypes qc_type; 57 enum vfs_quotactl_argtypes qc_type;
57 union { 58 union {
58 struct { 59 struct {
59 prop_dictionary_t qc_cmddict; 60 prop_dictionary_t qc_cmddict;
60 int qc_q2type; 61 int qc_q2type;
61 prop_array_t qc_datas; 62 prop_array_t qc_datas;
62 } proplib; 63 } proplib;
63 struct { 64 struct {
64 int *qc_version_ret; 65 int *qc_version_ret;
65 } getversion; 66 } getversion;
66 struct { 67 struct {
67 const struct quotakey *qc_key; 68 const struct quotakey *qc_key;
68 struct quotaval *qc_ret; 69 struct quotaval *qc_ret;
69 } get; 70 } get;
 71 struct {
 72 id_t qc_id;
 73 int qc_defaultq;
 74 int qc_q2type;
 75 prop_dictionary_t qc_data;
 76 } set;
70 } u; 77 } u;
71}; 78};
72 79
73#endif /* _SYS_QUOTACTL_H_ */ 80#endif /* _SYS_QUOTACTL_H_ */

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

--- src/sys/ufs/ufs/ufs_quota.c 2012/01/29 06:42:14 1.79
+++ src/sys/ufs/ufs/ufs_quota.c 2012/01/29 06:44:33 1.80
@@ -1,850 +1,820 @@ @@ -1,850 +1,820 @@
1/* $NetBSD: ufs_quota.c,v 1.79 2012/01/29 06:42:14 dholland Exp $ */ 1/* $NetBSD: ufs_quota.c,v 1.80 2012/01/29 06:44:33 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.79 2012/01/29 06:42:14 dholland Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.80 2012/01/29 06:44:33 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_set(struct mount *, struct lwp *, 78static int quota_handle_cmd_set(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_SET: 175 case QUOTACTL_SET:
176 error = quota_handle_cmd_set(mp, l, args); 176 error = quota_handle_cmd_set(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_set(struct mount *mp, struct lwp *l,  267quota_handle_cmd_set(struct mount *mp, struct lwp *l,
268 struct vfs_quotactl_args *args) 268 struct vfs_quotactl_args *args)
269{ 269{
270 prop_array_t replies; 
271 prop_object_iterator_t iter; 
272 prop_dictionary_t data; 
273 uint32_t id; 
274 struct ufsmount *ump = VFSTOUFS(mp); 270 struct ufsmount *ump = VFSTOUFS(mp);
275 int error, defaultq = 0; 271 id_t id;
276 const char *idstr; 272 int defaultq;
277 prop_dictionary_t cmddict; 
278 int q2type; 273 int q2type;
279 prop_array_t datas; 274 prop_dictionary_t data;
 275 int error;
280 276
281 KASSERT(args->qc_type == QCT_PROPLIB); 277 KASSERT(args->qc_type == QCT_SET);
282 cmddict = args->u.proplib.qc_cmddict; 278 id = args->u.set.qc_id;
283 q2type = args->u.proplib.qc_q2type; 279 defaultq = args->u.set.qc_defaultq;
284 datas = args->u.proplib.qc_datas; 280 q2type = args->u.set.qc_q2type;
 281 data = args->u.set.qc_data;
285 282
286 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 283 KASSERT(prop_object_type(data) == PROP_TYPE_DICTIONARY);
287 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 
288 284
289 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) 285 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0)
290 return EOPNOTSUPP; 286 return EOPNOTSUPP;
291  
292 replies = prop_array_create(); 
293 if (replies == NULL) 
294 return ENOMEM; 
295 287
296 iter = prop_array_iterator(datas); 288 /* avoid whitespace changes */
297 if (iter == NULL) { 289 {
298 prop_object_release(replies); 
299 return ENOMEM; 
300 } 
301 while ((data = prop_object_iterator_next(iter)) != NULL) { 
302 if (!prop_dictionary_get_uint32(data, "id", &id)) { 
303 if (!prop_dictionary_get_cstring_nocopy(data, "id", 
304 &idstr)) 
305 continue; 
306 if (strcmp(idstr, "default")) 
307 continue; 
308 id = 0; 
309 defaultq = 1; 
310 } else { 
311 defaultq = 0; 
312 } 
313 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 290 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
314 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(id), NULL); 291 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(id), NULL);
315 if (error != 0) 292 if (error != 0)
316 goto err; 293 goto err;
317#ifdef QUOTA 294#ifdef QUOTA
318 if (ump->um_flags & UFS_QUOTA) 295 if (ump->um_flags & UFS_QUOTA)
319 error = quota1_handle_cmd_set(ump, q2type, id, defaultq, 296 error = quota1_handle_cmd_set(ump, q2type, id, defaultq,
320 data); 297 data);
321 else 298 else
322#endif 299#endif
323#ifdef QUOTA2 300#ifdef QUOTA2
324 if (ump->um_flags & UFS_QUOTA2) { 301 if (ump->um_flags & UFS_QUOTA2) {
325 error = quota2_handle_cmd_set(ump, q2type, id, defaultq, 302 error = quota2_handle_cmd_set(ump, q2type, id, defaultq,
326 data); 303 data);
327 } else 304 } else
328#endif 305#endif
329 panic("quota_handle_cmd_get: no support ?"); 306 panic("quota_handle_cmd_get: no support ?");
330  307
331 if (error && error != ENOENT) 308 if (error && error != ENOENT)
332 goto err; 309 goto err;
333 } 310 }
334 prop_object_iterator_release(iter); 311
335 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 312 return 0;
336 error = ENOMEM; 313 err:
337 } else { 
338 error = 0; 
339 } 
340 return error; 
341err: 
342 prop_object_iterator_release(iter); 
343 prop_object_release(replies); 
344 return error; 314 return error;
345} 315}
346 316
347static int  317static int
348quota_handle_cmd_clear(struct mount *mp, struct lwp *l,  318quota_handle_cmd_clear(struct mount *mp, struct lwp *l,
349 struct vfs_quotactl_args *args) 319 struct vfs_quotactl_args *args)
350{ 320{
351 prop_array_t replies; 321 prop_array_t replies;
352 prop_object_iterator_t iter; 322 prop_object_iterator_t iter;
353 prop_dictionary_t data; 323 prop_dictionary_t data;
354 uint32_t id; 324 uint32_t id;
355 struct ufsmount *ump = VFSTOUFS(mp); 325 struct ufsmount *ump = VFSTOUFS(mp);
356 int error, defaultq = 0; 326 int error, defaultq = 0;
357 const char *idstr; 327 const char *idstr;
358 prop_dictionary_t cmddict; 328 prop_dictionary_t cmddict;
359 int q2type; 329 int q2type;
360 prop_array_t datas; 330 prop_array_t datas;
361 331
362 KASSERT(args->qc_type == QCT_PROPLIB); 332 KASSERT(args->qc_type == QCT_PROPLIB);
363 cmddict = args->u.proplib.qc_cmddict; 333 cmddict = args->u.proplib.qc_cmddict;
364 q2type = args->u.proplib.qc_q2type; 334 q2type = args->u.proplib.qc_q2type;
365 datas = args->u.proplib.qc_datas; 335 datas = args->u.proplib.qc_datas;
366 336
367 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 337 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
368 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 338 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
369 339
370 if ((ump->um_flags & UFS_QUOTA2) == 0) 340 if ((ump->um_flags & UFS_QUOTA2) == 0)
371 return EOPNOTSUPP; 341 return EOPNOTSUPP;
372  342
373 replies = prop_array_create(); 343 replies = prop_array_create();
374 if (replies == NULL) 344 if (replies == NULL)
375 return ENOMEM; 345 return ENOMEM;
376 346
377 iter = prop_array_iterator(datas); 347 iter = prop_array_iterator(datas);
378 if (iter == NULL) { 348 if (iter == NULL) {
379 prop_object_release(replies); 349 prop_object_release(replies);
380 return ENOMEM; 350 return ENOMEM;
381 } 351 }
382 while ((data = prop_object_iterator_next(iter)) != NULL) { 352 while ((data = prop_object_iterator_next(iter)) != NULL) {
383 if (!prop_dictionary_get_uint32(data, "id", &id)) { 353 if (!prop_dictionary_get_uint32(data, "id", &id)) {
384 if (!prop_dictionary_get_cstring_nocopy(data, "id", 354 if (!prop_dictionary_get_cstring_nocopy(data, "id",
385 &idstr)) 355 &idstr))
386 continue; 356 continue;
387 if (strcmp(idstr, "default")) 357 if (strcmp(idstr, "default"))
388 continue; 358 continue;
389 id = 0; 359 id = 0;
390 defaultq = 1; 360 defaultq = 1;
391 } else { 361 } else {
392 defaultq = 0; 362 defaultq = 0;
393 } 363 }
394 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 364 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
395 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(id), NULL); 365 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(id), NULL);
396 if (error != 0) 366 if (error != 0)
397 goto err; 367 goto err;
398#ifdef QUOTA2 368#ifdef QUOTA2
399 if (ump->um_flags & UFS_QUOTA2) { 369 if (ump->um_flags & UFS_QUOTA2) {
400 error = quota2_handle_cmd_clear(ump, q2type, id, defaultq, 370 error = quota2_handle_cmd_clear(ump, q2type, id, defaultq,
401 data); 371 data);
402 } else 372 } else
403#endif 373#endif
404 panic("quota_handle_cmd_get: no support ?"); 374 panic("quota_handle_cmd_get: no support ?");
405  375
406 if (error && error != ENOENT) 376 if (error && error != ENOENT)
407 goto err; 377 goto err;
408 } 378 }
409 prop_object_iterator_release(iter); 379 prop_object_iterator_release(iter);
410 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 380 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
411 error = ENOMEM; 381 error = ENOMEM;
412 } else { 382 } else {
413 error = 0; 383 error = 0;
414 } 384 }
415 return error; 385 return error;
416err: 386err:
417 prop_object_iterator_release(iter); 387 prop_object_iterator_release(iter);
418 prop_object_release(replies); 388 prop_object_release(replies);
419 return error; 389 return error;
420} 390}
421 391
422static int  392static int
423quota_handle_cmd_getall(struct mount *mp, struct lwp *l,  393quota_handle_cmd_getall(struct mount *mp, struct lwp *l,
424 struct vfs_quotactl_args *args) 394 struct vfs_quotactl_args *args)
425{ 395{
426 prop_array_t replies; 396 prop_array_t replies;
427 struct ufsmount *ump = VFSTOUFS(mp); 397 struct ufsmount *ump = VFSTOUFS(mp);
428 int error; 398 int error;
429 prop_dictionary_t cmddict; 399 prop_dictionary_t cmddict;
430 int q2type; 400 int q2type;
431 prop_array_t datas; 401 prop_array_t datas;
432 402
433 KASSERT(args->qc_type == QCT_PROPLIB); 403 KASSERT(args->qc_type == QCT_PROPLIB);
434 cmddict = args->u.proplib.qc_cmddict; 404 cmddict = args->u.proplib.qc_cmddict;
435 q2type = args->u.proplib.qc_q2type; 405 q2type = args->u.proplib.qc_q2type;
436 datas = args->u.proplib.qc_datas; 406 datas = args->u.proplib.qc_datas;
437 407
438 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 408 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
439 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 409 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
440 410
441 if ((ump->um_flags & UFS_QUOTA2) == 0) 411 if ((ump->um_flags & UFS_QUOTA2) == 0)
442 return EOPNOTSUPP; 412 return EOPNOTSUPP;
443  413
444 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 414 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
445 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL); 415 KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL);
446 if (error) 416 if (error)
447 return error; 417 return error;
448  418
449 replies = prop_array_create(); 419 replies = prop_array_create();
450 if (replies == NULL) 420 if (replies == NULL)
451 return ENOMEM; 421 return ENOMEM;
452 422
453#ifdef QUOTA2 423#ifdef QUOTA2
454 if (ump->um_flags & UFS_QUOTA2) { 424 if (ump->um_flags & UFS_QUOTA2) {
455 error = quota2_handle_cmd_getall(ump, q2type, replies); 425 error = quota2_handle_cmd_getall(ump, q2type, replies);
456 } else 426 } else
457#endif 427#endif
458 panic("quota_handle_cmd_getall: no support ?"); 428 panic("quota_handle_cmd_getall: no support ?");
459 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { 429 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
460 error = ENOMEM; 430 error = ENOMEM;
461 } else { 431 } else {
462 error = 0; 432 error = 0;
463 } 433 }
464 return error; 434 return error;
465} 435}
466 436
467static int  437static int
468quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l,  438quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l,
469 struct vfs_quotactl_args *args) 439 struct vfs_quotactl_args *args)
470{ 440{
471 prop_dictionary_t data; 441 prop_dictionary_t data;
472 struct ufsmount *ump = VFSTOUFS(mp); 442 struct ufsmount *ump = VFSTOUFS(mp);
473 int error; 443 int error;
474 const char *qfile; 444 const char *qfile;
475 prop_dictionary_t cmddict; 445 prop_dictionary_t cmddict;
476 int q2type; 446 int q2type;
477 prop_array_t datas; 447 prop_array_t datas;
478 448
479 KASSERT(args->qc_type == QCT_PROPLIB); 449 KASSERT(args->qc_type == QCT_PROPLIB);
480 cmddict = args->u.proplib.qc_cmddict; 450 cmddict = args->u.proplib.qc_cmddict;
481 q2type = args->u.proplib.qc_q2type; 451 q2type = args->u.proplib.qc_q2type;
482 datas = args->u.proplib.qc_datas; 452 datas = args->u.proplib.qc_datas;
483 453
484 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 454 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
485 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 455 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
486 456
487 if ((ump->um_flags & UFS_QUOTA2) != 0) 457 if ((ump->um_flags & UFS_QUOTA2) != 0)
488 return EBUSY; 458 return EBUSY;
489  459
490 if (prop_array_count(datas) != 1) 460 if (prop_array_count(datas) != 1)
491 return EINVAL; 461 return EINVAL;
492 462
493 data = prop_array_get(datas, 0); 463 data = prop_array_get(datas, 0);
494 if (data == NULL) 464 if (data == NULL)
495 return ENOMEM; 465 return ENOMEM;
496 if (!prop_dictionary_get_cstring_nocopy(data, "quotafile", 466 if (!prop_dictionary_get_cstring_nocopy(data, "quotafile",
497 &qfile)) 467 &qfile))
498 return EINVAL; 468 return EINVAL;
499 469
500 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 470 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
501 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL); 471 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
502 if (error != 0) { 472 if (error != 0) {
503 return error; 473 return error;
504 } 474 }
505#ifdef QUOTA 475#ifdef QUOTA
506 error = quota1_handle_cmd_quotaon(l, ump, q2type, qfile); 476 error = quota1_handle_cmd_quotaon(l, ump, q2type, qfile);
507#else 477#else
508 error = EOPNOTSUPP; 478 error = EOPNOTSUPP;
509#endif 479#endif
510  480
511 return error; 481 return error;
512} 482}
513 483
514static int  484static int
515quota_handle_cmd_quotaoff(struct mount *mp, struct lwp *l,  485quota_handle_cmd_quotaoff(struct mount *mp, struct lwp *l,
516 struct vfs_quotactl_args *args) 486 struct vfs_quotactl_args *args)
517{ 487{
518 struct ufsmount *ump = VFSTOUFS(mp); 488 struct ufsmount *ump = VFSTOUFS(mp);
519 int error; 489 int error;
520 prop_dictionary_t cmddict; 490 prop_dictionary_t cmddict;
521 int q2type; 491 int q2type;
522 prop_array_t datas; 492 prop_array_t datas;
523 493
524 KASSERT(args->qc_type == QCT_PROPLIB); 494 KASSERT(args->qc_type == QCT_PROPLIB);
525 cmddict = args->u.proplib.qc_cmddict; 495 cmddict = args->u.proplib.qc_cmddict;
526 q2type = args->u.proplib.qc_q2type; 496 q2type = args->u.proplib.qc_q2type;
527 datas = args->u.proplib.qc_datas; 497 datas = args->u.proplib.qc_datas;
528 498
529 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); 499 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
530 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY); 500 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
531 501
532 if ((ump->um_flags & UFS_QUOTA2) != 0) 502 if ((ump->um_flags & UFS_QUOTA2) != 0)
533 return EOPNOTSUPP; 503 return EOPNOTSUPP;
534  504
535 if (prop_array_count(datas) != 0) 505 if (prop_array_count(datas) != 0)
536 return EINVAL; 506 return EINVAL;
537 507
538 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, 508 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
539 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL); 509 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
540 if (error != 0) { 510 if (error != 0) {
541 return error; 511 return error;
542 } 512 }
543#ifdef QUOTA 513#ifdef QUOTA
544 error = quota1_handle_cmd_quotaoff(l, ump, q2type); 514 error = quota1_handle_cmd_quotaoff(l, ump, q2type);
545#else 515#else
546 error = EOPNOTSUPP; 516 error = EOPNOTSUPP;
547#endif 517#endif
548  518
549 return error; 519 return error;
550} 520}
551 521
552/* 522/*
553 * Initialize the quota system. 523 * Initialize the quota system.
554 */ 524 */
555void 525void
556dqinit(void) 526dqinit(void)
557{ 527{
558 528
559 mutex_init(&dqlock, MUTEX_DEFAULT, IPL_NONE); 529 mutex_init(&dqlock, MUTEX_DEFAULT, IPL_NONE);
560 cv_init(&dqcv, "quota"); 530 cv_init(&dqcv, "quota");
561 dqhashtbl = hashinit(desiredvnodes, HASH_LIST, true, &dqhash); 531 dqhashtbl = hashinit(desiredvnodes, HASH_LIST, true, &dqhash);
562 dquot_cache = pool_cache_init(sizeof(struct dquot), 0, 0, 0, "ufsdq", 532 dquot_cache = pool_cache_init(sizeof(struct dquot), 0, 0, 0, "ufsdq",
563 NULL, IPL_NONE, NULL, NULL, NULL); 533 NULL, IPL_NONE, NULL, NULL, NULL);
564} 534}
565 535
566void 536void
567dqreinit(void) 537dqreinit(void)
568{ 538{
569 struct dquot *dq; 539 struct dquot *dq;
570 struct dqhashhead *oldhash, *hash; 540 struct dqhashhead *oldhash, *hash;
571 struct vnode *dqvp; 541 struct vnode *dqvp;
572 u_long oldmask, mask, hashval; 542 u_long oldmask, mask, hashval;
573 int i; 543 int i;
574 544
575 hash = hashinit(desiredvnodes, HASH_LIST, true, &mask); 545 hash = hashinit(desiredvnodes, HASH_LIST, true, &mask);
576 mutex_enter(&dqlock); 546 mutex_enter(&dqlock);
577 oldhash = dqhashtbl; 547 oldhash = dqhashtbl;
578 oldmask = dqhash; 548 oldmask = dqhash;
579 dqhashtbl = hash; 549 dqhashtbl = hash;
580 dqhash = mask; 550 dqhash = mask;
581 for (i = 0; i <= oldmask; i++) { 551 for (i = 0; i <= oldmask; i++) {
582 while ((dq = LIST_FIRST(&oldhash[i])) != NULL) { 552 while ((dq = LIST_FIRST(&oldhash[i])) != NULL) {
583 dqvp = dq->dq_ump->um_quotas[dq->dq_type]; 553 dqvp = dq->dq_ump->um_quotas[dq->dq_type];
584 LIST_REMOVE(dq, dq_hash); 554 LIST_REMOVE(dq, dq_hash);
585 hashval = DQHASH(dqvp, dq->dq_id); 555 hashval = DQHASH(dqvp, dq->dq_id);
586 LIST_INSERT_HEAD(&dqhashtbl[hashval], dq, dq_hash); 556 LIST_INSERT_HEAD(&dqhashtbl[hashval], dq, dq_hash);
587 } 557 }
588 } 558 }
589 mutex_exit(&dqlock); 559 mutex_exit(&dqlock);
590 hashdone(oldhash, HASH_LIST, oldmask); 560 hashdone(oldhash, HASH_LIST, oldmask);
591} 561}
592 562
593/* 563/*
594 * Free resources held by quota system. 564 * Free resources held by quota system.
595 */ 565 */
596void 566void
597dqdone(void) 567dqdone(void)
598{ 568{
599 569
600 pool_cache_destroy(dquot_cache); 570 pool_cache_destroy(dquot_cache);
601 hashdone(dqhashtbl, HASH_LIST, dqhash); 571 hashdone(dqhashtbl, HASH_LIST, dqhash);
602 cv_destroy(&dqcv); 572 cv_destroy(&dqcv);
603 mutex_destroy(&dqlock); 573 mutex_destroy(&dqlock);
604} 574}
605 575
606/* 576/*
607 * Set up the quotas for an inode. 577 * Set up the quotas for an inode.
608 * 578 *
609 * This routine completely defines the semantics of quotas. 579 * This routine completely defines the semantics of quotas.
610 * If other criterion want to be used to establish quotas, the 580 * If other criterion want to be used to establish quotas, the
611 * MAXQUOTAS value in quotas.h should be increased, and the 581 * MAXQUOTAS value in quotas.h should be increased, and the
612 * additional dquots set up here. 582 * additional dquots set up here.
613 */ 583 */
614int 584int
615getinoquota(struct inode *ip) 585getinoquota(struct inode *ip)
616{ 586{
617 struct ufsmount *ump = ip->i_ump; 587 struct ufsmount *ump = ip->i_ump;
618 struct vnode *vp = ITOV(ip); 588 struct vnode *vp = ITOV(ip);
619 int i, error; 589 int i, error;
620 u_int32_t ino_ids[MAXQUOTAS]; 590 u_int32_t ino_ids[MAXQUOTAS];
621 591
622 /* 592 /*
623 * To avoid deadlocks never update quotas for quota files 593 * To avoid deadlocks never update quotas for quota files
624 * on the same file system 594 * on the same file system
625 */ 595 */
626 for (i = 0; i < MAXQUOTAS; i++) 596 for (i = 0; i < MAXQUOTAS; i++)
627 if (vp == ump->um_quotas[i]) 597 if (vp == ump->um_quotas[i])
628 return 0; 598 return 0;
629 599
630 ino_ids[USRQUOTA] = ip->i_uid; 600 ino_ids[USRQUOTA] = ip->i_uid;
631 ino_ids[GRPQUOTA] = ip->i_gid; 601 ino_ids[GRPQUOTA] = ip->i_gid;
632 for (i = 0; i < MAXQUOTAS; i++) { 602 for (i = 0; i < MAXQUOTAS; i++) {
633 /* 603 /*
634 * If the file id changed the quota needs update. 604 * If the file id changed the quota needs update.
635 */ 605 */
636 if (ip->i_dquot[i] != NODQUOT && 606 if (ip->i_dquot[i] != NODQUOT &&
637 ip->i_dquot[i]->dq_id != ino_ids[i]) { 607 ip->i_dquot[i]->dq_id != ino_ids[i]) {
638 dqrele(ITOV(ip), ip->i_dquot[i]); 608 dqrele(ITOV(ip), ip->i_dquot[i]);
639 ip->i_dquot[i] = NODQUOT; 609 ip->i_dquot[i] = NODQUOT;
640 } 610 }
641 /* 611 /*
642 * Set up the quota based on file id. 612 * Set up the quota based on file id.
643 * ENODEV means that quotas are not enabled. 613 * ENODEV means that quotas are not enabled.
644 */ 614 */
645 if (ip->i_dquot[i] == NODQUOT && 615 if (ip->i_dquot[i] == NODQUOT &&
646 (error = dqget(vp, ino_ids[i], ump, i, &ip->i_dquot[i])) && 616 (error = dqget(vp, ino_ids[i], ump, i, &ip->i_dquot[i])) &&
647 error != ENODEV) 617 error != ENODEV)
648 return (error); 618 return (error);
649 } 619 }
650 return 0; 620 return 0;
651} 621}
652 622
653/* 623/*
654 * Obtain a dquot structure for the specified identifier and quota file 624 * Obtain a dquot structure for the specified identifier and quota file
655 * reading the information from the file if necessary. 625 * reading the information from the file if necessary.
656 */ 626 */
657int 627int
658dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type, 628dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type,
659 struct dquot **dqp) 629 struct dquot **dqp)
660{ 630{
661 struct dquot *dq, *ndq; 631 struct dquot *dq, *ndq;
662 struct dqhashhead *dqh; 632 struct dqhashhead *dqh;
663 struct vnode *dqvp; 633 struct vnode *dqvp;
664 int error = 0; /* XXX gcc */ 634 int error = 0; /* XXX gcc */
665 635
666 /* Lock to see an up to date value for QTF_CLOSING. */ 636 /* Lock to see an up to date value for QTF_CLOSING. */
667 mutex_enter(&dqlock); 637 mutex_enter(&dqlock);
668 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) { 638 if ((ump->um_flags & (UFS_QUOTA|UFS_QUOTA2)) == 0) {
669 mutex_exit(&dqlock); 639 mutex_exit(&dqlock);
670 *dqp = NODQUOT; 640 *dqp = NODQUOT;
671 return (ENODEV); 641 return (ENODEV);
672 } 642 }
673 dqvp = ump->um_quotas[type]; 643 dqvp = ump->um_quotas[type];
674#ifdef QUOTA 644#ifdef QUOTA
675 if (ump->um_flags & UFS_QUOTA) { 645 if (ump->um_flags & UFS_QUOTA) {
676 if (dqvp == NULLVP || (ump->umq1_qflags[type] & QTF_CLOSING)) { 646 if (dqvp == NULLVP || (ump->umq1_qflags[type] & QTF_CLOSING)) {
677 mutex_exit(&dqlock); 647 mutex_exit(&dqlock);
678 *dqp = NODQUOT; 648 *dqp = NODQUOT;
679 return (ENODEV); 649 return (ENODEV);
680 } 650 }
681 } 651 }
682#endif 652#endif
683#ifdef QUOTA2 653#ifdef QUOTA2
684 if (ump->um_flags & UFS_QUOTA2) { 654 if (ump->um_flags & UFS_QUOTA2) {
685 if (dqvp == NULLVP) { 655 if (dqvp == NULLVP) {
686 mutex_exit(&dqlock); 656 mutex_exit(&dqlock);
687 *dqp = NODQUOT; 657 *dqp = NODQUOT;
688 return (ENODEV); 658 return (ENODEV);
689 } 659 }
690 } 660 }
691#endif 661#endif
692 KASSERT(dqvp != vp); 662 KASSERT(dqvp != vp);
693 /* 663 /*
694 * Check the cache first. 664 * Check the cache first.
695 */ 665 */
696 dqh = &dqhashtbl[DQHASH(dqvp, id)]; 666 dqh = &dqhashtbl[DQHASH(dqvp, id)];
697 LIST_FOREACH(dq, dqh, dq_hash) { 667 LIST_FOREACH(dq, dqh, dq_hash) {
698 if (dq->dq_id != id || 668 if (dq->dq_id != id ||
699 dq->dq_ump->um_quotas[dq->dq_type] != dqvp) 669 dq->dq_ump->um_quotas[dq->dq_type] != dqvp)
700 continue; 670 continue;
701 KASSERT(dq->dq_cnt > 0); 671 KASSERT(dq->dq_cnt > 0);
702 dqref(dq); 672 dqref(dq);
703 mutex_exit(&dqlock); 673 mutex_exit(&dqlock);
704 *dqp = dq; 674 *dqp = dq;
705 return (0); 675 return (0);
706 } 676 }
707 /* 677 /*
708 * Not in cache, allocate a new one. 678 * Not in cache, allocate a new one.
709 */ 679 */
710 mutex_exit(&dqlock); 680 mutex_exit(&dqlock);
711 ndq = pool_cache_get(dquot_cache, PR_WAITOK); 681 ndq = pool_cache_get(dquot_cache, PR_WAITOK);
712 /* 682 /*
713 * Initialize the contents of the dquot structure. 683 * Initialize the contents of the dquot structure.
714 */ 684 */
715 memset((char *)ndq, 0, sizeof *ndq); 685 memset((char *)ndq, 0, sizeof *ndq);
716 ndq->dq_flags = 0; 686 ndq->dq_flags = 0;
717 ndq->dq_id = id; 687 ndq->dq_id = id;
718 ndq->dq_ump = ump; 688 ndq->dq_ump = ump;
719 ndq->dq_type = type; 689 ndq->dq_type = type;
720 mutex_init(&ndq->dq_interlock, MUTEX_DEFAULT, IPL_NONE); 690 mutex_init(&ndq->dq_interlock, MUTEX_DEFAULT, IPL_NONE);
721 mutex_enter(&dqlock); 691 mutex_enter(&dqlock);
722 dqh = &dqhashtbl[DQHASH(dqvp, id)]; 692 dqh = &dqhashtbl[DQHASH(dqvp, id)];
723 LIST_FOREACH(dq, dqh, dq_hash) { 693 LIST_FOREACH(dq, dqh, dq_hash) {
724 if (dq->dq_id != id || 694 if (dq->dq_id != id ||
725 dq->dq_ump->um_quotas[dq->dq_type] != dqvp) 695 dq->dq_ump->um_quotas[dq->dq_type] != dqvp)
726 continue; 696 continue;
727 /* 697 /*
728 * Another thread beat us allocating this dquot. 698 * Another thread beat us allocating this dquot.
729 */ 699 */
730 KASSERT(dq->dq_cnt > 0); 700 KASSERT(dq->dq_cnt > 0);
731 dqref(dq); 701 dqref(dq);
732 mutex_exit(&dqlock); 702 mutex_exit(&dqlock);
733 mutex_destroy(&ndq->dq_interlock); 703 mutex_destroy(&ndq->dq_interlock);
734 pool_cache_put(dquot_cache, ndq); 704 pool_cache_put(dquot_cache, ndq);
735 *dqp = dq; 705 *dqp = dq;
736 return 0; 706 return 0;
737 } 707 }
738 dq = ndq; 708 dq = ndq;
739 LIST_INSERT_HEAD(dqh, dq, dq_hash); 709 LIST_INSERT_HEAD(dqh, dq, dq_hash);
740 dqref(dq); 710 dqref(dq);
741 mutex_enter(&dq->dq_interlock); 711 mutex_enter(&dq->dq_interlock);
742 mutex_exit(&dqlock); 712 mutex_exit(&dqlock);
743#ifdef QUOTA 713#ifdef QUOTA
744 if (ump->um_flags & UFS_QUOTA) 714 if (ump->um_flags & UFS_QUOTA)
745 error = dq1get(dqvp, id, ump, type, dq); 715 error = dq1get(dqvp, id, ump, type, dq);
746#endif 716#endif
747#ifdef QUOTA2 717#ifdef QUOTA2
748 if (ump->um_flags & UFS_QUOTA2) 718 if (ump->um_flags & UFS_QUOTA2)
749 error = dq2get(dqvp, id, ump, type, dq); 719 error = dq2get(dqvp, id, ump, type, dq);
750#endif 720#endif
751 /* 721 /*
752 * I/O error in reading quota file, release 722 * I/O error in reading quota file, release
753 * quota structure and reflect problem to caller. 723 * quota structure and reflect problem to caller.
754 */ 724 */
755 if (error) { 725 if (error) {
756 mutex_enter(&dqlock); 726 mutex_enter(&dqlock);
757 LIST_REMOVE(dq, dq_hash); 727 LIST_REMOVE(dq, dq_hash);
758 mutex_exit(&dqlock); 728 mutex_exit(&dqlock);
759 mutex_exit(&dq->dq_interlock); 729 mutex_exit(&dq->dq_interlock);
760 dqrele(vp, dq); 730 dqrele(vp, dq);
761 *dqp = NODQUOT; 731 *dqp = NODQUOT;
762 return (error); 732 return (error);
763 } 733 }
764 mutex_exit(&dq->dq_interlock); 734 mutex_exit(&dq->dq_interlock);
765 *dqp = dq; 735 *dqp = dq;
766 return (0); 736 return (0);
767} 737}
768 738
769/* 739/*
770 * Obtain a reference to a dquot. 740 * Obtain a reference to a dquot.
771 */ 741 */
772void 742void
773dqref(struct dquot *dq) 743dqref(struct dquot *dq)
774{ 744{
775 745
776 KASSERT(mutex_owned(&dqlock)); 746 KASSERT(mutex_owned(&dqlock));
777 dq->dq_cnt++; 747 dq->dq_cnt++;
778 KASSERT(dq->dq_cnt > 0); 748 KASSERT(dq->dq_cnt > 0);
779} 749}
780 750
781/* 751/*
782 * Release a reference to a dquot. 752 * Release a reference to a dquot.
783 */ 753 */
784void 754void
785dqrele(struct vnode *vp, struct dquot *dq) 755dqrele(struct vnode *vp, struct dquot *dq)
786{ 756{
787 757
788 if (dq == NODQUOT) 758 if (dq == NODQUOT)
789 return; 759 return;
790 mutex_enter(&dq->dq_interlock); 760 mutex_enter(&dq->dq_interlock);
791 for (;;) { 761 for (;;) {
792 mutex_enter(&dqlock); 762 mutex_enter(&dqlock);
793 if (dq->dq_cnt > 1) { 763 if (dq->dq_cnt > 1) {
794 dq->dq_cnt--; 764 dq->dq_cnt--;
795 mutex_exit(&dqlock); 765 mutex_exit(&dqlock);
796 mutex_exit(&dq->dq_interlock); 766 mutex_exit(&dq->dq_interlock);
797 return; 767 return;
798 } 768 }
799 if ((dq->dq_flags & DQ_MOD) == 0) 769 if ((dq->dq_flags & DQ_MOD) == 0)
800 break; 770 break;
801 mutex_exit(&dqlock); 771 mutex_exit(&dqlock);
802#ifdef QUOTA 772#ifdef QUOTA
803 if (dq->dq_ump->um_flags & UFS_QUOTA) 773 if (dq->dq_ump->um_flags & UFS_QUOTA)
804 (void) dq1sync(vp, dq); 774 (void) dq1sync(vp, dq);
805#endif 775#endif
806#ifdef QUOTA2 776#ifdef QUOTA2
807 if (dq->dq_ump->um_flags & UFS_QUOTA2) 777 if (dq->dq_ump->um_flags & UFS_QUOTA2)
808 (void) dq2sync(vp, dq); 778 (void) dq2sync(vp, dq);
809#endif 779#endif
810 } 780 }
811 KASSERT(dq->dq_cnt == 1 && (dq->dq_flags & DQ_MOD) == 0); 781 KASSERT(dq->dq_cnt == 1 && (dq->dq_flags & DQ_MOD) == 0);
812 LIST_REMOVE(dq, dq_hash); 782 LIST_REMOVE(dq, dq_hash);
813 mutex_exit(&dqlock); 783 mutex_exit(&dqlock);
814 mutex_exit(&dq->dq_interlock); 784 mutex_exit(&dq->dq_interlock);
815 mutex_destroy(&dq->dq_interlock); 785 mutex_destroy(&dq->dq_interlock);
816 pool_cache_put(dquot_cache, dq); 786 pool_cache_put(dquot_cache, dq);
817} 787}
818 788
819int 789int
820qsync(struct mount *mp) 790qsync(struct mount *mp)
821{ 791{
822 struct ufsmount *ump = VFSTOUFS(mp); 792 struct ufsmount *ump = VFSTOUFS(mp);
823#ifdef QUOTA 793#ifdef QUOTA
824 if (ump->um_flags & UFS_QUOTA) 794 if (ump->um_flags & UFS_QUOTA)
825 return q1sync(mp); 795 return q1sync(mp);
826#endif 796#endif
827#ifdef QUOTA2 797#ifdef QUOTA2
828 if (ump->um_flags & UFS_QUOTA2) 798 if (ump->um_flags & UFS_QUOTA2)
829 return q2sync(mp); 799 return q2sync(mp);
830#endif 800#endif
831 return 0; 801 return 0;
832} 802}
833 803
834#ifdef DIAGNOSTIC 804#ifdef DIAGNOSTIC
835/* 805/*
836 * Check the hash chains for stray dquot's. 806 * Check the hash chains for stray dquot's.
837 */ 807 */
838void 808void
839dqflush(struct vnode *vp) 809dqflush(struct vnode *vp)
840{ 810{
841 struct dquot *dq; 811 struct dquot *dq;
842 int i; 812 int i;
843 813
844 mutex_enter(&dqlock); 814 mutex_enter(&dqlock);
845 for (i = 0; i <= dqhash; i++) 815 for (i = 0; i <= dqhash; i++)
846 LIST_FOREACH(dq, &dqhashtbl[i], dq_hash) 816 LIST_FOREACH(dq, &dqhashtbl[i], dq_hash)
847 KASSERT(dq->dq_ump->um_quotas[dq->dq_type] != vp); 817 KASSERT(dq->dq_ump->um_quotas[dq->dq_type] != vp);
848 mutex_exit(&dqlock); 818 mutex_exit(&dqlock);
849} 819}
850#endif 820#endif