Sun Jan 29 06:50:54 2012 UTC ()
Tidy up a bit.


(dholland)
diff -r1.86 -r1.87 src/sys/ufs/ufs/ufs_quota.c

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

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