readdir now returns an eof indication
[unix-history] / usr / src / sys / ufs / ffs / ufs_vnops.c
index 4327385..3778eb8 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.25 (Berkeley) %G%
+ *     @(#)ufs_vnops.c 7.33 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -69,7 +69,8 @@ int   ufs_lookup(),
        ufs_unlock(),
        ufs_bmap(),
        ufs_strategy(),
        ufs_unlock(),
        ufs_bmap(),
        ufs_strategy(),
-       ufs_print();
+       ufs_print(),
+       ufs_islocked();
 
 struct vnodeops ufs_vnodeops = {
        ufs_lookup,             /* lookup */
 
 struct vnodeops ufs_vnodeops = {
        ufs_lookup,             /* lookup */
@@ -103,6 +104,7 @@ struct vnodeops ufs_vnodeops = {
        ufs_bmap,               /* bmap */
        ufs_strategy,           /* strategy */
        ufs_print,              /* print */
        ufs_bmap,               /* bmap */
        ufs_strategy,           /* strategy */
        ufs_print,              /* print */
+       ufs_islocked,           /* islocked */
 };
 
 int    spec_lookup(),
 };
 
 int    spec_lookup(),
@@ -149,13 +151,64 @@ struct vnodeops spec_inodeops = {
        spec_bmap,              /* bmap */
        spec_strategy,          /* strategy */
        ufs_print,              /* print */
        spec_bmap,              /* bmap */
        spec_strategy,          /* strategy */
        ufs_print,              /* print */
+       ufs_islocked,           /* islocked */
 };
 
 };
 
-enum vtype iftovt_tab[8] = {
-       VNON, VCHR, VDIR, VBLK, VREG, VLNK, VSOCK, VBAD,
+#ifdef FIFO
+int    fifo_lookup(),
+       fifo_open(),
+       ufsfifo_read(),
+       ufsfifo_write(),
+       fifo_bmap(),
+       fifo_ioctl(),
+       fifo_select(),
+       ufsfifo_close(),
+       fifo_print(),
+       fifo_badop(),
+       fifo_nullop();
+
+struct vnodeops fifo_inodeops = {
+       fifo_lookup,            /* lookup */
+       fifo_badop,             /* create */
+       fifo_badop,             /* mknod */
+       fifo_open,              /* open */
+       ufsfifo_close,          /* close */
+       ufs_access,             /* access */
+       ufs_getattr,            /* getattr */
+       ufs_setattr,            /* setattr */
+       ufsfifo_read,           /* read */
+       ufsfifo_write,          /* write */
+       fifo_ioctl,             /* ioctl */
+       fifo_select,            /* select */
+       fifo_badop,             /* mmap */
+       fifo_nullop,            /* fsync */
+       fifo_badop,             /* seek */
+       fifo_badop,             /* remove */
+       fifo_badop,             /* link */
+       fifo_badop,             /* rename */
+       fifo_badop,             /* mkdir */
+       fifo_badop,             /* rmdir */
+       fifo_badop,             /* symlink */
+       fifo_badop,             /* readdir */
+       fifo_badop,             /* readlink */
+       fifo_badop,             /* abortop */
+       ufs_inactive,           /* inactive */
+       ufs_reclaim,            /* reclaim */
+       ufs_lock,               /* lock */
+       ufs_unlock,             /* unlock */
+       fifo_bmap,              /* bmap */
+       fifo_badop,             /* strategy */
+       ufs_print,              /* print */
+       ufs_islocked,           /* islocked */
+};
+#endif /* FIFO */
+
+enum vtype iftovt_tab[16] = {
+       VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
+       VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
 };
 };
-int    vttoif_tab[8] = {
-       0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFMT,
+int    vttoif_tab[9] = {
+       0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT,
 };
 
 /*
 };
 
 /*
@@ -189,21 +242,21 @@ ufs_mknod(ndp, vap, cred)
 
        if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
                return (error);
 
        if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip))
                return (error);
-       vp = ITOV(ip);
-       if (vap->va_rdev) {
+       ip->i_flag |= IACC|IUPD|ICHG;
+       if (vap->va_rdev != VNOVAL) {
                /*
                 * Want to be able to use this to make badblock
                 * inodes, so don't truncate the dev number.
                 */
                ip->i_rdev = vap->va_rdev;
                /*
                 * Want to be able to use this to make badblock
                 * inodes, so don't truncate the dev number.
                 */
                ip->i_rdev = vap->va_rdev;
-               ip->i_flag |= IACC|IUPD|ICHG;
        }
        /*
         * Remove inode so that it will be reloaded by iget and
         * checked to see if it is an alias of an existing entry
         * in the inode cache.
         */
        }
        /*
         * Remove inode so that it will be reloaded by iget and
         * checked to see if it is an alias of an existing entry
         * in the inode cache.
         */
