iaccess moves into ufs_access; changes for the new quota implementation
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Thu, 3 May 1990 10:41:39 +0000 (02:41 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Thu, 3 May 1990 10:41:39 +0000 (02:41 -0800)
SCCS-vsn: sys/ufs/ffs/ffs_vnops.c 7.36
SCCS-vsn: sys/ufs/ffs/ufs_vnops.c 7.36
SCCS-vsn: sys/ufs/lfs/lfs_vnops.c 7.36
SCCS-vsn: sys/ufs/ufs/ufs_vnops.c 7.36
SCCS-vsn: sys/ufs/ffs/ffs_inode.c 7.30
SCCS-vsn: sys/ufs/ffs/ufs_inode.c 7.30
SCCS-vsn: sys/ufs/lfs/lfs_inode.c 7.30
SCCS-vsn: sys/ufs/ufs/ufs_inode.c 7.30

usr/src/sys/ufs/ffs/ffs_inode.c
usr/src/sys/ufs/ffs/ffs_vnops.c
usr/src/sys/ufs/ffs/ufs_inode.c
usr/src/sys/ufs/ffs/ufs_vnops.c
usr/src/sys/ufs/lfs/lfs_inode.c
usr/src/sys/ufs/lfs/lfs_vnops.c
usr/src/sys/ufs/ufs/ufs_inode.c
usr/src/sys/ufs/ufs/ufs_vnops.c

index 06acd86..b0d6fdb 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)ffs_inode.c 7.29 (Berkeley) %G%
+ *     @(#)ffs_inode.c 7.30 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
 #include "buf.h"
 #include "cmap.h"
 #include "vnode.h"
 #include "buf.h"
 #include "cmap.h"
 #include "vnode.h"
+#include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/ufsmount.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/ufsmount.h"
-#ifdef QUOTA
-#include "../ufs/quota.h"
-#endif
 #include "kernel.h"
 #include "malloc.h"
 
 #include "kernel.h"
 #include "malloc.h"
 
@@ -65,6 +63,9 @@ ufs_init()
                ih->ih_head[0] = ih;
                ih->ih_head[1] = ih;
        }
                ih->ih_head[0] = ih;
                ih->ih_head[1] = ih;
        }
+#ifdef QUOTA
+       dqinit();
+#endif /* QUOTA */
 }
 
 /*
 }
 
 /*
@@ -91,8 +92,8 @@ iget(xp, ino, ipp)
        struct vnode *nvp;
        struct buf *bp;
        struct dinode *dp;
        struct vnode *nvp;
        struct buf *bp;
        struct dinode *dp;
-       union  ihead *ih;
-       int error;
+       union ihead *ih;
+       int i, error;
 
        ih = &ihead[INOHASH(dev, ino)];
 loop:
 
        ih = &ihead[INOHASH(dev, ino)];
 loop:
@@ -123,7 +124,8 @@ loop:
        ip->i_mode = 0;
        ip->i_diroff = 0;
 #ifdef QUOTA
        ip->i_mode = 0;
        ip->i_diroff = 0;
 #ifdef QUOTA
-       ip->i_dquot = NODQUOT;
+       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
 #endif
        /*
         * Put it onto its hash chain and lock it so that other requests for
@@ -198,10 +200,6 @@ loop:
        ip->i_fs = fs;
        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
        VREF(ip->i_devvp);
        ip->i_fs = fs;
        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
        VREF(ip->i_devvp);
-#ifdef QUOTA
-       if (ip->i_mode != 0)
-               ip->i_dquot = inoquota(ip);
-#endif
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
@@ -252,17 +250,15 @@ ufs_inactive(vp)
        }
        ILOCK(ip);
        if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) {
        }
        ILOCK(ip);
        if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) {
+#ifdef QUOTA
+               if (!getinoquota(ip))
+                       (void) chkiq(ip, -1, NOCRED, 0);
+#endif
                error = itrunc(ip, (u_long)0, 0);
                mode = ip->i_mode;
                ip->i_mode = 0;
                error = itrunc(ip, (u_long)0, 0);
                mode = ip->i_mode;
                ip->i_mode = 0;
-               ip->i_rdev = 0;
                ip->i_flag |= IUPD|ICHG;
                ifree(ip, ip->i_number, mode);
                ip->i_flag |= IUPD|ICHG;
                ifree(ip, ip->i_number, mode);
-#ifdef QUOTA
-               (void) chkiq(ip->i_dev, ip, ip->i_uid, 0);
-               dqrele(ip->i_dquot);
-               ip->i_dquot = NODQUOT;
-#endif
        }
        IUPDAT(ip, &time, &time, 0);
        IUNLOCK(ip);
        }
        IUPDAT(ip, &time, &time, 0);
        IUNLOCK(ip);
@@ -271,8 +267,7 @@ ufs_inactive(vp)
         * If we are done with the inode, reclaim it
         * so that it can be reused immediately.
         */
         * If we are done with the inode, reclaim it
         * so that it can be reused immediately.
         */
-       if (vp->v_usecount == 0 && ip->i_mode == 0 &&
-           (vp->v_flag & VXLOCK) == 0)
+       if (vp->v_usecount == 0 && ip->i_mode == 0)
                vgone(vp);
        return (error);
 }
                vgone(vp);
        return (error);
 }
@@ -284,6 +279,7 @@ ufs_reclaim(vp)
        register struct vnode *vp;
 {
        register struct inode *ip = VTOI(vp);
        register struct vnode *vp;
 {
        register struct inode *ip = VTOI(vp);
+       int i;
 
        if (prtactive && vp->v_usecount != 0)
                vprint("ufs_reclaim: pushing active", vp);
 
        if (prtactive && vp->v_usecount != 0)
                vprint("ufs_reclaim: pushing active", vp);
@@ -302,8 +298,12 @@ ufs_reclaim(vp)
                ip->i_devvp = 0;
        }
 #ifdef QUOTA
                ip->i_devvp = 0;
        }
 #ifdef QUOTA
-       dqrele(ip->i_dquot);
-       ip->i_dquot = NODQUOT;
+       for (i = 0; i < MAXQUOTAS; i++) {
+               if (ip->i_dquot[i] != NODQUOT) {
+                       dqrele(vp, ip->i_dquot[i]);
+                       ip->i_dquot[i] = NODQUOT;
+               }
+       }
 #endif
        ip->i_flag = 0;
        return (0);
 #endif
        ip->i_flag = 0;
        return (0);
@@ -411,6 +411,10 @@ itrunc(oip, length, flags)
                aflags = B_CLRBUF;
                if (flags & IO_SYNC)
                        aflags |= B_SYNC;
                aflags = B_CLRBUF;
                if (flags & IO_SYNC)
                        aflags |= B_SYNC;
+#ifdef QUOTA
+               if (error = getinoquota(oip))
+                       return (error);
+#endif
                if (error = balloc(oip, lbn, offset, &bp, aflags))
                        return (error);
                oip->i_size = length;
                if (error = balloc(oip, lbn, offset, &bp, aflags))
                        return (error);
                oip->i_size = length;
@@ -527,7 +531,8 @@ done:
                oip->i_blocks = 0;
        oip->i_flag |= ICHG;
 #ifdef QUOTA
                oip->i_blocks = 0;
        oip->i_flag |= ICHG;
 #ifdef QUOTA
-       (void) chkdq(oip, -blocksreleased, 0);
+       if (!getinoquota(oip))
+               (void) chkdq(oip, -blocksreleased, NOCRED, 0);
 #endif
        return (allerror);
 }
 #endif
        return (allerror);
 }
@@ -670,44 +675,3 @@ iunlock(ip)
                wakeup((caddr_t)ip);
        }
 }
                wakeup((caddr_t)ip);
        }
 }
