Sun Jan 29 06:36:51 2012 UTC ()
Move proplib frobbing for QUOTACTL_GETVERSION to FS-independent code.

Note: this change requires a kernel version bump.


(dholland)
diff -r1.5 -r1.6 src/sys/kern/vfs_quotactl.c
diff -r1.3 -r1.4 src/sys/sys/quotactl.h
diff -r1.72 -r1.73 src/sys/ufs/ufs/ufs_quota.c

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

--- src/sys/kern/vfs_quotactl.c 2012/01/29 06:36:06 1.5
+++ src/sys/kern/vfs_quotactl.c 2012/01/29 06:36:50 1.6
@@ -1,272 +1,309 @@ @@ -1,272 +1,309 @@
1/* $NetBSD: vfs_quotactl.c,v 1.5 2012/01/29 06:36:06 dholland Exp $ */ 1/* $NetBSD: vfs_quotactl.c,v 1.6 2012/01/29 06:36:50 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.5 2012/01/29 06:36:06 dholland Exp $"); 83__KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.6 2012/01/29 06:36:50 dholland Exp $");
84 84
85#include <sys/mount.h> 85#include <sys/mount.h>
86#include <sys/quotactl.h> 86#include <sys/quotactl.h>
87#include <quota/quotaprop.h> 87#include <quota/quotaprop.h>
88 88
89static int 89static int
90vfs_quotactl_getversion(struct mount *mp, 90vfs_quotactl_getversion(struct mount *mp,
91 prop_dictionary_t cmddict, int q2type, 91 prop_dictionary_t cmddict, int q2type,
92 prop_array_t datas) 92 prop_array_t datas)
93{ 93{
 94 prop_array_t replies;
 95 prop_dictionary_t data;
 96 int q2version;
94 struct vfs_quotactl_args args; 97 struct vfs_quotactl_args args;
 98 int error;
95 99
96 args.qc_type = QCT_PROPLIB; 100 KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY);
97 args.u.proplib.qc_cmddict = cmddict; 101 KASSERT(prop_object_type(datas) == PROP_TYPE_ARRAY);
98 args.u.proplib.qc_q2type = q2type; 102
99 args.u.proplib.qc_datas = datas; 103 args.qc_type = QCT_GETVERSION;
100 return VFS_QUOTACTL(mp, QUOTACTL_GETVERSION, &args); 104 args.u.getversion.qc_version_ret = &q2version;
 105 error = VFS_QUOTACTL(mp, QUOTACTL_GETVERSION, &args);
 106 if (error) {
 107 return error;
 108 }
 109
 110 data = prop_dictionary_create();
 111 if (data == NULL) {
 112 return ENOMEM;
 113 }
 114
 115 if (!prop_dictionary_set_int8(data, "version", q2version)) {
 116 prop_object_release(data);
 117 return ENOMEM;
 118 }
 119
 120 replies = prop_array_create();
 121 if (replies == NULL) {
 122 prop_object_release(data);
 123 return ENOMEM;
 124 }
 125
 126 if (!prop_array_add_and_rel(replies, data)) {
 127 prop_object_release(data);
 128 prop_object_release(replies);
 129 return ENOMEM;
 130 }
 131
 132 if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) {
 133 prop_object_release(replies);
 134 return ENOMEM;
 135 }
 136
 137 return error;
101} 138}
102 139
103static int 140static int
104vfs_quotactl_quotaon(struct mount *mp, 141vfs_quotactl_quotaon(struct mount *mp,
105 prop_dictionary_t cmddict, int q2type, 142 prop_dictionary_t cmddict, int q2type,
106 prop_array_t datas) 143 prop_array_t datas)
107{ 144{
108 struct vfs_quotactl_args args; 145 struct vfs_quotactl_args args;
109 146
110 args.qc_type = QCT_PROPLIB; 147 args.qc_type = QCT_PROPLIB;
111 args.u.proplib.qc_cmddict = cmddict; 148 args.u.proplib.qc_cmddict = cmddict;
112 args.u.proplib.qc_q2type = q2type; 149 args.u.proplib.qc_q2type = q2type;
113 args.u.proplib.qc_datas = datas; 150 args.u.proplib.qc_datas = datas;
114 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAON, &args); 151 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAON, &args);
115} 152}
116 153
117static int 154static int
118vfs_quotactl_quotaoff(struct mount *mp, 155vfs_quotactl_quotaoff(struct mount *mp,
119 prop_dictionary_t cmddict, int q2type, 156 prop_dictionary_t cmddict, int q2type,
120 prop_array_t datas) 157 prop_array_t datas)
121{ 158{
122 struct vfs_quotactl_args args; 159 struct vfs_quotactl_args args;
123 160
124 args.qc_type = QCT_PROPLIB; 161 args.qc_type = QCT_PROPLIB;
125 args.u.proplib.qc_cmddict = cmddict; 162 args.u.proplib.qc_cmddict = cmddict;
126 args.u.proplib.qc_q2type = q2type; 163 args.u.proplib.qc_q2type = q2type;
127 args.u.proplib.qc_datas = datas; 164 args.u.proplib.qc_datas = datas;
128 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAOFF, &args); 165 return VFS_QUOTACTL(mp, QUOTACTL_QUOTAOFF, &args);
129} 166}
130 167
131static int 168static int
132vfs_quotactl_get(struct mount *mp, 169vfs_quotactl_get(struct mount *mp,
133 prop_dictionary_t cmddict, int q2type, 170 prop_dictionary_t cmddict, int q2type,
134 prop_array_t datas) 171 prop_array_t datas)
135{ 172{
136 struct vfs_quotactl_args args; 173 struct vfs_quotactl_args args;
137 174
138 args.qc_type = QCT_PROPLIB; 175 args.qc_type = QCT_PROPLIB;
139 args.u.proplib.qc_cmddict = cmddict; 176 args.u.proplib.qc_cmddict = cmddict;
140 args.u.proplib.qc_q2type = q2type; 177 args.u.proplib.qc_q2type = q2type;
141 args.u.proplib.qc_datas = datas; 178 args.u.proplib.qc_datas = datas;
142 return VFS_QUOTACTL(mp, QUOTACTL_GET, &args); 179 return VFS_QUOTACTL(mp, QUOTACTL_GET, &args);
143} 180}
144 181
145static int 182static int
146vfs_quotactl_set(struct mount *mp, 183vfs_quotactl_set(struct mount *mp,
147 prop_dictionary_t cmddict, int q2type, 184 prop_dictionary_t cmddict, int q2type,
148 prop_array_t datas) 185 prop_array_t datas)
149{ 186{
150 struct vfs_quotactl_args args; 187 struct vfs_quotactl_args args;
151 188
152 args.qc_type = QCT_PROPLIB; 189 args.qc_type = QCT_PROPLIB;
153 args.u.proplib.qc_cmddict = cmddict; 190 args.u.proplib.qc_cmddict = cmddict;
154 args.u.proplib.qc_q2type = q2type; 191 args.u.proplib.qc_q2type = q2type;
155 args.u.proplib.qc_datas = datas; 192 args.u.proplib.qc_datas = datas;
156 return VFS_QUOTACTL(mp, QUOTACTL_SET, &args); 193 return VFS_QUOTACTL(mp, QUOTACTL_SET, &args);
157} 194}
158 195
159static int 196static int
160vfs_quotactl_getall(struct mount *mp, 197vfs_quotactl_getall(struct mount *mp,
161 prop_dictionary_t cmddict, int q2type, 198 prop_dictionary_t cmddict, int q2type,
162 prop_array_t datas) 199 prop_array_t datas)
163{ 200{
164 struct vfs_quotactl_args args; 201 struct vfs_quotactl_args args;
165 202
166 args.qc_type = QCT_PROPLIB; 203 args.qc_type = QCT_PROPLIB;
167 args.u.proplib.qc_cmddict = cmddict; 204 args.u.proplib.qc_cmddict = cmddict;
168 args.u.proplib.qc_q2type = q2type; 205 args.u.proplib.qc_q2type = q2type;
169 args.u.proplib.qc_datas = datas; 206 args.u.proplib.qc_datas = datas;
170 return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args); 207 return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args);
171} 208}
172 209
173static int 210static int
174vfs_quotactl_clear(struct mount *mp, 211vfs_quotactl_clear(struct mount *mp,
175 prop_dictionary_t cmddict, int q2type, 212 prop_dictionary_t cmddict, int q2type,
176 prop_array_t datas) 213 prop_array_t datas)
177{ 214{
178 struct vfs_quotactl_args args; 215 struct vfs_quotactl_args args;
179 216
180 args.qc_type = QCT_PROPLIB; 217 args.qc_type = QCT_PROPLIB;
181 args.u.proplib.qc_cmddict = cmddict; 218 args.u.proplib.qc_cmddict = cmddict;
182 args.u.proplib.qc_q2type = q2type; 219 args.u.proplib.qc_q2type = q2type;
183 args.u.proplib.qc_datas = datas; 220 args.u.proplib.qc_datas = datas;
184 return VFS_QUOTACTL(mp, QUOTACTL_CLEAR, &args); 221 return VFS_QUOTACTL(mp, QUOTACTL_CLEAR, &args);
185} 222}
186 223
187static int 224static int
188vfs_quotactl_cmd(struct mount *mp, prop_dictionary_t cmddict) 225vfs_quotactl_cmd(struct mount *mp, prop_dictionary_t cmddict)
189{ 226{
190 int error; 227 int error;
191 const char *cmd, *type; 228 const char *cmd, *type;
192 prop_array_t datas; 229 prop_array_t datas;
193 int q2type; 230 int q2type;
194 231
195 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd)) 232 if (!prop_dictionary_get_cstring_nocopy(cmddict, "command", &cmd))
196 return EINVAL; 233 return EINVAL;
197 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type)) 234 if (!prop_dictionary_get_cstring_nocopy(cmddict, "type", &type))
198 return EINVAL; 235 return EINVAL;
199 236
200 if (!strcmp(type, QUOTADICT_CLASS_USER)) { 237 if (!strcmp(type, QUOTADICT_CLASS_USER)) {
201 q2type = QUOTA_CLASS_USER; 238 q2type = QUOTA_CLASS_USER;
202 } else if (!strcmp(type, QUOTADICT_CLASS_GROUP)) { 239 } else if (!strcmp(type, QUOTADICT_CLASS_GROUP)) {
203 q2type = QUOTA_CLASS_GROUP; 240 q2type = QUOTA_CLASS_GROUP;
204 } else { 241 } else {
205 /* XXX this is a bad errno for this case */ 242 /* XXX this is a bad errno for this case */
206 return EOPNOTSUPP; 243 return EOPNOTSUPP;
207 } 244 }
208 245
209 datas = prop_dictionary_get(cmddict, "data"); 246 datas = prop_dictionary_get(cmddict, "data");
210 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY) 247 if (datas == NULL || prop_object_type(datas) != PROP_TYPE_ARRAY)
211 return EINVAL; 248 return EINVAL;
212 249
213 prop_object_retain(datas); 250 prop_object_retain(datas);
214 prop_dictionary_remove(cmddict, "data"); /* prepare for return */ 251 prop_dictionary_remove(cmddict, "data"); /* prepare for return */
215 252
216 if (strcmp(cmd, "get version") == 0) { 253 if (strcmp(cmd, "get version") == 0) {
217 error = vfs_quotactl_getversion(mp, cmddict, q2type, datas); 254 error = vfs_quotactl_getversion(mp, cmddict, q2type, datas);
218 } else if (strcmp(cmd, "quotaon") == 0) { 255 } else if (strcmp(cmd, "quotaon") == 0) {
219 error = vfs_quotactl_quotaon(mp, cmddict, q2type, datas); 256 error = vfs_quotactl_quotaon(mp, cmddict, q2type, datas);
220 } else if (strcmp(cmd, "quotaoff") == 0) { 257 } else if (strcmp(cmd, "quotaoff") == 0) {
221 error = vfs_quotactl_quotaoff(mp, cmddict, q2type, datas); 258 error = vfs_quotactl_quotaoff(mp, cmddict, q2type, datas);
222 } else if (strcmp(cmd, "get") == 0) { 259 } else if (strcmp(cmd, "get") == 0) {
223 error = vfs_quotactl_get(mp, cmddict, q2type, datas); 260 error = vfs_quotactl_get(mp, cmddict, q2type, datas);
224 } else if (strcmp(cmd, "set") == 0) { 261 } else if (strcmp(cmd, "set") == 0) {
225 error = vfs_quotactl_set(mp, cmddict, q2type, datas); 262 error = vfs_quotactl_set(mp, cmddict, q2type, datas);
226 } else if (strcmp(cmd, "getall") == 0) { 263 } else if (strcmp(cmd, "getall") == 0) {
227 error = vfs_quotactl_getall(mp, cmddict, q2type, datas); 264 error = vfs_quotactl_getall(mp, cmddict, q2type, datas);
228 } else if (strcmp(cmd, "clear") == 0) { 265 } else if (strcmp(cmd, "clear") == 0) {
229 error = vfs_quotactl_clear(mp, cmddict, q2type, datas); 266 error = vfs_quotactl_clear(mp, cmddict, q2type, datas);
230 } else { 267 } else {
231 /* XXX this a bad errno for this case */ 268 /* XXX this a bad errno for this case */
232 error = EOPNOTSUPP; 269 error = EOPNOTSUPP;
233 } 270 }
234 271
235 error = (prop_dictionary_set_int8(cmddict, "return", 272 error = (prop_dictionary_set_int8(cmddict, "return",
236 error) ? 0 : ENOMEM); 273 error) ? 0 : ENOMEM);
237 prop_object_release(datas); 274 prop_object_release(datas);
238 275
239 return error; 276 return error;
240} 277}
241 278
242int 279int
243vfs_quotactl(struct mount *mp, prop_dictionary_t dict) 280vfs_quotactl(struct mount *mp, prop_dictionary_t dict)
244{ 281{
245 prop_dictionary_t cmddict; 282 prop_dictionary_t cmddict;
246 prop_array_t commands; 283 prop_array_t commands;
247 prop_object_iterator_t iter; 284 prop_object_iterator_t iter;
248 int error; 285 int error;
249 286
250 error = quota_get_cmds(dict, &commands); 287 error = quota_get_cmds(dict, &commands);
251 if (error) { 288 if (error) {
252 return error; 289 return error;
253 } 290 }
254 291
255 iter = prop_array_iterator(commands); 292 iter = prop_array_iterator(commands);
256 if (iter == NULL) { 293 if (iter == NULL) {
257 return ENOMEM; 294 return ENOMEM;
258 } 295 }
259 296
260 while ((cmddict = prop_object_iterator_next(iter)) != NULL) { 297 while ((cmddict = prop_object_iterator_next(iter)) != NULL) {
261 if (prop_object_type(cmddict) != PROP_TYPE_DICTIONARY) { 298 if (prop_object_type(cmddict) != PROP_TYPE_DICTIONARY) {
262 /* XXX shouldn't this be an error? */ 299 /* XXX shouldn't this be an error? */
263 continue; 300 continue;
264 } 301 }
265 error = vfs_quotactl_cmd(mp, cmddict); 302 error = vfs_quotactl_cmd(mp, cmddict);
266 if (error) { 303 if (error) {
267 break; 304 break;
268 } 305 }
269 } 306 }
270 prop_object_iterator_release(iter); 307 prop_object_iterator_release(iter);
271 return error; 308 return error;
272} 309}

