Sun Jan 29 06:46:50 2012 UTC ()
For QUOTACTL_SET in quota2, use the quotaval data instead of proplib.


(dholland)
diff -r1.81 -r1.82 src/sys/ufs/ufs/ufs_quota.c
diff -r1.6 -r1.7 src/sys/ufs/ufs/ufs_quota.h
diff -r1.7 -r1.8 src/sys/ufs/ufs/ufs_quota2.c

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

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

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

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

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

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