Home | History | Annotate | Line # | Download | only in lfs
ulfs_quota.c revision 1.10.2.1
      1  1.10.2.1       tls /*	$NetBSD: ulfs_quota.c,v 1.10.2.1 2014/08/10 06:56:58 tls Exp $	*/
      2       1.9  dholland /*  from NetBSD: ufs_quota.c,v 1.115 2013/11/16 17:04:53 dholland Exp  */
      3       1.1  dholland 
      4       1.1  dholland /*
      5       1.1  dholland  * Copyright (c) 1982, 1986, 1990, 1993, 1995
      6       1.1  dholland  *	The Regents of the University of California.  All rights reserved.
      7       1.1  dholland  *
      8       1.1  dholland  * This code is derived from software contributed to Berkeley by
      9       1.1  dholland  * Robert Elz at The University of Melbourne.
     10       1.1  dholland  *
     11       1.1  dholland  * Redistribution and use in source and binary forms, with or without
     12       1.1  dholland  * modification, are permitted provided that the following conditions
     13       1.1  dholland  * are met:
     14       1.1  dholland  * 1. Redistributions of source code must retain the above copyright
     15       1.1  dholland  *    notice, this list of conditions and the following disclaimer.
     16       1.1  dholland  * 2. Redistributions in binary form must reproduce the above copyright
     17       1.1  dholland  *    notice, this list of conditions and the following disclaimer in the
     18       1.1  dholland  *    documentation and/or other materials provided with the distribution.
     19       1.1  dholland  * 3. Neither the name of the University nor the names of its contributors
     20       1.1  dholland  *    may be used to endorse or promote products derived from this software
     21       1.1  dholland  *    without specific prior written permission.
     22       1.1  dholland  *
     23       1.1  dholland  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24       1.1  dholland  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25       1.1  dholland  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26       1.1  dholland  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27       1.1  dholland  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28       1.1  dholland  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29       1.1  dholland  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30       1.1  dholland  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31       1.1  dholland  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32       1.1  dholland  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33       1.1  dholland  * SUCH DAMAGE.
     34       1.1  dholland  *
     35       1.1  dholland  *	@(#)ufs_quota.c	8.5 (Berkeley) 5/20/95
     36       1.1  dholland  */
     37       1.1  dholland 
     38       1.1  dholland #include <sys/cdefs.h>
     39  1.10.2.1       tls __KERNEL_RCSID(0, "$NetBSD: ulfs_quota.c,v 1.10.2.1 2014/08/10 06:56:58 tls Exp $");
     40       1.1  dholland 
     41       1.1  dholland #if defined(_KERNEL_OPT)
     42       1.1  dholland #include "opt_quota.h"
     43       1.1  dholland #endif
     44       1.1  dholland #include <sys/param.h>
     45       1.1  dholland #include <sys/kernel.h>
     46       1.1  dholland #include <sys/systm.h>
     47       1.1  dholland #include <sys/namei.h>
     48       1.1  dholland #include <sys/file.h>
     49       1.1  dholland #include <sys/proc.h>
     50       1.1  dholland #include <sys/vnode.h>
     51       1.1  dholland #include <sys/mount.h>
     52       1.1  dholland #include <sys/kauth.h>
     53       1.1  dholland 
     54       1.1  dholland #include <sys/quotactl.h>
     55       1.2  dholland #include <ufs/lfs/ulfs_quotacommon.h>
     56       1.2  dholland #include <ufs/lfs/ulfs_inode.h>
     57       1.2  dholland #include <ufs/lfs/ulfsmount.h>
     58       1.2  dholland #include <ufs/lfs/ulfs_extern.h>
     59       1.2  dholland #include <ufs/lfs/ulfs_quota.h>
     60       1.1  dholland 
     61       1.5  dholland kmutex_t lfs_dqlock;
     62       1.5  dholland kcondvar_t lfs_dqcv;
     63       1.5  dholland const char *lfs_quotatypes[ULFS_MAXQUOTAS] = INITQFNAMES;
     64       1.1  dholland 
     65       1.1  dholland /*
     66       1.1  dholland  * Code pertaining to management of the in-core dquot data structures.
     67       1.1  dholland  */
     68       1.1  dholland #define DQHASH(dqvp, id) \
     69       1.1  dholland 	(((((long)(dqvp)) >> 8) + id) & dqhash)
     70       1.1  dholland static LIST_HEAD(dqhashhead, dquot) *dqhashtbl;
     71       1.1  dholland static u_long dqhash;
     72       1.1  dholland static pool_cache_t dquot_cache;
     73       1.1  dholland 
     74       1.1  dholland 
     75       1.1  dholland static int quota_handle_cmd_stat(struct mount *, struct lwp *,
     76       1.1  dholland     struct quotactl_args *args);
     77       1.1  dholland static int quota_handle_cmd_idtypestat(struct mount *, struct lwp *,
     78       1.1  dholland     struct quotactl_args *args);
     79       1.1  dholland static int quota_handle_cmd_objtypestat(struct mount *, struct lwp *,
     80       1.1  dholland     struct quotactl_args *args);
     81       1.1  dholland static int quota_handle_cmd_get(struct mount *, struct lwp *,
     82       1.1  dholland     struct quotactl_args *args);
     83       1.1  dholland static int quota_handle_cmd_put(struct mount *, struct lwp *,
     84       1.1  dholland     struct quotactl_args *args);
     85       1.1  dholland static int quota_handle_cmd_cursorget(struct mount *, struct lwp *,
     86       1.1  dholland     struct quotactl_args *args);
     87  1.10.2.1       tls static int quota_handle_cmd_del(struct mount *, struct lwp *,
     88       1.1  dholland     struct quotactl_args *args);
     89       1.1  dholland static int quota_handle_cmd_quotaon(struct mount *, struct lwp *,
     90       1.1  dholland     struct quotactl_args *args);
     91       1.1  dholland static int quota_handle_cmd_quotaoff(struct mount *, struct lwp *,
     92       1.1  dholland     struct quotactl_args *args);
     93       1.1  dholland static int quota_handle_cmd_cursoropen(struct mount *, struct lwp *,
     94       1.1  dholland     struct quotactl_args *args);
     95       1.1  dholland static int quota_handle_cmd_cursorclose(struct mount *, struct lwp *,
     96       1.1  dholland     struct quotactl_args *args);
     97       1.1  dholland static int quota_handle_cmd_cursorskipidtype(struct mount *, struct lwp *,
     98       1.1  dholland     struct quotactl_args *args);
     99       1.1  dholland static int quota_handle_cmd_cursoratend(struct mount *, struct lwp *,
    100       1.1  dholland     struct quotactl_args *args);
    101       1.1  dholland static int quota_handle_cmd_cursorrewind(struct mount *, struct lwp *,
    102       1.1  dholland     struct quotactl_args *args);
    103       1.1  dholland 
    104       1.1  dholland /*
    105       1.1  dholland  * Initialize the quota fields of an inode.
    106       1.1  dholland  */
    107       1.1  dholland void
    108       1.4  dholland ulfsquota_init(struct inode *ip)
    109       1.1  dholland {
    110       1.1  dholland 	int i;
    111       1.1  dholland 
    112       1.4  dholland 	for (i = 0; i < ULFS_MAXQUOTAS; i++)
    113       1.1  dholland 		ip->i_dquot[i] = NODQUOT;
    114       1.1  dholland }
    115       1.1  dholland 
    116       1.1  dholland /*
    117       1.1  dholland  * Release the quota fields from an inode.
    118       1.1  dholland  */
    119       1.1  dholland void
    120       1.4  dholland ulfsquota_free(struct inode *ip)
    121       1.1  dholland {
    122       1.1  dholland 	int i;
    123       1.1  dholland 
    124       1.4  dholland 	for (i = 0; i < ULFS_MAXQUOTAS; i++) {
    125       1.5  dholland 		lfs_dqrele(ITOV(ip), ip->i_dquot[i]);
    126       1.1  dholland 		ip->i_dquot[i] = NODQUOT;
    127       1.1  dholland 	}
    128       1.1  dholland }
    129       1.1  dholland 
    130       1.1  dholland /*
    131       1.1  dholland  * Update disk usage, and take corrective action.
    132       1.1  dholland  */
    133       1.1  dholland int
    134       1.5  dholland lfs_chkdq(struct inode *ip, int64_t change, kauth_cred_t cred, int flags)
    135       1.1  dholland {
    136       1.1  dholland 	/* do not track snapshot usage, or we will deadlock */
    137       1.1  dholland 	if ((ip->i_flags & SF_SNAPSHOT) != 0)
    138       1.1  dholland 		return 0;
    139       1.1  dholland 
    140       1.3  dholland #ifdef LFS_QUOTA
    141       1.7  dholland 	if (ip->i_lfs->um_flags & ULFS_QUOTA)
    142       1.5  dholland 		return lfs_chkdq1(ip, change, cred, flags);
    143       1.1  dholland #endif
    144       1.3  dholland #ifdef LFS_QUOTA2
    145       1.7  dholland 	if (ip->i_lfs->um_flags & ULFS_QUOTA2)
    146       1.5  dholland 		return lfs_chkdq2(ip, change, cred, flags);
    147       1.1  dholland #endif
    148       1.1  dholland 	return 0;
    149       1.1  dholland }
    150       1.1  dholland 
    151       1.1  dholland /*
    152       1.1  dholland  * Check the inode limit, applying corrective action.
    153       1.1  dholland  */
    154       1.1  dholland int
    155       1.5  dholland lfs_chkiq(struct inode *ip, int32_t change, kauth_cred_t cred, int flags)
    156       1.1  dholland {
    157       1.1  dholland 	/* do not track snapshot usage, or we will deadlock */
    158       1.1  dholland 	if ((ip->i_flags & SF_SNAPSHOT) != 0)
    159       1.1  dholland 		return 0;
    160       1.3  dholland #ifdef LFS_QUOTA
    161       1.7  dholland 	if (ip->i_lfs->um_flags & ULFS_QUOTA)
    162       1.5  dholland 		return lfs_chkiq1(ip, change, cred, flags);
    163       1.1  dholland #endif
    164       1.3  dholland #ifdef LFS_QUOTA2
    165       1.7  dholland 	if (ip->i_lfs->um_flags & ULFS_QUOTA2)
    166       1.5  dholland 		return lfs_chkiq2(ip, change, cred, flags);
    167       1.1  dholland #endif
    168       1.1  dholland 	return 0;
    169       1.1  dholland }
    170       1.1  dholland 
    171       1.1  dholland int
    172       1.5  dholland lfsquota_handle_cmd(struct mount *mp, struct lwp *l,
    173       1.1  dholland 		 struct quotactl_args *args)
    174       1.1  dholland {
    175       1.1  dholland 	int error = 0;
    176       1.1  dholland 
    177       1.1  dholland 	switch (args->qc_op) {
    178       1.1  dholland 	    case QUOTACTL_STAT:
    179       1.1  dholland 		error = quota_handle_cmd_stat(mp, l, args);
    180       1.1  dholland 		break;
    181       1.1  dholland 	    case QUOTACTL_IDTYPESTAT:
    182       1.1  dholland 		error = quota_handle_cmd_idtypestat(mp, l, args);
    183       1.1  dholland 		break;
    184       1.1  dholland 	    case QUOTACTL_OBJTYPESTAT:
    185       1.1  dholland 		error = quota_handle_cmd_objtypestat(mp, l, args);
    186       1.1  dholland 		break;
    187       1.1  dholland 	    case QUOTACTL_QUOTAON:
    188       1.1  dholland 		error = quota_handle_cmd_quotaon(mp, l, args);
    189       1.1  dholland 		break;
    190       1.1  dholland 	    case QUOTACTL_QUOTAOFF:
    191       1.1  dholland 		error = quota_handle_cmd_quotaoff(mp, l, args);
    192       1.1  dholland 		break;
    193       1.1  dholland 	    case QUOTACTL_GET:
    194       1.1  dholland 		error = quota_handle_cmd_get(mp, l, args);
    195       1.1  dholland 		break;
    196       1.1  dholland 	    case QUOTACTL_PUT:
    197       1.1  dholland 		error = quota_handle_cmd_put(mp, l, args);
    198       1.1  dholland 		break;
    199       1.1  dholland 	    case QUOTACTL_CURSORGET:
    200       1.1  dholland 		error = quota_handle_cmd_cursorget(mp, l, args);
    201       1.1  dholland 		break;
    202  1.10.2.1       tls 	    case QUOTACTL_DEL:
    203  1.10.2.1       tls 		error = quota_handle_cmd_del(mp, l, args);
    204       1.1  dholland 		break;
    205       1.1  dholland 	    case QUOTACTL_CURSOROPEN:
    206       1.1  dholland 		error = quota_handle_cmd_cursoropen(mp, l, args);
    207       1.1  dholland 		break;
    208       1.1  dholland 	    case QUOTACTL_CURSORCLOSE:
    209       1.1  dholland 		error = quota_handle_cmd_cursorclose(mp, l, args);
    210       1.1  dholland 		break;
    211       1.1  dholland 	    case QUOTACTL_CURSORSKIPIDTYPE:
    212       1.1  dholland 		error = quota_handle_cmd_cursorskipidtype(mp, l, args);
    213       1.1  dholland 		break;
    214       1.1  dholland 	    case QUOTACTL_CURSORATEND:
    215       1.1  dholland 		error = quota_handle_cmd_cursoratend(mp, l, args);
    216       1.1  dholland 		break;
    217       1.1  dholland 	    case QUOTACTL_CURSORREWIND:
    218       1.1  dholland 		error = quota_handle_cmd_cursorrewind(mp, l, args);
    219       1.1  dholland 		break;
    220       1.1  dholland 	    default:
    221       1.1  dholland 		panic("Invalid quotactl operation %d\n", args->qc_op);
    222       1.1  dholland 	}
    223       1.1  dholland 
    224       1.1  dholland 	return error;
    225       1.1  dholland }
    226       1.1  dholland 
    227       1.1  dholland static int
    228       1.1  dholland quota_handle_cmd_stat(struct mount *mp, struct lwp *l,
    229       1.1  dholland     struct quotactl_args *args)
    230       1.1  dholland {
    231       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    232       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    233       1.1  dholland 
    234       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_STAT);
    235       1.1  dholland 
    236       1.7  dholland 	if ((fs->um_flags & (ULFS_QUOTA|ULFS_QUOTA2)) == 0)
    237       1.1  dholland 		return EOPNOTSUPP;
    238       1.1  dholland 
    239       1.3  dholland #ifdef LFS_QUOTA
    240       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA) {
    241       1.8  christos 		struct quotastat *info = args->u.stat.qc_info;
    242       1.4  dholland 		strcpy(info->qs_implname, "lfs quota v1");
    243       1.4  dholland 		info->qs_numidtypes = ULFS_MAXQUOTAS;
    244       1.1  dholland 		/* XXX no define for this */
    245       1.1  dholland 		info->qs_numobjtypes = 2;
    246       1.1  dholland 		info->qs_restrictions = 0;
    247       1.1  dholland 		info->qs_restrictions |= QUOTA_RESTRICT_NEEDSQUOTACHECK;
    248       1.1  dholland 		info->qs_restrictions |= QUOTA_RESTRICT_UNIFORMGRACE;
    249       1.1  dholland 		info->qs_restrictions |= QUOTA_RESTRICT_32BIT;
    250       1.1  dholland 	} else
    251       1.1  dholland #endif
    252       1.3  dholland #ifdef LFS_QUOTA2
    253       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    254       1.8  christos 		struct quotastat *info = args->u.stat.qc_info;
    255       1.4  dholland 		strcpy(info->qs_implname, "lfs quota v2");
    256       1.4  dholland 		info->qs_numidtypes = ULFS_MAXQUOTAS;
    257       1.1  dholland 		info->qs_numobjtypes = N_QL;
    258       1.1  dholland 		info->qs_restrictions = 0;
    259       1.1  dholland 	} else
    260       1.1  dholland #endif
    261       1.1  dholland 		return EOPNOTSUPP;
    262       1.1  dholland 
    263       1.1  dholland 	return 0;
    264       1.1  dholland }
    265       1.1  dholland 
    266       1.1  dholland static int
    267       1.1  dholland quota_handle_cmd_idtypestat(struct mount *mp, struct lwp *l,
    268       1.1  dholland     struct quotactl_args *args)
    269       1.1  dholland {
    270       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    271       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    272       1.1  dholland 	int idtype;
    273       1.1  dholland 	struct quotaidtypestat *info;
    274       1.1  dholland 	const char *name;
    275       1.1  dholland 
    276       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_IDTYPESTAT);
    277       1.1  dholland 	idtype = args->u.idtypestat.qc_idtype;
    278       1.1  dholland 	info = args->u.idtypestat.qc_info;
    279       1.1  dholland 
    280       1.7  dholland 	if ((fs->um_flags & (ULFS_QUOTA|ULFS_QUOTA2)) == 0)
    281       1.1  dholland 		return EOPNOTSUPP;
    282       1.1  dholland 
    283       1.1  dholland 	/*
    284       1.1  dholland 	 * These are the same for both QUOTA and QUOTA2.
    285       1.1  dholland 	 */
    286       1.1  dholland 	switch (idtype) {
    287       1.1  dholland 	    case QUOTA_IDTYPE_USER:
    288       1.1  dholland 		name = "user";
    289       1.1  dholland 		break;
    290       1.1  dholland 	    case QUOTA_IDTYPE_GROUP:
    291       1.1  dholland 		name = "group";
    292       1.1  dholland 		break;
    293       1.1  dholland 	    default:
    294       1.1  dholland 		return EINVAL;
    295       1.1  dholland 	}
    296       1.1  dholland 	strlcpy(info->qis_name, name, sizeof(info->qis_name));
    297       1.1  dholland 	return 0;
    298       1.1  dholland }
    299       1.1  dholland 
    300       1.1  dholland static int
    301       1.1  dholland quota_handle_cmd_objtypestat(struct mount *mp, struct lwp *l,
    302       1.1  dholland     struct quotactl_args *args)
    303       1.1  dholland {
    304       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    305       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    306       1.1  dholland 	int objtype;
    307       1.1  dholland 	struct quotaobjtypestat *info;
    308       1.1  dholland 	const char *name;
    309       1.1  dholland 	int isbytes;
    310       1.1  dholland 
    311       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_OBJTYPESTAT);
    312       1.1  dholland 	objtype = args->u.objtypestat.qc_objtype;
    313       1.1  dholland 	info = args->u.objtypestat.qc_info;
    314       1.1  dholland 
    315       1.7  dholland 	if ((fs->um_flags & (ULFS_QUOTA|ULFS_QUOTA2)) == 0)
    316       1.1  dholland 		return EOPNOTSUPP;
    317       1.1  dholland 
    318       1.1  dholland 	/*
    319       1.1  dholland 	 * These are the same for both QUOTA and QUOTA2.
    320       1.1  dholland 	 */
    321       1.1  dholland 	switch (objtype) {
    322       1.1  dholland 	    case QUOTA_OBJTYPE_BLOCKS:
    323       1.1  dholland 		name = "block";
    324       1.1  dholland 		isbytes = 1;
    325       1.1  dholland 		break;
    326       1.1  dholland 	    case QUOTA_OBJTYPE_FILES:
    327       1.1  dholland 		name = "file";
    328       1.1  dholland 		isbytes = 0;
    329       1.1  dholland 		break;
    330       1.1  dholland 	    default:
    331       1.1  dholland 		return EINVAL;
    332       1.1  dholland 	}
    333       1.1  dholland 	strlcpy(info->qos_name, name, sizeof(info->qos_name));
    334       1.1  dholland 	info->qos_isbytes = isbytes;
    335       1.1  dholland 	return 0;
    336       1.1  dholland }
    337       1.1  dholland 
    338       1.1  dholland /* XXX shouldn't all this be in kauth ? */
    339       1.1  dholland static int
    340       1.1  dholland quota_get_auth(struct mount *mp, struct lwp *l, uid_t id) {
    341       1.1  dholland 	/* The user can always query about his own quota. */
    342       1.1  dholland 	if (id == kauth_cred_geteuid(l->l_cred))
    343       1.1  dholland 		return 0;
    344       1.1  dholland 	return kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
    345       1.1  dholland 	    KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(id), NULL);
    346       1.1  dholland }
    347       1.1  dholland 
    348       1.1  dholland static int
    349       1.1  dholland quota_handle_cmd_get(struct mount *mp, struct lwp *l,
    350       1.1  dholland     struct quotactl_args *args)
    351       1.1  dholland {
    352       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    353       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    354       1.1  dholland 	int error;
    355       1.1  dholland 	const struct quotakey *qk;
    356       1.1  dholland 
    357       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_GET);
    358       1.1  dholland 	qk = args->u.get.qc_key;
    359       1.1  dholland 
    360       1.7  dholland 	if ((fs->um_flags & (ULFS_QUOTA|ULFS_QUOTA2)) == 0)
    361       1.1  dholland 		return EOPNOTSUPP;
    362       1.1  dholland 
    363       1.1  dholland 	error = quota_get_auth(mp, l, qk->qk_id);
    364       1.1  dholland 	if (error != 0)
    365       1.1  dholland 		return error;
    366       1.3  dholland #ifdef LFS_QUOTA
    367       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA) {
    368       1.8  christos 		struct quotaval *qv = args->u.get.qc_val;
    369       1.5  dholland 		error = lfsquota1_handle_cmd_get(ump, qk, qv);
    370       1.1  dholland 	} else
    371       1.1  dholland #endif
    372       1.3  dholland #ifdef LFS_QUOTA2
    373       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    374       1.8  christos 		struct quotaval *qv = args->u.get.qc_val;
    375       1.5  dholland 		error = lfsquota2_handle_cmd_get(ump, qk, qv);
    376       1.1  dholland 	} else
    377       1.1  dholland #endif
    378       1.1  dholland 		panic("quota_handle_cmd_get: no support ?");
    379       1.1  dholland 
    380       1.1  dholland 	if (error != 0)
    381       1.1  dholland 		return error;
    382       1.1  dholland 
    383       1.1  dholland 	return error;
    384       1.1  dholland }
    385       1.1  dholland 
    386       1.1  dholland static int
    387       1.1  dholland quota_handle_cmd_put(struct mount *mp, struct lwp *l,
    388       1.1  dholland     struct quotactl_args *args)
    389       1.1  dholland {
    390       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    391       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    392       1.1  dholland 	const struct quotakey *qk;
    393       1.1  dholland 	id_t kauth_id;
    394       1.1  dholland 	int error;
    395       1.1  dholland 
    396       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_PUT);
    397       1.1  dholland 	qk = args->u.put.qc_key;
    398       1.1  dholland 
    399       1.7  dholland 	if ((fs->um_flags & (ULFS_QUOTA|ULFS_QUOTA2)) == 0)
    400       1.1  dholland 		return EOPNOTSUPP;
    401       1.1  dholland 
    402       1.1  dholland 	kauth_id = qk->qk_id;
    403       1.1  dholland 	if (kauth_id == QUOTA_DEFAULTID) {
    404       1.1  dholland 		kauth_id = 0;
    405       1.1  dholland 	}
    406       1.1  dholland 
    407       1.1  dholland 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
    408       1.1  dholland 	    KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(kauth_id),
    409       1.1  dholland 	    NULL);
    410       1.1  dholland 	if (error != 0) {
    411       1.1  dholland 		return error;
    412       1.1  dholland 	}
    413       1.1  dholland 
    414       1.3  dholland #ifdef LFS_QUOTA
    415       1.8  christos 	if (fs->um_flags & ULFS_QUOTA) {
    416       1.8  christos 		const struct quotaval *qv = args->u.put.qc_val;
    417       1.5  dholland 		error = lfsquota1_handle_cmd_put(ump, qk, qv);
    418       1.8  christos 	} else
    419       1.1  dholland #endif
    420       1.3  dholland #ifdef LFS_QUOTA2
    421       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    422       1.8  christos 		const struct quotaval *qv = args->u.put.qc_val;
    423       1.5  dholland 		error = lfsquota2_handle_cmd_put(ump, qk, qv);
    424       1.1  dholland 	} else
    425       1.1  dholland #endif
    426       1.1  dholland 		panic("quota_handle_cmd_get: no support ?");
    427       1.1  dholland 
    428       1.1  dholland 	if (error == ENOENT) {
    429       1.1  dholland 		error = 0;
    430       1.1  dholland 	}
    431       1.1  dholland 
    432       1.1  dholland 	return error;
    433       1.1  dholland }
    434       1.1  dholland 
    435       1.1  dholland static int
    436  1.10.2.1       tls quota_handle_cmd_del(struct mount *mp, struct lwp *l,
    437       1.1  dholland     struct quotactl_args *args)
    438       1.1  dholland {
    439       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    440       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    441       1.1  dholland 	const struct quotakey *qk;
    442       1.1  dholland 	id_t kauth_id;
    443       1.1  dholland 	int error;
    444       1.1  dholland 
    445  1.10.2.1       tls 	KASSERT(args->qc_op == QUOTACTL_DEL);
    446  1.10.2.1       tls 	qk = args->u.del.qc_key;
    447       1.1  dholland 
    448       1.1  dholland 	kauth_id = qk->qk_id;
    449       1.1  dholland 	if (kauth_id == QUOTA_DEFAULTID) {
    450       1.1  dholland 		kauth_id = 0;
    451       1.1  dholland 	}
    452       1.1  dholland 
    453       1.7  dholland 	if ((fs->um_flags & ULFS_QUOTA2) == 0)
    454       1.1  dholland 		return EOPNOTSUPP;
    455       1.1  dholland 
    456       1.1  dholland 	/* avoid whitespace changes */
    457       1.1  dholland 	{
    458       1.1  dholland 		error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
    459       1.1  dholland 		    KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(kauth_id),
    460       1.1  dholland 		    NULL);
    461       1.1  dholland 		if (error != 0)
    462       1.1  dholland 			goto err;
    463       1.3  dholland #ifdef LFS_QUOTA2
    464       1.7  dholland 		if (fs->um_flags & ULFS_QUOTA2) {
    465  1.10.2.1       tls 			error = lfsquota2_handle_cmd_del(ump, qk);
    466       1.1  dholland 		} else
    467       1.1  dholland #endif
    468       1.1  dholland 			panic("quota_handle_cmd_get: no support ?");
    469       1.1  dholland 
    470       1.1  dholland 		if (error && error != ENOENT)
    471       1.1  dholland 			goto err;
    472       1.1  dholland 	}
    473       1.1  dholland 
    474       1.1  dholland 	return 0;
    475       1.1  dholland  err:
    476       1.1  dholland 	return error;
    477       1.1  dholland }
    478       1.1  dholland 
    479       1.1  dholland static int
    480       1.1  dholland quota_handle_cmd_cursorget(struct mount *mp, struct lwp *l,
    481       1.1  dholland     struct quotactl_args *args)
    482       1.1  dholland {
    483       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    484       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    485       1.1  dholland 	int error;
    486       1.1  dholland 
    487       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_CURSORGET);
    488       1.1  dholland 
    489       1.7  dholland 	if ((fs->um_flags & ULFS_QUOTA2) == 0)
    490       1.1  dholland 		return EOPNOTSUPP;
    491       1.1  dholland 
    492       1.1  dholland 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
    493       1.1  dholland 	    KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL);
    494       1.1  dholland 	if (error)
    495       1.1  dholland 		return error;
    496       1.1  dholland 
    497       1.3  dholland #ifdef LFS_QUOTA2
    498       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    499      1.10  dholland 		struct quotakcursor *cursor = args->u.cursorget.qc_cursor;
    500       1.8  christos 		struct quotakey *keys = args->u.cursorget.qc_keys;
    501       1.8  christos 		struct quotaval *vals = args->u.cursorget.qc_vals;
    502       1.8  christos 		unsigned maxnum = args->u.cursorget.qc_maxnum;
    503       1.8  christos 		unsigned *ret = args->u.cursorget.qc_ret;
    504       1.8  christos 
    505       1.5  dholland 		error = lfsquota2_handle_cmd_cursorget(ump, cursor, keys, vals,
    506       1.8  christos 		    maxnum, ret);
    507       1.1  dholland 	} else
    508       1.1  dholland #endif
    509       1.1  dholland 		panic("quota_handle_cmd_cursorget: no support ?");
    510       1.1  dholland 
    511       1.1  dholland 	return error;
    512       1.1  dholland }
    513       1.1  dholland 
    514       1.1  dholland static int
    515       1.1  dholland quota_handle_cmd_cursoropen(struct mount *mp, struct lwp *l,
    516       1.1  dholland     struct quotactl_args *args)
    517       1.1  dholland {
    518       1.3  dholland #ifdef LFS_QUOTA2
    519       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    520       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    521       1.8  christos 	struct quotakcursor *cursor;
    522       1.1  dholland #endif
    523       1.1  dholland 	int error;
    524       1.1  dholland 
    525       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_CURSOROPEN);
    526       1.1  dholland 
    527       1.1  dholland 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
    528       1.1  dholland 	    KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL);
    529       1.1  dholland 	if (error)
    530       1.1  dholland 		return error;
    531       1.1  dholland 
    532       1.3  dholland #ifdef LFS_QUOTA2
    533       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    534       1.8  christos 		cursor = args->u.cursoropen.qc_cursor;
    535       1.5  dholland 		error = lfsquota2_handle_cmd_cursoropen(ump, cursor);
    536       1.1  dholland 	} else
    537       1.1  dholland #endif
    538       1.1  dholland 		error = EOPNOTSUPP;
    539       1.1  dholland 
    540       1.1  dholland 	return error;
    541       1.1  dholland }
    542       1.1  dholland 
    543       1.1  dholland static int
    544       1.1  dholland quota_handle_cmd_cursorclose(struct mount *mp, struct lwp *l,
    545       1.1  dholland     struct quotactl_args *args)
    546       1.1  dholland {
    547       1.3  dholland #ifdef LFS_QUOTA2
    548       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    549       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    550       1.1  dholland #endif
    551       1.1  dholland 	int error;
    552       1.1  dholland 
    553       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_CURSORCLOSE);
    554       1.1  dholland 
    555       1.1  dholland 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
    556       1.1  dholland 	    KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL);
    557       1.1  dholland 	if (error)
    558       1.1  dholland 		return error;
    559       1.1  dholland 
    560       1.3  dholland #ifdef LFS_QUOTA2
    561       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    562       1.8  christos 		struct quotakcursor *cursor = args->u.cursorclose.qc_cursor;
    563       1.5  dholland 		error = lfsquota2_handle_cmd_cursorclose(ump, cursor);
    564       1.1  dholland 	} else
    565       1.1  dholland #endif
    566       1.1  dholland 		error = EOPNOTSUPP;
    567       1.1  dholland 
    568       1.1  dholland 	return error;
    569       1.1  dholland }
    570       1.1  dholland 
    571       1.1  dholland static int
    572       1.1  dholland quota_handle_cmd_cursorskipidtype(struct mount *mp, struct lwp *l,
    573       1.1  dholland     struct quotactl_args *args)
    574       1.1  dholland {
    575       1.3  dholland #ifdef LFS_QUOTA2
    576       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    577       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    578       1.1  dholland #endif
    579       1.1  dholland 	int error;
    580       1.1  dholland 
    581       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_CURSORSKIPIDTYPE);
    582       1.1  dholland 
    583       1.3  dholland #ifdef LFS_QUOTA2
    584       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    585       1.8  christos 		struct quotakcursor *cursor = args->u.cursorskipidtype.qc_cursor;
    586       1.8  christos 		int idtype = args->u.cursorskipidtype.qc_idtype;
    587       1.5  dholland 		error = lfsquota2_handle_cmd_cursorskipidtype(ump, cursor, idtype);
    588       1.1  dholland 	} else
    589       1.1  dholland #endif
    590       1.1  dholland 		error = EOPNOTSUPP;
    591       1.1  dholland 
    592       1.1  dholland 	return error;
    593       1.1  dholland }
    594       1.1  dholland 
    595       1.1  dholland static int
    596       1.1  dholland quota_handle_cmd_cursoratend(struct mount *mp, struct lwp *l,
    597       1.1  dholland     struct quotactl_args *args)
    598       1.1  dholland {
    599       1.3  dholland #ifdef LFS_QUOTA2
    600       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    601       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    602       1.1  dholland #endif
    603       1.1  dholland 	int error;
    604       1.1  dholland 
    605       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_CURSORATEND);
    606       1.1  dholland 
    607       1.3  dholland #ifdef LFS_QUOTA2
    608       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    609       1.8  christos 		struct quotakcursor *cursor = args->u.cursoratend.qc_cursor;
    610       1.8  christos 		int *ret = args->u.cursoratend.qc_ret;
    611       1.5  dholland 		error = lfsquota2_handle_cmd_cursoratend(ump, cursor, ret);
    612       1.1  dholland 	} else
    613       1.1  dholland #endif
    614       1.1  dholland 		error = EOPNOTSUPP;
    615       1.1  dholland 
    616       1.1  dholland 	return error;
    617       1.1  dholland }
    618       1.1  dholland 
    619       1.1  dholland static int
    620       1.1  dholland quota_handle_cmd_cursorrewind(struct mount *mp, struct lwp *l,
    621       1.1  dholland     struct quotactl_args *args)
    622       1.1  dholland {
    623       1.3  dholland #ifdef LFS_QUOTA2
    624       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    625       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    626       1.1  dholland #endif
    627       1.1  dholland 	int error;
    628       1.1  dholland 
    629       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_CURSORREWIND);
    630       1.1  dholland 
    631       1.3  dholland #ifdef LFS_QUOTA2
    632       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    633       1.8  christos 		struct quotakcursor *cursor = args->u.cursorrewind.qc_cursor;
    634       1.5  dholland 		error = lfsquota2_handle_cmd_cursorrewind(ump, cursor);
    635       1.1  dholland 	} else
    636       1.1  dholland #endif
    637       1.1  dholland 		error = EOPNOTSUPP;
    638       1.1  dholland 
    639       1.1  dholland 	return error;
    640       1.1  dholland }
    641       1.1  dholland 
    642       1.1  dholland static int
    643       1.1  dholland quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l,
    644       1.1  dholland     struct quotactl_args *args)
    645       1.1  dholland {
    646       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    647       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    648       1.1  dholland 	int error;
    649       1.1  dholland 
    650       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_QUOTAON);
    651       1.1  dholland 
    652       1.7  dholland 	if ((fs->um_flags & ULFS_QUOTA2) != 0)
    653       1.1  dholland 		return EBUSY;
    654       1.1  dholland 
    655       1.1  dholland 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
    656       1.1  dholland 	    KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
    657       1.1  dholland 	if (error != 0) {
    658       1.1  dholland 		return error;
    659       1.1  dholland 	}
    660       1.3  dholland #ifdef LFS_QUOTA
    661       1.8  christos 	int idtype = args->u.quotaon.qc_idtype;
    662       1.8  christos 	const char *qfile = args->u.quotaon.qc_quotafile;
    663       1.5  dholland 	error = lfsquota1_handle_cmd_quotaon(l, ump, idtype, qfile);
    664       1.1  dholland #else
    665       1.1  dholland 	error = EOPNOTSUPP;
    666       1.1  dholland #endif
    667       1.1  dholland 
    668       1.1  dholland 	return error;
    669       1.1  dholland }
    670       1.1  dholland 
    671       1.1  dholland static int
    672       1.1  dholland quota_handle_cmd_quotaoff(struct mount *mp, struct lwp *l,
    673       1.1  dholland     struct quotactl_args *args)
    674       1.1  dholland {
    675       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    676       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    677       1.1  dholland 	int error;
    678       1.1  dholland 
    679       1.1  dholland 	KASSERT(args->qc_op == QUOTACTL_QUOTAOFF);
    680       1.1  dholland 
    681       1.7  dholland 	if ((fs->um_flags & ULFS_QUOTA2) != 0)
    682       1.1  dholland 		return EOPNOTSUPP;
    683       1.1  dholland 
    684       1.1  dholland 	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
    685       1.1  dholland 	    KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
    686       1.1  dholland 	if (error != 0) {
    687       1.1  dholland 		return error;
    688       1.1  dholland 	}
    689       1.3  dholland #ifdef LFS_QUOTA
    690       1.8  christos 	int idtype = args->u.quotaoff.qc_idtype;
    691       1.5  dholland 	error = lfsquota1_handle_cmd_quotaoff(l, ump, idtype);
    692       1.1  dholland #else
    693       1.1  dholland 	error = EOPNOTSUPP;
    694       1.1  dholland #endif
    695       1.1  dholland 
    696       1.1  dholland 	return error;
    697       1.1  dholland }
    698       1.1  dholland 
    699       1.1  dholland /*
    700       1.1  dholland  * Initialize the quota system.
    701       1.1  dholland  */
    702       1.1  dholland void
    703       1.5  dholland lfs_dqinit(void)
    704       1.1  dholland {
    705       1.1  dholland 
    706       1.5  dholland 	mutex_init(&lfs_dqlock, MUTEX_DEFAULT, IPL_NONE);
    707       1.5  dholland 	cv_init(&lfs_dqcv, "quota");
    708       1.1  dholland 	dqhashtbl = hashinit(desiredvnodes, HASH_LIST, true, &dqhash);
    709       1.4  dholland 	dquot_cache = pool_cache_init(sizeof(struct dquot), 0, 0, 0, "lfsdq",
    710       1.1  dholland 	    NULL, IPL_NONE, NULL, NULL, NULL);
    711       1.1  dholland }
    712       1.1  dholland 
    713       1.1  dholland void
    714       1.5  dholland lfs_dqreinit(void)
    715       1.1  dholland {
    716       1.1  dholland 	struct dquot *dq;
    717       1.1  dholland 	struct dqhashhead *oldhash, *hash;
    718       1.1  dholland 	struct vnode *dqvp;
    719       1.1  dholland 	u_long oldmask, mask, hashval;
    720       1.1  dholland 	int i;
    721       1.1  dholland 
    722       1.1  dholland 	hash = hashinit(desiredvnodes, HASH_LIST, true, &mask);
    723       1.5  dholland 	mutex_enter(&lfs_dqlock);
    724       1.1  dholland 	oldhash = dqhashtbl;
    725       1.1  dholland 	oldmask = dqhash;
    726       1.1  dholland 	dqhashtbl = hash;
    727       1.1  dholland 	dqhash = mask;
    728       1.1  dholland 	for (i = 0; i <= oldmask; i++) {
    729       1.1  dholland 		while ((dq = LIST_FIRST(&oldhash[i])) != NULL) {
    730       1.1  dholland 			dqvp = dq->dq_ump->um_quotas[dq->dq_type];
    731       1.1  dholland 			LIST_REMOVE(dq, dq_hash);
    732       1.1  dholland 			hashval = DQHASH(dqvp, dq->dq_id);
    733       1.1  dholland 			LIST_INSERT_HEAD(&dqhashtbl[hashval], dq, dq_hash);
    734       1.1  dholland 		}
    735       1.1  dholland 	}
    736       1.5  dholland 	mutex_exit(&lfs_dqlock);
    737       1.1  dholland 	hashdone(oldhash, HASH_LIST, oldmask);
    738       1.1  dholland }
    739       1.1  dholland 
    740       1.1  dholland /*
    741       1.1  dholland  * Free resources held by quota system.
    742       1.1  dholland  */
    743       1.1  dholland void
    744       1.5  dholland lfs_dqdone(void)
    745       1.1  dholland {
    746       1.1  dholland 
    747       1.1  dholland 	pool_cache_destroy(dquot_cache);
    748       1.1  dholland 	hashdone(dqhashtbl, HASH_LIST, dqhash);
    749       1.5  dholland 	cv_destroy(&lfs_dqcv);
    750       1.5  dholland 	mutex_destroy(&lfs_dqlock);
    751       1.1  dholland }
    752       1.1  dholland 
    753       1.1  dholland /*
    754       1.1  dholland  * Set up the quotas for an inode.
    755       1.1  dholland  *
    756       1.1  dholland  * This routine completely defines the semantics of quotas.
    757       1.4  dholland  * If other criteria want to be used to establish quotas, the
    758       1.4  dholland  * ULFS_MAXQUOTAS value in quotas.h should be increased, and the
    759       1.1  dholland  * additional dquots set up here.
    760       1.1  dholland  */
    761       1.1  dholland int
    762       1.5  dholland lfs_getinoquota(struct inode *ip)
    763       1.1  dholland {
    764       1.4  dholland 	struct ulfsmount *ump = ip->i_ump;
    765       1.7  dholland 	//struct lfs *fs = ump->um_lfs; // notyet
    766       1.1  dholland 	struct vnode *vp = ITOV(ip);
    767       1.1  dholland 	int i, error;
    768       1.4  dholland 	u_int32_t ino_ids[ULFS_MAXQUOTAS];
    769       1.1  dholland 
    770       1.1  dholland 	/*
    771       1.1  dholland 	 * To avoid deadlocks never update quotas for quota files
    772       1.1  dholland 	 * on the same file system
    773       1.1  dholland 	 */
    774       1.4  dholland 	for (i = 0; i < ULFS_MAXQUOTAS; i++)
    775       1.1  dholland 		if (vp == ump->um_quotas[i])
    776       1.1  dholland 			return 0;
    777       1.1  dholland 
    778       1.4  dholland 	ino_ids[ULFS_USRQUOTA] = ip->i_uid;
    779       1.4  dholland 	ino_ids[ULFS_GRPQUOTA] = ip->i_gid;
    780       1.4  dholland 	for (i = 0; i < ULFS_MAXQUOTAS; i++) {
    781       1.1  dholland 		/*
    782       1.1  dholland 		 * If the file id changed the quota needs update.
    783       1.1  dholland 		 */
    784       1.1  dholland 		if (ip->i_dquot[i] != NODQUOT &&
    785       1.1  dholland 		    ip->i_dquot[i]->dq_id != ino_ids[i]) {
    786       1.5  dholland 			lfs_dqrele(ITOV(ip), ip->i_dquot[i]);
    787       1.1  dholland 			ip->i_dquot[i] = NODQUOT;
    788       1.1  dholland 		}
    789       1.1  dholland 		/*
    790       1.1  dholland 		 * Set up the quota based on file id.
    791       1.1  dholland 		 * ENODEV means that quotas are not enabled.
    792       1.1  dholland 		 */
    793       1.1  dholland 		if (ip->i_dquot[i] == NODQUOT &&
    794       1.5  dholland 		    (error = lfs_dqget(vp, ino_ids[i], ump, i, &ip->i_dquot[i])) &&
    795       1.1  dholland 		    error != ENODEV)
    796       1.1  dholland 			return (error);
    797       1.1  dholland 	}
    798       1.1  dholland 	return 0;
    799       1.1  dholland }
    800       1.1  dholland 
    801       1.1  dholland /*
    802       1.1  dholland  * Obtain a dquot structure for the specified identifier and quota file
    803       1.1  dholland  * reading the information from the file if necessary.
    804       1.1  dholland  */
    805       1.1  dholland int
    806       1.5  dholland lfs_dqget(struct vnode *vp, u_long id, struct ulfsmount *ump, int type,
    807       1.1  dholland     struct dquot **dqp)
    808       1.1  dholland {
    809       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    810       1.1  dholland 	struct dquot *dq, *ndq;
    811       1.1  dholland 	struct dqhashhead *dqh;
    812       1.1  dholland 	struct vnode *dqvp;
    813       1.1  dholland 	int error = 0; /* XXX gcc */
    814       1.1  dholland 
    815       1.1  dholland 	/* Lock to see an up to date value for QTF_CLOSING. */
    816       1.5  dholland 	mutex_enter(&lfs_dqlock);
    817       1.7  dholland 	if ((fs->um_flags & (ULFS_QUOTA|ULFS_QUOTA2)) == 0) {
    818       1.5  dholland 		mutex_exit(&lfs_dqlock);
    819       1.1  dholland 		*dqp = NODQUOT;
    820       1.1  dholland 		return (ENODEV);
    821       1.1  dholland 	}
    822       1.1  dholland 	dqvp = ump->um_quotas[type];
    823       1.3  dholland #ifdef LFS_QUOTA
    824       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA) {
    825       1.1  dholland 		if (dqvp == NULLVP || (ump->umq1_qflags[type] & QTF_CLOSING)) {
    826       1.5  dholland 			mutex_exit(&lfs_dqlock);
    827       1.1  dholland 			*dqp = NODQUOT;
    828       1.1  dholland 			return (ENODEV);
    829       1.1  dholland 		}
    830       1.1  dholland 	}
    831       1.1  dholland #endif
    832       1.3  dholland #ifdef LFS_QUOTA2
    833       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2) {
    834       1.1  dholland 		if (dqvp == NULLVP) {
    835       1.5  dholland 			mutex_exit(&lfs_dqlock);
    836       1.1  dholland 			*dqp = NODQUOT;
    837       1.1  dholland 			return (ENODEV);
    838       1.1  dholland 		}
    839       1.1  dholland 	}
    840       1.1  dholland #endif
    841       1.1  dholland 	KASSERT(dqvp != vp);
    842       1.1  dholland 	/*
    843       1.1  dholland 	 * Check the cache first.
    844       1.1  dholland 	 */
    845       1.1  dholland 	dqh = &dqhashtbl[DQHASH(dqvp, id)];
    846       1.1  dholland 	LIST_FOREACH(dq, dqh, dq_hash) {
    847       1.1  dholland 		if (dq->dq_id != id ||
    848       1.1  dholland 		    dq->dq_ump->um_quotas[dq->dq_type] != dqvp)
    849       1.1  dholland 			continue;
    850       1.1  dholland 		KASSERT(dq->dq_cnt > 0);
    851       1.5  dholland 		lfs_dqref(dq);
    852       1.5  dholland 		mutex_exit(&lfs_dqlock);
    853       1.1  dholland 		*dqp = dq;
    854       1.1  dholland 		return (0);
    855       1.1  dholland 	}
    856       1.1  dholland 	/*
    857       1.1  dholland 	 * Not in cache, allocate a new one.
    858       1.1  dholland 	 */
    859       1.5  dholland 	mutex_exit(&lfs_dqlock);
    860       1.1  dholland 	ndq = pool_cache_get(dquot_cache, PR_WAITOK);
    861       1.1  dholland 	/*
    862       1.1  dholland 	 * Initialize the contents of the dquot structure.
    863       1.1  dholland 	 */
    864       1.1  dholland 	memset((char *)ndq, 0, sizeof *ndq);
    865       1.1  dholland 	ndq->dq_flags = 0;
    866       1.1  dholland 	ndq->dq_id = id;
    867       1.1  dholland 	ndq->dq_ump = ump;
    868       1.1  dholland 	ndq->dq_type = type;
    869       1.1  dholland 	mutex_init(&ndq->dq_interlock, MUTEX_DEFAULT, IPL_NONE);
    870       1.5  dholland 	mutex_enter(&lfs_dqlock);
    871       1.1  dholland 	dqh = &dqhashtbl[DQHASH(dqvp, id)];
    872       1.1  dholland 	LIST_FOREACH(dq, dqh, dq_hash) {
    873       1.1  dholland 		if (dq->dq_id != id ||
    874       1.1  dholland 		    dq->dq_ump->um_quotas[dq->dq_type] != dqvp)
    875       1.1  dholland 			continue;
    876       1.1  dholland 		/*
    877       1.1  dholland 		 * Another thread beat us allocating this dquot.
    878       1.1  dholland 		 */
    879       1.1  dholland 		KASSERT(dq->dq_cnt > 0);
    880       1.5  dholland 		lfs_dqref(dq);
    881       1.5  dholland 		mutex_exit(&lfs_dqlock);
    882       1.1  dholland 		mutex_destroy(&ndq->dq_interlock);
    883       1.1  dholland 		pool_cache_put(dquot_cache, ndq);
    884       1.1  dholland 		*dqp = dq;
    885       1.1  dholland 		return 0;
    886       1.1  dholland 	}
    887       1.1  dholland 	dq = ndq;
    888       1.1  dholland 	LIST_INSERT_HEAD(dqh, dq, dq_hash);
    889       1.5  dholland 	lfs_dqref(dq);
    890       1.1  dholland 	mutex_enter(&dq->dq_interlock);
    891       1.5  dholland 	mutex_exit(&lfs_dqlock);
    892       1.3  dholland #ifdef LFS_QUOTA
    893       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA)
    894       1.5  dholland 		error = lfs_dq1get(dqvp, id, ump, type, dq);
    895       1.1  dholland #endif
    896       1.3  dholland #ifdef LFS_QUOTA2
    897       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2)
    898       1.5  dholland 		error = lfs_dq2get(dqvp, id, ump, type, dq);
    899       1.1  dholland #endif
    900       1.1  dholland 	/*
    901       1.1  dholland 	 * I/O error in reading quota file, release
    902       1.1  dholland 	 * quota structure and reflect problem to caller.
    903       1.1  dholland 	 */
    904       1.1  dholland 	if (error) {
    905       1.5  dholland 		mutex_enter(&lfs_dqlock);
    906       1.1  dholland 		LIST_REMOVE(dq, dq_hash);
    907       1.5  dholland 		mutex_exit(&lfs_dqlock);
    908       1.1  dholland 		mutex_exit(&dq->dq_interlock);
    909       1.5  dholland 		lfs_dqrele(vp, dq);
    910       1.1  dholland 		*dqp = NODQUOT;
    911       1.1  dholland 		return (error);
    912       1.1  dholland 	}
    913       1.1  dholland 	mutex_exit(&dq->dq_interlock);
    914       1.1  dholland 	*dqp = dq;
    915       1.1  dholland 	return (0);
    916       1.1  dholland }
    917       1.1  dholland 
    918       1.1  dholland /*
    919       1.1  dholland  * Obtain a reference to a dquot.
    920       1.1  dholland  */
    921       1.1  dholland void
    922       1.5  dholland lfs_dqref(struct dquot *dq)
    923       1.1  dholland {
    924       1.1  dholland 
    925       1.5  dholland 	KASSERT(mutex_owned(&lfs_dqlock));
    926       1.1  dholland 	dq->dq_cnt++;
    927       1.1  dholland 	KASSERT(dq->dq_cnt > 0);
    928       1.1  dholland }
    929       1.1  dholland 
    930       1.1  dholland /*
    931       1.1  dholland  * Release a reference to a dquot.
    932       1.1  dholland  */
    933       1.1  dholland void
    934       1.5  dholland lfs_dqrele(struct vnode *vp, struct dquot *dq)
    935       1.1  dholland {
    936       1.1  dholland 
    937       1.1  dholland 	if (dq == NODQUOT)
    938       1.1  dholland 		return;
    939       1.1  dholland 	mutex_enter(&dq->dq_interlock);
    940       1.1  dholland 	for (;;) {
    941       1.5  dholland 		mutex_enter(&lfs_dqlock);
    942       1.1  dholland 		if (dq->dq_cnt > 1) {
    943       1.1  dholland 			dq->dq_cnt--;
    944       1.5  dholland 			mutex_exit(&lfs_dqlock);
    945       1.1  dholland 			mutex_exit(&dq->dq_interlock);
    946       1.1  dholland 			return;
    947       1.1  dholland 		}
    948       1.1  dholland 		if ((dq->dq_flags & DQ_MOD) == 0)
    949       1.1  dholland 			break;
    950       1.5  dholland 		mutex_exit(&lfs_dqlock);
    951       1.3  dholland #ifdef LFS_QUOTA
    952       1.7  dholland 		if (dq->dq_ump->um_lfs->um_flags & ULFS_QUOTA)
    953       1.5  dholland 			(void) lfs_dq1sync(vp, dq);
    954       1.1  dholland #endif
    955       1.3  dholland #ifdef LFS_QUOTA2
    956       1.7  dholland 		if (dq->dq_ump->um_lfs->um_flags & ULFS_QUOTA2)
    957       1.5  dholland 			(void) lfs_dq2sync(vp, dq);
    958       1.1  dholland #endif
    959       1.1  dholland 	}
    960       1.1  dholland 	KASSERT(dq->dq_cnt == 1 && (dq->dq_flags & DQ_MOD) == 0);
    961       1.1  dholland 	LIST_REMOVE(dq, dq_hash);
    962       1.5  dholland 	mutex_exit(&lfs_dqlock);
    963       1.1  dholland 	mutex_exit(&dq->dq_interlock);
    964       1.1  dholland 	mutex_destroy(&dq->dq_interlock);
    965       1.1  dholland 	pool_cache_put(dquot_cache, dq);
    966       1.1  dholland }
    967       1.1  dholland 
    968       1.1  dholland int
    969       1.5  dholland lfs_qsync(struct mount *mp)
    970       1.1  dholland {
    971       1.4  dholland 	struct ulfsmount *ump = VFSTOULFS(mp);
    972       1.7  dholland 	struct lfs *fs = ump->um_lfs;
    973       1.6  dholland 
    974       1.6  dholland 	/* avoid compiler warning when quotas aren't enabled */
    975       1.6  dholland 	(void)ump;
    976       1.7  dholland 	(void)fs;
    977       1.6  dholland 
    978       1.3  dholland #ifdef LFS_QUOTA
    979       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA)
    980       1.5  dholland 		return lfs_q1sync(mp);
    981       1.1  dholland #endif
    982       1.3  dholland #ifdef LFS_QUOTA2
    983       1.7  dholland 	if (fs->um_flags & ULFS_QUOTA2)
    984       1.5  dholland 		return lfs_q2sync(mp);
    985       1.1  dholland #endif
    986       1.1  dholland 	return 0;
    987       1.1  dholland }
    988       1.1  dholland 
    989       1.1  dholland #ifdef DIAGNOSTIC
    990       1.1  dholland /*
    991       1.1  dholland  * Check the hash chains for stray dquot's.
    992       1.1  dholland  */
    993       1.1  dholland void
    994       1.5  dholland lfs_dqflush(struct vnode *vp)
    995       1.1  dholland {
    996       1.1  dholland 	struct dquot *dq;
    997       1.1  dholland 	int i;
    998       1.1  dholland 
    999       1.5  dholland 	mutex_enter(&lfs_dqlock);
   1000       1.1  dholland 	for (i = 0; i <= dqhash; i++)
   1001       1.1  dholland 		LIST_FOREACH(dq, &dqhashtbl[i], dq_hash)
   1002       1.1  dholland 			KASSERT(dq->dq_ump->um_quotas[dq->dq_type] != vp);
   1003       1.5  dholland 	mutex_exit(&lfs_dqlock);
   1004       1.1  dholland }
   1005       1.1  dholland #endif
   1006