-       iput(ip);
+       vp = ITOV(ip);
+       vput(vp);
        vp->v_type = VNON;
        vgone(vp);
        return (0);
        vp->v_type = VNON;
        vgone(vp);
        return (0);
@@ -237,7 +290,7 @@ ufs_close(vp, fflag, cred)
 {
        register struct inode *ip = VTOI(vp);
 
 {
        register struct inode *ip = VTOI(vp);
 
-       if (vp->v_count > 1 && !(ip->i_flag & ILOCKED))
+       if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
                ITIMES(ip, &time, &time);
        return (0);
 }
                ITIMES(ip, &time, &time);
        return (0);
 }
@@ -452,7 +505,7 @@ ufs_read(vp, uio, ioflag, cred)
        register struct fs *fs;
        struct buf *bp;
        daddr_t lbn, bn, rablock;
        register struct fs *fs;
        struct buf *bp;
        daddr_t lbn, bn, rablock;
-       int size, rasize, diff, error = 0;
+       int size, diff, error = 0;
        long n, on, type;
 
        if (uio->uio_rw != UIO_READ)
        long n, on, type;
 
        if (uio->uio_rw != UIO_READ)
@@ -477,13 +530,13 @@ ufs_read(vp, uio, ioflag, cred)
                        n = diff;
                size = blksize(fs, ip, lbn);
                rablock = lbn + 1;
                        n = diff;
                size = blksize(fs, ip, lbn);
                rablock = lbn + 1;
-               rasize = blksize(fs, ip, rablock);
-               if (ip->i_lastr + 1 == lbn)
-                       error = breada(ITOV(ip), lbn, size, rablock, rasize,
-                               NOCRED, &bp);
+               if (vp->v_lastr + 1 == lbn &&
+                   lblktosize(fs, rablock) < ip->i_size)
+                       error = breada(ITOV(ip), lbn, size, rablock,
+                               blksize(fs, ip, rablock), NOCRED, &bp);
                else
                        error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
                else
                        error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