-
-/*
- * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
- * The mode is shifted to select the owner/group/other fields. The
- * super user is granted all permissions.
- *
- * NB: Called from vnode op table. It seems this could all be done
- * using vattr's but...
- */
-iaccess(ip, mode, cred)
-       register struct inode *ip;
-       register int mode;
-       struct ucred *cred;
-{
-       register gid_t *gp;
-       int i;
-
-       /*
-        * If you're the super-user, you always get access.
-        */
-       if (cred->cr_uid == 0)
-               return (0);
-       /*
-        * Access check is based on only one of owner, group, public.
-        * If not owner, then check group. If not a member of the
-        * group, then check public access.
-        */
-       if (cred->cr_uid != ip->i_uid) {
-               mode >>= 3;
-               gp = cred->cr_groups;
-               for (i = 0; i < cred->cr_ngroups; i++, gp++)
-                       if (ip->i_gid == *gp)
-                               goto found;
-               mode >>= 3;
-found:
-               ;
-       }
-       if ((ip->i_mode & mode) != 0)
-               return (0);
-       return (EACCES);
-}
index b43745b..cbe31ff 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)ffs_vnops.c 7.35 (Berkeley) %G%
+ *     @(#)ffs_vnops.c 7.36 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -31,9 +31,9 @@
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
+#include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
-#include "../ufs/quota.h"
 
 /*
  * Global vfs data structures for ufs
 
 /*
  * Global vfs data structures for ufs
@@ -295,13 +295,58 @@ ufs_close(vp, fflag, cred)
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
+ * The mode is shifted to select the owner/group/other fields. The
+ * super user is granted all permissions.
+ */
 ufs_access(vp, mode, cred)
        struct vnode *vp;
 ufs_access(vp, mode, cred)
        struct vnode *vp;
-       int mode;
+       register int mode;
        struct ucred *cred;
 {
        struct ucred *cred;
 {
+       register struct inode *ip = VTOI(vp);
+       register gid_t *gp;
+       int i, error;
 
 
-       return (iaccess(VTOI(vp), mode, cred));
+#ifdef DIAGNOSTIC
+       if (!VOP_ISLOCKED(vp)) {
+               vprint("ufs_access: not locked", vp);
+               panic("ufs_access: not locked");
+       }
+#endif
+#ifdef QUOTA
+       if (mode & VWRITE) {
+               switch (vp->v_type) {
+               case VREG: case VDIR: case VLNK:
+                       if (error = getinoquota(ip))
+                               return (error);
+               }
+       }
+#endif /* QUOTA */
+       /*
+        * If you're the super-user, you always get access.
+        */
+       if (cred->cr_uid == 0)
+               return (0);
+       /*
+        * Access check is based on only one of owner, group, public.
+        * If not owner, then check group. If not a member of the
+        * group, then check public access.
+        */
+       if (cred->cr_uid != ip->i_uid) {
+               mode >>= 3;
+               gp = cred->cr_groups;
+               for (i = 0; i < cred->cr_ngroups; i++, gp++)
+                       if (ip->i_gid == *gp)
+                               goto found;
+               mode >>= 3;
+found:
+               ;
+       }
+       if ((ip->i_mode & mode) != 0)
+               return (0);
+       return (EACCES);
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -323,7 +368,12 @@ ufs_getattr(vp, vap, cred)
        vap->va_uid = ip->i_uid;
        vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)ip->i_rdev;
        vap->va_uid = ip->i_uid;
        vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)ip->i_rdev;
+#ifdef tahoe
+       vap->va_size = ip->i_size;
+       vap->va_size_rsv = 0;
+#else
        vap->va_qsize = ip->i_din.di_qsize;
        vap->va_qsize = ip->i_din.di_qsize;
+#endif
        vap->va_atime.tv_sec = ip->i_atime;
        vap->va_atime.tv_usec = 0;
        vap->va_mtime.tv_sec = ip->i_mtime;
        vap->va_atime.tv_sec = ip->i_atime;
        vap->va_atime.tv_usec = 0;
        vap->va_mtime.tv_sec = ip->i_mtime;
@@ -446,10 +496,13 @@ chown1(vp, uid, gid, cred)
        struct ucred *cred;
 {
        register struct inode *ip = VTOI(vp);
        struct ucred *cred;
 {
        register struct inode *ip = VTOI(vp);
+       uid_t ouid;
+       gid_t ogid;
+       int error = 0;
 #ifdef QUOTA
 #ifdef QUOTA
-       register long change;
+       register int i;
+       long change;
 #endif
 #endif
-       int error;
 
        if (uid == (u_short)VNOVAL)
                uid = ip->i_uid;
 
        if (uid == (u_short)VNOVAL)
                uid = ip->i_uid;
@@ -464,30 +517,74 @@ chown1(vp, uid, gid, cred)
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &u.u_acflag)))
                return (error);
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &u.u_acflag)))
                return (error);
+       ouid = ip->i_uid;
+       ogid = ip->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_uid == uid)           /* this just speeds things a little */
-               change = 0;
-       else
-               change = ip->i_blocks;
-       (void) chkdq(ip, -change, 1);
-       (void) chkiq(ip->i_dev, ip, ip->i_uid, 1);
-       dqrele(ip->i_dquot);
+       if (error = getinoquota(ip))
+               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_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
 #endif
-       if (ip->i_uid != uid && cred->cr_uid != 0)
-               ip->i_mode &= ~ISUID;
-       if (ip->i_gid != gid && cred->cr_uid != 0)
-               ip->i_mode &= ~ISGID;
        ip->i_uid = uid;
        ip->i_gid = gid;
        ip->i_uid = uid;
        ip->i_gid = gid;
-       ip->i_flag |= ICHG;
 #ifdef QUOTA
 #ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-       (void) chkdq(ip, change, 1);
-       (void) chkiq(ip->i_dev, (struct inode *)NULL, (uid_t)uid, 1);
-       return (u.u_error);             /* should == 0 ALWAYS !! */
-#else
-       return (0);
+       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)
+                               return (0);
+                       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_uid = ouid;
+       ip->i_gid = ogid;
+       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);
+               (void) chkiq(ip, 1, cred, FORCE);
+       }
+       if (error)
+               return (error);
 #endif
 #endif
+       if (ouid != uid || ogid != gid)
+               ip->i_flag |= ICHG;
+       if (ouid != uid && cred->cr_uid != 0)
+               ip->i_mode &= ~ISUID;
+       if (ogid != gid && cred->cr_uid != 0)
+               ip->i_mode &= ~ISGID;
+       return (0);
 }
 
 /*
 }
 
 /*
@@ -855,7 +952,7 @@ ufs_rename(fndp, tndp)
        if (oldparent != dp->i_number)
                newparent = dp->i_number;
        if (doingdirectory && newparent) {
        if (oldparent != dp->i_number)
                newparent = dp->i_number;
        if (doingdirectory && newparent) {
-               if (error = iaccess(ip, IWRITE, tndp->ni_cred))
+               if (error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred))
                        goto bad;
                tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
                        goto bad;
                tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
@@ -1075,25 +1172,26 @@ ufs_mkdir(ndp, vap)
         * directory.  The entry is made later
         * after writing "." and ".." entries out.
         */
         * directory.  The entry is made later
         * after writing "." and ".." entries out.
         */
-       error = ialloc(dp, dirpref(dp->i_fs), dmode, &tip);
-       if (error) {
+       if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
                iput(dp);
                return (error);
        }
        ip = tip;
                iput(dp);
                return (error);
        }
        ip = tip;
+       ip->i_uid = ndp->ni_cred->cr_uid;
+       ip->i_gid = dp->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_dquot != NODQUOT)
-               panic("mkdir: dquot");
+       if ((error = getinoquota(ip)) ||
+           (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+               ifree(ip, ip->i_number, dmode);
+               iput(ip);
+               iput(dp);
+               return (error);
+       }
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
        ip->i_mode = dmode;
        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
        ip->i_nlink = 2;
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
        ip->i_mode = dmode;
        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
        ip->i_nlink = 2;
-       ip->i_uid = ndp->ni_cred->cr_uid;
-       ip->i_gid = dp->i_gid;
-#ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-#endif
        error = iupdat(ip, &time, &time, 1);
 
        /*
        error = iupdat(ip, &time, &time, 1);
 
        /*
@@ -1554,49 +1652,57 @@ maknode(mode, ndp, ipp)
        int error;
 
        *ipp = 0;
        int error;
 
        *ipp = 0;
+       if ((mode & IFMT) == 0)
+               mode |= IFREG;
        if ((mode & IFMT) == IFDIR)
                ipref = dirpref(pdir->i_fs);
        else
                ipref = pdir->i_number;
        if ((mode & IFMT) == IFDIR)
                ipref = dirpref(pdir->i_fs);
        else
                ipref = pdir->i_number;
-       error = ialloc(pdir, ipref, mode, &tip);
-       if (error) {
+       if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
                iput(pdir);
                return (error);
        }
        ip = tip;
                iput(pdir);
                return (error);
        }
        ip = tip;
+       ip->i_uid = ndp->ni_cred->cr_uid;
+       ip->i_gid = pdir->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_dquot != NODQUOT)
-               panic("maknode: dquot");
+       if ((error = getinoquota(ip)) ||
+           (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+               ifree(ip, ip->i_number, mode);
+               iput(ip);
+               iput(pdir);
+               return (error);
+       }
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
-       if ((mode & IFMT) == 0)
-               mode |= IFREG;
        ip->i_mode = mode;
        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
        ip->i_nlink = 1;
        ip->i_mode = mode;
        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
        ip->i_nlink = 1;
-       ip->i_uid = ndp->ni_cred->cr_uid;
-       ip->i_gid = pdir->i_gid;
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
            suser(ndp->ni_cred, NULL))
                ip->i_mode &= ~ISGID;
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
            suser(ndp->ni_cred, NULL))
                ip->i_mode &= ~ISGID;
-#ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-#endif
 
        /*
         * Make sure inode goes to disk before directory entry.
         */
 
        /*
         * Make sure inode goes to disk before directory entry.
         */
-       if ((error = iupdat(ip, &time, &time, 1)) ||
-           (error = direnter(ip, ndp))) {
-               /*
-                * Write error occurred trying to update the inode
-                * or the directory so must deallocate the inode.
-                */
-               ip->i_nlink = 0;
-               ip->i_flag |= ICHG;
-               iput(ip);
-               return (error);
+       if (error = iupdat(ip, &time, &time, 1))
+               goto bad;
+       if (error = direnter(ip, ndp)) {
+               pdir = NULL;
+               goto bad;
        }
        *ipp = ip;
        return (0);
        }
        *ipp = ip;
        return (0);
+
+bad:
+       /*
+        * Write error occurred trying to update the inode
+        * or the directory so must deallocate the inode.
+        */
+       if (pdir)
+               iput(pdir);
+       ip->i_nlink = 0;
+       ip->i_flag |= ICHG;
+       iput(ip);
+       return (error);
 }
 }
