diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 827af171d8b9..a746a69a2de5 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -188,6 +188,7 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) *bnp = bno; return (0); } +nospace: #ifdef QUOTA UFS_UNLOCK(ump); /* @@ -196,7 +197,6 @@ ffs_alloc(ip, lbn, bpref, size, cred, bnp) (void) chkdq(ip, -btodb(size), cred, FORCE); UFS_LOCK(ump); #endif -nospace: if (fs->fs_pendingblocks > 0 && reclaimed == 0) { reclaimed = 1; softdep_request_cleanup(fs, ITOV(ip)); diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 6ab9af25bcde..14b231cda6eb 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -281,6 +281,7 @@ ffs_snapshot(mp, snapfile) return (error); } vp = nd.ni_vp; + vp->v_vflag |= VV_SYSTEM; ip = VTOI(vp); devvp = ip->i_devvp; /* @@ -367,18 +368,6 @@ ffs_snapshot(mp, snapfile) if (error) goto out; } -#ifdef QUOTA - /* - * Turn off disk quotas for snapshot file. - */ - (void) chkdq(ip, -DIP(ip, i_blocks), KERNCRED, FORCE); - for (i = 0; i < MAXQUOTAS; i++) { - if (ip->i_dquot[i] != NODQUOT) { - dqrele(vp, ip->i_dquot[i]); - ip->i_dquot[i] = NODQUOT; - } - } -#endif /* * Change inode to snapshot type file. */ @@ -682,7 +671,6 @@ ffs_snapshot(mp, snapfile) devvp->v_vflag |= VV_COPYONWRITE; VI_UNLOCK(devvp); ASSERT_VOP_LOCKED(vp, "ffs_snapshot vp"); - vp->v_vflag |= VV_SYSTEM; out1: KASSERT((sn != NULL && sbp != NULL && error == 0) || (sn == NULL && sbp == NULL && error != 0), diff --git a/sys/ufs/ufs/quota.h b/sys/ufs/ufs/quota.h index 8fb9eb267c18..a42493e8f17e 100644 --- a/sys/ufs/ufs/quota.h +++ b/sys/ufs/ufs/quota.h @@ -174,7 +174,7 @@ struct ucred; struct vnode; int chkdq(struct inode *, int64_t, struct ucred *, int); -int chkiq(struct inode *, ino_t, struct ucred *, int); +int chkiq(struct inode *, int, struct ucred *, int); void dqinit(void); void dqrele(struct vnode *, struct dquot *); void dquninit(void); diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index c4a93cdbfb7f..a3f426bc7902 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -72,7 +72,7 @@ static MALLOC_DEFINE(M_DQUOT, "ufs_quota", "UFS quota entries"); static char *quotatypes[] = INITQFNAMES; static int chkdqchg(struct inode *, ufs2_daddr_t, struct ucred *, int); -static int chkiqchg(struct inode *, ino_t, struct ucred *, int); +static int chkiqchg(struct inode *, int, struct ucred *, int); static int dqget(struct vnode *, u_long, struct ufsmount *, int, struct dquot **); static int dqsync(struct vnode *, struct dquot *); @@ -99,13 +99,18 @@ getinoquota(ip) struct vnode *vp = ITOV(ip); int error; -#ifndef NO_FFS_SNAPSHOT /* - * Disk quotas must be turned off for snapshot files. + * Disk quotas must be turned off for system files. Currently + * snapshot and quota files. */ - if ((ip->i_flags & SF_SNAPSHOT) != 0) + if ((vp->v_vflag & VV_SYSTEM) != 0) + return (0); + /* + * XXX: Turn off quotas for files with a negative UID or GID. + * This prevents the creation of 100GB+ quota files. + */ + if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0) return (0); -#endif ump = VFSTOUFS(vp->v_mount); /* * Set up the user quota based on file uid. @@ -140,8 +145,21 @@ chkdq(ip, change, cred, flags) { struct dquot *dq; ufs2_daddr_t ncurblocks; + struct vnode *vp = ITOV(ip); int i, error; + /* + * Disk quotas must be turned off for system files. Currently + * snapshot and quota files. + */ + if ((vp->v_vflag & VV_SYSTEM) != 0) + return (0); + /* + * XXX: Turn off quotas for files with a negative UID or GID. + * This prevents the creation of 100GB+ quota files. + */ + if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0) + return (0); #ifdef DIAGNOSTIC if ((flags & CHOWN) == 0) chkdquot(ip); @@ -256,7 +274,7 @@ chkdqchg(ip, change, cred, type) int chkiq(ip, change, cred, flags) struct inode *ip; - ino_t change; + int change; struct ucred *cred; int flags; { @@ -270,7 +288,6 @@ chkiq(ip, change, cred, flags) #endif if (change == 0) return (0); - /* XXX: change is unsigned */ if (change < 0) { for (i = 0; i < MAXQUOTAS; i++) { if ((dq = ip->i_dquot[i]) == NODQUOT) @@ -281,7 +298,7 @@ chkiq(ip, change, cred, flags) } ncurinodes = dq->dq_curinodes + change; /* XXX: ncurinodes is unsigned */ - if (ncurinodes >= 0) + if (dq->dq_curinodes != 0 && ncurinodes >= 0) dq->dq_curinodes = ncurinodes; else dq->dq_curinodes = 0; @@ -325,7 +342,7 @@ chkiq(ip, change, cred, flags) static int chkiqchg(ip, change, cred, type) struct inode *ip; - ino_t change; + int change; struct ucred *cred; int type; { @@ -384,15 +401,21 @@ chkdquot(ip) struct inode *ip; { struct ufsmount *ump = VFSTOUFS(ITOV(ip)->v_mount); + struct vnode *vp = ITOV(ip); int i; -#ifndef NO_FFS_SNAPSHOT /* - * Disk quotas must be turned off for snapshot files. + * Disk quotas must be turned off for system files. Currently + * these are snapshots and quota files. */ - if ((ip->i_flags & SF_SNAPSHOT) != 0) + if ((vp->v_vflag & VV_SYSTEM) != 0) return; -#endif + /* + * XXX: Turn off quotas for files with a negative UID or GID. + * This prevents the creation of 100GB+ quota files. + */ + if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0) + return (0); for (i = 0; i < MAXQUOTAS; i++) { if (ump->um_quotas[i] == NULLVP || (ump->um_qflags[i] & (QTF_OPENING|QTF_CLOSING))) @@ -929,7 +952,7 @@ dqget(vp, id, ump, type, dqp) aiov.iov_base = &dq->dq_dqb; aiov.iov_len = sizeof (struct dqblk); auio.uio_resid = sizeof (struct dqblk); - auio.uio_offset = (off_t)(id * sizeof (struct dqblk)); + auio.uio_offset = (off_t)id * sizeof (struct dqblk); auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_READ; auio.uio_td = (struct thread *)0; @@ -1044,7 +1067,7 @@ dqsync(vp, dq) aiov.iov_base = &dq->dq_dqb; aiov.iov_len = sizeof (struct dqblk); auio.uio_resid = sizeof (struct dqblk); - auio.uio_offset = (off_t)(dq->dq_id * sizeof (struct dqblk)); + auio.uio_offset = (off_t)dq->dq_id * sizeof (struct dqblk); auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_WRITE; auio.uio_td = (struct thread *)0;