1 /* $NetBSD: ulfs_quota.c,v 1.12 2014/06/28 22:27:51 dholland Exp $ */
2 /* from NetBSD: ufs_quota.c,v 1.115 2013/11/16 17:04:53 dholland Exp */
5 * Copyright (c) 1982, 1986, 1990, 1993, 1995
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
9 * Robert Elz at The University of Melbourne.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: ulfs_quota.c,v 1.12 2014/06/28 22:27:51 dholland Exp $");
41 #if defined(_KERNEL_OPT)
42 #include "opt_quota.h"
44 #include <sys/param.h>
45 #include <sys/kernel.h>
46 #include <sys/systm.h>
47 #include <sys/namei.h>
50 #include <sys/vnode.h>
51 #include <sys/mount.h>
52 #include <sys/kauth.h>
54 #include <sys/quotactl.h>
55 #include <ufs/lfs/ulfs_quotacommon.h>
56 #include <ufs/lfs/ulfs_inode.h>
57 #include <ufs/lfs/ulfsmount.h>
58 #include <ufs/lfs/ulfs_extern.h>
59 #include <ufs/lfs/ulfs_quota.h>
63 const char *lfs_quotatypes
[ULFS_MAXQUOTAS
] = INITQFNAMES
;
66 * Code pertaining to management of the in-core dquot data structures.
68 #define DQHASH(dqvp, id) \
69 (((((long)(dqvp)) >> 8) + id) & dqhash)
70 static LIST_HEAD(dqhashhead
, dquot
) *dqhashtbl
;
72 static pool_cache_t dquot_cache
;
75 static int quota_handle_cmd_stat(struct mount
*, struct lwp
*,
76 struct quotactl_args
*args
);
77 static int quota_handle_cmd_idtypestat(struct mount
*, struct lwp
*,
78 struct quotactl_args
*args
);
79 static int quota_handle_cmd_objtypestat(struct mount
*, struct lwp
*,
80 struct quotactl_args
*args
);
81 static int quota_handle_cmd_get(struct mount
*, struct lwp
*,
82 struct quotactl_args
*args
);
83 static int quota_handle_cmd_put(struct mount
*, struct lwp
*,
84 struct quotactl_args
*args
);
85 static int quota_handle_cmd_cursorget(struct mount
*, struct lwp
*,
86 struct quotactl_args
*args
);
87 static int quota_handle_cmd_del(struct mount
*, struct lwp
*,
88 struct quotactl_args
*args
);
89 static int quota_handle_cmd_quotaon(struct mount
*, struct lwp
*,
90 struct quotactl_args
*args
);
91 static int quota_handle_cmd_quotaoff(struct mount
*, struct lwp
*,
92 struct quotactl_args
*args
);
93 static int quota_handle_cmd_cursoropen(struct mount
*, struct lwp
*,
94 struct quotactl_args
*args
);
95 static int quota_handle_cmd_cursorclose(struct mount
*, struct lwp
*,
96 struct quotactl_args
*args
);
97 static int quota_handle_cmd_cursorskipidtype(struct mount
*, struct lwp
*,
98 struct quotactl_args
*args
);
99 static int quota_handle_cmd_cursoratend(struct mount
*, struct lwp
*,
100 struct quotactl_args
*args
);
101 static int quota_handle_cmd_cursorrewind(struct mount
*, struct lwp
*,
102 struct quotactl_args
*args
);
105 * Initialize the quota fields of an inode.
108 ulfsquota_init(struct inode
*ip
)
112 for (i
= 0; i
< ULFS_MAXQUOTAS
; i
++)
113 ip
->i_dquot
[i
] = NODQUOT
;
117 * Release the quota fields from an inode.
120 ulfsquota_free(struct inode
*ip
)
124 for (i
= 0; i
< ULFS_MAXQUOTAS
; i
++) {
125 lfs_dqrele(ITOV(ip
), ip
->i_dquot
[i
]);
126 ip
->i_dquot
[i
] = NODQUOT
;
131 * Update disk usage, and take corrective action.
134 lfs_chkdq(struct inode
*ip
, int64_t change
, kauth_cred_t cred
, int flags
)
136 /* do not track snapshot usage, or we will deadlock */
137 if ((ip
->i_flags
& SF_SNAPSHOT
) != 0)
141 if (ip
->i_lfs
->um_flags
& ULFS_QUOTA
)
142 return lfs_chkdq1(ip
, change
, cred
, flags
);
145 if (ip
->i_lfs
->um_flags
& ULFS_QUOTA2
)
146 return lfs_chkdq2(ip
, change
, cred
, flags
);
152 * Check the inode limit, applying corrective action.
155 lfs_chkiq(struct inode
*ip
, int32_t change
, kauth_cred_t cred
, int flags
)
157 /* do not track snapshot usage, or we will deadlock */
158 if ((ip
->i_flags
& SF_SNAPSHOT
) != 0)
161 if (ip
->i_lfs
->um_flags
& ULFS_QUOTA
)
162 return lfs_chkiq1(ip
, change
, cred
, flags
);
165 if (ip
->i_lfs
->um_flags
& ULFS_QUOTA2
)
166 return lfs_chkiq2(ip
, change
, cred
, flags
);
172 lfsquota_handle_cmd(struct mount
*mp
, struct lwp
*l
,
173 struct quotactl_args
*args
)
177 switch (args
->qc_op
) {
179 error
= quota_handle_cmd_stat(mp
, l
, args
);
181 case QUOTACTL_IDTYPESTAT
:
182 error
= quota_handle_cmd_idtypestat(mp
, l
, args
);
184 case QUOTACTL_OBJTYPESTAT
:
185 error
= quota_handle_cmd_objtypestat(mp
, l
, args
);
187 case QUOTACTL_QUOTAON
:
188 error
= quota_handle_cmd_quotaon(mp
, l
, args
);
190 case QUOTACTL_QUOTAOFF
:
191 error
= quota_handle_cmd_quotaoff(mp
, l
, args
);
194 error
= quota_handle_cmd_get(mp
, l
, args
);
197 error
= quota_handle_cmd_put(mp
, l
, args
);
199 case QUOTACTL_CURSORGET
:
200 error
= quota_handle_cmd_cursorget(mp
, l
, args
);
203 error
= quota_handle_cmd_del(mp
, l
, args
);
205 case QUOTACTL_CURSOROPEN
:
206 error
= quota_handle_cmd_cursoropen(mp
, l
, args
);
208 case QUOTACTL_CURSORCLOSE
:
209 error
= quota_handle_cmd_cursorclose(mp
, l
, args
);
211 case QUOTACTL_CURSORSKIPIDTYPE
:
212 error
= quota_handle_cmd_cursorskipidtype(mp
, l
, args
);
214 case QUOTACTL_CURSORATEND
:
215 error
= quota_handle_cmd_cursoratend(mp
, l
, args
);
217 case QUOTACTL_CURSORREWIND
:
218 error
= quota_handle_cmd_cursorrewind(mp
, l
, args
);
221 panic("Invalid quotactl operation %d\n", args
->qc_op
);
228 quota_handle_cmd_stat(struct mount
*mp
, struct lwp
*l
,
229 struct quotactl_args
*args
)
231 struct ulfsmount
*ump
= VFSTOULFS(mp
);
232 struct lfs
*fs
= ump
->um_lfs
;
234 KASSERT(args
->qc_op
== QUOTACTL_STAT
);
236 if ((fs
->um_flags
& (ULFS_QUOTA
|ULFS_QUOTA2
)) == 0)
240 if (fs
->um_flags
& ULFS_QUOTA
) {
241 struct quotastat
*info
= args
->u
.stat
.qc_info
;
242 strcpy(info
->qs_implname
, "lfs quota v1");
243 info
->qs_numidtypes
= ULFS_MAXQUOTAS
;
244 /* XXX no define for this */
245 info
->qs_numobjtypes
= 2;
246 info
->qs_restrictions
= 0;
247 info
->qs_restrictions
|= QUOTA_RESTRICT_NEEDSQUOTACHECK
;
248 info
->qs_restrictions
|= QUOTA_RESTRICT_UNIFORMGRACE
;
249 info
->qs_restrictions
|= QUOTA_RESTRICT_32BIT
;
253 if (fs
->um_flags
& ULFS_QUOTA2
) {
254 struct quotastat
*info
= args
->u
.stat
.qc_info
;
255 strcpy(info
->qs_implname
, "lfs quota v2");
256 info
->qs_numidtypes
= ULFS_MAXQUOTAS
;
257 info
->qs_numobjtypes
= N_QL
;
258 info
->qs_restrictions
= 0;
267 quota_handle_cmd_idtypestat(struct mount
*mp
, struct lwp
*l
,
268 struct quotactl_args
*args
)
270 struct ulfsmount
*ump
= VFSTOULFS(mp
);
271 struct lfs
*fs
= ump
->um_lfs
;
273 struct quotaidtypestat
*info
;
276 KASSERT(args
->qc_op
== QUOTACTL_IDTYPESTAT
);
277 idtype
= args
->u
.idtypestat
.qc_idtype
;
278 info
= args
->u
.idtypestat
.qc_info
;
280 if ((fs
->um_flags
& (ULFS_QUOTA
|ULFS_QUOTA2
)) == 0)
284 * These are the same for both QUOTA and QUOTA2.
287 case QUOTA_IDTYPE_USER
:
290 case QUOTA_IDTYPE_GROUP
:
296 strlcpy(info
->qis_name
, name
, sizeof(info
->qis_name
));
301 quota_handle_cmd_objtypestat(struct mount
*mp
, struct lwp
*l
,
302 struct quotactl_args
*args
)
304 struct ulfsmount
*ump
= VFSTOULFS(mp
);
305 struct lfs
*fs
= ump
->um_lfs
;
307 struct quotaobjtypestat
*info
;
311 KASSERT(args
->qc_op
== QUOTACTL_OBJTYPESTAT
);
312 objtype
= args
->u
.objtypestat
.qc_objtype
;
313 info
= args
->u
.objtypestat
.qc_info
;
315 if ((fs
->um_flags
& (ULFS_QUOTA
|ULFS_QUOTA2
)) == 0)
319 * These are the same for both QUOTA and QUOTA2.
322 case QUOTA_OBJTYPE_BLOCKS
:
326 case QUOTA_OBJTYPE_FILES
:
333 strlcpy(info
->qos_name
, name
, sizeof(info
->qos_name
));
334 info
->qos_isbytes
= isbytes
;
338 /* XXX shouldn't all this be in kauth ? */
340 quota_get_auth(struct mount
*mp
, struct lwp
*l
, uid_t id
) {
341 /* The user can always query about his own quota. */
342 if (id
== kauth_cred_geteuid(l
->l_cred
))
344 return kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FS_QUOTA
,
345 KAUTH_REQ_SYSTEM_FS_QUOTA_GET
, mp
, KAUTH_ARG(id
), NULL
);
349 quota_handle_cmd_get(struct mount
*mp
, struct lwp
*l
,
350 struct quotactl_args
*args
)
352 struct ulfsmount
*ump
= VFSTOULFS(mp
);
353 struct lfs
*fs
= ump
->um_lfs
;
355 const struct quotakey
*qk
;
357 KASSERT(args
->qc_op
== QUOTACTL_GET
);
358 qk
= args
->u
.get
.qc_key
;
360 if ((fs
->um_flags
& (ULFS_QUOTA
|ULFS_QUOTA2
)) == 0)
363 error
= quota_get_auth(mp
, l
, qk
->qk_id
);
367 if (fs
->um_flags
& ULFS_QUOTA
) {
368 struct quotaval
*qv
= args
->u
.get
.qc_val
;
369 error
= lfsquota1_handle_cmd_get(ump
, qk
, qv
);
373 if (fs
->um_flags
& ULFS_QUOTA2
) {
374 struct quotaval
*qv
= args
->u
.get
.qc_val
;
375 error
= lfsquota2_handle_cmd_get(ump
, qk
, qv
);
378 panic("quota_handle_cmd_get: no support ?");
387 quota_handle_cmd_put(struct mount
*mp
, struct lwp
*l
,
388 struct quotactl_args
*args
)
390 struct ulfsmount
*ump
= VFSTOULFS(mp
);
391 struct lfs
*fs
= ump
->um_lfs
;
392 const struct quotakey
*qk
;
396 KASSERT(args
->qc_op
== QUOTACTL_PUT
);
397 qk
= args
->u
.put
.qc_key
;
399 if ((fs
->um_flags
& (ULFS_QUOTA
|ULFS_QUOTA2
)) == 0)
402 kauth_id
= qk
->qk_id
;
403 if (kauth_id
== QUOTA_DEFAULTID
) {
407 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FS_QUOTA
,
408 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE
, mp
, KAUTH_ARG(kauth_id
),
415 if (fs
->um_flags
& ULFS_QUOTA
) {
416 const struct quotaval
*qv
= args
->u
.put
.qc_val
;
417 error
= lfsquota1_handle_cmd_put(ump
, qk
, qv
);
421 if (fs
->um_flags
& ULFS_QUOTA2
) {
422 const struct quotaval
*qv
= args
->u
.put
.qc_val
;
423 error
= lfsquota2_handle_cmd_put(ump
, qk
, qv
);
426 panic("quota_handle_cmd_get: no support ?");
428 if (error
== ENOENT
) {
436 quota_handle_cmd_del(struct mount
*mp
, struct lwp
*l
,
437 struct quotactl_args
*args
)
439 struct ulfsmount
*ump
= VFSTOULFS(mp
);
440 struct lfs
*fs
= ump
->um_lfs
;
441 const struct quotakey
*qk
;
445 KASSERT(args
->qc_op
== QUOTACTL_DEL
);
446 qk
= args
->u
.del
.qc_key
;
448 kauth_id
= qk
->qk_id
;
449 if (kauth_id
== QUOTA_DEFAULTID
) {
453 if ((fs
->um_flags
& ULFS_QUOTA2
) == 0)
456 /* avoid whitespace changes */
458 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FS_QUOTA
,
459 KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE
, mp
, KAUTH_ARG(kauth_id
),
464 if (fs
->um_flags
& ULFS_QUOTA2
) {
465 error
= lfsquota2_handle_cmd_del(ump
, qk
);
468 panic("quota_handle_cmd_get: no support ?");
470 if (error
&& error
!= ENOENT
)
480 quota_handle_cmd_cursorget(struct mount
*mp
, struct lwp
*l
,
481 struct quotactl_args
*args
)
483 struct ulfsmount
*ump
= VFSTOULFS(mp
);
484 struct lfs
*fs
= ump
->um_lfs
;
487 KASSERT(args
->qc_op
== QUOTACTL_CURSORGET
);
489 if ((fs
->um_flags
& ULFS_QUOTA2
) == 0)
492 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FS_QUOTA
,
493 KAUTH_REQ_SYSTEM_FS_QUOTA_GET
, mp
, NULL
, NULL
);
498 if (fs
->um_flags
& ULFS_QUOTA2
) {
499 struct quotakcursor
*cursor
= args
->u
.cursorget
.qc_cursor
;
500 struct quotakey
*keys
= args
->u
.cursorget
.qc_keys
;
501 struct quotaval
*vals
= args
->u
.cursorget
.qc_vals
;
502 unsigned maxnum
= args
->u
.cursorget
.qc_maxnum
;
503 unsigned *ret
= args
->u
.cursorget
.qc_ret
;
505 error
= lfsquota2_handle_cmd_cursorget(ump
, cursor
, keys
, vals
,
509 panic("quota_handle_cmd_cursorget: no support ?");
515 quota_handle_cmd_cursoropen(struct mount
*mp
, struct lwp
*l
,
516 struct quotactl_args
*args
)
519 struct ulfsmount
*ump
= VFSTOULFS(mp
);
520 struct lfs
*fs
= ump
->um_lfs
;
521 struct quotakcursor
*cursor
;
525 KASSERT(args
->qc_op
== QUOTACTL_CURSOROPEN
);
527 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FS_QUOTA
,
528 KAUTH_REQ_SYSTEM_FS_QUOTA_GET
, mp
, NULL
, NULL
);
533 if (fs
->um_flags
& ULFS_QUOTA2
) {
534 cursor
= args
->u
.cursoropen
.qc_cursor
;
535 error
= lfsquota2_handle_cmd_cursoropen(ump
, cursor
);
544 quota_handle_cmd_cursorclose(struct mount
*mp
, struct lwp
*l
,
545 struct quotactl_args
*args
)
548 struct ulfsmount
*ump
= VFSTOULFS(mp
);
549 struct lfs
*fs
= ump
->um_lfs
;
553 KASSERT(args
->qc_op
== QUOTACTL_CURSORCLOSE
);
555 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FS_QUOTA
,
556 KAUTH_REQ_SYSTEM_FS_QUOTA_GET
, mp
, NULL
, NULL
);
561 if (fs
->um_flags
& ULFS_QUOTA2
) {
562 struct quotakcursor
*cursor
= args
->u
.cursorclose
.qc_cursor
;
563 error
= lfsquota2_handle_cmd_cursorclose(ump
, cursor
);
572 quota_handle_cmd_cursorskipidtype(struct mount
*mp
, struct lwp
*l
,
573 struct quotactl_args
*args
)
576 struct ulfsmount
*ump
= VFSTOULFS(mp
);
577 struct lfs
*fs
= ump
->um_lfs
;
581 KASSERT(args
->qc_op
== QUOTACTL_CURSORSKIPIDTYPE
);
584 if (fs
->um_flags
& ULFS_QUOTA2
) {
585 struct quotakcursor
*cursor
= args
->u
.cursorskipidtype
.qc_cursor
;
586 int idtype
= args
->u
.cursorskipidtype
.qc_idtype
;
587 error
= lfsquota2_handle_cmd_cursorskipidtype(ump
, cursor
, idtype
);
596 quota_handle_cmd_cursoratend(struct mount
*mp
, struct lwp
*l
,
597 struct quotactl_args
*args
)
600 struct ulfsmount
*ump
= VFSTOULFS(mp
);
601 struct lfs
*fs
= ump
->um_lfs
;
605 KASSERT(args
->qc_op
== QUOTACTL_CURSORATEND
);
608 if (fs
->um_flags
& ULFS_QUOTA2
) {
609 struct quotakcursor
*cursor
= args
->u
.cursoratend
.qc_cursor
;
610 int *ret
= args
->u
.cursoratend
.qc_ret
;
611 error
= lfsquota2_handle_cmd_cursoratend(ump
, cursor
, ret
);
620 quota_handle_cmd_cursorrewind(struct mount
*mp
, struct lwp
*l
,
621 struct quotactl_args
*args
)
624 struct ulfsmount
*ump
= VFSTOULFS(mp
);
625 struct lfs
*fs
= ump
->um_lfs
;
629 KASSERT(args
->qc_op
== QUOTACTL_CURSORREWIND
);
632 if (fs
->um_flags
& ULFS_QUOTA2
) {
633 struct quotakcursor
*cursor
= args
->u
.cursorrewind
.qc_cursor
;
634 error
= lfsquota2_handle_cmd_cursorrewind(ump
, cursor
);
643 quota_handle_cmd_quotaon(struct mount
*mp
, struct lwp
*l
,
644 struct quotactl_args
*args
)
646 struct ulfsmount
*ump
= VFSTOULFS(mp
);
647 struct lfs
*fs
= ump
->um_lfs
;
650 KASSERT(args
->qc_op
== QUOTACTL_QUOTAON
);
652 if ((fs
->um_flags
& ULFS_QUOTA2
) != 0)
655 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FS_QUOTA
,
656 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF
, mp
, NULL
, NULL
);
661 int idtype
= args
->u
.quotaon
.qc_idtype
;
662 const char *qfile
= args
->u
.quotaon
.qc_quotafile
;
663 error
= lfsquota1_handle_cmd_quotaon(l
, ump
, idtype
, qfile
);
672 quota_handle_cmd_quotaoff(struct mount
*mp
, struct lwp
*l
,
673 struct quotactl_args
*args
)
675 struct ulfsmount
*ump
= VFSTOULFS(mp
);
676 struct lfs
*fs
= ump
->um_lfs
;
679 KASSERT(args
->qc_op
== QUOTACTL_QUOTAOFF
);
681 if ((fs
->um_flags
& ULFS_QUOTA2
) != 0)
684 error
= kauth_authorize_system(l
->l_cred
, KAUTH_SYSTEM_FS_QUOTA
,
685 KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF
, mp
, NULL
, NULL
);
690 int idtype
= args
->u
.quotaoff
.qc_idtype
;
691 error
= lfsquota1_handle_cmd_quotaoff(l
, ump
, idtype
);
700 * Initialize the quota system.
706 mutex_init(&lfs_dqlock
, MUTEX_DEFAULT
, IPL_NONE
);
707 cv_init(&lfs_dqcv
, "quota");
708 dqhashtbl
= hashinit(desiredvnodes
, HASH_LIST
, true, &dqhash
);
709 dquot_cache
= pool_cache_init(sizeof(struct dquot
), 0, 0, 0, "lfsdq",
710 NULL
, IPL_NONE
, NULL
, NULL
, NULL
);
717 struct dqhashhead
*oldhash
, *hash
;
719 u_long oldmask
, mask
, hashval
;
722 hash
= hashinit(desiredvnodes
, HASH_LIST
, true, &mask
);
723 mutex_enter(&lfs_dqlock
);
728 for (i
= 0; i
<= oldmask
; i
++) {
729 while ((dq
= LIST_FIRST(&oldhash
[i
])) != NULL
) {
730 dqvp
= dq
->dq_ump
->um_quotas
[dq
->dq_type
];
731 LIST_REMOVE(dq
, dq_hash
);
732 hashval
= DQHASH(dqvp
, dq
->dq_id
);
733 LIST_INSERT_HEAD(&dqhashtbl
[hashval
], dq
, dq_hash
);
736 mutex_exit(&lfs_dqlock
);
737 hashdone(oldhash
, HASH_LIST
, oldmask
);
741 * Free resources held by quota system.
747 pool_cache_destroy(dquot_cache
);
748 hashdone(dqhashtbl
, HASH_LIST
, dqhash
);
749 cv_destroy(&lfs_dqcv
);
750 mutex_destroy(&lfs_dqlock
);
754 * Set up the quotas for an inode.
756 * This routine completely defines the semantics of quotas.
757 * If other criteria want to be used to establish quotas, the
758 * ULFS_MAXQUOTAS value in quotas.h should be increased, and the
759 * additional dquots set up here.
762 lfs_getinoquota(struct inode
*ip
)
764 struct ulfsmount
*ump
= ip
->i_ump
;
765 //struct lfs *fs = ump->um_lfs; // notyet
766 struct vnode
*vp
= ITOV(ip
);
768 u_int32_t ino_ids
[ULFS_MAXQUOTAS
];
771 * To avoid deadlocks never update quotas for quota files
772 * on the same file system
774 for (i
= 0; i
< ULFS_MAXQUOTAS
; i
++)
775 if (vp
== ump
->um_quotas
[i
])
778 ino_ids
[ULFS_USRQUOTA
] = ip
->i_uid
;
779 ino_ids
[ULFS_GRPQUOTA
] = ip
->i_gid
;
780 for (i
= 0; i
< ULFS_MAXQUOTAS
; i
++) {
782 * If the file id changed the quota needs update.
784 if (ip
->i_dquot
[i
] != NODQUOT
&&
785 ip
->i_dquot
[i
]->dq_id
!= ino_ids
[i
]) {
786 lfs_dqrele(ITOV(ip
), ip
->i_dquot
[i
]);
787 ip
->i_dquot
[i
] = NODQUOT
;
790 * Set up the quota based on file id.
791 * ENODEV means that quotas are not enabled.
793 if (ip
->i_dquot
[i
] == NODQUOT
&&
794 (error
= lfs_dqget(vp
, ino_ids
[i
], ump
, i
, &ip
->i_dquot
[i
])) &&
802 * Obtain a dquot structure for the specified identifier and quota file
803 * reading the information from the file if necessary.
806 lfs_dqget(struct vnode
*vp
, u_long id
, struct ulfsmount
*ump
, int type
,
809 struct lfs
*fs
= ump
->um_lfs
;
810 struct dquot
*dq
, *ndq
;
811 struct dqhashhead
*dqh
;
813 int error
= 0; /* XXX gcc */
815 /* Lock to see an up to date value for QTF_CLOSING. */
816 mutex_enter(&lfs_dqlock
);
817 if ((fs
->um_flags
& (ULFS_QUOTA
|ULFS_QUOTA2
)) == 0) {
818 mutex_exit(&lfs_dqlock
);
822 dqvp
= ump
->um_quotas
[type
];
824 if (fs
->um_flags
& ULFS_QUOTA
) {
825 if (dqvp
== NULLVP
|| (ump
->umq1_qflags
[type
] & QTF_CLOSING
)) {
826 mutex_exit(&lfs_dqlock
);
833 if (fs
->um_flags
& ULFS_QUOTA2
) {
834 if (dqvp
== NULLVP
) {
835 mutex_exit(&lfs_dqlock
);
843 * Check the cache first.
845 dqh
= &dqhashtbl
[DQHASH(dqvp
, id
)];
846 LIST_FOREACH(dq
, dqh
, dq_hash
) {
847 if (dq
->dq_id
!= id
||
848 dq
->dq_ump
->um_quotas
[dq
->dq_type
] != dqvp
)
850 KASSERT(dq
->dq_cnt
> 0);
852 mutex_exit(&lfs_dqlock
);
857 * Not in cache, allocate a new one.
859 mutex_exit(&lfs_dqlock
);
860 ndq
= pool_cache_get(dquot_cache
, PR_WAITOK
);
862 * Initialize the contents of the dquot structure.
864 memset((char *)ndq
, 0, sizeof *ndq
);
869 mutex_init(&ndq
->dq_interlock
, MUTEX_DEFAULT
, IPL_NONE
);
870 mutex_enter(&lfs_dqlock
);
871 dqh
= &dqhashtbl
[DQHASH(dqvp
, id
)];
872 LIST_FOREACH(dq
, dqh
, dq_hash
) {
873 if (dq
->dq_id
!= id
||
874 dq
->dq_ump
->um_quotas
[dq
->dq_type
] != dqvp
)
877 * Another thread beat us allocating this dquot.
879 KASSERT(dq
->dq_cnt
> 0);
881 mutex_exit(&lfs_dqlock
);
882 mutex_destroy(&ndq
->dq_interlock
);
883 pool_cache_put(dquot_cache
, ndq
);
888 LIST_INSERT_HEAD(dqh
, dq
, dq_hash
);
890 mutex_enter(&dq
->dq_interlock
);
891 mutex_exit(&lfs_dqlock
);
893 if (fs
->um_flags
& ULFS_QUOTA
)
894 error
= lfs_dq1get(dqvp
, id
, ump
, type
, dq
);
897 if (fs
->um_flags
& ULFS_QUOTA2
)
898 error
= lfs_dq2get(dqvp
, id
, ump
, type
, dq
);
901 * I/O error in reading quota file, release
902 * quota structure and reflect problem to caller.
905 mutex_enter(&lfs_dqlock
);
906 LIST_REMOVE(dq
, dq_hash
);
907 mutex_exit(&lfs_dqlock
);
908 mutex_exit(&dq
->dq_interlock
);
913 mutex_exit(&dq
->dq_interlock
);
919 * Obtain a reference to a dquot.
922 lfs_dqref(struct dquot
*dq
)
925 KASSERT(mutex_owned(&lfs_dqlock
));
927 KASSERT(dq
->dq_cnt
> 0);
931 * Release a reference to a dquot.
934 lfs_dqrele(struct vnode
*vp
, struct dquot
*dq
)
939 mutex_enter(&dq
->dq_interlock
);
941 mutex_enter(&lfs_dqlock
);
942 if (dq
->dq_cnt
> 1) {
944 mutex_exit(&lfs_dqlock
);
945 mutex_exit(&dq
->dq_interlock
);
948 if ((dq
->dq_flags
& DQ_MOD
) == 0)
950 mutex_exit(&lfs_dqlock
);
952 if (dq
->dq_ump
->um_lfs
->um_flags
& ULFS_QUOTA
)
953 (void) lfs_dq1sync(vp
, dq
);
956 if (dq
->dq_ump
->um_lfs
->um_flags
& ULFS_QUOTA2
)
957 (void) lfs_dq2sync(vp
, dq
);
960 KASSERT(dq
->dq_cnt
== 1 && (dq
->dq_flags
& DQ_MOD
) == 0);
961 LIST_REMOVE(dq
, dq_hash
);
962 mutex_exit(&lfs_dqlock
);
963 mutex_exit(&dq
->dq_interlock
);
964 mutex_destroy(&dq
->dq_interlock
);
965 pool_cache_put(dquot_cache
, dq
);
969 lfs_qsync(struct mount
*mp
)
971 struct ulfsmount
*ump
= VFSTOULFS(mp
);
972 struct lfs
*fs
= ump
->um_lfs
;
974 /* avoid compiler warning when quotas aren't enabled */
979 if (fs
->um_flags
& ULFS_QUOTA
)
980 return lfs_q1sync(mp
);
983 if (fs
->um_flags
& ULFS_QUOTA2
)
984 return lfs_q2sync(mp
);
991 * Check the hash chains for stray dquot's.
994 lfs_dqflush(struct vnode
*vp
)
999 mutex_enter(&lfs_dqlock
);
1000 for (i
= 0; i
<= dqhash
; i
++)
1001 LIST_FOREACH(dq
, &dqhashtbl
[i
], dq_hash
)
1002 KASSERT(dq
->dq_ump
->um_quotas
[dq
->dq_type
] != vp
);
1003 mutex_exit(&lfs_dqlock
);