index aaf852e..c02f473 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)ufs_inode.c 7.29 (Berkeley) %G%
+ *     @(#)ufs_inode.c 7.30 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
 #include "buf.h"
 #include "cmap.h"
 #include "vnode.h"
 #include "buf.h"
 #include "cmap.h"
 #include "vnode.h"
+#include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/ufsmount.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/ufsmount.h"
-#ifdef QUOTA
-#include "../ufs/quota.h"
-#endif
 #include "kernel.h"
 #include "malloc.h"
 
 #include "kernel.h"
 #include "malloc.h"
 
@@ -65,6 +63,9 @@ ufs_init()
                ih->ih_head[0] = ih;
                ih->ih_head[1] = ih;
        }
                ih->ih_head[0] = ih;
                ih->ih_head[1] = ih;
        }
+#ifdef QUOTA
+       dqinit();
+#endif /* QUOTA */
 }
 
 /*
 }
 
 /*
@@ -91,8 +92,8 @@ iget(xp, ino, ipp)
        struct vnode *nvp;
        struct buf *bp;
        struct dinode *dp;
        struct vnode *nvp;
        struct buf *bp;
        struct dinode *dp;
-       union  ihead *ih;
-       int error;
+       union ihead *ih;
+       int i, error;
 
        ih = &ihead[INOHASH(dev, ino)];
 loop:
 
        ih = &ihead[INOHASH(dev, ino)];
 loop:
@@ -123,7 +124,8 @@ loop:
        ip->i_mode = 0;
        ip->i_diroff = 0;
 #ifdef QUOTA
        ip->i_mode = 0;
        ip->i_diroff = 0;
 #ifdef QUOTA
-       ip->i_dquot = NODQUOT;
+       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
 #endif
        /*
         * Put it onto its hash chain and lock it so that other requests for
@@ -198,10 +200,6 @@ loop:
        ip->i_fs = fs;
        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
        VREF(ip->i_devvp);
        ip->i_fs = fs;
        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
        VREF(ip->i_devvp);
-#ifdef QUOTA
-       if (ip->i_mode != 0)
-               ip->i_dquot = inoquota(ip);
-#endif
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
@@ -252,17 +250,15 @@ ufs_inactive(vp)
        }
        ILOCK(ip);
        if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) {
        }
        ILOCK(ip);
        if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) {
+#ifdef QUOTA
+               if (!getinoquota(ip))
+                       (void) chkiq(ip, -1, NOCRED, 0);
+#endif
                error = itrunc(ip, (u_long)0, 0);
                mode = ip->i_mode;
                ip->i_mode = 0;
                error = itrunc(ip, (u_long)0, 0);
                mode = ip->i_mode;
                ip->i_mode = 0;
-               ip->i_rdev = 0;
                ip->i_flag |= IUPD|ICHG;
                ifree(ip, ip->i_number, mode);
                ip->i_flag |= IUPD|ICHG;
                ifree(ip, ip->i_number, mode);
-#ifdef QUOTA
-               (void) chkiq(ip->i_dev, ip, ip->i_uid, 0);
-               dqrele(ip->i_dquot);
-               ip->i_dquot = NODQUOT;
-#endif
        }
        IUPDAT(ip, &time, &time, 0);
        IUNLOCK(ip);
        }
        IUPDAT(ip, &time, &time, 0);
        IUNLOCK(ip);
@@ -271,8 +267,7 @@ ufs_inactive(vp)
         * If we are done with the inode, reclaim it
         * so that it can be reused immediately.
         */
         * If we are done with the inode, reclaim it
         * so that it can be reused immediately.
         */
-       if (vp->v_usecount == 0 && ip->i_mode == 0 &&
-           (vp->v_flag & VXLOCK) == 0)
+       if (vp->v_usecount == 0 && ip->i_mode == 0)
                vgone(vp);
        return (error);
 }
                vgone(vp);
        return (error);
 }
@@ -284,6 +279,7 @@ ufs_reclaim(vp)
        register struct vnode *vp;
 {
        register struct inode *ip = VTOI(vp);
        register struct vnode *vp;
 {
        register struct inode *ip = VTOI(vp);
+       int i;
 
        if (prtactive && vp->v_usecount != 0)
                vprint("ufs_reclaim: pushing active", vp);
 
        if (prtactive && vp->v_usecount != 0)
                vprint("ufs_reclaim: pushing active", vp);
@@ -302,8 +298,12 @@ ufs_reclaim(vp)
                ip->i_devvp = 0;
        }
 #ifdef QUOTA
                ip->i_devvp = 0;
        }
 #ifdef QUOTA
-       dqrele(ip->i_dquot);
-       ip->i_dquot = NODQUOT;
+       for (i = 0; i < MAXQUOTAS; i++) {
+               if (ip->i_dquot[i] != NODQUOT) {
+                       dqrele(vp, ip->i_dquot[i]);
+                       ip->i_dquot[i] = NODQUOT;
+               }
+       }
 #endif
        ip->i_flag = 0;
        return (0);
 #endif
        ip->i_flag = 0;
        return (0);
@@ -411,6 +411,10 @@ itrunc(oip, length, flags)
                aflags = B_CLRBUF;
                if (flags & IO_SYNC)
                        aflags |= B_SYNC;
                aflags = B_CLRBUF;
                if (flags & IO_SYNC)
                        aflags |= B_SYNC;
+#ifdef QUOTA
+               if (error = getinoquota(oip))
+                       return (error);
+#endif
                if (error = balloc(oip, lbn, offset, &bp, aflags))
                        return (error);
                oip->i_size = length;
                if (error = balloc(oip, lbn, offset, &bp, aflags))
                        return (error);
                oip->i_size = length;
@@ -527,7 +531,8 @@ done:
                oip->i_blocks = 0;
        oip->i_flag |= ICHG;
 #ifdef QUOTA
                oip->i_blocks = 0;
        oip->i_flag |= ICHG;
 #ifdef QUOTA
-       (void) chkdq(oip, -blocksreleased, 0);
+       if (!getinoquota(oip))
+               (void) chkdq(oip, -blocksreleased, NOCRED, 0);
 #endif
        return (allerror);
 }
 #endif
        return (allerror);
 }
@@ -670,44 +675,3 @@ iunlock(ip)
                wakeup((caddr_t)ip);
        }
 }
                wakeup((caddr_t)ip);
        }
 }
-
-/*
- * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
- * The mode is shifted to select the owner/group/other fields. The
- * super user is granted all permissions.
- *
- * NB: Called from vnode op table. It seems this could all be done
- * using vattr's but...
- */
-iaccess(ip, mode, cred)
-       register struct inode *ip;
-       register int mode;
-       struct ucred *cred;
-{
-       register gid_t *gp;
-       int i;
-
-       /*
-        * If you're the super-user, you always get access.
-        */
-       if (cred->cr_uid == 0)
-               return (0);
-       /*
-        * Access check is based on only one of owner, group, public.
-        * If not owner, then check group. If not a member of the
-        * group, then check public access.
-        */
-       if (cred->cr_uid != ip->i_uid) {
-               mode >>= 3;
-               gp = cred->cr_groups;
-               for (i = 0; i < cred->cr_ngroups; i++, gp++)
-                       if (ip->i_gid == *gp)
-                               goto found;
-               mode >>= 3;
-found:
-               ;
-       }
-       if ((ip->i_mode & mode) != 0)
-               return (0);
-       return (EACCES);
-}
index 63556d6..140a4d0 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)ufs_vnops.c 7.35 (Berkeley) %G%
+ *     @(#)ufs_vnops.c 7.36 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -31,9 +31,9 @@
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
+#include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
-#include "../ufs/quota.h"
 
 /*
  * Global vfs data structures for ufs
 
 /*
  * Global vfs data structures for ufs
@@ -295,13 +295,58 @@ ufs_close(vp, fflag, cred)
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
+ * The mode is shifted to select the owner/group/other fields. The
+ * super user is granted all permissions.
+ */
 ufs_access(vp, mode, cred)
        struct vnode *vp;
 ufs_access(vp, mode, cred)
        struct vnode *vp;
-       int mode;
+       register int mode;
        struct ucred *cred;
 {
        struct ucred *cred;
 {
+       register struct inode *ip = VTOI(vp);
+       register gid_t *gp;
+       int i, error;
 
 
-       return (iaccess(VTOI(vp), mode, cred));
+#ifdef DIAGNOSTIC
+       if (!VOP_ISLOCKED(vp)) {
+               vprint("ufs_access: not locked", vp);
+               panic("ufs_access: not locked");
+       }
+#endif
+#ifdef QUOTA
+       if (mode & VWRITE) {
+               switch (vp->v_type) {
+               case VREG: case VDIR: case VLNK:
+                       if (error = getinoquota(ip))
+                               return (error);
+               }
+       }
+#endif /* QUOTA */
+       /*
+        * If you're the super-user, you always get access.
+        */
+       if (cred->cr_uid == 0)
+               return (0);
+       /*
+        * Access check is based on only one of owner, group, public.
+        * If not owner, then check group. If not a member of the
+        * group, then check public access.
+        */
+       if (cred->cr_uid != ip->i_uid) {
+               mode >>= 3;
+               gp = cred->cr_groups;
+               for (i = 0; i < cred->cr_ngroups; i++, gp++)
+                       if (ip->i_gid == *gp)
+                               goto found;
+               mode >>= 3;
+found:
+               ;
+       }
+       if ((ip->i_mode & mode) != 0)
+               return (0);
+       return (EACCES);
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -323,7 +368,12 @@ ufs_getattr(vp, vap, cred)
        vap->va_uid = ip->i_uid;
        vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)ip->i_rdev;
        vap->va_uid = ip->i_uid;
        vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)ip->i_rdev;
+#ifdef tahoe
+       vap->va_size = ip->i_size;
+       vap->va_size_rsv = 0;
+#else
        vap->va_qsize = ip->i_din.di_qsize;
        vap->va_qsize = ip->i_din.di_qsize;
+#endif
        vap->va_atime.tv_sec = ip->i_atime;
        vap->va_atime.tv_usec = 0;
        vap->va_mtime.tv_sec = ip->i_mtime;
        vap->va_atime.tv_sec = ip->i_atime;
        vap->va_atime.tv_usec = 0;
        vap->va_mtime.tv_sec = ip->i_mtime;
@@ -446,10 +496,13 @@ chown1(vp, uid, gid, cred)
        struct ucred *cred;
 {
        register struct inode *ip = VTOI(vp);
        struct ucred *cred;
 {
        register struct inode *ip = VTOI(vp);
+       uid_t ouid;
+       gid_t ogid;
+       int error = 0;
 #ifdef QUOTA
 #ifdef QUOTA
-       register long change;
+       register int i;
+       long change;
 #endif
 #endif
-       int error;
 
        if (uid == (u_short)VNOVAL)
                uid = ip->i_uid;
 
        if (uid == (u_short)VNOVAL)
                uid = ip->i_uid;
@@ -464,30 +517,74 @@ chown1(vp, uid, gid, cred)
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &u.u_acflag)))
                return (error);
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &u.u_acflag)))
                return (error);
+       ouid = ip->i_uid;
+       ogid = ip->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_uid == uid)           /* this just speeds things a little */
-               change = 0;
-       else
-               change = ip->i_blocks;
-       (void) chkdq(ip, -change, 1);
-       (void) chkiq(ip->i_dev, ip, ip->i_uid, 1);
-       dqrele(ip->i_dquot);
+       if (error = getinoquota(ip))
+               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_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
 #endif
-       if (ip->i_uid != uid && cred->cr_uid != 0)
-               ip->i_mode &= ~ISUID;
-       if (ip->i_gid != gid && cred->cr_uid != 0)
-               ip->i_mode &= ~ISGID;
        ip->i_uid = uid;
        ip->i_gid = gid;
        ip->i_uid = uid;
        ip->i_gid = gid;
-       ip->i_flag |= ICHG;
 #ifdef QUOTA
 #ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-       (void) chkdq(ip, change, 1);
-       (void) chkiq(ip->i_dev, (struct inode *)NULL, (uid_t)uid, 1);
-       return (u.u_error);             /* should == 0 ALWAYS !! */
-#else
-       return (0);
+       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)
+                               return (0);
+                       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_uid = ouid;
+       ip->i_gid = ogid;
+       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);
+               (void) chkiq(ip, 1, cred, FORCE);
+       }
+       if (error)
+               return (error);
 #endif
 #endif
+       if (ouid != uid || ogid != gid)
+               ip->i_flag |= ICHG;
+       if (ouid != uid && cred->cr_uid != 0)
+               ip->i_mode &= ~ISUID;
+       if (ogid != gid && cred->cr_uid != 0)
+               ip->i_mode &= ~ISGID;
+       return (0);
 }
 
 /*
 }
 
 /*
@@ -855,7 +952,7 @@ ufs_rename(fndp, tndp)
        if (oldparent != dp->i_number)
                newparent = dp->i_number;
        if (doingdirectory && newparent) {
        if (oldparent != dp->i_number)
                newparent = dp->i_number;
        if (doingdirectory && newparent) {
-               if (error = iaccess(ip, IWRITE, tndp->ni_cred))
+               if (error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred))
                        goto bad;
                tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
                        goto bad;
                tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
@@ -1075,25 +1172,26 @@ ufs_mkdir(ndp, vap)
         * directory.  The entry is made later
         * after writing "." and ".." entries out.
         */
         * directory.  The entry is made later
         * after writing "." and ".." entries out.
         */
-       error = ialloc(dp, dirpref(dp->i_fs), dmode, &tip);
-       if (error) {
+       if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
                iput(dp);
                return (error);
        }
        ip = tip;
                iput(dp);
                return (error);
        }
        ip = tip;
+       ip->i_uid = ndp->ni_cred->cr_uid;
+       ip->i_gid = dp->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_dquot != NODQUOT)
-               panic("mkdir: dquot");
+       if ((error = getinoquota(ip)) ||
+           (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+               ifree(ip, ip->i_number, dmode);
+               iput(ip);
+               iput(dp);
+               return (error);
+       }
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
        ip->i_mode = dmode;
        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
        ip->i_nlink = 2;
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
        ip->i_mode = dmode;
        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
        ip->i_nlink = 2;
-       ip->i_uid = ndp->ni_cred->cr_uid;
-       ip->i_gid = dp->i_gid;
-#ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-#endif
        error = iupdat(ip, &time, &time, 1);
 
        /*
        error = iupdat(ip, &time, &time, 1);
 
        /*
@@ -1554,49 +1652,57 @@ maknode(mode, ndp, ipp)
        int error;
 
        *ipp = 0;
        int error;
 
        *ipp = 0;
+       if ((mode & IFMT) == 0)
+               mode |= IFREG;
        if ((mode & IFMT) == IFDIR)
                ipref = dirpref(pdir->i_fs);
        else
                ipref = pdir->i_number;
        if ((mode & IFMT) == IFDIR)
                ipref = dirpref(pdir->i_fs);
        else
                ipref = pdir->i_number;
-       error = ialloc(pdir, ipref, mode, &tip);
-       if (error) {
+       if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
                iput(pdir);
                return (error);
        }
        ip = tip;
                iput(pdir);
                return (error);
        }
        ip = tip;
+       ip->i_uid = ndp->ni_cred->cr_uid;
+       ip->i_gid = pdir->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_dquot != NODQUOT)
-               panic("maknode: dquot");
+       if ((error = getinoquota(ip)) ||
+           (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+               ifree(ip, ip->i_number, mode);
+               iput(ip);
+               iput(pdir);
+               return (error);
+       }
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
-       if ((mode & IFMT) == 0)
-               mode |= IFREG;
        ip->i_mode = mode;
        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
        ip->i_nlink = 1;
        ip->i_mode = mode;
        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
        ip->i_nlink = 1;
-       ip->i_uid = ndp->ni_cred->cr_uid;
-       ip->i_gid = pdir->i_gid;
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
            suser(ndp->ni_cred, NULL))
                ip->i_mode &= ~ISGID;
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
            suser(ndp->ni_cred, NULL))
                ip->i_mode &= ~ISGID;
-#ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-#endif
 
        /*
         * Make sure inode goes to disk before directory entry.
         */
 
        /*
         * Make sure inode goes to disk before directory entry.
         */
-       if ((error = iupdat(ip, &time, &time, 1)) ||
-           (error = direnter(ip, ndp))) {
-               /*
-                * Write error occurred trying to update the inode
-                * or the directory so must deallocate the inode.
-                */
-               ip->i_nlink = 0;
-               ip->i_flag |= ICHG;
-               iput(ip);
-               return (error);
+       if (error = iupdat(ip, &time, &time, 1))
+               goto bad;
+       if (error = direnter(ip, ndp)) {
+               pdir = NULL;
+               goto bad;
        }
        *ipp = ip;
        return (0);
        }
        *ipp = ip;
        return (0);
+
+bad:
+       /*
+        * Write error occurred trying to update the inode
+        * or the directory so must deallocate the inode.
+        */
+       if (pdir)
+               iput(pdir);
+       ip->i_nlink = 0;
+       ip->i_flag |= ICHG;
+       iput(ip);
+       return (error);
 }
 }
