diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2001-11-21 21:23:57 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2001-11-21 21:23:57 +0000 |
commit | 2eb4d9d2d38cc3eb793eb11a9635b95d702fbc8c (patch) | |
tree | b79f1f20dc3691c47d6083bdb3f285c530af0c46 /sys | |
parent | 707190112f1bbf51379b1e841680aac8aaec1c77 (diff) |
Don't use #define QUOTA - use stub file instead
Pass over the quota code in ufs/. Make code paths clearer. Clean up some names.
Move all code that manipulates quotas directly into ufs_quota.c
Use vfs_mount_foreach_vnode to traverse list of vnodes in mountpoint.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_alloc.c | 105 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_balloc.c | 7 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_inode.c | 15 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 18 | ||||
-rw-r--r-- | sys/ufs/ufs/quota.h | 102 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_extern.h | 22 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_inode.c | 26 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_quota.c | 541 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_quota_stub.c | 73 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vfsops.c | 85 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 122 |
12 files changed, 605 insertions, 514 deletions
diff --git a/sys/conf/files b/sys/conf/files index 730bc46e57a..a6ce3bcedb0 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.229 2001/11/02 10:06:13 jjbg Exp $ +# $OpenBSD: files,v 1.230 2001/11/21 21:23:56 csapuntz Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -772,6 +772,7 @@ file ufs/ufs/ufs_ihash.c ffs | mfs | ext2fs file ufs/ufs/ufs_inode.c ffs | mfs | ext2fs file ufs/ufs/ufs_lookup.c ffs | mfs | ext2fs file ufs/ufs/ufs_quota.c quota & ( ffs | mfs | ext2fs ) +file ufs/ufs/ufs_quota_stub.c ffs | mfs file ufs/ufs/ufs_vfsops.c ffs | mfs | ext2fs file ufs/ufs/ufs_vnops.c ffs | mfs | ext2fs file ufs/ext2fs/ext2fs_alloc.c ext2fs diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 7c2870fed77..8ddf99405fc 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_alloc.c,v 1.34 2001/11/15 06:08:31 art Exp $ */ +/* $OpenBSD: ffs_alloc.c,v 1.35 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ffs_alloc.c,v 1.11 1996/05/11 18:27:09 mycroft Exp $ */ /* @@ -104,9 +104,7 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) register struct fs *fs; daddr_t bno; int cg; -#ifdef QUOTA int error; -#endif *bnp = 0; fs = ip->i_fs; @@ -123,10 +121,10 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) goto nospace; if (cred->cr_uid != 0 && freespace(fs, fs->fs_minfree) <= 0) goto nospace; -#ifdef QUOTA - if ((error = chkdq(ip, (long)btodb(size), cred, 0)) != 0) + + if ((error = ufs_quota_alloc_blocks(ip, btodb(size), cred)) != 0) return (error); -#endif + if (bpref >= fs->fs_size) bpref = 0; if (bpref == 0) @@ -141,12 +139,12 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) *bnp = bno; return (0); } -#ifdef QUOTA + /* * Restore user's disk quota because allocation failed. */ - (void) chkdq(ip, (long)-btodb(size), cred, FORCE); -#endif + (void) ufs_quota_free_blocks(ip, btodb(size), cred); + nospace: ffs_fserr(fs, cred->cr_uid, "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); @@ -172,7 +170,8 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp, blknop) ufs_daddr_t *blknop; { register struct fs *fs; - struct buf *bp; + struct buf *bp = NULL; + ufs_daddr_t quota_updated = 0; int cg, request, error; daddr_t bprev, bno; @@ -201,18 +200,15 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp, blknop) * Allocate the extra space in the buffer. */ if (bpp != NULL && - (error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp)) != 0) { - brelse(bp); - return (error); - } -#ifdef QUOTA - if ((error = chkdq(ip, (long)btodb(nsize - osize), cred, 0)) != 0) { - if (bpp != NULL) { - brelse(bp); - } - return (error); - } -#endif + (error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp)) != 0) + goto error; + + if ((error = ufs_quota_alloc_blocks(ip, btodb(nsize - osize), cred)) + != 0) + goto error; + + quota_updated = btodb(nsize - osize); + /* * Check for extension in the existing location. */ @@ -283,43 +279,50 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp, blknop) } bno = (daddr_t)ffs_hashalloc(ip, cg, (long)bpref, request, ffs_alloccg); - if (bno > 0) { - (void) uvm_vnp_uncache(ITOV(ip)); - if (!DOINGSOFTDEP(ITOV(ip))) - ffs_blkfree(ip, bprev, (long)osize); - if (nsize < request) - ffs_blkfree(ip, bno + numfrags(fs, nsize), - (long)(request - nsize)); - ip->i_ffs_blocks += btodb(nsize - osize); - ip->i_flag |= IN_CHANGE | IN_UPDATE; - if (bpp != NULL) { - bp->b_blkno = fsbtodb(fs, bno); - allocbuf(bp, nsize); - bp->b_flags |= B_DONE; - bzero((char *)bp->b_data + osize, (u_int)nsize - osize); - *bpp = bp; - } - if (blknop != NULL) { - *blknop = bno; - } - return (0); - } -#ifdef QUOTA - /* - * Restore user's disk quota because allocation failed. - */ - (void) chkdq(ip, (long)-btodb(nsize - osize), cred, FORCE); -#endif + if (bno <= 0) + goto nospace; + + (void) uvm_vnp_uncache(ITOV(ip)); + if (!DOINGSOFTDEP(ITOV(ip))) + ffs_blkfree(ip, bprev, (long)osize); + if (nsize < request) + ffs_blkfree(ip, bno + numfrags(fs, nsize), + (long)(request - nsize)); + ip->i_ffs_blocks += btodb(nsize - osize); + ip->i_flag |= IN_CHANGE | IN_UPDATE; if (bpp != NULL) { - brelse(bp); + bp->b_blkno = fsbtodb(fs, bno); + allocbuf(bp, nsize); + bp->b_flags |= B_DONE; + bzero((char *)bp->b_data + osize, (u_int)nsize - osize); + *bpp = bp; } + if (blknop != NULL) { + *blknop = bno; + } + return (0); + nospace: /* * no space available */ ffs_fserr(fs, cred->cr_uid, "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); - return (ENOSPC); + error = ENOSPC; + +error: + if (bp != NULL) { + brelse(bp); + bp = NULL; + } + + /* + * Restore user's disk quota because allocation failed. + */ + if (quota_updated != 0) + (void)ufs_quota_free_blocks(ip, quota_updated, cred); + + return error; } /* diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 681de31b2e6..009adc91ff9 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_balloc.c,v 1.17 2001/11/13 16:01:10 art Exp $ */ +/* $OpenBSD: ffs_balloc.c,v 1.18 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ffs_balloc.c,v 1.3 1996/02/09 22:22:21 christos Exp $ */ /* @@ -391,12 +391,11 @@ fail: } } if (deallocated) { -#ifdef QUOTA /* * Restore user's disk quota because allocation failed. */ - (void)chkdq(ip, (long)-btodb(deallocated), cred, FORCE); -#endif + (void)ufs_quota_free_blocks(ip, btodb(deallocated), cred); + ip->i_ffs_blocks -= btodb(deallocated); ip->i_flag |= IN_CHANGE | IN_UPDATE; } diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index 3c024a15fa8..c81c795b2ac 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_inode.c,v 1.24 2001/11/06 19:53:21 miod Exp $ */ +/* $OpenBSD: ffs_inode.c,v 1.25 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ffs_inode.c,v 1.10 1996/05/11 18:27:19 mycroft Exp $ */ /* @@ -184,10 +184,10 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred) oip->i_flag |= IN_CHANGE | IN_UPDATE; return (UFS_UPDATE(oip, MNT_WAIT)); } -#ifdef QUOTA + if ((error = getinoquota(oip)) != 0) return (error); -#endif + uvm_vnp_setsize(ovp, length); oip->i_ci.ci_lasta = oip->i_ci.ci_clen = oip->i_ci.ci_cstart = oip->i_ci.ci_lastw = 0; @@ -207,9 +207,8 @@ ffs_truncate(struct inode *oip, off_t length, int flags, struct ucred *cred) curproc)) != 0) return (error); } else { -#ifdef QUOTA - (void) chkdq(oip, -oip->i_ffs_blocks, NOCRED, 0); -#endif + (void)ufs_quota_free_blocks(oip, oip->i_ffs_blocks, + NOCRED); softdep_setup_freeblocks(oip, length); (void) vinvalbuf(ovp, 0, cred, curproc, 0, 0); oip->i_flag |= IN_CHANGE | IN_UPDATE; @@ -404,9 +403,7 @@ done: if (oip->i_ffs_blocks < 0) /* sanity */ oip->i_ffs_blocks = 0; oip->i_flag |= IN_CHANGE; -#ifdef QUOTA - (void) chkdq(oip, -blocksreleased, NOCRED, 0); -#endif + (void)ufs_quota_free_blocks(oip, blocksreleased, NOCRED); return (allerror); } diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index c16953ed2a3..454966ebff2 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ffs_vfsops.c,v 1.43 2001/06/23 02:07:55 csapuntz Exp $ */ +/* $OpenBSD: ffs_vfsops.c,v 1.44 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */ /* @@ -887,7 +887,6 @@ ffs_flushfiles(mp, flags, p) int error; ump = VFSTOUFS(mp); -#ifdef QUOTA if (mp->mnt_flag & MNT_QUOTA) { int i; if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0) @@ -902,7 +901,7 @@ ffs_flushfiles(mp, flags, p) * that we have gotten rid of all the system vnodes. */ } -#endif + /* * Flush all the files. */ @@ -1040,9 +1039,7 @@ loop: allerror = error; VOP_UNLOCK(ump->um_devvp, 0, p); } -#ifdef QUOTA qsync(mp); -#endif /* * Write back modified superblock. */ @@ -1099,14 +1096,6 @@ retry: ip->i_number = ino; ip->i_vtbl = &ffs_vtbl; -#ifdef QUOTA - { - int i; - - for (i = 0; i < MAXQUOTAS; i++) - ip->i_dquot[i] = NODQUOT; - } -#endif /* * Put it onto its hash chain and lock it so that other requests for * this inode will block if they arrive while we are sleeping waiting @@ -1114,7 +1103,7 @@ retry: * disk portion of this inode to be read. */ error = ufs_ihashins(ip); - + if (error) { /* * VOP_INACTIVE will treat this as a stale file @@ -1352,4 +1341,3 @@ ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) } /* NOTREACHED */ } - diff --git a/sys/ufs/ufs/quota.h b/sys/ufs/ufs/quota.h index 34750deac09..7389b145f83 100644 --- a/sys/ufs/ufs/quota.h +++ b/sys/ufs/ufs/quota.h @@ -1,4 +1,4 @@ -/* $OpenBSD: quota.h,v 1.2 1997/02/24 14:27:16 niklas Exp $ */ +/* $OpenBSD: quota.h,v 1.3 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: quota.h,v 1.6 1995/03/26 20:38:17 jtc Exp $ */ /* @@ -111,67 +111,14 @@ struct dqblk { }; #ifdef _KERNEL -#include <sys/queue.h> - -/* - * The following structure records disk usage for a user or group on a - * filesystem. There is one allocated for each quota that exists on any - * filesystem for the current user or group. A cache is kept of recently - * used entries. - */ -struct dquot { - LIST_ENTRY(dquot) dq_hash; /* hash list */ - TAILQ_ENTRY(dquot) dq_freelist; /* free list */ - u_int16_t dq_flags; /* flags, see below */ - u_int16_t dq_cnt; /* count of active references */ - u_int16_t dq_spare; /* unused spare padding */ - u_int16_t dq_type; /* quota type of this dquot */ - u_int32_t dq_id; /* identifier this applies to */ - struct ufsmount *dq_ump; /* filesystem that this is taken from */ - struct dqblk dq_dqb; /* actual usage & quotas */ -}; -/* - * Flag values. - */ -#define DQ_LOCK 0x01 /* this quota locked (no MODS) */ -#define DQ_WANT 0x02 /* wakeup on unlock */ -#define DQ_MOD 0x04 /* this quota modified since read */ -#define DQ_FAKE 0x08 /* no limits here, just usage */ -#define DQ_BLKS 0x10 /* has been warned about blk limit */ -#define DQ_INODS 0x20 /* has been warned about inode limit */ -/* - * Shorthand notation. - */ -#define dq_bhardlimit dq_dqb.dqb_bhardlimit -#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit -#define dq_curblocks dq_dqb.dqb_curblocks -#define dq_ihardlimit dq_dqb.dqb_ihardlimit -#define dq_isoftlimit dq_dqb.dqb_isoftlimit -#define dq_curinodes dq_dqb.dqb_curinodes -#define dq_btime dq_dqb.dqb_btime -#define dq_itime dq_dqb.dqb_itime - -/* - * If the system has never checked for a quota for this file, then it is - * set to NODQUOT. Once a write attempt is made the inode pointer is set - * to reference a dquot structure. - */ -#define NODQUOT NULL - -/* - * Flags to chkdq() and chkiq() - */ -#define FORCE 0x01 /* force usage changes independent of limits */ -#define CHOWN 0x02 /* (advisory) change initiated by chown */ - /* - * Macros to avoid subroutine calls to trivial functions. + * Flargs to ufs_quota_{alloc,free}_{blocks,inode}2 */ -#ifdef DIAGNOSTIC -#define DQREF(dq) dqref(dq) -#else -#define DQREF(dq) (dq)->dq_cnt++ -#endif +enum ufs_quota_flags { + UFS_QUOTA_NOUID = 0x1, /* Don't change UID quota */ + UFS_QUOTA_NOGID = 0x2, /* Don't change GID quota */ + UFS_QUOTA_FORCE = 0x1000, /* don't check limits - just change it */ +}; /* Change GID */ #include <sys/cdefs.h> @@ -183,32 +130,25 @@ struct ucred; struct ufsmount; struct vnode; __BEGIN_DECLS -int chkdq __P((struct inode *, long, struct ucred *, int)); -int chkdqchg __P((struct inode *, long, struct ucred *, int)); -int chkiq __P((struct inode *, long, struct ucred *, int)); -int chkiqchg __P((struct inode *, long, struct ucred *, int)); -void dqflush __P((struct vnode *)); -int dqget __P((struct vnode *, - u_long, struct ufsmount *, int, struct dquot **)); -void dqinit __P((void)); -void dqref __P((struct dquot *)); -void dqrele __P((struct vnode *, struct dquot *)); -int dqsync __P((struct vnode *, struct dquot *)); +#define ufs_quota_alloc_blocks(i, c, cr) ufs_quota_alloc_blocks2(i, c, cr, 0) +#define ufs_quota_free_blocks(i, c, cr) ufs_quota_free_blocks2(i, c, cr, 0) +#define ufs_quota_alloc_inode(i, cr) ufs_quota_alloc_inode2(i, cr, 0) +#define ufs_quota_free_inode(i, cr) ufs_quota_free_inode2(i, cr, 0) +int ufs_quota_alloc_blocks2(struct inode *, int32_t, struct ucred *, enum ufs_quota_flags); +int ufs_quota_free_blocks2(struct inode *, int32_t, struct ucred *, enum ufs_quota_flags); +int ufs_quota_alloc_inode2(struct inode *, struct ucred *, enum ufs_quota_flags); +int ufs_quota_free_inode2(struct inode *, struct ucred *, enum ufs_quota_flags); + +int ufs_quota_delete(struct inode *); + int getinoquota __P((struct inode *)); -int getquota __P((struct mount *, u_long, int, caddr_t)); -int qsync __P((struct mount *mp)); int quotaoff __P((struct proc *, struct mount *, int)); -int quotaon __P((struct proc *, struct mount *, int, caddr_t)); -int setquota __P((struct mount *, u_long, int, caddr_t)); -int setuse __P((struct mount *, u_long, int, caddr_t)); +int qsync __P((struct mount *mp)); int ufs_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *)); -__END_DECLS -#ifdef DIAGNOSTIC -__BEGIN_DECLS -void chkdquot __P((struct inode *)); +void ufs_quota_init(void); + __END_DECLS -#endif #endif /* _KERNEL */ #endif /* _QUOTA_ */ diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h index c0f10acdf92..50175a0ec86 100644 --- a/sys/ufs/ufs/ufs_extern.h +++ b/sys/ufs/ufs/ufs_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_extern.h,v 1.11 2001/03/01 20:54:36 provos Exp $ */ +/* $OpenBSD: ufs_extern.h,v 1.12 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ufs_extern.h,v 1.5 1996/02/09 22:36:03 christos Exp $ */ /*- @@ -135,26 +135,6 @@ int ufs_dirrewrite __P((struct inode *, struct inode *, int ufs_dirempty __P((struct inode *, ino_t, struct ucred *)); int ufs_checkpath __P((struct inode *, struct inode *, struct ucred *)); -/* ufs_quota.c */ -int getinoquota __P((struct inode *)); -int chkdq __P((struct inode *, long, struct ucred *, int)); -int chkdqchg __P((struct inode *, long, struct ucred *, int)); -int chkiq __P((struct inode *, long, struct ucred *, int)); -int chkiqchg __P((struct inode *, long, struct ucred *, int)); -void chkdquot __P((struct inode *)); -int quotaon __P((struct proc *, struct mount *, int, caddr_t)); -int quotaoff __P((struct proc *, struct mount *, int)); -int getquota __P((struct mount *, u_long, int, caddr_t)); -int setquota __P((struct mount *, u_long, int, caddr_t)); -int setuse __P((struct mount *, u_long, int, caddr_t)); -int qsync __P((struct mount *)); -int dqget __P((struct vnode *, u_long, struct ufsmount *, int, - struct dquot **)); -void dqref __P((struct dquot *)); -void dqrele __P((struct vnode *, struct dquot *)); -int dqsync __P((struct vnode *, struct dquot *)); -void dqflush __P((struct vnode *)); - /* ufs_vfsops.c */ int ufs_start __P((struct mount *, int, struct proc *)); int ufs_root __P((struct mount *, struct vnode **)); diff --git a/sys/ufs/ufs/ufs_inode.c b/sys/ufs/ufs/ufs_inode.c index fa9caa326c6..8a3935632fb 100644 --- a/sys/ufs/ufs/ufs_inode.c +++ b/sys/ufs/ufs/ufs_inode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_inode.c,v 1.9 2001/07/16 02:56:48 csapuntz Exp $ */ +/* $OpenBSD: ufs_inode.c,v 1.10 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ufs_inode.c,v 1.7 1996/05/11 18:27:52 mycroft Exp $ */ /* @@ -67,9 +67,8 @@ ufs_init() return; done = 1; ufs_ihashinit(); -#ifdef QUOTA - dqinit(); -#endif + ufs_quota_init(); + return; } #endif @@ -99,10 +98,9 @@ ufs_inactive(v) if (ip->i_ffs_mode == 0) goto out; if (ip->i_ffs_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { -#ifdef QUOTA - if (!getinoquota(ip)) - (void)chkiq(ip, -1, NOCRED, 0); -#endif + if (getinoquota(ip) != 0) + (void)ufs_quota_free_inode(ip, NOCRED); + (void) UFS_TRUNCATE(ip, (off_t)0, 0, NOCRED); ip->i_ffs_rdev = 0; mode = ip->i_ffs_mode; @@ -150,16 +148,6 @@ ufs_reclaim(vp, p) vrele(ip->i_devvp); ip->i_devvp = 0; } -#ifdef QUOTA - { - int i; - for (i = 0; i < MAXQUOTAS; i++) { - if (ip->i_dquot[i] != NODQUOT) { - dqrele(vp, ip->i_dquot[i]); - ip->i_dquot[i] = NODQUOT; - } - } - } -#endif + ufs_quota_delete(ip); return (0); } diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index affc8bbfde5..492b1e0a18f 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ufs_quota.c,v 1.7 1999/04/28 09:28:18 art Exp $ */ +/* $OpenBSD: ufs_quota.c,v 1.8 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ufs_quota.c,v 1.8 1996/02/09 22:36:09 christos Exp $ */ /* - * Copyright (c) 1982, 1986, 1990, 1993 + * Copyright (c) 1982, 1986, 1990, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -36,7 +36,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)ufs_quota.c 8.3 (Berkeley) 8/19/94 + * @(#)ufs_quota.c 8.5 (Berkeley) 8/19/94 */ #include <sys/param.h> #include <sys/kernel.h> @@ -53,6 +53,86 @@ #include <ufs/ufs/ufsmount.h> #include <ufs/ufs/ufs_extern.h> +#include <sys/queue.h> + +/* + * The following structure records disk usage for a user or group on a + * filesystem. There is one allocated for each quota that exists on any + * filesystem for the current user or group. A cache is kept of recently + * used entries. + */ +struct dquot { + LIST_ENTRY(dquot) dq_hash; /* hash list */ + TAILQ_ENTRY(dquot) dq_freelist; /* free list */ + u_int16_t dq_flags; /* flags, see below */ + u_int16_t dq_cnt; /* count of active references */ + u_int16_t dq_spare; /* unused spare padding */ + u_int16_t dq_type; /* quota type of this dquot */ + u_int32_t dq_id; /* identifier this applies to */ + struct ufsmount *dq_ump; /* filesystem that this is taken from */ + struct dqblk dq_dqb; /* actual usage & quotas */ +}; +/* + * Flag values. + */ +#define DQ_LOCK 0x01 /* this quota locked (no MODS) */ +#define DQ_WANT 0x02 /* wakeup on unlock */ +#define DQ_MOD 0x04 /* this quota modified since read */ +#define DQ_FAKE 0x08 /* no limits here, just usage */ +#define DQ_BLKS 0x10 /* has been warned about blk limit */ +#define DQ_INODS 0x20 /* has been warned about inode limit */ +/* + * Shorthand notation. + */ +#define dq_bhardlimit dq_dqb.dqb_bhardlimit +#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit +#define dq_curblocks dq_dqb.dqb_curblocks +#define dq_ihardlimit dq_dqb.dqb_ihardlimit +#define dq_isoftlimit dq_dqb.dqb_isoftlimit +#define dq_curinodes dq_dqb.dqb_curinodes +#define dq_btime dq_dqb.dqb_btime +#define dq_itime dq_dqb.dqb_itime + +/* + * If the system has never checked for a quota for this file, then it is + * set to NODQUOT. Once a write attempt is made the inode pointer is set + * to reference a dquot structure. + */ +#define NODQUOT NULL + +/* + * Macros to avoid subroutine calls to trivial functions. + */ +#ifdef DIAGNOSTIC +#define DQREF(dq) dqref(dq) +#else +#define DQREF(dq) (dq)->dq_cnt++ +#endif + +void dqref __P((struct dquot *)); +void dqrele __P((struct vnode *, struct dquot *)); +int dqsync __P((struct vnode *, struct dquot *)); + +#ifdef DIAGNOSTIC +void chkdquot __P((struct inode *)); +#endif + +int getquota __P((struct mount *, u_long, int, caddr_t)); +int quotaon __P((struct proc *, struct mount *, int, caddr_t)); +int setquota __P((struct mount *, u_long, int, caddr_t)); +int setuse __P((struct mount *, u_long, int, caddr_t)); + +int chkdqchg __P((struct inode *, long, struct ucred *, int)); +int chkiqchg __P((struct inode *, long, struct ucred *, int)); + +int dqget __P((struct vnode *, u_long, struct ufsmount *, int, + struct dquot **)); +void dqflush __P((struct vnode *)); + +int quotaon_vnode(struct vnode *, void *); +int quotaoff_vnode(struct vnode *, void *); +int qsync_vnode(struct vnode *, void *); + /* * Quota name to error message mapping. */ @@ -68,7 +148,7 @@ static char *quotatypes[] = INITQFNAMES; */ int getinoquota(ip) - register struct inode *ip; + struct inode *ip; { struct ufsmount *ump; struct vnode *vp = ITOV(ip); @@ -99,43 +179,25 @@ getinoquota(ip) /* * Update disk usage, and take corrective action. */ -int -chkdq(ip, change, cred, flags) - register struct inode *ip; - long change; - struct ucred *cred; - int flags; -{ - register struct dquot *dq; - register int i; - int ncurblocks, error; +int +ufs_quota_alloc_blocks2(struct inode *ip, int32_t change, + struct ucred *cred, enum ufs_quota_flags flags) { + struct dquot *dq; + int i; + int error; #ifdef DIAGNOSTIC - if ((flags & CHOWN) == 0) - chkdquot(ip); + chkdquot(ip); #endif + if (change == 0) return (0); - if (change < 0) { + + if ((flags & UFS_QUOTA_FORCE) == 0 && + (cred != NOCRED && cred->cr_uid != 0)) { for (i = 0; i < MAXQUOTAS; i++) { - if ((dq = ip->i_dquot[i]) == NODQUOT) + if (flags & (1 << i)) continue; - while (dq->dq_flags & DQ_LOCK) { - dq->dq_flags |= DQ_WANT; - sleep((caddr_t)dq, PINOD+1); - } - ncurblocks = dq->dq_curblocks + change; - if (ncurblocks >= 0) - dq->dq_curblocks = ncurblocks; - else - dq->dq_curblocks = 0; - dq->dq_flags &= ~DQ_BLKS; - dq->dq_flags |= DQ_MOD; - } - return (0); - } - if ((flags & FORCE) == 0 && cred->cr_uid != 0) { - for (i = 0; i < MAXQUOTAS; i++) { if ((dq = ip->i_dquot[i]) == NODQUOT) continue; if ((error = chkdqchg(ip, change, cred, i)) != 0) @@ -143,11 +205,13 @@ chkdq(ip, change, cred, flags) } } for (i = 0; i < MAXQUOTAS; i++) { + if (flags & (1 << i)) + continue; if ((dq = ip->i_dquot[i]) == NODQUOT) continue; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; - sleep((caddr_t)dq, PINOD+1); + (void) tsleep(dq, PINOD+1, "chkdq", 0); } dq->dq_curblocks += change; dq->dq_flags |= DQ_MOD; @@ -155,6 +219,39 @@ chkdq(ip, change, cred, flags) return (0); } +int +ufs_quota_free_blocks2(struct inode *ip, int32_t change, + struct ucred *cred, enum ufs_quota_flags flags) { + struct dquot *dq; + int i; + +#ifdef DIAGNOSTIC + if (!VOP_ISLOCKED(ITOV(ip))) + panic ("ufs_quota_free_blocks2: vnode is not locked"); +#endif + + if (change == 0) + return (0); + + for (i = 0; i < MAXQUOTAS; i++) { + if (flags & (1 << i)) + continue; + if ((dq = ip->i_dquot[i]) == NODQUOT) + continue; + while (dq->dq_flags & DQ_LOCK) { + dq->dq_flags |= DQ_WANT; + (void) tsleep(dq, PINOD+1, "chkdq", 0); + } + if (dq->dq_curblocks >= change) + dq->dq_curblocks -= change; + else + dq->dq_curblocks = 0; + dq->dq_flags &= ~DQ_BLKS; + dq->dq_flags |= DQ_MOD; + } + return (0); +} + /* * Check for a valid change to a users allocation. * Issue an error message if appropriate. @@ -166,7 +263,7 @@ chkdqchg(ip, change, cred, type) struct ucred *cred; int type; { - register struct dquot *dq = ip->i_dquot[type]; + struct dquot *dq = ip->i_dquot[type]; long ncurblocks = dq->dq_curblocks + change; /* @@ -215,56 +312,64 @@ chkdqchg(ip, change, cred, type) * Check the inode limit, applying corrective action. */ int -chkiq(ip, change, cred, flags) - register struct inode *ip; - long change; - struct ucred *cred; - int flags; -{ - register struct dquot *dq; - register int i; - int ncurinodes, error; +ufs_quota_alloc_inode2(struct inode *ip, struct ucred *cred, + enum ufs_quota_flags flags) { + struct dquot *dq; + int i; + int error; #ifdef DIAGNOSTIC - if ((flags & CHOWN) == 0) - chkdquot(ip); + chkdquot(ip); #endif - if (change == 0) - return (0); - if (change < 0) { + + if ((flags & UFS_QUOTA_FORCE) == 0 && cred->cr_uid != 0) { for (i = 0; i < MAXQUOTAS; i++) { - if ((dq = ip->i_dquot[i]) == NODQUOT) + if (flags & (1 << i)) continue; - while (dq->dq_flags & DQ_LOCK) { - dq->dq_flags |= DQ_WANT; - sleep((caddr_t)dq, PINOD+1); - } - ncurinodes = dq->dq_curinodes + change; - if (ncurinodes >= 0) - dq->dq_curinodes = ncurinodes; - else - dq->dq_curinodes = 0; - dq->dq_flags &= ~DQ_INODS; - dq->dq_flags |= DQ_MOD; - } - return (0); - } - if ((flags & FORCE) == 0 && cred->cr_uid != 0) { - for (i = 0; i < MAXQUOTAS; i++) { if ((dq = ip->i_dquot[i]) == NODQUOT) continue; - if ((error = chkiqchg(ip, change, cred, i)) != 0) + if ((error = chkiqchg(ip, 1, cred, i)) != 0) return (error); } } for (i = 0; i < MAXQUOTAS; i++) { + if (flags & (1 << i)) + continue; + if ((dq = ip->i_dquot[i]) == NODQUOT) + continue; + while (dq->dq_flags & DQ_LOCK) { + dq->dq_flags |= DQ_WANT; + (void) tsleep(dq, PINOD+1, "chkiq", 0); + } + dq->dq_curinodes++; + dq->dq_flags |= DQ_MOD; + } + return (0); +} + +int +ufs_quota_free_inode2(struct inode *ip, struct ucred *cred, + enum ufs_quota_flags flags) { + struct dquot *dq; + int i; + +#ifdef DIAGNOSTIC + if (!VOP_ISLOCKED(ITOV(ip))) + panic ("ufs_quota_free_blocks2: vnode is not locked"); +#endif + + for (i = 0; i < MAXQUOTAS; i++) { + if (flags & (1 << i)) + continue; if ((dq = ip->i_dquot[i]) == NODQUOT) continue; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; - sleep((caddr_t)dq, PINOD+1); + (void) tsleep(dq, PINOD+1, "chkiq", 0); } - dq->dq_curinodes += change; + if (dq->dq_curinodes > 0) + dq->dq_curinodes--; + dq->dq_flags &= ~DQ_INODS; dq->dq_flags |= DQ_MOD; } return (0); @@ -281,7 +386,7 @@ chkiqchg(ip, change, cred, type) struct ucred *cred; int type; { - register struct dquot *dq = ip->i_dquot[type]; + struct dquot *dq = ip->i_dquot[type]; long ncurinodes = dq->dq_curinodes + change; /* @@ -333,11 +438,15 @@ chkiqchg(ip, change, cred, type) */ void chkdquot(ip) - register struct inode *ip; + struct inode *ip; { struct ufsmount *ump = VFSTOUFS(ITOV(ip)->v_mount); - register int i; + int i; + struct vnode *vp = ITOV(ip); + if (!VOP_ISLOCKED(vp)) + panic ("chkdquot: vnode is not locked"); + for (i = 0; i < MAXQUOTAS; i++) { if (ump->um_quotas[i] == NULLVP || (ump->um_qflags[i] & (QTF_OPENING|QTF_CLOSING))) @@ -354,6 +463,27 @@ chkdquot(ip) * Code to process quotactl commands. */ +int +quotaon_vnode(struct vnode *vp, void *arg) +{ + int error; + struct proc *p = (struct proc *)arg; + + if (vp->v_type == VNON || vp->v_writecount == 0) { + simple_unlock(&vp->v_interlock); + return (0); + } + + if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { + return (0); + } + + error = getinoquota(VTOI(vp)); + vput(vp); + + return (error); +} + /* * Q_QUOTAON - set up a quota file for a particular file system. */ @@ -361,16 +491,20 @@ int quotaon(p, mp, type, fname) struct proc *p; struct mount *mp; - register int type; + int type; caddr_t fname; { - register struct ufsmount *ump = VFSTOUFS(mp); - register struct vnode *vp, **vpp; - struct vnode *nextvp; + struct ufsmount *ump = VFSTOUFS(mp); + struct vnode *vp, **vpp; struct dquot *dq; int error; struct nameidata nd; +#ifdef DIAGNOSTIC + if (!vfs_isbusy(mp)) + panic ("quotaon: mount point not busy"); +#endif + vpp = &ump->um_quotas[type]; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, p); if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) @@ -407,27 +541,41 @@ quotaon(p, mp, type, fname) * adding references to quota file being opened. * NB: only need to add dquot's for inodes being modified. */ -again: - for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) { - nextvp = vp->v_mntvnodes.le_next; - if (vp->v_type == VNON || vp->v_writecount == 0) - continue; - if (vget(vp, LK_EXCLUSIVE, p)) - goto again; - if ((error = getinoquota(VTOI(vp))) != 0) { - vput(vp); - break; - } - vput(vp); - if (vp->v_mntvnodes.le_next != nextvp || vp->v_mount != mp) - goto again; - } + error = vfs_mount_foreach_vnode(mp, quotaon_vnode, p); + ump->um_qflags[type] &= ~QTF_OPENING; if (error) quotaoff(p, mp, type); return (error); } +struct quotaoff_arg { + struct proc *p; + int type; +}; + +int +quotaoff_vnode(struct vnode *vp, void *arg) +{ + struct quotaoff_arg *qa = (struct quotaoff_arg *)arg; + struct inode *ip; + struct dquot *dq; + + if (vp->v_type == VNON) { + simple_unlock(&vp->v_interlock); + return (0); + } + + if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, qa->p)) + return (0); + ip = VTOI(vp); + dq = ip->i_dquot[qa->type]; + ip->i_dquot[qa->type] = NODQUOT; + dqrele(vp, dq); + vput(vp); + return (0); +} + /* * Q_QUOTAOFF - turn off disk quotas for a filesystem. */ @@ -435,15 +583,17 @@ int quotaoff(p, mp, type) struct proc *p; struct mount *mp; - register int type; + int type; { - register struct vnode *vp; - struct vnode *qvp, *nextvp; + struct vnode *qvp; struct ufsmount *ump = VFSTOUFS(mp); - register struct dquot *dq; - register struct inode *ip; + struct quotaoff_arg qa; int error; +#ifdef DIAGNOSTIC + if (!vfs_isbusy(mp)) + panic ("quotaoff: mount point not busy"); +#endif if ((qvp = ump->um_quotas[type]) == NULLVP) return (0); ump->um_qflags[type] |= QTF_CLOSING; @@ -451,21 +601,10 @@ quotaoff(p, mp, type) * Search vnodes associated with this mount point, * deleting any references to quota file being closed. */ -again: - for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) { - nextvp = vp->v_mntvnodes.le_next; - if (vp->v_type == VNON) - continue; - if (vget(vp, LK_EXCLUSIVE, p)) - goto again; - ip = VTOI(vp); - dq = ip->i_dquot[type]; - ip->i_dquot[type] = NODQUOT; - dqrele(vp, dq); - vput(vp); - if (vp->v_mntvnodes.le_next != nextvp || vp->v_mount != mp) - goto again; - } + qa.p = p; + qa.type = type; + vfs_mount_foreach_vnode(mp, quotaoff_vnode, &qa); + dqflush(qvp); qvp->v_flag &= ~VSYSTEM; error = vn_close(qvp, FREAD|FWRITE, p->p_ucred, p); @@ -511,7 +650,7 @@ setquota(mp, id, type, addr) int type; caddr_t addr; { - register struct dquot *dq; + struct dquot *dq; struct dquot *ndq; struct ufsmount *ump = VFSTOUFS(mp); struct dqblk newlim; @@ -525,7 +664,7 @@ setquota(mp, id, type, addr) dq = ndq; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; - sleep((caddr_t)dq, PINOD+1); + (void) tsleep(dq, PINOD+1, "setquota", 0); } /* * Copy all but the current values. @@ -571,7 +710,7 @@ setuse(mp, id, type, addr) int type; caddr_t addr; { - register struct dquot *dq; + struct dquot *dq; struct ufsmount *ump = VFSTOUFS(mp); struct dquot *ndq; struct dqblk usage; @@ -585,7 +724,7 @@ setuse(mp, id, type, addr) dq = ndq; while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; - sleep((caddr_t)dq, PINOD+1); + (void) tsleep(dq, PINOD+1, "setuse", 0); } /* * Reset time limit if have a soft limit and were @@ -608,6 +747,31 @@ setuse(mp, id, type, addr) return (0); } + + +int +qsync_vnode(struct vnode *vp, void *arg) { + int i; + struct proc *p = curproc; + struct dquot *dq; + + if (vp->v_type == VNON) { + simple_unlock(&vp->v_interlock); + return (0); + } + + if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p)) + return (0); + + for (i = 0; i < MAXQUOTAS; i++) { + dq = VTOI(vp)->i_dquot[i]; + if (dq != NODQUOT && (dq->dq_flags & DQ_MOD)) + dqsync(vp, dq); + } + vput(vp); + return (0); +} + /* * Q_SYNC - sync quota files to disk. */ @@ -616,11 +780,7 @@ qsync(mp) struct mount *mp; { struct ufsmount *ump = VFSTOUFS(mp); - struct proc *p = curproc; - register struct vnode *vp, *nextvp; - register struct dquot *dq; - register int i; - int error = 0; + int i; /* * Check if the mount point has any quotas. @@ -635,34 +795,7 @@ qsync(mp) * Search vnodes associated with this mount point, * synchronizing any modified dquot structures. */ - simple_lock(&mntvnode_slock); -again: - for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) { - if (vp->v_mount != mp) - goto again; - nextvp = vp->v_mntvnodes.le_next; - if (vp->v_type == VNON) - continue; - simple_lock(&vp->v_interlock); - simple_unlock(&mntvnode_slock); - error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p); - if (error) { - simple_lock(&mntvnode_slock); - if (error == ENOENT) - goto again; - continue; - } - for (i = 0; i < MAXQUOTAS; i++) { - dq = VTOI(vp)->i_dquot[i]; - if (dq != NODQUOT && (dq->dq_flags & DQ_MOD)) - dqsync(vp, dq); - } - vput(vp); - simple_lock(&mntvnode_slock); - if (vp->v_mntvnodes.le_next != nextvp) - goto again; - } - simple_unlock(&mntvnode_slock); + vfs_mount_foreach_vnode(mp, qsync_vnode, NULL); return (0); } @@ -685,7 +818,7 @@ long numdquot, desireddquot = DQUOTINC; * Initialize the quota system. */ void -dqinit() +ufs_quota_init() { dqhashtbl = hashinit(desiredvnodes, M_DQUOT, M_WAITOK, &dqhash); @@ -700,14 +833,14 @@ int dqget(vp, id, ump, type, dqp) struct vnode *vp; u_long id; - register struct ufsmount *ump; - register int type; + struct ufsmount *ump; + int type; struct dquot **dqp; { struct proc *p = curproc; - register struct dquot *dq; + struct dquot *dq; struct dqhash *dqh; - register struct vnode *dqvp; + struct vnode *dqvp; struct iovec aiov; struct uio auio; int error; @@ -782,7 +915,7 @@ dqget(vp, id, ump, type, dqp) if (vp != dqvp) VOP_UNLOCK(dqvp, 0, p); if (dq->dq_flags & DQ_WANT) - wakeup((caddr_t)dq); + wakeup(dq); dq->dq_flags = 0; /* * I/O error in reading quota file, release @@ -828,7 +961,7 @@ dqref(dq) void dqrele(vp, dq) struct vnode *vp; - register struct dquot *dq; + struct dquot *dq; { if (dq == NODQUOT) @@ -850,7 +983,7 @@ dqrele(vp, dq) int dqsync(vp, dq) struct vnode *vp; - register struct dquot *dq; + struct dquot *dq; { struct proc *p = curproc; struct vnode *dqvp; @@ -868,7 +1001,7 @@ dqsync(vp, dq) vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY, p); while (dq->dq_flags & DQ_LOCK) { dq->dq_flags |= DQ_WANT; - sleep((caddr_t)dq, PINOD+2); + (void) tsleep(dq, PINOD+2, "dqsync", 0); if ((dq->dq_flags & DQ_MOD) == 0) { if (vp != dqvp) VOP_UNLOCK(dqvp, 0, p); @@ -889,7 +1022,7 @@ dqsync(vp, dq) if (auio.uio_resid && error == 0) error = EIO; if (dq->dq_flags & DQ_WANT) - wakeup((caddr_t)dq); + wakeup(dq); dq->dq_flags &= ~(DQ_MOD|DQ_LOCK|DQ_WANT); if (vp != dqvp) VOP_UNLOCK(dqvp, 0, p); @@ -901,9 +1034,9 @@ dqsync(vp, dq) */ void dqflush(vp) - register struct vnode *vp; + struct vnode *vp; { - register struct dquot *dq, *nextdq; + struct dquot *dq, *nextdq; struct dqhash *dqh; /* @@ -923,3 +1056,89 @@ dqflush(vp) } } } + +int +ufs_quota_delete(struct inode *ip) { + struct vnode *vp = ITOV(ip); + int i; + for (i = 0; i < MAXQUOTAS; i++) { + if (ip->i_dquot[i] != NODQUOT) { + dqrele(vp, ip->i_dquot[i]); + ip->i_dquot[i] = NODQUOT; + } + } + + return (0); +} + +/* + * Do operations associated with quotas + */ +int +ufs_quotactl(mp, cmds, uid, arg, p) + struct mount *mp; + int cmds; + uid_t uid; + caddr_t arg; + struct proc *p; +{ + int cmd, type, error; + + if (uid == -1) + uid = p->p_cred->p_ruid; + cmd = cmds >> SUBCMDSHIFT; + + switch (cmd) { + case Q_SYNC: + break; + case Q_GETQUOTA: + if (uid == p->p_cred->p_ruid) + break; + /* fall through */ + default: + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); + } + + type = cmds & SUBCMDMASK; + if ((u_int)type >= MAXQUOTAS) + return (EINVAL); + + if (vfs_busy(mp, LK_NOWAIT, 0, p)) + return (0); + + + switch (cmd) { + + case Q_QUOTAON: + error = quotaon(p, mp, type, arg); + break; + + case Q_QUOTAOFF: + error = quotaoff(p, mp, type); + break; + + case Q_SETQUOTA: + error = setquota(mp, uid, type, arg) ; + break; + + case Q_SETUSE: + error = setuse(mp, uid, type, arg); + break; + + case Q_GETQUOTA: + error = getquota(mp, uid, type, arg); + break; + + case Q_SYNC: + error = qsync(mp); + break; + + default: + error = EINVAL; + break; + } + + vfs_unbusy(mp, p); + return (error); +} diff --git a/sys/ufs/ufs/ufs_quota_stub.c b/sys/ufs/ufs/ufs_quota_stub.c new file mode 100644 index 00000000000..977525184b4 --- /dev/null +++ b/sys/ufs/ufs/ufs_quota_stub.c @@ -0,0 +1,73 @@ +/* $OpenBSD: ufs_quota_stub.c,v 1.1 2001/11/21 21:23:56 csapuntz Exp $ */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/namei.h> +#include <sys/malloc.h> +#include <sys/file.h> +#include <sys/proc.h> +#include <sys/vnode.h> +#include <sys/mount.h> + +#include <ufs/ufs/quota.h> +#include <ufs/ufs/inode.h> +#include <ufs/ufs/ufsmount.h> +#include <ufs/ufs/ufs_extern.h> + +#ifndef QUOTA + +int +getinoquota(struct inode *ip) { + return (0); +} + +int +ufs_quota_alloc_blocks2(struct inode *ip, ufs_daddr_t change, + struct ucred *cred, enum ufs_quota_flags flags) { + return (0); +} + +int +ufs_quota_free_blocks2(struct inode *ip, ufs_daddr_t change, + struct ucred *cred, enum ufs_quota_flags flags) { + return (0); +} + +int +ufs_quota_alloc_inode2(struct inode *ip, struct ucred *cred, + enum ufs_quota_flags flags) { + return (0); +} + +int +ufs_quota_free_inode2(struct inode *ip, struct ucred *cred, + enum ufs_quota_flags flags) { + return (0); +} + +int +quotaoff(struct proc *p, struct mount *mp, int flags) { + return (0); +} + +int +qsync(struct mount *mp) { + return (0); +} + +int +ufs_quotactl(struct mount *mp, int a, uid_t u, caddr_t addr, struct proc *p) { + return (EOPNOTSUPP); +} + +void +ufs_quota_init(void) { +} + +int +ufs_quota_delete(struct inode *ip) { + return (0); +} + +#endif diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c index 26e977735ad..81e10edf115 100644 --- a/sys/ufs/ufs/ufs_vfsops.c +++ b/sys/ufs/ufs/ufs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vfsops.c,v 1.7 2000/02/07 04:57:19 assar Exp $ */ +/* $OpenBSD: ufs_vfsops.c,v 1.8 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ufs_vfsops.c,v 1.4 1996/02/09 22:36:12 christos Exp $ */ /* @@ -89,84 +89,6 @@ ufs_root(mp, vpp) } /* - * Do operations associated with quotas - */ -int -ufs_quotactl(mp, cmds, uid, arg, p) - struct mount *mp; - int cmds; - uid_t uid; - caddr_t arg; - struct proc *p; -{ - -#ifndef QUOTA - return (EOPNOTSUPP); -#else - int cmd, type, error; - - if (uid == -1) - uid = p->p_cred->p_ruid; - cmd = cmds >> SUBCMDSHIFT; - - switch (cmd) { - case Q_SYNC: - break; - case Q_GETQUOTA: - if (uid == p->p_cred->p_ruid) - break; - /* fall through */ - default: - if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) - return (error); - } - - type = cmds & SUBCMDMASK; - if ((u_int)type >= MAXQUOTAS) - return (EINVAL); - - if (vfs_busy(mp, LK_NOWAIT, 0, p)) - return (0); - - - switch (cmd) { - - case Q_QUOTAON: - error = quotaon(p, mp, type, arg); - break; - - case Q_QUOTAOFF: - error = quotaoff(p, mp, type); - break; - - case Q_SETQUOTA: - error = setquota(mp, uid, type, arg) ; - break; - - case Q_SETUSE: - error = setuse(mp, uid, type, arg); - break; - - case Q_GETQUOTA: - error = getquota(mp, uid, type, arg); - break; - - case Q_SYNC: - error = qsync(mp); - break; - - default: - error = EINVAL; - break; - } - - vfs_unbusy(mp, p); - return (error); -#endif -} - - -/* * Verify a remote client has export rights and return these rights via. * exflagsp and credanonp. */ @@ -205,9 +127,8 @@ ufs_init(vfsp) return (0); done = 1; ufs_ihashinit(); -#ifdef QUOTA - dqinit(); -#endif + ufs_quota_init(); + return (0); } diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 684a0a1f563..4caf0ef78c7 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vnops.c,v 1.38 2001/11/06 19:53:21 miod Exp $ */ +/* $OpenBSD: ufs_vnops.c,v 1.39 2001/11/21 21:23:56 csapuntz Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* @@ -257,18 +257,15 @@ ufs_access(v) */ if (mode & VWRITE) { switch (vp->v_type) { -#ifdef QUOTA int error; -#endif case VDIR: case VLNK: case VREG: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); -#ifdef QUOTA + if ((error = getinoquota(ip)) != 0) return (error); -#endif break; case VBAD: case VBLK: @@ -493,10 +490,8 @@ ufs_chown(vp, uid, gid, cred, p) uid_t ouid; gid_t ogid; int error = 0; -#ifdef QUOTA - int i; - long change; -#endif + ufs_daddr_t change; + enum ufs_quota_flags quota_flags = 0; if (uid == (uid_t)VNOVAL) uid = ip->i_ffs_uid; @@ -513,68 +508,40 @@ ufs_chown(vp, uid, gid, cred, p) return (error); ogid = ip->i_ffs_gid; ouid = ip->i_ffs_uid; -#ifdef QUOTA + change = ip->i_ffs_blocks; + + if (ouid == uid) + quota_flags |= UFS_QUOTA_NOUID; + + if (ogid == gid) + quota_flags |= UFS_QUOTA_NOGID; + if ((error = getinoquota(ip)) != 0) return (error); - if (ouid == uid) { - dqrele(vp, ip->i_dquot[USRQUOTA]); - ip->i_dquot[USRQUOTA] = NODQUOT; - } - if (ogid == gid) { - dqrele(vp, ip->i_dquot[GRPQUOTA]); - ip->i_dquot[GRPQUOTA] = NODQUOT; - } - change = ip->i_ffs_blocks; - (void) chkdq(ip, -change, cred, CHOWN); - (void) chkiq(ip, -1, cred, CHOWN); - for (i = 0; i < MAXQUOTAS; i++) { - dqrele(vp, ip->i_dquot[i]); - ip->i_dquot[i] = NODQUOT; - } -#endif + (void) ufs_quota_free_blocks2(ip, change, cred, quota_flags); + (void) ufs_quota_free_inode2(ip, cred, quota_flags); + (void) ufs_quota_delete(ip); + ip->i_ffs_gid = gid; ip->i_ffs_uid = uid; -#ifdef QUOTA - if ((error = getinoquota(ip)) == 0) { - if (ouid == uid) { - dqrele(vp, ip->i_dquot[USRQUOTA]); - ip->i_dquot[USRQUOTA] = NODQUOT; - } - if (ogid == gid) { - dqrele(vp, ip->i_dquot[GRPQUOTA]); - ip->i_dquot[GRPQUOTA] = NODQUOT; - } - if ((error = chkdq(ip, change, cred, CHOWN)) == 0) { - if ((error = chkiq(ip, 1, cred, CHOWN)) == 0) - goto good; - else - (void) chkdq(ip, -change, cred, CHOWN|FORCE); - } - for (i = 0; i < MAXQUOTAS; i++) { - dqrele(vp, ip->i_dquot[i]); - ip->i_dquot[i] = NODQUOT; - } - } - ip->i_ffs_gid = ogid; - ip->i_ffs_uid = ouid; - if (getinoquota(ip) == 0) { - if (ouid == uid) { - dqrele(vp, ip->i_dquot[USRQUOTA]); - ip->i_dquot[USRQUOTA] = NODQUOT; - } - if (ogid == gid) { - dqrele(vp, ip->i_dquot[GRPQUOTA]); - ip->i_dquot[GRPQUOTA] = NODQUOT; - } - (void) chkdq(ip, change, cred, FORCE|CHOWN); - (void) chkiq(ip, 1, cred, FORCE|CHOWN); - (void) getinoquota(ip); + + if ((error = getinoquota(ip)) != 0) + goto error; + + if ((error = ufs_quota_alloc_blocks2(ip, change, cred, + quota_flags)) != 0) + goto error; + + if ((error = ufs_quota_alloc_inode2(ip, cred , + quota_flags)) != 0) { + (void)ufs_quota_free_blocks2(ip, change, cred, + quota_flags); + goto error; } - return (error); -good: + if (getinoquota(ip)) panic("chown: lost quota"); -#endif /* QUOTA */ + if (ouid != uid || ogid != gid) ip->i_flag |= IN_CHANGE; if (ouid != uid && cred->cr_uid != 0) @@ -582,6 +549,21 @@ good: if (ogid != gid && cred->cr_uid != 0) ip->i_ffs_mode &= ~ISGID; return (0); + +error: + (void) ufs_quota_delete(ip); + + ip->i_ffs_gid = ogid; + ip->i_ffs_uid = ouid; + if (getinoquota(ip) == 0) { + (void) ufs_quota_alloc_blocks2(ip, change, cred, + quota_flags | UFS_QUOTA_FORCE); + (void) ufs_quota_alloc_inode2(ip, cred, + quota_flags | UFS_QUOTA_FORCE); + (void) getinoquota(ip); + } + return (error); + } /* ARGSUSED */ @@ -1317,16 +1299,16 @@ ufs_mkdir(v) ip = VTOI(tvp); ip->i_ffs_uid = cnp->cn_cred->cr_uid; ip->i_ffs_gid = dp->i_ffs_gid; -#ifdef QUOTA + if ((error = getinoquota(ip)) || - (error = chkiq(ip, 1, cnp->cn_cred, 0))) { + (error = ufs_quota_alloc_inode(ip, cnp->cn_cred))) { free(cnp->cn_pnbuf, M_NAMEI); UFS_INODE_FREE(ip, ip->i_number, dmode); vput(tvp); vput(dvp); return (error); } -#endif + ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; ip->i_ffs_mode = dmode; tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ @@ -2129,16 +2111,16 @@ ufs_makeinode(mode, dvp, vpp, cnp) ip = VTOI(tvp); ip->i_ffs_gid = pdir->i_ffs_gid; ip->i_ffs_uid = cnp->cn_cred->cr_uid; -#ifdef QUOTA + if ((error = getinoquota(ip)) || - (error = chkiq(ip, 1, cnp->cn_cred, 0))) { + (error = ufs_quota_alloc_inode(ip, cnp->cn_cred))) { free(cnp->cn_pnbuf, M_NAMEI); UFS_INODE_FREE(ip, ip->i_number, mode); vput(tvp); vput(dvp); return (error); } -#endif + ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; ip->i_ffs_mode = mode; tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ |