summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>2001-11-21 21:23:57 +0000
committerConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>2001-11-21 21:23:57 +0000
commit2eb4d9d2d38cc3eb793eb11a9635b95d702fbc8c (patch)
treeb79f1f20dc3691c47d6083bdb3f285c530af0c46 /sys
parent707190112f1bbf51379b1e841680aac8aaec1c77 (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/files3
-rw-r--r--sys/ufs/ffs/ffs_alloc.c105
-rw-r--r--sys/ufs/ffs/ffs_balloc.c7
-rw-r--r--sys/ufs/ffs/ffs_inode.c15
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c18
-rw-r--r--sys/ufs/ufs/quota.h102
-rw-r--r--sys/ufs/ufs/ufs_extern.h22
-rw-r--r--sys/ufs/ufs/ufs_inode.c26
-rw-r--r--sys/ufs/ufs/ufs_quota.c541
-rw-r--r--sys/ufs/ufs/ufs_quota_stub.c73
-rw-r--r--sys/ufs/ufs/ufs_vfsops.c85
-rw-r--r--sys/ufs/ufs/ufs_vnops.c122
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(). */