index efd4b8b..2f6b348 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)lfs_inode.c 7.29 (Berkeley) %G%
+ *     @(#)lfs_inode.c 7.30 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
 #include "buf.h"
 #include "cmap.h"
 #include "vnode.h"
 #include "buf.h"
 #include "cmap.h"
 #include "vnode.h"
+#include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/ufsmount.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/ufsmount.h"
-#ifdef QUOTA
-#include "../ufs/quota.h"
-#endif
 #include "kernel.h"
 #include "malloc.h"
 
 #include "kernel.h"
 #include "malloc.h"
 
@@ -65,6 +63,9 @@ ufs_init()
                ih->ih_head[0] = ih;
                ih->ih_head[1] = ih;
        }
                ih->ih_head[0] = ih;
                ih->ih_head[1] = ih;
        }
+#ifdef QUOTA
+       dqinit();
+#endif /* QUOTA */
 }
 
 /*
 }
 
 /*
@@ -91,8 +92,8 @@ iget(xp, ino, ipp)
        struct vnode *nvp;
        struct buf *bp;
        struct dinode *dp;
        struct vnode *nvp;
        struct buf *bp;
        struct dinode *dp;
-       union  ihead *ih;
-       int error;
+       union ihead *ih;
+       int i, error;
 
        ih = &ihead[INOHASH(dev, ino)];
 loop:
 
        ih = &ihead[INOHASH(dev, ino)];
 loop:
@@ -123,7 +124,8 @@ loop:
        ip->i_mode = 0;
        ip->i_diroff = 0;
 #ifdef QUOTA
        ip->i_mode = 0;
        ip->i_diroff = 0;
 #ifdef QUOTA
-       ip->i_dquot = NODQUOT;
+       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
 #endif
        /*
         * Put it onto its hash chain and lock it so that other requests for
@@ -198,10 +200,6 @@ loop:
        ip->i_fs = fs;
        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
        VREF(ip->i_devvp);
        ip->i_fs = fs;
        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
        VREF(ip->i_devvp);
-#ifdef QUOTA
-       if (ip->i_mode != 0)
-               ip->i_dquot = inoquota(ip);
-#endif
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
@@ -252,17 +250,15 @@ ufs_inactive(vp)
        }
        ILOCK(ip);
        if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) {
        }
        ILOCK(ip);
        if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) {
+#ifdef QUOTA
+               if (!getinoquota(ip))
+                       (void) chkiq(ip, -1, NOCRED, 0);
+#endif
                error = itrunc(ip, (u_long)0, 0);
                mode = ip->i_mode;
                ip->i_mode = 0;
                error = itrunc(ip, (u_long)0, 0);
                mode = ip->i_mode;
                ip->i_mode = 0;
-               ip->i_rdev = 0;
                ip->i_flag |= IUPD|ICHG;
                ifree(ip, ip->i_number, mode);
                ip->i_flag |= IUPD|ICHG;
                ifree(ip, ip->i_number, mode);
-#ifdef QUOTA
-               (void) chkiq(ip->i_dev, ip, ip->i_uid, 0);
-               dqrele(ip->i_dquot);
-               ip->i_dquot = NODQUOT;
-#endif
        }
        IUPDAT(ip, &time, &time, 0);
        IUNLOCK(ip);
        }
        IUPDAT(ip, &time, &time, 0);
        IUNLOCK(ip);
@@ -271,8 +267,7 @@ ufs_inactive(vp)
         * If we are done with the inode, reclaim it
         * so that it can be reused immediately.
         */
         * If we are done with the inode, reclaim it
         * so that it can be reused immediately.
         */
-       if (vp->v_usecount == 0 && ip->i_mode == 0 &&
-           (vp->v_flag & VXLOCK) == 0)
+       if (vp->v_usecount == 0 && ip->i_mode == 0)
                vgone(vp);
        return (error);
 }
                vgone(vp);
        return (error);
 }
@@ -284,6 +279,7 @@ ufs_reclaim(vp)
        register struct vnode *vp;
 {
        register struct inode *ip = VTOI(vp);
        register struct vnode *vp;
 {
        register struct inode *ip = VTOI(vp);
+       int i;
 
        if (prtactive && vp->v_usecount != 0)
                vprint("ufs_reclaim: pushing active", vp);
 
        if (prtactive && vp->v_usecount != 0)
                vprint("ufs_reclaim: pushing active", vp);
@@ -302,8 +298,12 @@ ufs_reclaim(vp)
                ip->i_devvp = 0;
        }
 #ifdef QUOTA
                ip->i_devvp = 0;
        }
 #ifdef QUOTA
-       dqrele(ip->i_dquot);
-       ip->i_dquot = NODQUOT;
+       for (i = 0; i < MAXQUOTAS; i++) {
+               if (ip->i_dquot[i] != NODQUOT) {
+                       dqrele(vp, ip->i_dquot[i]);
+                       ip->i_dquot[i] = NODQUOT;
+               }
+       }
 #endif
        ip->i_flag = 0;
        return (0);
 #endif
        ip->i_flag = 0;
        return (0);
@@ -411,6 +411,10 @@ itrunc(oip, length, flags)
                aflags = B_CLRBUF;
                if (flags & IO_SYNC)
                        aflags |= B_SYNC;
                aflags = B_CLRBUF;
                if (flags & IO_SYNC)
                        aflags |= B_SYNC;
+#ifdef QUOTA
+               if (error = getinoquota(oip))
+                       return (error);
+#endif
                if (error = balloc(oip, lbn, offset, &bp, aflags))
                        return (error);
                oip->i_size = length;
                if (error = balloc(oip, lbn, offset, &bp, aflags))
                        return (error);
                oip->i_size = length;
@@ -527,7 +531,8 @@ done:
                oip->i_blocks = 0;
        oip->i_flag |= ICHG;
 #ifdef QUOTA
                oip->i_blocks = 0;
        oip->i_flag |= ICHG;
 #ifdef QUOTA
-       (void) chkdq(oip, -blocksreleased, 0);
+       if (!getinoquota(oip))
+               (void) chkdq(oip, -blocksreleased, NOCRED, 0);
 #endif
        return (allerror);
 }
 #endif
        return (allerror);
 }
@@ -670,44 +675,3 @@ iunlock(ip)
                wakeup((caddr_t)ip);
        }
 }
                wakeup((caddr_t)ip);
        }
 }
-
-/*
- * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
- * The mode is shifted to select the owner/group/other fields. The
- * super user is granted all permissions.
- *
- * NB: Called from vnode op table. It seems this could all be done
- * using vattr's but...
- */
-iaccess(ip, mode, cred)
-       register struct inode *ip;
-       register int mode;
-       struct ucred *cred;
-{
-       register gid_t *gp;
-       int i;
-
-       /*
-        * If you're the super-user, you always get access.
-        */
-       if (cred->cr_uid == 0)
-               return (0);
-       /*
-        * Access check is based on only one of owner, group, public.
-        * If not owner, then check group. If not a member of the
-        * group, then check public access.
-        */
-       if (cred->cr_uid != ip->i_uid) {
-               mode >>= 3;
-               gp = cred->cr_groups;
-               for (i = 0; i < cred->cr_ngroups; i++, gp++)
-                       if (ip->i_gid == *gp)
-                               goto found;
-               mode >>= 3;
-found:
-               ;
-       }
-       if ((ip->i_mode & mode) != 0)
-               return (0);
-       return (EACCES);
-}
index 4c66d34..4360487 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)lfs_vnops.c 7.35 (Berkeley) %G%
+ *     @(#)lfs_vnops.c 7.36 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -31,9 +31,9 @@
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
+#include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
-#include "../ufs/quota.h"
 
 /*
  * Global vfs data structures for ufs
 
 /*
  * Global vfs data structures for ufs
@@ -295,13 +295,58 @@ ufs_close(vp, fflag, cred)
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
+ * The mode is shifted to select the owner/group/other fields. The
+ * super user is granted all permissions.
+ */
 ufs_access(vp, mode, cred)
        struct vnode *vp;
 ufs_access(vp, mode, cred)
        struct vnode *vp;
-       int mode;
+       register int mode;
        struct ucred *cred;
 {
        struct ucred *cred;
 {
+       register struct inode *ip = VTOI(vp);
+       register gid_t *gp;
+       int i, error;
 
 
-       return (iaccess(VTOI(vp), mode, cred));
+#ifdef DIAGNOSTIC
+       if (!VOP_ISLOCKED(vp)) {
+               vprint("ufs_access: not locked", vp);
+               panic("ufs_access: not locked");
+       }
+#endif
+#ifdef QUOTA
+       if (mode & VWRITE) {
+               switch (vp->v_type) {
+               case VREG: case VDIR: case VLNK:
+                       if (error = getinoquota(ip))
+                               return (error);
+               }
+       }
+#endif /* QUOTA */
+       /*
+        * If you're the super-user, you always get access.
+        */
+       if (cred->cr_uid == 0)
+               return (0);
+       /*
+        * Access check is based on only one of owner, group, public.
+        * If not owner, then check group. If not a member of the
+        * group, then check public access.
+        */
+       if (cred->cr_uid != ip->i_uid) {
+               mode >>= 3;
+               gp = cred->cr_groups;
+               for (i = 0; i < cred->cr_ngroups; i++, gp++)
+                       if (ip->i_gid == *gp)
+                               goto found;
+               mode >>= 3;
+found:
+               ;
+       }
+       if ((ip->i_mode & mode) != 0)
+               return (0);
+       return (EACCES);
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -323,7 +368,12 @@ ufs_getattr(vp, vap, cred)
        vap->va_uid = ip->i_uid;
        vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)ip->i_rdev;
        vap->va_uid = ip->i_uid;
        vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)ip->i_rdev;
+#ifdef tahoe
+       vap->va_size = ip->i_size;
+       vap->va_size_rsv = 0;
+#else
        vap->va_qsize = ip->i_din.di_qsize;
        vap->va_qsize = ip->i_din.di_qsize;
+#endif
        vap->va_atime.tv_sec = ip->i_atime;
        vap->va_atime.tv_usec = 0;
        vap->va_mtime.tv_sec = ip->i_mtime;
        vap->va_atime.tv_sec = ip->i_atime;
        vap->va_atime.tv_usec = 0;
        vap->va_mtime.tv_sec = ip->i_mtime;
@@ -446,10 +496,13 @@ chown1(vp, uid, gid, cred)
        struct ucred *cred;
 {
        register struct inode *ip = VTOI(vp);
        struct ucred *cred;
 {
        register struct inode *ip = VTOI(vp);
+       uid_t ouid;
+       gid_t ogid;
+       int error = 0;
 #ifdef QUOTA
 #ifdef QUOTA
-       register long change;
+       register int i;
+       long change;
 #endif
 #endif
-       int error;
 
        if (uid == (u_short)VNOVAL)
                uid = ip->i_uid;
 
        if (uid == (u_short)VNOVAL)
                uid = ip->i_uid;
@@ -464,30 +517,74 @@ chown1(vp, uid, gid, cred)
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &u.u_acflag)))
                return (error);
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &u.u_acflag)))
                return (error);
