/*
- * 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%
*
- * @(#)ffs_vnops.c 7.88 (Berkeley) %G%
+ * @(#)ffs_vnops.c 8.1 (Berkeley) %G%
*/
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/vnode.h>
-#include <sys/specdev.h>
-#include <sys/fifo.h>
#include <sys/malloc.h>
#include <vm/vm.h>
+#include <miscfs/specfs/specdev.h>
+#include <miscfs/fifofs/fifo.h>
+
#include <ufs/ufs/lockf.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
{ &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_bmap_desc, ffs_bmap }, /* bmap */
+ { &vop_bmap_desc, ufs_bmap }, /* bmap */
{ &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_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_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_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_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 */
{ &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.
struct buf *bp;
daddr_t lbn, bn, rablock;
off_t diff;
- int rasize, error = 0;
+ int type, rasize, error = 0;
long size, n, on;
+ type = ip->i_mode & IFMT;
#ifdef DIAGNOSTIC
- int type;
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 && ip->i_size < vp->v_mount->mnt_maxsymlinklen)
+ if (type == IFLNK && (int)ip->i_size < vp->v_mount->mnt_maxsymlinklen)
panic("read short symlink");
#endif
if (uio->uio_resid == 0)
do {
lbn = lblkno(fs, uio->uio_offset);
on = blkoff(fs, uio->uio_offset);
- n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
+ n = min((unsigned)(fs->fs_bsize - on), uio->uio_resid);
diff = ip->i_size - uio->uio_offset;
if (diff <= 0)
return (0);
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,
} else
error = bread(vp, lbn, size, NOCRED, &bp);
vp->v_lastr = lbn;
- n = MIN(n, size - bp->b_resid);
+ n = min(n, size - bp->b_resid);
if (error) {
brelse(bp);
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);
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;
if (uio->uio_resid == 0)
return (0);
fs = ip->i_fs;
- if (uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize)
+ if (uio->uio_offset < 0 ||
+ (u_quad_t)uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize)
return (EFBIG);
/*
* Maybe this should be above the vnode op call, but so long as
do {
lbn = lblkno(fs, uio->uio_offset);
on = blkoff(fs, uio->uio_offset);
- n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
+ n = min((unsigned)(fs->fs_bsize - on), uio->uio_resid);
if (n < fs->fs_bsize)
flags |= B_CLRBUF;
else
}
size = blksize(fs, ip, lbn);
(void) vnode_pager_uncache(vp);
- n = MIN(n, size - bp->b_resid);
+ n = min(n, size - bp->b_resid);
error = uiomove(bp->b_un.b_addr + on, n, uio);
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;
- 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)) {
*/
loop:
s = splbio();
- for (bp = vp->v_dirtyblkhd; bp; bp = nbp) {
- nbp = bp->b_blockf;
+ for (bp = vp->v_dirtyblkhd.le_next; bp; bp = nbp) {
+ nbp = bp->b_vnbufs.qe_next;
if ((bp->b_flags & B_BUSY))
continue;
if ((bp->b_flags & B_DELWRI) == 0)
sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
}
#ifdef DIAGNOSTIC
- if (vp->v_dirtyblkhd) {
+ if (vp->v_dirtyblkhd.le_next) {
vprint("ffs_fsync: dirty", vp);
goto loop;
}
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);
-}