X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/3088dd32775db0757d9445fa08d553b846aa78f9..930730fda4a84d270ddd788e2c31846b66b96054:/usr/src/sys/ufs/ffs/ufs_vnops.c diff --git a/usr/src/sys/ufs/ffs/ufs_vnops.c b/usr/src/sys/ufs/ffs/ufs_vnops.c index c45f25e89b..3778eb892f 100644 --- a/usr/src/sys/ufs/ffs/ufs_vnops.c +++ b/usr/src/sys/ufs/ffs/ufs_vnops.c @@ -14,7 +14,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)ufs_vnops.c 7.16 (Berkeley) %G% + * @(#)ufs_vnops.c 7.33 (Berkeley) %G% */ #include "param.h" @@ -64,48 +64,151 @@ int ufs_lookup(), ufs_readlink(), ufs_abortop(), ufs_inactive(), + ufs_reclaim(), ufs_lock(), ufs_unlock(), ufs_bmap(), - ufs_strategy(); + ufs_strategy(), + ufs_print(), + ufs_islocked(); struct vnodeops ufs_vnodeops = { - ufs_lookup, - ufs_create, - ufs_mknod, - ufs_open, - ufs_close, - ufs_access, - ufs_getattr, - ufs_setattr, - ufs_read, - ufs_write, - ufs_ioctl, - ufs_select, - ufs_mmap, - ufs_fsync, - ufs_seek, - ufs_remove, - ufs_link, - ufs_rename, - ufs_mkdir, - ufs_rmdir, - ufs_symlink, - ufs_readdir, - ufs_readlink, - ufs_abortop, - ufs_inactive, - ufs_lock, - ufs_unlock, - ufs_bmap, - ufs_strategy, + ufs_lookup, /* lookup */ + ufs_create, /* create */ + ufs_mknod, /* mknod */ + ufs_open, /* open */ + ufs_close, /* close */ + ufs_access, /* access */ + ufs_getattr, /* getattr */ + ufs_setattr, /* setattr */ + ufs_read, /* read */ + ufs_write, /* write */ + ufs_ioctl, /* ioctl */ + ufs_select, /* select */ + ufs_mmap, /* mmap */ + ufs_fsync, /* fsync */ + ufs_seek, /* seek */ + ufs_remove, /* remove */ + ufs_link, /* link */ + ufs_rename, /* rename */ + ufs_mkdir, /* mkdir */ + ufs_rmdir, /* rmdir */ + ufs_symlink, /* symlink */ + ufs_readdir, /* readdir */ + ufs_readlink, /* readlink */ + ufs_abortop, /* abortop */ + ufs_inactive, /* inactive */ + ufs_reclaim, /* reclaim */ + ufs_lock, /* lock */ + ufs_unlock, /* unlock */ + ufs_bmap, /* bmap */ + ufs_strategy, /* strategy */ + ufs_print, /* print */ + ufs_islocked, /* islocked */ }; -enum vtype iftovt_tab[8] = { - VNON, VCHR, VDIR, VBLK, VREG, VLNK, VSOCK, VBAD, +int spec_lookup(), + spec_open(), + ufsspec_read(), + ufsspec_write(), + spec_strategy(), + spec_bmap(), + spec_ioctl(), + spec_select(), + ufsspec_close(), + spec_badop(), + spec_nullop(); + +struct vnodeops spec_inodeops = { + spec_lookup, /* lookup */ + spec_badop, /* create */ + spec_badop, /* mknod */ + spec_open, /* open */ + ufsspec_close, /* close */ + ufs_access, /* access */ + ufs_getattr, /* getattr */ + ufs_setattr, /* setattr */ + ufsspec_read, /* read */ + ufsspec_write, /* write */ + spec_ioctl, /* ioctl */ + spec_select, /* select */ + spec_badop, /* mmap */ + spec_nullop, /* fsync */ + spec_badop, /* seek */ + spec_badop, /* remove */ + spec_badop, /* link */ + spec_badop, /* rename */ + spec_badop, /* mkdir */ + spec_badop, /* rmdir */ + spec_badop, /* symlink */ + spec_badop, /* readdir */ + spec_badop, /* readlink */ + spec_badop, /* abortop */ + ufs_inactive, /* inactive */ + ufs_reclaim, /* reclaim */ + ufs_lock, /* lock */ + ufs_unlock, /* unlock */ + spec_bmap, /* bmap */ + spec_strategy, /* strategy */ + ufs_print, /* print */ + ufs_islocked, /* islocked */ }; -int vttoif_tab[8] = { - 0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFMT, + +#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[9] = { + 0, IFREG, IFDIR, IFBLK, IFCHR, IFLNK, IFSOCK, IFIFO, IFMT, }; /* @@ -133,28 +236,29 @@ ufs_mknod(ndp, vap, cred) struct ucred *cred; struct vattr *vap; { + register struct vnode *vp; struct inode *ip; int error; if (error = maknode(MAKEIMODE(vap->va_type, vap->va_mode), ndp, &ip)) return (error); - 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. */ - ITOV(ip)->v_rdev = ip->i_rdev = vap->va_rdev; - ip->i_flag |= IACC|IUPD|ICHG; + ip->i_rdev = vap->va_rdev; } - iput(ip); /* * 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. */ - remque(ip); - ip->i_forw = ip; - ip->i_back = ip; + vp = ITOV(ip); + vput(vp); + vp->v_type = VNON; + vgone(vp); return (0); } @@ -186,7 +290,7 @@ ufs_close(vp, fflag, cred) { 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); } @@ -219,8 +323,8 @@ 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_size = ip->i_ic.ic_size.val[0]; - vap->va_size1 = ip->i_ic.ic_size.val[1]; + vap->va_size = ip->i_din.di_qsize.val[0]; + vap->va_size1 = ip->i_din.di_qsize.val[1]; vap->va_atime.tv_sec = ip->i_atime; vap->va_atime.tv_usec = 0; vap->va_mtime.tv_sec = ip->i_mtime; @@ -271,7 +375,7 @@ ufs_setattr(vp, vap, cred) if (vap->va_size != VNOVAL) { if (vp->v_type == VDIR) return (EISDIR); - if (error = itrunc(ip, vap->va_size)) + if (error = itrunc(ip, vap->va_size, 0)) /* XXX IO_SYNC? */ return (error); } if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { @@ -370,10 +474,13 @@ chown1(vp, uid, gid, cred) (void) chkiq(ip->i_dev, ip, ip->i_uid, 1); dqrele(ip->i_dquot); #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_flag |= ICHG; - ip->i_mode &= ~(ISUID|ISGID); #ifdef QUOTA ip->i_dquot = inoquota(ip); (void) chkdq(ip, change, 1); @@ -384,6 +491,158 @@ chown1(vp, uid, gid, cred) #endif } +/* + * Vnode op for reading. + */ +/* ARGSUSED */ +ufs_read(vp, uio, ioflag, cred) + struct vnode *vp; + register struct uio *uio; + int ioflag; + struct ucred *cred; +{ + register struct inode *ip = VTOI(vp); + register struct fs *fs; + struct buf *bp; + daddr_t lbn, bn, rablock; + int size, diff, error = 0; + long n, on, type; + + if (uio->uio_rw != UIO_READ) + panic("ufs_read mode"); + type = ip->i_mode & IFMT; + if (type != IFDIR && type != IFREG && type != IFLNK) + panic("ufs_read type"); + if (uio->uio_resid == 0) + return (0); + if (uio->uio_offset < 0) + return (EINVAL); + ip->i_flag |= IACC; + fs = ip->i_fs; + do { + lbn = lblkno(fs, uio->uio_offset); + on = blkoff(fs, uio->uio_offset); + n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid); + diff = ip->i_size - uio->uio_offset; + if (diff <= 0) + return (0); + if (diff < n) + n = diff; + size = blksize(fs, ip, lbn); + rablock = lbn + 1; + 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); + vp->v_lastr = lbn; + 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) + bp->b_flags |= B_AGE; + brelse(bp); + } while (error == 0 && uio->uio_resid > 0 && n != 0); + return (error); +} + +/* + * Vnode op for writing. + */ +ufs_write(vp, uio, ioflag, cred) + register struct vnode *vp; + struct uio *uio; + int ioflag; + struct ucred *cred; +{ + register struct inode *ip = VTOI(vp); + register struct fs *fs; + struct buf *bp; + daddr_t lbn, bn; + u_long osize; + int i, n, on, flags; + int count, size, resid, error = 0; + + if (uio->uio_rw != UIO_WRITE) + panic("ufs_write mode"); + switch (vp->v_type) { + case VREG: + if (ioflag & IO_APPEND) + uio->uio_offset = ip->i_size; + /* fall through */ + case VLNK: + break; + + case VDIR: + if ((ioflag & IO_SYNC) == 0) + panic("ufs_write nonsync dir write"); + break; + + default: + panic("ufs_write type"); + } + if (uio->uio_offset < 0) + return (EINVAL); + if (uio->uio_resid == 0) + return (0); + /* + * Maybe this should be above the vnode op call, but so long as + * file servers have no limits, i don't think it matters + */ + if (vp->v_type == VREG && + uio->uio_offset + uio->uio_resid > + u.u_rlimit[RLIMIT_FSIZE].rlim_cur) { + psignal(u.u_procp, SIGXFSZ); + return (EFBIG); + } + resid = uio->uio_resid; + osize = ip->i_size; + fs = ip->i_fs; + flags = 0; + if (ioflag & IO_SYNC) + flags = B_SYNC; + do { + lbn = lblkno(fs, uio->uio_offset); + on = blkoff(fs, uio->uio_offset); + n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid); + if (n < fs->fs_bsize) + flags |= B_CLRBUF; + else + flags &= ~B_CLRBUF; + if (error = balloc(ip, lbn, (int)(on + n), &bp, flags)) + break; + bn = bp->b_blkno; + if (uio->uio_offset + n > ip->i_size) + ip->i_size = uio->uio_offset + n; + size = blksize(fs, ip, lbn); + count = howmany(size, CLBYTES); + for (i = 0; i < count; i++) + munhash(ip->i_devvp, bn + i * CLBYTES / DEV_BSIZE); + 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); + } else + bdwrite(bp); + ip->i_flag |= IUPD|ICHG; + if (cred->cr_uid != 0) + ip->i_mode &= ~(ISUID|ISGID); + } while (error == 0 && uio->uio_resid > 0 && n != 0); + if (error && (ioflag & IO_UNIT)) { + (void) itrunc(ip, osize, ioflag & IO_SYNC); + uio->uio_offset -= resid - uio->uio_resid; + uio->uio_resid = resid; + } + return (error); +} + /* ARGSUSED */ ufs_ioctl(vp, com, data, fflag, cred) struct vnode *vp; @@ -393,18 +652,16 @@ ufs_ioctl(vp, com, data, fflag, cred) struct ucred *cred; { - printf("ufs_ioctl called with type %d\n", vp->v_type); return (ENOTTY); } /* ARGSUSED */ -ufs_select(vp, which, cred) +ufs_select(vp, which, fflags, cred) struct vnode *vp; - int which; + int which, fflags; struct ucred *cred; { - printf("ufs_select called with type %d\n", vp->v_type); return (1); /* XXX */ } @@ -427,20 +684,18 @@ ufs_mmap(vp, fflags, cred) * Synch an open file. */ /* ARGSUSED */ -ufs_fsync(vp, fflags, cred) +ufs_fsync(vp, fflags, cred, waitfor) struct vnode *vp; int fflags; struct ucred *cred; + int waitfor; { - register struct inode *ip = VTOI(vp); - int error; + struct inode *ip = VTOI(vp); - ILOCK(ip); if (fflags&FWRITE) ip->i_flag |= ICHG; - error = syncip(ip); - IUNLOCK(ip); - return (error); + vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0); + return (iupdat(ip, &time, &time, waitfor == MNT_WAIT)); } /* @@ -698,7 +953,7 @@ ufs_rename(fndp, tndp) if (doingdirectory) { if (--xp->i_nlink != 0) panic("rename: linked directory"); - error = itrunc(xp, (u_long)0); + error = itrunc(xp, (u_long)0, IO_SYNC); } xp->i_flag |= ICHG; iput(xp); @@ -742,20 +997,22 @@ ufs_rename(fndp, tndp) if (doingdirectory && newparent) { dp->i_nlink--; dp->i_flag |= ICHG; - error = rdwri(UIO_READ, xp, (caddr_t)&dirbuf, + error = vn_rdwr(UIO_READ, ITOV(xp), (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, - UIO_SYSSPACE, tndp->ni_cred, (int *)0); + UIO_SYSSPACE, IO_NODELOCKED, + tndp->ni_cred, (int *)0); if (error == 0) { if (dirbuf.dotdot_namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') { - printf("rename: mangled dir\n"); + dirbad(xp, 12, "rename: mangled dir"); } else { dirbuf.dotdot_ino = newparent; - (void) rdwri(UIO_WRITE, xp, + (void) vn_rdwr(UIO_WRITE, ITOV(xp), (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, + IO_NODELOCKED|IO_SYNC, tndp->ni_cred, (int *)0); cache_purge(ITOV(dp)); } @@ -857,9 +1114,9 @@ ufs_mkdir(ndp, vap) dirtemplate = mastertemplate; dirtemplate.dot_ino = ip->i_number; dirtemplate.dotdot_ino = dp->i_number; - error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, + error = vn_rdwr(UIO_WRITE, ITOV(ip), (caddr_t)&dirtemplate, sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE, - ndp->ni_cred, (int *)0); + IO_NODELOCKED|IO_SYNC, ndp->ni_cred, (int *)0); if (error) { dp->i_nlink--; dp->i_flag |= ICHG; @@ -956,7 +1213,7 @@ ufs_rmdir(ndp) * worry about them later. */ ip->i_nlink -= 2; - error = itrunc(ip, (u_long)0); + error = itrunc(ip, (u_long)0, IO_SYNC); cache_purge(ITOV(ip)); out: if (ndp->ni_dvp) @@ -979,8 +1236,8 @@ ufs_symlink(ndp, vap, target) error = maknode(IFLNK | vap->va_mode, ndp, &ip); if (error) return (error); - error = rdwri(UIO_WRITE, ip, target, strlen(target), (off_t)0, - UIO_SYSSPACE, ndp->ni_cred, (int *)0); + error = vn_rdwr(UIO_WRITE, ITOV(ip), target, strlen(target), (off_t)0, + UIO_SYSSPACE, IO_NODELOCKED, ndp->ni_cred, (int *)0); iput(ip); return (error); } @@ -988,29 +1245,27 @@ ufs_symlink(ndp, vap, target) /* * Vnode op for read and write */ -ufs_readdir(vp, uio, offp, cred) +ufs_readdir(vp, uio, cred, eofflagp) struct vnode *vp; register struct uio *uio; - off_t *offp; struct ucred *cred; + int *eofflagp; { - register struct inode *ip = VTOI(vp); - int count, error; + int count, lost, error; - ILOCK(ip); - uio->uio_offset = *offp; count = uio->uio_resid; count &= ~(DIRBLKSIZ - 1); - if (vp->v_type != VDIR || uio->uio_iovcnt != 1 || - (count < DIRBLKSIZ) || (uio->uio_offset & (DIRBLKSIZ -1))) { - IUNLOCK(ip); + lost = uio->uio_resid - count; + if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1))) return (EINVAL); - } uio->uio_resid = count; uio->uio_iov->iov_len = count; - error = readip(ip, uio, cred); - *offp += count - uio->uio_resid; - IUNLOCK(ip); + 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); } @@ -1023,7 +1278,7 @@ ufs_readlink(vp, uiop, cred) struct ucred *cred; { - return (readip(VTOI(vp), uiop, cred)); + return (ufs_read(vp, uiop, 0, cred)); } /* @@ -1033,23 +1288,23 @@ ufs_readlink(vp, uiop, cred) 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) { - 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); } + if (ndp->ni_vp) { + if (VOP_ISLOCKED(ndp->ni_vp)) + VOP_UNLOCK(ndp->ni_vp); + vrele(ndp->ni_vp); + } return; } +/* + * Lock an inode. + */ ufs_lock(vp) struct vnode *vp; { @@ -1059,6 +1314,9 @@ ufs_lock(vp) return (0); } +/* + * Unlock an inode. + */ ufs_unlock(vp) struct vnode *vp; { @@ -1070,6 +1328,18 @@ ufs_unlock(vp) 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 */ @@ -1091,13 +1361,185 @@ ufs_bmap(vp, bn, vpp, bnp) /* * Just call the device strategy routine */ +int checkoverlap = 1; + ufs_strategy(bp) register struct buf *bp; { - (*bdevsw[major(bp->b_dev)].d_strategy)(bp); + register struct inode *ip = VTOI(bp->b_vp); + register struct buf *ep; + struct vnode *vp; + struct buf *ebp; + daddr_t start, last; + int error; + + if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR) + panic("ufs_strategy: spec"); + 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) + clrbuf(bp); + } + if ((long)bp->b_blkno == -1) { + biodone(bp); + return (0); + } + if (checkoverlap) { + ebp = &buf[nbuf]; + start = bp->b_blkno; + last = start + btodb(bp->b_bcount) - 1; + for (ep = buf; ep < ebp; ep++) { + if (ep == bp || (ep->b_flags & B_INVAL) || + ep->b_vp == (struct vnode *)0) + continue; + if (VOP_BMAP(ep->b_vp, (daddr_t)0, &vp, (daddr_t)0)) + continue; + if (vp != ip->i_devvp) + continue; + /* look for overlap */ + if (ep->b_bcount == 0 || ep->b_blkno > last || + ep->b_blkno + btodb(ep->b_bcount) <= start) + continue; + 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; + bp->b_dev = vp->v_rdev; + (*(vp->v_op->vn_strategy))(bp); return (0); } +/* + * Print out the contents of an inode. + */ +ufs_print(vp) + struct vnode *vp; +{ + register struct inode *ip = VTOI(vp); + + 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"); +} + +/* + * Read wrapper for special devices. + */ +ufsspec_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 (spec_read(vp, uio, ioflag, cred)); +} + +/* + * Write wrapper for special devices. + */ +ufsspec_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 (spec_write(vp, uio, ioflag, cred)); +} + +/* + * Close wrapper for special devices. + * + * Update the times on the inode then do device close. + */ +ufsspec_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 (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. */