+       ouid = ip->i_uid;
+       ogid = ip->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_uid == uid)           /* this just speeds things a little */
-               change = 0;
-       else
-               change = ip->i_blocks;
-       (void) chkdq(ip, -change, 1);
-       (void) chkiq(ip->i_dev, ip, ip->i_uid, 1);
-       dqrele(ip->i_dquot);
+       if (error = getinoquota(ip))
+               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_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
 #endif
-       if (ip->i_uid != uid && cred->cr_uid != 0)
-               ip->i_mode &= ~ISUID;
-       if (ip->i_gid != gid && cred->cr_uid != 0)
-               ip->i_mode &= ~ISGID;
        ip->i_uid = uid;
        ip->i_gid = gid;
        ip->i_uid = uid;
        ip->i_gid = gid;
-       ip->i_flag |= ICHG;
 #ifdef QUOTA
 #ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-       (void) chkdq(ip, change, 1);
-       (void) chkiq(ip->i_dev, (struct inode *)NULL, (uid_t)uid, 1);
-       return (u.u_error);             /* should == 0 ALWAYS !! */
-#else
-       return (0);
+       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)
+                               return (0);
+                       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_uid = ouid;
+       ip->i_gid = ogid;
+       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);
+               (void) chkiq(ip, 1, cred, FORCE);
+       }
+       if (error)
+               return (error);
 #endif
 #endif
+       if (ouid != uid || ogid != gid)
+               ip->i_flag |= ICHG;
+       if (ouid != uid && cred->cr_uid != 0)
+               ip->i_mode &= ~ISUID;
+       if (ogid != gid && cred->cr_uid != 0)
+               ip->i_mode &= ~ISGID;
+       return (0);
 }
 
 /*
 }
 
 /*
@@ -855,7 +952,7 @@ ufs_rename(fndp, tndp)
        if (oldparent != dp->i_number)
                newparent = dp->i_number;
        if (doingdirectory && newparent) {
        if (oldparent != dp->i_number)
                newparent = dp->i_number;
        if (doingdirectory && newparent) {
-               if (error = iaccess(ip, IWRITE, tndp->ni_cred))
+               if (error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred))
                        goto bad;
                tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
                        goto bad;
                tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
@@ -1075,25 +1172,26 @@ ufs_mkdir(ndp, vap)
         * directory.  The entry is made later
         * after writing "." and ".." entries out.
         */
         * directory.  The entry is made later
         * after writing "." and ".." entries out.
         */
-       error = ialloc(dp, dirpref(dp->i_fs), dmode, &tip);
-       if (error) {
+       if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
                iput(dp);
                return (error);
        }
        ip = tip;
                iput(dp);
                return (error);
        }
        ip = tip;
+       ip->i_uid = ndp->ni_cred->cr_uid;
+       ip->i_gid = dp->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_dquot != NODQUOT)
-               panic("mkdir: dquot");
+       if ((error = getinoquota(ip)) ||
+           (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+               ifree(ip, ip->i_number, dmode);
+               iput(ip);
+               iput(dp);
+               return (error);
+       }
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
        ip->i_mode = dmode;
        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
        ip->i_nlink = 2;
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
        ip->i_mode = dmode;
        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
        ip->i_nlink = 2;
-       ip->i_uid = ndp->ni_cred->cr_uid;
-       ip->i_gid = dp->i_gid;
-#ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-#endif
        error = iupdat(ip, &time, &time, 1);
 
        /*
        error = iupdat(ip, &time, &time, 1);
 
        /*
@@ -1554,49 +1652,57 @@ maknode(mode, ndp, ipp)
        int error;
 
        *ipp = 0;
        int error;
 
        *ipp = 0;
+       if ((mode & IFMT) == 0)
+               mode |= IFREG;
        if ((mode & IFMT) == IFDIR)
                ipref = dirpref(pdir->i_fs);
        else
                ipref = pdir->i_number;
        if ((mode & IFMT) == IFDIR)
                ipref = dirpref(pdir->i_fs);
        else
                ipref = pdir->i_number;
-       error = ialloc(pdir, ipref, mode, &tip);
-       if (error) {
+       if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
                iput(pdir);
                return (error);
        }
        ip = tip;
                iput(pdir);
                return (error);
        }
        ip = tip;
+       ip->i_uid = ndp->ni_cred->cr_uid;
+       ip->i_gid = pdir->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_dquot != NODQUOT)
-               panic("maknode: dquot");
+       if ((error = getinoquota(ip)) ||
+           (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+               ifree(ip, ip->i_number, mode);
+               iput(ip);
+               iput(pdir);
+               return (error);
+       }
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
-       if ((mode & IFMT) == 0)
-               mode |= IFREG;
        ip->i_mode = mode;
        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
        ip->i_nlink = 1;
        ip->i_mode = mode;
        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
        ip->i_nlink = 1;
-       ip->i_uid = ndp->ni_cred->cr_uid;
-       ip->i_gid = pdir->i_gid;
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
            suser(ndp->ni_cred, NULL))
                ip->i_mode &= ~ISGID;
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
            suser(ndp->ni_cred, NULL))
                ip->i_mode &= ~ISGID;
-#ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-#endif
 
        /*
         * Make sure inode goes to disk before directory entry.
         */
 
        /*
         * Make sure inode goes to disk before directory entry.
         */
-       if ((error = iupdat(ip, &time, &time, 1)) ||
-           (error = direnter(ip, ndp))) {
-               /*
-                * Write error occurred trying to update the inode
-                * or the directory so must deallocate the inode.
-                */
-               ip->i_nlink = 0;
-               ip->i_flag |= ICHG;
-               iput(ip);
-               return (error);
+       if (error = iupdat(ip, &time, &time, 1))
+               goto bad;
+       if (error = direnter(ip, ndp)) {
+               pdir = NULL;
+               goto bad;
        }
        *ipp = ip;
        return (0);
        }
        *ipp = ip;
        return (0);
+
+bad:
+       /*
+        * Write error occurred trying to update the inode
+        * or the directory so must deallocate the inode.
+        */
+       if (pdir)
+               iput(pdir);
+       ip->i_nlink = 0;
+       ip->i_flag |= ICHG;
+       iput(ip);
+       return (error);
 }
 }
index aaf852e..c02f473 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)ufs_inode.c 7.29 (Berkeley) %G%
+ *     @(#)ufs_inode.c 7.30 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
 #include "buf.h"
 #include "cmap.h"
 #include "vnode.h"
 #include "buf.h"
 #include "cmap.h"
 #include "vnode.h"
+#include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/ufsmount.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/ufsmount.h"
-#ifdef QUOTA
-#include "../ufs/quota.h"
-#endif
 #include "kernel.h"
 #include "malloc.h"
 
 #include "kernel.h"
 #include "malloc.h"
 
@@ -65,6 +63,9 @@ ufs_init()
                ih->ih_head[0] = ih;
                ih->ih_head[1] = ih;
        }
                ih->ih_head[0] = ih;
                ih->ih_head[1] = ih;
        }
