4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / sys / ufs / ffs / ffs_vnops.c
index 5a5e1c9..64fcc51 100644 (file)
@@ -1,10 +1,10 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)ffs_vnops.c 7.94 (Berkeley) %G%
+ *     @(#)ffs_vnops.c 8.1 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -62,7 +62,7 @@ struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
        { &vop_readdir_desc, ufs_readdir },             /* readdir */
        { &vop_readlink_desc, ufs_readlink },           /* readlink */
        { &vop_abortop_desc, ufs_abortop },             /* abortop */
        { &vop_readdir_desc, ufs_readdir },             /* readdir */
        { &vop_readlink_desc, ufs_readlink },           /* readlink */
        { &vop_abortop_desc, ufs_abortop },             /* abortop */
-       { &vop_inactive_desc, ffs_inactive },           /* inactive */
+       { &vop_inactive_desc, ufs_inactive },           /* inactive */
        { &vop_reclaim_desc, ufs_reclaim },             /* reclaim */
        { &vop_lock_desc, ufs_lock },                   /* lock */
        { &vop_unlock_desc, ufs_unlock },               /* unlock */
        { &vop_reclaim_desc, ufs_reclaim },             /* reclaim */
        { &vop_lock_desc, ufs_lock },                   /* lock */
        { &vop_unlock_desc, ufs_unlock },               /* unlock */
@@ -70,6 +70,7 @@ struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
        { &vop_strategy_desc, ufs_strategy },           /* strategy */
        { &vop_print_desc, ufs_print },                 /* print */
        { &vop_islocked_desc, ufs_islocked },           /* islocked */
        { &vop_strategy_desc, ufs_strategy },           /* strategy */
        { &vop_print_desc, ufs_print },                 /* print */
        { &vop_islocked_desc, ufs_islocked },           /* islocked */
+       { &vop_pathconf_desc, ufs_pathconf },           /* pathconf */
        { &vop_advlock_desc, ufs_advlock },             /* advlock */
        { &vop_blkatoff_desc, ffs_blkatoff },           /* blkatoff */
        { &vop_valloc_desc, ffs_valloc },               /* valloc */
        { &vop_advlock_desc, ufs_advlock },             /* advlock */
        { &vop_blkatoff_desc, ffs_blkatoff },           /* blkatoff */
        { &vop_valloc_desc, ffs_valloc },               /* valloc */
@@ -109,7 +110,7 @@ struct vnodeopv_entry_desc ffs_specop_entries[] = {
        { &vop_readdir_desc, spec_readdir },            /* readdir */
        { &vop_readlink_desc, spec_readlink },          /* readlink */
        { &vop_abortop_desc, spec_abortop },            /* abortop */
        { &vop_readdir_desc, spec_readdir },            /* readdir */
        { &vop_readlink_desc, spec_readlink },          /* readlink */
        { &vop_abortop_desc, spec_abortop },            /* abortop */
-       { &vop_inactive_desc, ffs_inactive },           /* inactive */
+       { &vop_inactive_desc, ufs_inactive },           /* inactive */
        { &vop_reclaim_desc, ufs_reclaim },             /* reclaim */
        { &vop_lock_desc, ufs_lock },                   /* lock */
        { &vop_unlock_desc, ufs_unlock },               /* unlock */
        { &vop_reclaim_desc, ufs_reclaim },             /* reclaim */
        { &vop_lock_desc, ufs_lock },                   /* lock */
        { &vop_unlock_desc, ufs_unlock },               /* unlock */
@@ -117,6 +118,7 @@ struct vnodeopv_entry_desc ffs_specop_entries[] = {
        { &vop_strategy_desc, spec_strategy },          /* strategy */
        { &vop_print_desc, ufs_print },                 /* print */
        { &vop_islocked_desc, ufs_islocked },           /* islocked */
        { &vop_strategy_desc, spec_strategy },          /* strategy */
        { &vop_print_desc, ufs_print },                 /* print */
        { &vop_islocked_desc, ufs_islocked },           /* islocked */
+       { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
        { &vop_advlock_desc, spec_advlock },            /* advlock */
        { &vop_blkatoff_desc, spec_blkatoff },          /* blkatoff */
        { &vop_valloc_desc, spec_valloc },              /* valloc */
        { &vop_advlock_desc, spec_advlock },            /* advlock */
        { &vop_blkatoff_desc, spec_blkatoff },          /* blkatoff */
        { &vop_valloc_desc, spec_valloc },              /* valloc */
@@ -157,7 +159,7 @@ struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
        { &vop_readdir_desc, fifo_readdir },            /* readdir */
        { &vop_readlink_desc, fifo_readlink },          /* readlink */
        { &vop_abortop_desc, fifo_abortop },            /* abortop */
        { &vop_readdir_desc, fifo_readdir },            /* readdir */
        { &vop_readlink_desc, fifo_readlink },          /* readlink */
        { &vop_abortop_desc, fifo_abortop },            /* abortop */
-       { &vop_inactive_desc, ffs_inactive },           /* inactive */
+       { &vop_inactive_desc, ufs_inactive },           /* inactive */
        { &vop_reclaim_desc, ufs_reclaim },             /* reclaim */
        { &vop_lock_desc, ufs_lock },                   /* lock */
        { &vop_unlock_desc, ufs_unlock },               /* unlock */
        { &vop_reclaim_desc, ufs_reclaim },             /* reclaim */
        { &vop_lock_desc, ufs_lock },                   /* lock */
        { &vop_unlock_desc, ufs_unlock },               /* unlock */
@@ -165,6 +167,7 @@ struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
        { &vop_strategy_desc, fifo_strategy },          /* strategy */
        { &vop_print_desc, ufs_print },                 /* print */
        { &vop_islocked_desc, ufs_islocked },           /* islocked */
        { &vop_strategy_desc, fifo_strategy },          /* strategy */
        { &vop_print_desc, ufs_print },                 /* print */
        { &vop_islocked_desc, ufs_islocked },           /* islocked */
+       { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
        { &vop_advlock_desc, fifo_advlock },            /* advlock */
        { &vop_blkatoff_desc, fifo_blkatoff },          /* blkatoff */
        { &vop_valloc_desc, fifo_valloc },              /* valloc */
        { &vop_advlock_desc, fifo_advlock },            /* advlock */
        { &vop_blkatoff_desc, fifo_blkatoff },          /* blkatoff */
        { &vop_valloc_desc, fifo_valloc },              /* valloc */
@@ -178,6 +181,14 @@ struct vnodeopv_desc ffs_fifoop_opv_desc =
        { &ffs_fifoop_p, ffs_fifoop_entries };
 #endif /* FIFO */
 
        { &ffs_fifoop_p, ffs_fifoop_entries };
 #endif /* FIFO */
 
+/*
+ * Enabling cluster read/write operations.
+ */
+#include <sys/sysctl.h>
+int doclusterread = 1;
+struct ctldebug debug11 = { "doclusterread", &doclusterread };
+int doclusterwrite = 1;
+struct ctldebug debug12 = { "doclusterwrite", &doclusterwrite };
 
 /*
  * Vnode op for reading.
 
 /*
  * Vnode op for reading.
@@ -198,14 +209,13 @@ ffs_read(ap)
        struct buf *bp;
        daddr_t lbn, bn, rablock;
        off_t diff;
        struct buf *bp;
        daddr_t lbn, bn, rablock;
        off_t diff;
-       int rasize, error = 0;
+       int type, rasize, error = 0;
        long size, n, on;
 
        long size, n, on;
 
+       type = ip->i_mode & IFMT;
 #ifdef DIAGNOSTIC
 #ifdef DIAGNOSTIC
-       int type;
        if (uio->uio_rw != UIO_READ)
                panic("ffs_read mode");
        if (uio->uio_rw != UIO_READ)
                panic("ffs_read mode");
-       type = ip->i_mode & IFMT;
        if (type != IFDIR && type != IFREG && type != IFLNK)
                panic("ffs_read type");
        if (type == IFLNK && (int)ip->i_size < vp->v_mount->mnt_maxsymlinklen)
        if (type != IFDIR && type != IFREG && type != IFLNK)
                panic("ffs_read type");
        if (type == IFLNK && (int)ip->i_size < vp->v_mount->mnt_maxsymlinklen)
@@ -228,7 +238,10 @@ ffs_read(ap)
                        n = diff;
                size = blksize(fs, ip, lbn);
                rablock = lbn + 1;
                        n = diff;
                size = blksize(fs, ip, lbn);
                rablock = lbn + 1;
-               if (vp->v_lastr + 1 == lbn &&
+               if (doclusterread && lblktosize(fs, rablock) <= ip->i_size) {
+                       error = cluster_read(vp, ip->i_size, lbn, size,
+                           NOCRED, &bp);
+               } else if (vp->v_lastr + 1 == lbn &&
                    lblktosize(fs, rablock) < ip->i_size) {
                        rasize = blksize(fs, ip, rablock);
                        error = breadn(vp, lbn, size, &rablock,
                    lblktosize(fs, rablock) < ip->i_size) {
                        rasize = blksize(fs, ip, rablock);
                        error = breadn(vp, lbn, size, &rablock,
@@ -242,7 +255,8 @@ ffs_read(ap)
                        return (error);
                }
                error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
                        return (error);
                }
                error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
-               if (n + on == fs->fs_bsize || uio->uio_offset == ip->i_size)
+               if (type == IFREG &&
+                   (n + on == fs->fs_bsize || uio->uio_offset == ip->i_size))
                        bp->b_flags |= B_AGE;
                brelse(bp);
        } while (error == 0 && uio->uio_resid > 0 && n != 0);
                        bp->b_flags |= B_AGE;
                brelse(bp);
        } while (error == 0 && uio->uio_resid > 0 && n != 0);
@@ -281,6 +295,8 @@ ffs_write(ap)
        case VREG:
                if (ioflag & IO_APPEND)
                        uio->uio_offset = ip->i_size;
        case VREG:
                if (ioflag & IO_APPEND)
                        uio->uio_offset = ip->i_size;
+               if ((ip->i_flags & APPEND) && uio->uio_offset != ip->i_size)
+                       return (EPERM);
                /* fall through */
        case VLNK:
                break;
                /* fall through */
        case VLNK:
                break;
@@ -336,12 +352,16 @@ ffs_write(ap)
                if (ioflag & IO_SYNC)
                        (void) bwrite(bp);
                else if (n + on == fs->fs_bsize) {
                if (ioflag & IO_SYNC)
                        (void) bwrite(bp);
                else if (n + on == fs->fs_bsize) {
-                       bp->b_flags |= B_AGE;
-                       bawrite(bp);
+                       if (doclusterwrite) {
+                               cluster_write(bp, ip->i_size);
+                       } else {
+                               bp->b_flags |= B_AGE;
+                               bawrite(bp);
+                       }
                } else
                        bdwrite(bp);
                ip->i_flag |= IUPD|ICHG;
                } else
                        bdwrite(bp);
                ip->i_flag |= IUPD|ICHG;
-               if (ap->a_cred->cr_uid != 0)
+               if (ap->a_cred && ap->a_cred->cr_uid != 0)
                        ip->i_mode &= ~(ISUID|ISGID);
        } while (error == 0 && uio->uio_resid > 0 && n != 0);
        if (error && (ioflag & IO_UNIT)) {
                        ip->i_mode &= ~(ISUID|ISGID);
        } while (error == 0 && uio->uio_resid > 0 && n != 0);
        if (error && (ioflag & IO_UNIT)) {
@@ -418,57 +438,3 @@ loop:
        return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
 }
 
        return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
 }
 
-/*
- * Last reference to an inode, write the inode out and if necessary,
- * truncate and deallocate the file.
- */
-int
-ffs_inactive(ap)
-       struct vop_inactive_args /* {
-               struct vnode *a_vp;
-       } */ *ap;
-{
-       register struct vnode *vp = ap->a_vp;
-       register struct inode *ip = VTOI(vp);
-       struct timeval tv;
-       int mode, error;
-       extern int prtactive;
-
-       if (prtactive && vp->v_usecount != 0)
-               vprint("ffs_inactive: pushing active", vp);
-
-       /* Get rid of inodes related to stale file handles. */
-       if (ip->i_mode == 0) {
-               if ((vp->v_flag & VXLOCK) == 0)
-                       vgone(vp);
-               return (0);
-       }
-
-       error = 0;
-       ILOCK(ip);
-       if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
-#ifdef QUOTA
-               if (!getinoquota(ip))
-                       (void)chkiq(ip, -1, NOCRED, 0);
-#endif
-               error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, NULL);
-               mode = ip->i_mode;
-               ip->i_mode = 0;
-               ip->i_rdev = 0;
-               ip->i_flag |= IUPD|ICHG;
-               VOP_VFREE(vp, ip->i_number, mode);
-       }
-       if (ip->i_flag&(IUPD|IACC|ICHG|IMOD)) {
-               tv = time;
-               VOP_UPDATE(vp, &tv, &tv, 0);
-       }
-       IUNLOCK(ip);
-       ip->i_flag = 0;
-       /*
-        * 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)
-               vgone(vp);
-       return (error);
-}