* This code is derived from software contributed to Berkeley by
* Robert Elz at The University of Melbourne.
*
- * Redistribution is only permitted until one year after the first shipment
- * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
- * binary forms are permitted provided that: (1) source distributions retain
- * this entire copyright notice and comment, and (2) distributions including
- * binaries display the following acknowledgement: This product includes
- * software developed by the University of California, Berkeley and its
- * contributors'' in the documentation or other materials provided with the
- * distribution and in all advertising materials mentioning features or use
- * of this software. Neither the name of the University nor the names of
- * its contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
*
- * @(#)ufs_quota.c 7.4 (Berkeley) 6/28/90
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ufs_quota.c 7.11 (Berkeley) 6/21/91
*/
#include "param.h"
-#include "time.h"
#include "kernel.h"
#include "systm.h"
-#include "ucred.h"
#include "namei.h"
-#include "errno.h"
#include "malloc.h"
#include "file.h"
+#include "proc.h"
#include "vnode.h"
#include "mount.h"
-#include "../ufs/fs.h"
-#include "../ufs/quota.h"
-#include "../ufs/inode.h"
-#include "../ufs/ufsmount.h"
+
+#include "fs.h"
+#include "quota.h"
+#include "inode.h"
+#include "ufsmount.h"
/*
* Quota name to error message mapping.
/*
* Q_QUOTAON - set up a quota file for a particular file system.
*/
-quotaon(ndp, mp, type, fname)
- register struct nameidata *ndp;
+quotaon(p, mp, type, fname)
+ struct proc *p;
struct mount *mp;
register int type;
caddr_t fname;
struct vnode *nextvp;
struct dquot *dq;
int error;
-
+ struct nameidata nd;
+
vpp = &ump->um_quotas[type];
- ndp->ni_segflg = UIO_USERSPACE;
- ndp->ni_dirp = fname;
- if (error = vn_open(ndp, FREAD|FWRITE, 0))
+ nd.ni_segflg = UIO_USERSPACE;
+ nd.ni_dirp = fname;
+ if (error = vn_open(&nd, p, FREAD|FWRITE, 0))
return (error);
- vp = ndp->ni_vp;
+ vp = nd.ni_vp;
+ VOP_UNLOCK(vp);
if (vp->v_type != VREG) {
- vrele(vp);
+ (void) vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
return (EACCES);
}
if (vfs_busy(mp)) {
- vrele(vp);
+ (void) vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
return (EBUSY);
}
if (*vpp != vp)
- quotaoff(mp, type);
+ quotaoff(p, mp, type);
ump->um_qflags[type] |= QTF_OPENING;
mp->mnt_flag |= MNT_QUOTA;
vp->v_flag |= VSYSTEM;
* Save the credential of the process that turned on quotas.
* Set up the time limits for this quota.
*/
- crhold(ndp->ni_cred);
- ump->um_cred[type] = ndp->ni_cred;
+ crhold(p->p_ucred);
+ ump->um_cred[type] = p->p_ucred;
ump->um_btime[type] = MAX_DQ_TIME;
ump->um_itime[type] = MAX_IQ_TIME;
if (dqget(NULLVP, 0, ump, type, &dq) == 0) {
/*
* Search vnodes associated with this mount point,
* adding references to quota file being opened.
- * NB: only need to add dquot's for inodes being modified;
- * vp->v_usecount == 0 below should use vp->v_writecnt == 0.
+ * NB: only need to add dquot's for inodes being modified.
*/
again:
for (vp = mp->mnt_mounth; vp; vp = nextvp) {
nextvp = vp->v_mountf;
- if (vp->v_usecount == 0)
+ if (vp->v_writecount == 0)
continue;
if (vget(vp))
goto again;
- if (error = getinoquota(VTOI(vp)))
+ if (error = getinoquota(VTOI(vp))) {
+ vput(vp);
break;
+ }
vput(vp);
if (vp->v_mountf != nextvp || vp->v_mount != mp)
goto again;
}
ump->um_qflags[type] &= ~QTF_OPENING;
if (error)
- quotaoff(mp, type);
+ quotaoff(p, mp, type);
vfs_unbusy(mp);
return (error);
}
/*
* Q_QUOTAOFF - turn off disk quotas for a filesystem.
*/
-quotaoff(mp, type)
+quotaoff(p, mp, type)
+ struct proc *p;
struct mount *mp;
register int type;
{
struct ufsmount *ump = VFSTOUFS(mp);
register struct dquot *dq;
register struct inode *ip;
+ int error;
if ((mp->mnt_flag & MNT_MPBUSY) == 0)
panic("quotaoff: not busy");
}
dqflush(qvp);
qvp->v_flag &= ~VSYSTEM;
- vrele(qvp);
+ error = vn_close(qvp, FREAD|FWRITE, p->p_ucred, p);
ump->um_quotas[type] = NULLVP;
crfree(ump->um_cred[type]);
ump->um_cred[type] = NOCRED;
break;
if (type == MAXQUOTAS)
mp->mnt_flag &= ~MNT_QUOTA;
- return (0);
+ return (error);
}
/*
register int i;
/*
- * Search vnodes associated with this mount point,
- * synchronizing any modified dquot structures.
+ * Check if the mount point has any quotas.
+ * If not, simply return.
*/
if ((mp->mnt_flag & MNT_MPBUSY) == 0)
panic("qsync: not busy");
+ for (i = 0; i < MAXQUOTAS; i++)
+ if (ump->um_quotas[i] != NULLVP)
+ break;
+ if (i == MAXQUOTAS)
+ return (0);
+ /*
+ * Search vnodes associated with this mount point,
+ * synchronizing any modified dquot structures.
+ */
again:
for (vp = mp->mnt_mounth; vp; vp = nextvp) {
nextvp = vp->v_mountf;
+ if (VOP_ISLOCKED(vp))
+ continue;
if (vget(vp))
goto again;
for (i = 0; i < MAXQUOTAS; i++) {
auio.uio_offset = (off_t)(id * sizeof (struct dqblk));
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_rw = UIO_READ;
+ auio.uio_procp = (struct proc *)0;
error = VOP_READ(dqvp, &auio, 0, ump->um_cred[type]);
if (auio.uio_resid == sizeof(struct dqblk) && error == 0)
bzero((caddr_t)&dq->dq_dqb, sizeof(struct dqblk));
while (dq->dq_flags & DQ_LOCK) {
dq->dq_flags |= DQ_WANT;
sleep((caddr_t)dq, PINOD+2);
- if ((dq->dq_flags & DQ_MOD) == 0)
+ if ((dq->dq_flags & DQ_MOD) == 0) {
+ if (vp != dqvp)
+ VOP_UNLOCK(dqvp);
return (0);
+ }
}
dq->dq_flags |= DQ_LOCK;
auio.uio_iov = &aiov;
auio.uio_offset = (off_t)(dq->dq_id * sizeof (struct dqblk));
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_rw = UIO_WRITE;
+ auio.uio_procp = (struct proc *)0;
error = VOP_WRITE(dqvp, &auio, 0, dq->dq_ump->um_cred[dq->dq_type]);
if (auio.uio_resid && error == 0)
error = EIO;