+#ifdef QUOTA
+       dqinit();
+#endif /* QUOTA */
 }
 
 /*
 }
 
 /*
@@ -91,8 +92,8 @@ iget(xp, ino, ipp)
        struct vnode *nvp;
        struct buf *bp;
        struct dinode *dp;
        struct vnode *nvp;
        struct buf *bp;
        struct dinode *dp;
-       union  ihead *ih;
-       int error;
+       union ihead *ih;
+       int i, error;
 
        ih = &ihead[INOHASH(dev, ino)];
 loop:
 
        ih = &ihead[INOHASH(dev, ino)];
 loop:
@@ -123,7 +124,8 @@ loop:
        ip->i_mode = 0;
        ip->i_diroff = 0;
 #ifdef QUOTA
        ip->i_mode = 0;
        ip->i_diroff = 0;
 #ifdef QUOTA
-       ip->i_dquot = NODQUOT;
+       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
 #endif
        /*
         * Put it onto its hash chain and lock it so that other requests for
@@ -198,10 +200,6 @@ loop:
        ip->i_fs = fs;
        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
        VREF(ip->i_devvp);
        ip->i_fs = fs;
        ip->i_devvp = VFSTOUFS(mntp)->um_devvp;
        VREF(ip->i_devvp);
-#ifdef QUOTA
-       if (ip->i_mode != 0)
-               ip->i_dquot = inoquota(ip);
-#endif
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
        /*
         * Set up a generation number for this inode if it does not
         * already have one. This should only happen on old filesystems.
@@ -252,17 +250,15 @@ ufs_inactive(vp)
        }
        ILOCK(ip);
        if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) {
        }
        ILOCK(ip);
        if (ip->i_nlink <= 0 && (vp->v_mount->m_flag & M_RDONLY) == 0) {
+#ifdef QUOTA
+               if (!getinoquota(ip))
+                       (void) chkiq(ip, -1, NOCRED, 0);
+#endif
                error = itrunc(ip, (u_long)0, 0);
                mode = ip->i_mode;
                ip->i_mode = 0;
                error = itrunc(ip, (u_long)0, 0);
                mode = ip->i_mode;
                ip->i_mode = 0;
-               ip->i_rdev = 0;
                ip->i_flag |= IUPD|ICHG;
                ifree(ip, ip->i_number, mode);
                ip->i_flag |= IUPD|ICHG;
                ifree(ip, ip->i_number, mode);
-#ifdef QUOTA
-               (void) chkiq(ip->i_dev, ip, ip->i_uid, 0);
-               dqrele(ip->i_dquot);
-               ip->i_dquot = NODQUOT;
-#endif
        }
        IUPDAT(ip, &time, &time, 0);
        IUNLOCK(ip);
        }
        IUPDAT(ip, &time, &time, 0);
        IUNLOCK(ip);
@@ -271,8 +267,7 @@ ufs_inactive(vp)
         * If we are done with the inode, reclaim it
         * so that it can be reused immediately.
         */
         * If we are done with the inode, reclaim it
         * so that it can be reused immediately.
         */
-       if (vp->v_usecount == 0 && ip->i_mode == 0 &&
-           (vp->v_flag & VXLOCK) == 0)
+       if (vp->v_usecount == 0 && ip->i_mode == 0)
                vgone(vp);
        return (error);
 }
                vgone(vp);
        return (error);
 }
@@ -284,6 +279,7 @@ ufs_reclaim(vp)
        register struct vnode *vp;
 {
        register struct inode *ip = VTOI(vp);
        register struct vnode *vp;
 {
        register struct inode *ip = VTOI(vp);
+       int i;
 
        if (prtactive && vp->v_usecount != 0)
                vprint("ufs_reclaim: pushing active", vp);
 
        if (prtactive && vp->v_usecount != 0)
                vprint("ufs_reclaim: pushing active", vp);
@@ -302,8 +298,12 @@ ufs_reclaim(vp)
                ip->i_devvp = 0;
        }
 #ifdef QUOTA
                ip->i_devvp = 0;
        }
 #ifdef QUOTA
-       dqrele(ip->i_dquot);
-       ip->i_dquot = NODQUOT;
+       for (i = 0; i < MAXQUOTAS; i++) {
+               if (ip->i_dquot[i] != NODQUOT) {
+                       dqrele(vp, ip->i_dquot[i]);
+                       ip->i_dquot[i] = NODQUOT;
+               }
+       }
 #endif
        ip->i_flag = 0;
        return (0);
 #endif
        ip->i_flag = 0;
        return (0);
@@ -411,6 +411,10 @@ itrunc(oip, length, flags)
                aflags = B_CLRBUF;
                if (flags & IO_SYNC)
                        aflags |= B_SYNC;
                aflags = B_CLRBUF;
                if (flags & IO_SYNC)
                        aflags |= B_SYNC;
+#ifdef QUOTA
+               if (error = getinoquota(oip))
+                       return (error);
+#endif
                if (error = balloc(oip, lbn, offset, &bp, aflags))
                        return (error);
                oip->i_size = length;
                if (error = balloc(oip, lbn, offset, &bp, aflags))
                        return (error);
                oip->i_size = length;
@@ -527,7 +531,8 @@ done:
                oip->i_blocks = 0;
        oip->i_flag |= ICHG;
 #ifdef QUOTA
                oip->i_blocks = 0;
        oip->i_flag |= ICHG;
 #ifdef QUOTA
-       (void) chkdq(oip, -blocksreleased, 0);
+       if (!getinoquota(oip))
+               (void) chkdq(oip, -blocksreleased, NOCRED, 0);
 #endif
        return (allerror);
 }
 #endif
        return (allerror);
 }
@@ -670,44 +675,3 @@ iunlock(ip)
                wakeup((caddr_t)ip);
        }
 }
                wakeup((caddr_t)ip);
        }
 }
-
-/*
- * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
- * The mode is shifted to select the owner/group/other fields. The
- * super user is granted all permissions.
- *
- * NB: Called from vnode op table. It seems this could all be done
- * using vattr's but...
- */
-iaccess(ip, mode, cred)
-       register struct inode *ip;
-       register int mode;
-       struct ucred *cred;
-{
-       register gid_t *gp;
-       int i;
-
-       /*
-        * If you're the super-user, you always get access.
-        */
-       if (cred->cr_uid == 0)
-               return (0);
-       /*
-        * Access check is based on only one of owner, group, public.
-        * If not owner, then check group. If not a member of the
-        * group, then check public access.
-        */
-       if (cred->cr_uid != ip->i_uid) {
-               mode >>= 3;
-               gp = cred->cr_groups;
-               for (i = 0; i < cred->cr_ngroups; i++, gp++)
-                       if (ip->i_gid == *gp)
-                               goto found;
-               mode >>= 3;
-found:
-               ;
-       }
-       if ((ip->i_mode & mode) != 0)
-               return (0);
-       return (EACCES);
-}
index 63556d6..140a4d0 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)ufs_vnops.c 7.35 (Berkeley) %G%
+ *     @(#)ufs_vnops.c 7.36 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -31,9 +31,9 @@
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
 #include "mount.h"
 #include "vnode.h"
 #include "specdev.h"
+#include "../ufs/quota.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
 #include "../ufs/inode.h"
 #include "../ufs/fs.h"
-#include "../ufs/quota.h"
 
 /*
  * Global vfs data structures for ufs
 
 /*
  * Global vfs data structures for ufs
@@ -295,13 +295,58 @@ ufs_close(vp, fflag, cred)
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
+ * The mode is shifted to select the owner/group/other fields. The
+ * super user is granted all permissions.
+ */
 ufs_access(vp, mode, cred)
        struct vnode *vp;
 ufs_access(vp, mode, cred)
        struct vnode *vp;
-       int mode;
+       register int mode;
        struct ucred *cred;
 {
        struct ucred *cred;
 {
+       register struct inode *ip = VTOI(vp);
+       register gid_t *gp;
+       int i, error;
 
 
-       return (iaccess(VTOI(vp), mode, cred));
+#ifdef DIAGNOSTIC
+       if (!VOP_ISLOCKED(vp)) {
+               vprint("ufs_access: not locked", vp);
+               panic("ufs_access: not locked");
+       }
+#endif
+#ifdef QUOTA
+       if (mode & VWRITE) {
+               switch (vp->v_type) {
+               case VREG: case VDIR: case VLNK:
+                       if (error = getinoquota(ip))
+                               return (error);
+               }
+       }
+#endif /* QUOTA */
+       /*
+        * If you're the super-user, you always get access.
+        */
+       if (cred->cr_uid == 0)
+               return (0);
+       /*
+        * Access check is based on only one of owner, group, public.
+        * If not owner, then check group. If not a member of the
+        * group, then check public access.
+        */
+       if (cred->cr_uid != ip->i_uid) {
+               mode >>= 3;
+               gp = cred->cr_groups;
+               for (i = 0; i < cred->cr_ngroups; i++, gp++)
+                       if (ip->i_gid == *gp)
+                               goto found;
+               mode >>= 3;
+found:
+               ;
+       }
+       if ((ip->i_mode & mode) != 0)
+               return (0);
+       return (EACCES);
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -323,7 +368,12 @@ ufs_getattr(vp, vap, cred)
        vap->va_uid = ip->i_uid;
        vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)ip->i_rdev;
        vap->va_uid = ip->i_uid;
        vap->va_gid = ip->i_gid;
        vap->va_rdev = (dev_t)ip->i_rdev;
+#ifdef tahoe
+       vap->va_size = ip->i_size;
+       vap->va_size_rsv = 0;
+#else
        vap->va_qsize = ip->i_din.di_qsize;
        vap->va_qsize = ip->i_din.di_qsize;
+#endif
        vap->va_atime.tv_sec = ip->i_atime;
        vap->va_atime.tv_usec = 0;
        vap->va_mtime.tv_sec = ip->i_mtime;
        vap->va_atime.tv_sec = ip->i_atime;
        vap->va_atime.tv_usec = 0;
        vap->va_mtime.tv_sec = ip->i_mtime;
@@ -446,10 +496,13 @@ chown1(vp, uid, gid, cred)
        struct ucred *cred;
 {
        register struct inode *ip = VTOI(vp);
        struct ucred *cred;
 {
        register struct inode *ip = VTOI(vp);
+       uid_t ouid;
+       gid_t ogid;
+       int error = 0;
 #ifdef QUOTA
 #ifdef QUOTA
-       register long change;
+       register int i;
+       long change;
 #endif
 #endif
-       int error;
 
        if (uid == (u_short)VNOVAL)
                uid = ip->i_uid;
 
        if (uid == (u_short)VNOVAL)
                uid = ip->i_uid;
@@ -464,30 +517,74 @@ chown1(vp, uid, gid, cred)
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &u.u_acflag)))
                return (error);
            !groupmember((gid_t)gid, cred)) &&
            (error = suser(cred, &u.u_acflag)))
                return (error);