-               ip->i_lastr = lbn;
+               vp->v_lastr = lbn;
                n = MIN(n, size - bp->b_resid);
                if (error) {
                        brelse(bp);
                n = MIN(n, size - bp->b_resid);
                if (error) {
                        brelse(bp);
@@ -603,9 +656,9 @@ ufs_ioctl(vp, com, data, fflag, cred)
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
-ufs_select(vp, which, cred)
+ufs_select(vp, which, fflags, cred)
        struct vnode *vp;
        struct vnode *vp;
-       int which;
+       int which, fflags;
        struct ucred *cred;
 {
 
        struct ucred *cred;
 {
 
@@ -1192,10 +1245,11 @@ ufs_symlink(ndp, vap, target)
 /*
  * Vnode op for read and write
  */
 /*
  * Vnode op for read and write
  */
-ufs_readdir(vp, uio, cred)
+ufs_readdir(vp, uio, cred, eofflagp)
        struct vnode *vp;
        register struct uio *uio;
        struct ucred *cred;
        struct vnode *vp;
        register struct uio *uio;
        struct ucred *cred;
+       int *eofflagp;
 {
        int count, lost, error;
 
 {
        int count, lost, error;
 
@@ -1208,6 +1262,10 @@ ufs_readdir(vp, uio, cred)
        uio->uio_iov->iov_len = count;
        error = ufs_read(vp, uio, 0, cred);
        uio->uio_resid += lost;
        uio->uio_iov->iov_len = count;
        error = ufs_read(vp, uio, 0, cred);
        uio->uio_resid += lost;
+       if ((VTOI(vp)->i_size - uio->uio_offset) <= 0)
+               *eofflagp = 1;
+       else
+               *eofflagp = 0;
        return (error);
 }
 
        return (error);
 }
 
@@ -1230,23 +1288,23 @@ ufs_readlink(vp, uiop, cred)
 ufs_abortop(ndp)
        register struct nameidata *ndp;
 {
 ufs_abortop(ndp)
        register struct nameidata *ndp;
 {
-       register struct inode *ip;
 
 
-       if (ndp->ni_vp) {
-               ip = VTOI(ndp->ni_vp);
-               if (ip->i_flag & ILOCKED)
-                       IUNLOCK(ip);
-               vrele(ndp->ni_vp);
-       }
        if (ndp->ni_dvp) {
        if (ndp->ni_dvp) {
-               ip = VTOI(ndp->ni_dvp);
-               if (ip->i_flag & ILOCKED)
-                       IUNLOCK(ip);
+               if (VOP_ISLOCKED(ndp->ni_dvp))
+                       VOP_UNLOCK(ndp->ni_dvp);
                vrele(ndp->ni_dvp);
        }
                vrele(ndp->ni_dvp);
        }
+       if (ndp->ni_vp) {
+               if (VOP_ISLOCKED(ndp->ni_vp))
+                       VOP_UNLOCK(ndp->ni_vp);
+               vrele(ndp->ni_vp);
+       }
        return;
 }
 
        return;
 }
 
+/*
+ * Lock an inode.
+ */
 ufs_lock(vp)
        struct vnode *vp;
 {
 ufs_lock(vp)
        struct vnode *vp;
 {
@@ -1256,6 +1314,9 @@ ufs_lock(vp)
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * Unlock an inode.
+ */
 ufs_unlock(vp)
        struct vnode *vp;
 {
 ufs_unlock(vp)
        struct vnode *vp;
 {
@@ -1267,6 +1328,18 @@ ufs_unlock(vp)
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * Check for a locked inode.
+ */
+ufs_islocked(vp)
+       struct vnode *vp;
+{
+
+       if (VTOI(vp)->i_flag & ILOCKED)
+               return (1);
+       return (0);
+}
+
 /*
  * Get access to bmap
  */
 /*
  * Get access to bmap
  */
@@ -1305,13 +1378,13 @@ ufs_strategy(bp)
        if (bp->b_blkno == bp->b_lblkno) {
                if (error = bmap(ip, bp->b_lblkno, &bp->b_blkno))
                        return (error);
        if (bp->b_blkno == bp->b_lblkno) {
                if (error = bmap(ip, bp->b_lblkno, &bp->b_blkno))
                        return (error);
-               if ((long)bp->b_blkno == -1) {
+               if ((long)bp->b_blkno == -1)
                        clrbuf(bp);
                        clrbuf(bp);
-                       biodone(bp);
-               }
        }
        }
-       if ((long)bp->b_blkno == -1)
+       if ((long)bp->b_blkno == -1) {
+               biodone(bp);
                return (0);
                return (0);
+       }
        if (checkoverlap) {
                ebp = &buf[nbuf];
                start = bp->b_blkno;
        if (checkoverlap) {
                ebp = &buf[nbuf];
                start = bp->b_blkno;
@@ -1328,7 +1401,10 @@ ufs_strategy(bp)
                        if (ep->b_bcount == 0 || ep->b_blkno > last ||
                            ep->b_blkno + btodb(ep->b_bcount) <= start)
                                continue;
                        if (ep->b_bcount == 0 || ep->b_blkno > last ||
                            ep->b_blkno + btodb(ep->b_bcount) <= start)
                                continue;
-                       panic("Disk overlap");
+                       vprint("Disk overlap", vp);
+                       printf("\tstart %d, end %d overlap start %d, end %d\n",
+                               start, last, ep->b_blkno,
+                               ep->b_blkno + btodb(ep->b_bcount) - 1);
                }
        }
        vp = ip->i_devvp;
                }
        }
        vp = ip->i_devvp;
@@ -1345,9 +1421,19 @@ ufs_print(vp)
 {
        register struct inode *ip = VTOI(vp);
 
 {
        register struct inode *ip = VTOI(vp);
 
-       printf("tag VT_UFS, ino %d, on dev %d, %d%s\n", ip->i_number,
-               major(ip->i_dev), minor(ip->i_dev),
-               (ip->i_flag & ILOCKED) ? " (LOCKED)" : "");
+       printf("tag VT_UFS, ino %d, on dev %d, %d", ip->i_number,
+               major(ip->i_dev), minor(ip->i_dev));
+#ifdef FIFO
+       if (vp->v_type == VFIFO)
+               fifo_printinfo(vp);
+#endif /* FIFO */
+       printf("%s\n", (ip->i_flag & ILOCKED) ? " (LOCKED)" : "");
+       if (ip->i_spare0 == 0)
+               return;
+       printf("\towner pid %d", ip->i_spare0);
+       if (ip->i_spare1)
+               printf(" waiting pid %d", ip->i_spare1);
+       printf("\n");
 }
 
 /*
 }
 
 /*
@@ -1396,11 +1482,64 @@ ufsspec_close(vp, fflag, cred)
 {
        register struct inode *ip = VTOI(vp);
 
 {
        register struct inode *ip = VTOI(vp);
 
-       if (vp->v_count > 1 && !(ip->i_flag & ILOCKED))
+       if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
                ITIMES(ip, &time, &time);
        return (spec_close(vp, fflag, cred));
 }
 
                ITIMES(ip, &time, &time);
        return (spec_close(vp, fflag, cred));
 }
 
+#ifdef FIFO
+/*
+ * Read wrapper for fifo's
+ */
+ufsfifo_read(vp, uio, ioflag, cred)
+       struct vnode *vp;
+       struct uio *uio;
+       int ioflag;
+       struct ucred *cred;
+{
+
+       /*
+        * Set access flag.
+        */
+       VTOI(vp)->i_flag |= IACC;
+       return (fifo_read(vp, uio, ioflag, cred));
+}
+
+/*
+ * Write wrapper for fifo's.
+ */
+ufsfifo_write(vp, uio, ioflag, cred)
+       struct vnode *vp;
+       struct uio *uio;
+       int ioflag;
+       struct ucred *cred;
+{
+
+       /*
+        * Set update and change flags.
+        */
+       VTOI(vp)->i_flag |= IUPD|ICHG;
+       return (fifo_write(vp, uio, ioflag, cred));
+}
+
+/*
+ * Close wrapper for fifo's.
+ *
+ * Update the times on the inode then do device close.
+ */
+ufsfifo_close(vp, fflag, cred)
+       struct vnode *vp;
+       int fflag;
+       struct ucred *cred;
+{
+       register struct inode *ip = VTOI(vp);
+
+       if (vp->v_usecount > 1 && !(ip->i_flag & ILOCKED))
+               ITIMES(ip, &time, &time);
+       return (fifo_close(vp, fflag, cred));
+}
+#endif /* FIFO */
+
 /*
  * Make a new file.
  */
 /*
  * Make a new file.
  */