cvs diff -r1.3 -r1.4 src/sys/sys/quotactl.h (switch to unified diff)

--- src/sys/sys/quotactl.h 2012/01/29 06:36:06 1.3
+++ src/sys/sys/quotactl.h 2012/01/29 06:36:50 1.4
@@ -1,64 +1,68 @@ @@ -1,64 +1,68 @@
1/* $NetBSD: quotactl.h,v 1.3 2012/01/29 06:36:06 dholland Exp $ */ 1/* $NetBSD: quotactl.h,v 1.4 2012/01/29 06:36:50 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, /* getversion, quotaon/off, get, set, getall, clear */ 51 QCT_PROPLIB, /* quotaon/off, get, set, getall, clear */
 52 QCT_GETVERSION, /* getversion */
52}; 53};
53struct vfs_quotactl_args { 54struct vfs_quotactl_args {
54 enum vfs_quotactl_argtypes qc_type; 55 enum vfs_quotactl_argtypes qc_type;
55 union { 56 union {
56 struct { 57 struct {
57 prop_dictionary_t qc_cmddict; 58 prop_dictionary_t qc_cmddict;
58 int qc_q2type; 59 int qc_q2type;
59 prop_array_t qc_datas; 60 prop_array_t qc_datas;
60 } proplib; 61 } proplib;
 62 struct {
 63 int *qc_version_ret;
 64 } getversion;
61 } u; 65 } u;
62}; 66};
63 67
64#endif /* _SYS_QUOTACTL_H_ */ 68#endif /* _SYS_QUOTACTL_H_ */

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

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