+       ouid = ip->i_uid;
+       ogid = ip->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_uid == uid)           /* this just speeds things a little */
-               change = 0;
-       else
-               change = ip->i_blocks;
-       (void) chkdq(ip, -change, 1);
-       (void) chkiq(ip->i_dev, ip, ip->i_uid, 1);
-       dqrele(ip->i_dquot);
+       if (error = getinoquota(ip))
+               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_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
 #endif
-       if (ip->i_uid != uid && cred->cr_uid != 0)
-               ip->i_mode &= ~ISUID;
-       if (ip->i_gid != gid && cred->cr_uid != 0)
-               ip->i_mode &= ~ISGID;
        ip->i_uid = uid;
        ip->i_gid = gid;
        ip->i_uid = uid;
        ip->i_gid = gid;
-       ip->i_flag |= ICHG;
 #ifdef QUOTA
 #ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-       (void) chkdq(ip, change, 1);
-       (void) chkiq(ip->i_dev, (struct inode *)NULL, (uid_t)uid, 1);
-       return (u.u_error);             /* should == 0 ALWAYS !! */
-#else
-       return (0);
+       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)
+                               return (0);
+                       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_uid = ouid;
+       ip->i_gid = ogid;
+       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);
+               (void) chkiq(ip, 1, cred, FORCE);
+       }
+       if (error)
+               return (error);
 #endif
 #endif
+       if (ouid != uid || ogid != gid)
+               ip->i_flag |= ICHG;
+       if (ouid != uid && cred->cr_uid != 0)
+               ip->i_mode &= ~ISUID;
+       if (ogid != gid && cred->cr_uid != 0)
+               ip->i_mode &= ~ISGID;
+       return (0);
 }
 
 /*
 }
 
 /*
@@ -855,7 +952,7 @@ ufs_rename(fndp, tndp)
        if (oldparent != dp->i_number)
                newparent = dp->i_number;
        if (doingdirectory && newparent) {
        if (oldparent != dp->i_number)
                newparent = dp->i_number;
        if (doingdirectory && newparent) {
-               if (error = iaccess(ip, IWRITE, tndp->ni_cred))
+               if (error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred))
                        goto bad;
                tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
                        goto bad;
                tndp->ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE;
                do {
@@ -1075,25 +1172,26 @@ ufs_mkdir(ndp, vap)
         * directory.  The entry is made later
         * after writing "." and ".." entries out.
         */
         * directory.  The entry is made later
         * after writing "." and ".." entries out.
         */
-       error = ialloc(dp, dirpref(dp->i_fs), dmode, &tip);
-       if (error) {
+       if (error = ialloc(dp, dirpref(dp->i_fs), dmode, ndp->ni_cred, &tip)) {
                iput(dp);
                return (error);
        }
        ip = tip;
                iput(dp);
                return (error);
        }
        ip = tip;
+       ip->i_uid = ndp->ni_cred->cr_uid;
+       ip->i_gid = dp->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_dquot != NODQUOT)
-               panic("mkdir: dquot");
+       if ((error = getinoquota(ip)) ||
+           (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+               ifree(ip, ip->i_number, dmode);
+               iput(ip);
+               iput(dp);
+               return (error);
+       }
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
        ip->i_mode = dmode;
        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
        ip->i_nlink = 2;
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
        ip->i_mode = dmode;
        ITOV(ip)->v_type = VDIR;        /* Rest init'd in iget() */
        ip->i_nlink = 2;
-       ip->i_uid = ndp->ni_cred->cr_uid;
-       ip->i_gid = dp->i_gid;
-#ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-#endif
        error = iupdat(ip, &time, &time, 1);
 
        /*
        error = iupdat(ip, &time, &time, 1);
 
        /*
@@ -1554,49 +1652,57 @@ maknode(mode, ndp, ipp)
        int error;
 
        *ipp = 0;
        int error;
 
        *ipp = 0;
+       if ((mode & IFMT) == 0)
+               mode |= IFREG;
        if ((mode & IFMT) == IFDIR)
                ipref = dirpref(pdir->i_fs);
        else
                ipref = pdir->i_number;
        if ((mode & IFMT) == IFDIR)
                ipref = dirpref(pdir->i_fs);
        else
                ipref = pdir->i_number;
-       error = ialloc(pdir, ipref, mode, &tip);
-       if (error) {
+       if (error = ialloc(pdir, ipref, mode, ndp->ni_cred, &tip)) {
                iput(pdir);
                return (error);
        }
        ip = tip;
                iput(pdir);
                return (error);
        }
        ip = tip;
+       ip->i_uid = ndp->ni_cred->cr_uid;
+       ip->i_gid = pdir->i_gid;
 #ifdef QUOTA
 #ifdef QUOTA
-       if (ip->i_dquot != NODQUOT)
-               panic("maknode: dquot");
+       if ((error = getinoquota(ip)) ||
+           (error = chkiq(ip, 1, ndp->ni_cred, 0))) {
+               ifree(ip, ip->i_number, mode);
+               iput(ip);
+               iput(pdir);
+               return (error);
+       }
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
 #endif
        ip->i_flag |= IACC|IUPD|ICHG;
-       if ((mode & IFMT) == 0)
-               mode |= IFREG;
        ip->i_mode = mode;
        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
        ip->i_nlink = 1;
        ip->i_mode = mode;
        ITOV(ip)->v_type = IFTOVT(mode);        /* Rest init'd in iget() */
        ip->i_nlink = 1;
-       ip->i_uid = ndp->ni_cred->cr_uid;
-       ip->i_gid = pdir->i_gid;
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
            suser(ndp->ni_cred, NULL))
                ip->i_mode &= ~ISGID;
        if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, ndp->ni_cred) &&
            suser(ndp->ni_cred, NULL))
                ip->i_mode &= ~ISGID;
-#ifdef QUOTA
-       ip->i_dquot = inoquota(ip);
-#endif
 
        /*
         * Make sure inode goes to disk before directory entry.
         */
 
        /*
         * Make sure inode goes to disk before directory entry.
         */
-       if ((error = iupdat(ip, &time, &time, 1)) ||
-           (error = direnter(ip, ndp))) {
-               /*
-                * Write error occurred trying to update the inode
-                * or the directory so must deallocate the inode.
-                */
-               ip->i_nlink = 0;
-               ip->i_flag |= ICHG;
-               iput(ip);
-               return (error);
+       if (error = iupdat(ip, &time, &time, 1))
+               goto bad;
+       if (error = direnter(ip, ndp)) {
+               pdir = NULL;
+               goto bad;
        }
        *ipp = ip;
        return (0);
        }
        *ipp = ip;
        return (0);
+
+bad:
+       /*
+        * Write error occurred trying to update the inode
+        * or the directory so must deallocate the inode.
+        */
+       if (pdir)
+               iput(pdir);
+       ip->i_nlink = 0;
+       ip->i_flag |= ICHG;
+       iput(ip);
+       return (error);
 }
 }