123398Smckusick /* 237731Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337731Smckusick * All rights reserved. 423398Smckusick * 537731Smckusick * Redistribution and use in source and binary forms are permitted 637731Smckusick * provided that the above copyright notice and this paragraph are 737731Smckusick * duplicated in all such forms and that any documentation, 837731Smckusick * advertising materials, and other materials related to such 937731Smckusick * distribution and use acknowledge that the software was developed 1037731Smckusick * by the University of California, Berkeley. The name of the 1137731Smckusick * University may not be used to endorse or promote products derived 1237731Smckusick * from this software without specific prior written permission. 1337731Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437731Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537731Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637731Smckusick * 17*38146Smckusick * @(#)vfs_vnops.c 7.5 (Berkeley) 05/27/89 1823398Smckusick */ 1918Sbill 2017099Sbloom #include "param.h" 2117099Sbloom #include "systm.h" 2217099Sbloom #include "user.h" 2337731Smckusick #include "kernel.h" 2417099Sbloom #include "file.h" 2537731Smckusick #include "stat.h" 2637731Smckusick #include "buf.h" 2737731Smckusick #include "proc.h" 2837731Smckusick #include "uio.h" 2917099Sbloom #include "socket.h" 3017099Sbloom #include "socketvar.h" 3137731Smckusick #include "mount.h" 3237731Smckusick #include "vnode.h" 3337731Smckusick #include "../ufs/inode.h" 3437731Smckusick #include "../ufs/fs.h" 3537731Smckusick #include "../ufs/quota.h" 3637731Smckusick #include "ioctl.h" 3737731Smckusick #include "tty.h" 3818Sbill 3937731Smckusick int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close(); 4037731Smckusick struct fileops vnops = 4137731Smckusick { vn_read, vn_write, vn_ioctl, vn_select, vn_close }; 4237520Smckusick 4318Sbill /* 4437731Smckusick * Common code for vnode open operations. 4537731Smckusick * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 4618Sbill */ 4737731Smckusick vn_open(ndp, fmode, cmode) 4837731Smckusick register struct nameidata *ndp; 4937731Smckusick int fmode, cmode; 5037731Smckusick { 5137731Smckusick register struct vnode *vp; 5237731Smckusick struct vattr vat; 5337731Smckusick struct vattr *vap = &vat; 5437731Smckusick int error; 5537731Smckusick 5637731Smckusick if (fmode & FCREAT) { 5737731Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 5837731Smckusick if ((fmode & FEXCL) == 0) 5937731Smckusick ndp->ni_nameiop |= FOLLOW; 6037731Smckusick if (error = namei(ndp)) 6137731Smckusick return (error); 6237731Smckusick if (ndp->ni_vp == NULL) { 6337731Smckusick vattr_null(vap); 6437731Smckusick vap->va_type = VREG; 6537731Smckusick vap->va_mode = cmode; 6637731Smckusick if (error = VOP_CREATE(ndp, vap)) 6737731Smckusick return (error); 6837731Smckusick fmode &= ~FTRUNC; 6937731Smckusick vp = ndp->ni_vp; 7037731Smckusick } else { 7137731Smckusick vp = ndp->ni_vp; 7237731Smckusick ndp->ni_vp = 0; 7337731Smckusick VOP_ABORTOP(ndp); 7437731Smckusick ndp->ni_vp = vp; 7537731Smckusick if (fmode & FEXCL) { 7637731Smckusick error = EEXIST; 7737731Smckusick goto bad; 7837731Smckusick } 7937731Smckusick fmode &= ~FCREAT; 8037731Smckusick } 8137731Smckusick } else { 8237731Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 8337731Smckusick if (error = namei(ndp)) 8437731Smckusick return (error); 8537731Smckusick vp = ndp->ni_vp; 8637731Smckusick } 8737731Smckusick if (vp->v_type == VSOCK) { 8837731Smckusick error = EOPNOTSUPP; 8937731Smckusick goto bad; 9037731Smckusick } 9137731Smckusick if ((fmode & FCREAT) == 0) { 9237731Smckusick if (fmode & FREAD) { 9337731Smckusick if (error = vn_access(vp, VREAD, ndp->ni_cred)) 9437731Smckusick goto bad; 9537731Smckusick } 9637731Smckusick if (fmode & (FWRITE|FTRUNC)) { 9737731Smckusick if (error = vn_access(vp, VWRITE, ndp->ni_cred)) 9837731Smckusick goto bad; 9937731Smckusick if (vp->v_type == VDIR) { 10037731Smckusick error = EISDIR; 10137731Smckusick goto bad; 10237731Smckusick } 10337731Smckusick } 10437731Smckusick } 10537731Smckusick if (fmode & FTRUNC) { 10637731Smckusick vattr_null(vap); 10737731Smckusick vap->va_size = 0; 10837731Smckusick if (error = VOP_SETATTR(vp, vap, ndp->ni_cred)) 10937731Smckusick goto bad; 11037731Smckusick } 11137731Smckusick VOP_UNLOCK(vp); 11237731Smckusick if (setjmp(&u.u_qsave)) { 11337731Smckusick if (error == 0) 11437731Smckusick error = EINTR; 11537731Smckusick return (error); 11637731Smckusick } 11737731Smckusick return (VOP_OPEN(vp, fmode, ndp->ni_cred)); 11837731Smckusick 11937731Smckusick bad: 12037731Smckusick vput(vp); 12137731Smckusick return(error); 12237731Smckusick } 12337731Smckusick 12437731Smckusick /* 12537731Smckusick * Check mode permission on vnode pointer. Mode is READ, WRITE or EXEC. 12637731Smckusick * In the case of WRITE, the read-only status of the file system is 12737731Smckusick * checked. Also in WRITE, prototype text segments cannot be written. 12837731Smckusick */ 12937731Smckusick vn_access(vp, mode, cred) 13037731Smckusick register struct vnode *vp; 1314817Swnj int mode; 13237731Smckusick struct ucred *cred; 13318Sbill { 13418Sbill 13537731Smckusick if (mode & VWRITE) { 13611162Ssam /* 13737731Smckusick * Disallow write attempts on read-only file systems; 13837731Smckusick * unless the file is a socket or a block or character 13937731Smckusick * device resident on the file system. 14011162Ssam */ 14137731Smckusick if ((vp->v_mount->m_flag & M_RDONLY) && 14237731Smckusick vp->v_type != VCHR && 14337731Smckusick vp->v_type != VBLK && 14437731Smckusick vp->v_type != VSOCK) 14537731Smckusick return (EROFS); 14611162Ssam /* 14711162Ssam * If there's shared text associated with 14811162Ssam * the inode, try to free it up once. If 14911162Ssam * we fail, we can't allow writing. 15011162Ssam */ 15137731Smckusick if (vp->v_flag & VTEXT) 15237731Smckusick xrele(vp); 15337731Smckusick if (vp->v_flag & VTEXT) 15437731Smckusick return (ETXTBSY); 15537731Smckusick } 15637731Smckusick return (VOP_ACCESS(vp, mode, cred)); 15737731Smckusick } 15837731Smckusick 15937731Smckusick /* 16037731Smckusick * Vnode version of rdwri() for calls on file systems. 16137731Smckusick */ 16237731Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) 16337731Smckusick enum uio_rw rw; 16437731Smckusick struct vnode *vp; 16537731Smckusick caddr_t base; 16637731Smckusick int len; 16737731Smckusick off_t offset; 16837731Smckusick enum uio_seg segflg; 16937731Smckusick int ioflg; 17037731Smckusick struct ucred *cred; 17137731Smckusick int *aresid; 17237731Smckusick { 17337731Smckusick struct uio auio; 17437731Smckusick struct iovec aiov; 17537731Smckusick int error; 17637731Smckusick 17737731Smckusick auio.uio_iov = &aiov; 17837731Smckusick auio.uio_iovcnt = 1; 17937731Smckusick aiov.iov_base = base; 18037731Smckusick aiov.iov_len = len; 18137731Smckusick auio.uio_resid = len; 18237731Smckusick auio.uio_offset = offset; 18337731Smckusick auio.uio_segflg = segflg; 18437731Smckusick auio.uio_rw = rw; 18537731Smckusick if (rw == UIO_READ) 18637731Smckusick error = VOP_READ(vp, &auio, &offset, ioflg, cred); 18737731Smckusick else 18837731Smckusick error = VOP_WRITE(vp, &auio, &offset, ioflg, cred); 18937731Smckusick if (aresid) 19037731Smckusick *aresid = auio.uio_resid; 19137731Smckusick else 19237731Smckusick if (auio.uio_resid && error == 0) 19337731Smckusick error = EIO; 19437731Smckusick return (error); 19537731Smckusick } 19637731Smckusick 19737731Smckusick vn_read(fp, uio, cred) 19837731Smckusick struct file *fp; 19937731Smckusick struct uio *uio; 20037731Smckusick struct ucred *cred; 20137731Smckusick { 20237731Smckusick 20337731Smckusick return (VOP_READ((struct vnode *)fp->f_data, uio, &(fp->f_offset), 20437731Smckusick (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred)); 20537731Smckusick } 20637731Smckusick 20737731Smckusick vn_write(fp, uio, cred) 20837731Smckusick struct file *fp; 20937731Smckusick struct uio *uio; 21037731Smckusick struct ucred *cred; 21137731Smckusick { 21237731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 21337731Smckusick int ioflag = 0; 21437731Smckusick 21537731Smckusick if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) 21637731Smckusick ioflag |= IO_APPEND; 21737731Smckusick if (fp->f_flag & FNDELAY) 21837731Smckusick ioflag |= IO_NDELAY; 21937731Smckusick return (VOP_WRITE(vp, uio, &(fp->f_offset), ioflag, cred)); 22037731Smckusick } 22137731Smckusick 22237731Smckusick /* 22337731Smckusick * Get stat info for a vnode. 22437731Smckusick */ 22537731Smckusick vn_stat(vp, sb) 22637731Smckusick struct vnode *vp; 22737731Smckusick register struct stat *sb; 22837731Smckusick { 22937731Smckusick struct vattr vattr; 23037731Smckusick register struct vattr *vap; 23137731Smckusick int error; 23237731Smckusick u_short mode; 23337731Smckusick 23437731Smckusick vap = &vattr; 23537731Smckusick error = VOP_GETATTR(vp, vap, u.u_cred); 23637731Smckusick if (error) 23737731Smckusick return (error); 23837731Smckusick /* 23937731Smckusick * Copy from vattr table 24037731Smckusick */ 24137731Smckusick sb->st_dev = vap->va_fsid; 24237731Smckusick sb->st_ino = vap->va_fileid; 24337731Smckusick mode = vap->va_mode; 24437731Smckusick switch (vp->v_type) { 24537731Smckusick case VREG: 24637731Smckusick mode |= IFREG; 24737731Smckusick break; 24837731Smckusick case VDIR: 24937731Smckusick mode |= IFDIR; 25037731Smckusick break; 25137731Smckusick case VBLK: 25237731Smckusick mode |= IFBLK; 25337731Smckusick break; 25437731Smckusick case VCHR: 25537731Smckusick mode |= IFCHR; 25637731Smckusick break; 25737731Smckusick case VLNK: 25837731Smckusick mode |= IFLNK; 25937731Smckusick break; 26037731Smckusick case VSOCK: 26137731Smckusick mode |= IFSOCK; 26237731Smckusick break; 26337731Smckusick default: 26437731Smckusick return (EBADF); 26537731Smckusick }; 26637731Smckusick sb->st_mode = mode; 26737731Smckusick sb->st_nlink = vap->va_nlink; 26837731Smckusick sb->st_uid = vap->va_uid; 26937731Smckusick sb->st_gid = vap->va_gid; 27037731Smckusick sb->st_rdev = vap->va_rdev; 27137731Smckusick sb->st_size = vap->va_size; 27237731Smckusick sb->st_atime = vap->va_atime.tv_sec; 27337731Smckusick sb->st_spare1 = 0; 27437731Smckusick sb->st_mtime = vap->va_mtime.tv_sec; 27537731Smckusick sb->st_spare2 = 0; 27637731Smckusick sb->st_ctime = vap->va_ctime.tv_sec; 27737731Smckusick sb->st_spare3 = 0; 27837731Smckusick sb->st_blksize = vap->va_blocksize; 27937731Smckusick sb->st_spare4[0] = sb->st_spare4[1] = 0; 28037731Smckusick /* 28137731Smckusick * XXX THIS IS NOT CORRECT!!, but be sure to change ufs_getattr() 28237731Smckusick * if you change it. 28337731Smckusick */ 28437731Smckusick sb->st_blocks = vap->va_bytes; 28537731Smckusick return (0); 28637731Smckusick } 28737731Smckusick 28837731Smckusick /* 28937731Smckusick * Vnode ioctl call 29037731Smckusick */ 29137731Smckusick vn_ioctl(fp, com, data) 29237731Smckusick struct file *fp; 29337731Smckusick int com; 29437731Smckusick caddr_t data; 29537731Smckusick { 29637731Smckusick register struct vnode *vp = ((struct vnode *)fp->f_data); 29737731Smckusick struct vattr vattr; 29837731Smckusick int error; 29937731Smckusick 30037731Smckusick switch (vp->v_type) { 30137731Smckusick 30237731Smckusick case VREG: 30337731Smckusick case VDIR: 30437731Smckusick if (com == FIONREAD) { 30537731Smckusick if (error = VOP_GETATTR(vp, &vattr, u.u_cred)) 30637731Smckusick return (error); 30737731Smckusick *(off_t *)data = vattr.va_size - fp->f_offset; 30837731Smckusick return (0); 30918Sbill } 31037731Smckusick if (com == FIONBIO || com == FIOASYNC) /* XXX */ 31137731Smckusick return (0); /* XXX */ 31237731Smckusick /* fall into ... */ 31337731Smckusick 31437731Smckusick default: 31537731Smckusick return (ENOTTY); 31637731Smckusick 31737731Smckusick case VCHR: 31837731Smckusick case VBLK: 31937731Smckusick u.u_r.r_val1 = 0; 32037731Smckusick if (setjmp(&u.u_qsave)) { 32137731Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 32237731Smckusick return(EINTR); 32337731Smckusick u.u_eosys = RESTARTSYS; 32437731Smckusick return (0); 32537731Smckusick } 32637731Smckusick return (VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred)); 32718Sbill } 32837731Smckusick } 32937731Smckusick 33037731Smckusick /* 33137731Smckusick * Vnode select call 33237731Smckusick */ 33337731Smckusick vn_select(fp, which) 33437731Smckusick struct file *fp; 33537731Smckusick int which; 33637731Smckusick { 33737731Smckusick return(VOP_SELECT(((struct vnode *)fp->f_data), which, u.u_cred)); 33837731Smckusick } 33937731Smckusick 34037731Smckusick /* 34137731Smckusick * Vnode close call 34237731Smckusick */ 34337731Smckusick vn_close(fp) 34437731Smckusick register struct file *fp; 34537731Smckusick { 34637731Smckusick struct vnode *vp = ((struct vnode *)fp->f_data); 34737731Smckusick int error; 34837731Smckusick 34937731Smckusick if (fp->f_flag & (FSHLOCK|FEXLOCK)) 35037731Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 35111162Ssam /* 35237731Smckusick * Must delete vnode reference from this file entry 35337731Smckusick * before VOP_CLOSE, so that only other references 35437731Smckusick * will prevent close. 35511162Ssam */ 35637731Smckusick fp->f_data = (caddr_t) 0; 35737731Smckusick error = VOP_CLOSE(vp, fp->f_flag, u.u_cred); 35837731Smckusick vrele(vp); 35937731Smckusick return (error); 36037731Smckusick } 36137731Smckusick 36237731Smckusick /* 36337731Smckusick * Place an advisory lock on a vnode. 36437731Smckusick * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries 36537731Smckusick */ 36637731Smckusick vn_lock(fp, cmd) 36737731Smckusick register struct file *fp; 36837731Smckusick int cmd; 36937731Smckusick { 37037731Smckusick register int priority = PLOCK; 37137731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 37237731Smckusick 37337731Smckusick if ((cmd & LOCK_EX) == 0) 37437731Smckusick priority += 4; 37537731Smckusick if (setjmp(&u.u_qsave)) { 37637731Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 37737731Smckusick return(EINTR); 37837731Smckusick u.u_eosys = RESTARTSYS; 3794817Swnj return (0); 38037731Smckusick } 38111162Ssam /* 38237731Smckusick * If there's a exclusive lock currently applied 38337731Smckusick * to the file, then we've gotta wait for the 38437731Smckusick * lock with everyone else. 38511162Ssam */ 38637731Smckusick again: 38737731Smckusick while (vp->v_flag & VEXLOCK) { 38837731Smckusick /* 38937731Smckusick * If we're holding an exclusive 39037731Smckusick * lock, then release it. 39137731Smckusick */ 39237731Smckusick if (fp->f_flag & FEXLOCK) { 39337731Smckusick vn_unlock(fp, FEXLOCK); 39437731Smckusick continue; 39537731Smckusick } 39637731Smckusick if (cmd & LOCK_NB) 39737731Smckusick return (EWOULDBLOCK); 39837731Smckusick vp->v_flag |= VLWAIT; 39937731Smckusick sleep((caddr_t)&vp->v_exlockc, priority); 40018Sbill } 40137731Smckusick if ((cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) { 40237731Smckusick /* 40337731Smckusick * Must wait for any shared locks to finish 40437731Smckusick * before we try to apply a exclusive lock. 40537731Smckusick * 40637731Smckusick * If we're holding a shared 40737731Smckusick * lock, then release it. 40837731Smckusick */ 40937731Smckusick if (fp->f_flag & FSHLOCK) { 41037731Smckusick vn_unlock(fp, FSHLOCK); 41137731Smckusick goto again; 41237731Smckusick } 41337731Smckusick if (cmd & LOCK_NB) 41437731Smckusick return (EWOULDBLOCK); 41537731Smckusick vp->v_flag |= VLWAIT; 41637731Smckusick sleep((caddr_t)&vp->v_shlockc, PLOCK); 41737731Smckusick goto again; 41837731Smckusick } 41937731Smckusick if (fp->f_flag & FEXLOCK) 42037731Smckusick panic("vn_lock"); 42137731Smckusick if (cmd & LOCK_EX) { 42237731Smckusick cmd &= ~LOCK_SH; 42337731Smckusick vp->v_exlockc++; 42437731Smckusick vp->v_flag |= VEXLOCK; 42537731Smckusick fp->f_flag |= FEXLOCK; 42637731Smckusick } 42737731Smckusick if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { 42837731Smckusick vp->v_shlockc++; 42937731Smckusick vp->v_flag |= VSHLOCK; 43037731Smckusick fp->f_flag |= FSHLOCK; 43137731Smckusick } 43237731Smckusick return (0); 43318Sbill } 43418Sbill 43518Sbill /* 43637731Smckusick * Unlock a file. 43718Sbill */ 43837731Smckusick vn_unlock(fp, kind) 43937731Smckusick register struct file *fp; 44037731Smckusick int kind; 44118Sbill { 44237731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 44337731Smckusick int flags; 44418Sbill 44537731Smckusick kind &= fp->f_flag; 44637731Smckusick if (vp == NULL || kind == 0) 44737731Smckusick return; 44837731Smckusick flags = vp->v_flag; 44937731Smckusick if (kind & FSHLOCK) { 45037731Smckusick if ((flags & VSHLOCK) == 0) 45137731Smckusick panic("vn_unlock: SHLOCK"); 45237731Smckusick if (--vp->v_shlockc == 0) { 45337731Smckusick vp->v_flag &= ~VSHLOCK; 45437731Smckusick if (flags & VLWAIT) 45537731Smckusick wakeup((caddr_t)&vp->v_shlockc); 45637731Smckusick } 45737731Smckusick fp->f_flag &= ~FSHLOCK; 45837552Smckusick } 45937731Smckusick if (kind & FEXLOCK) { 46037731Smckusick if ((flags & VEXLOCK) == 0) 46137731Smckusick panic("vn_unlock: EXLOCK"); 46237731Smckusick if (--vp->v_exlockc == 0) { 46337731Smckusick vp->v_flag &= ~(VEXLOCK|VLWAIT); 46437731Smckusick if (flags & VLWAIT) 46537731Smckusick wakeup((caddr_t)&vp->v_exlockc); 46637731Smckusick } 46737731Smckusick fp->f_flag &= ~FEXLOCK; 46837731Smckusick } 46918Sbill } 47018Sbill 47118Sbill /* 47237731Smckusick * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 47337731Smckusick * - look up fsid in mount list (if not found ret error) 47437731Smckusick * - get vp by calling VFS_FHTOVP() macro 47537731Smckusick * - if lockflag lock it with VOP_LOCK() 47618Sbill */ 47737731Smckusick vn_fhtovp(fhp, lockflag, vpp) 47837731Smckusick fhandle_t *fhp; 47937731Smckusick int lockflag; 48037731Smckusick struct vnode **vpp; 48118Sbill { 48237731Smckusick register struct mount *mp; 48337731Smckusick int error; 48418Sbill 48537731Smckusick if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 48637731Smckusick return (ESTALE); 487*38146Smckusick if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 488*38146Smckusick return (ESTALE); 489*38146Smckusick if (!lockflag) 490*38146Smckusick VOP_UNLOCK(*vpp); 49137731Smckusick return (0); 49237731Smckusick } 49337731Smckusick 49437731Smckusick /* 49537731Smckusick * Revoke access the current tty by all processes. 49637731Smckusick * Used only by the super-user in init 49737731Smckusick * to give ``clean'' terminals at login. 49837731Smckusick */ 49937731Smckusick vhangup() 50037731Smckusick { 50137731Smckusick 50237731Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 50337731Smckusick return; 50437731Smckusick if (u.u_ttyp == NULL) 50537731Smckusick return; 50637731Smckusick forceclose(u.u_ttyd); 50737731Smckusick if ((u.u_ttyp->t_state) & TS_ISOPEN) 50837731Smckusick gsignal(u.u_ttyp->t_pgid, SIGHUP); 50937731Smckusick u.u_ttyp->t_session = 0; 51037731Smckusick u.u_ttyp->t_pgid = 0; 51137731Smckusick } 51237731Smckusick 51337731Smckusick forceclose(dev) 51437731Smckusick dev_t dev; 51537731Smckusick { 51637731Smckusick register struct file *fp; 51737731Smckusick register struct vnode *vp; 51837731Smckusick 51937731Smckusick for (fp = file; fp < fileNFILE; fp++) { 52037731Smckusick if (fp->f_count == 0) 52137731Smckusick continue; 52237731Smckusick if (fp->f_type != DTYPE_VNODE) 52337731Smckusick continue; 52437731Smckusick vp = (struct vnode *)fp->f_data; 52537731Smckusick if (vp == 0) 52637731Smckusick continue; 52737731Smckusick if (vp->v_type != VCHR) 52837731Smckusick continue; 52937731Smckusick if (vp->v_rdev != dev) 53037731Smckusick continue; 53137731Smckusick fp->f_flag &= ~(FREAD|FWRITE); 53218Sbill } 53318Sbill } 53437731Smckusick 53537731Smckusick /* 53637731Smckusick * Vnode release, just decrement the count and call VOP_INACTIVE() 53737731Smckusick */ 53837731Smckusick void vrele(vp) 53937731Smckusick register struct vnode *vp; 54037731Smckusick { 54137731Smckusick 54237731Smckusick if (vp == NULL) 54337731Smckusick return; 54437731Smckusick vp->v_count--; 54537731Smckusick if (vp->v_count < 0) 54637731Smckusick printf("inode %d, bad ref count %d\n", 54737731Smckusick VTOI(vp)->i_number, vp->v_count); 54837731Smckusick if (vp->v_count == 0) 54937731Smckusick VOP_INACTIVE(vp); 55037731Smckusick } 55137731Smckusick 55237731Smckusick /* 55337731Smckusick * vput(), just unlock and vrele() 55437731Smckusick */ 55537731Smckusick vput(vp) 55637731Smckusick register struct vnode *vp; 55737731Smckusick { 55837731Smckusick VOP_UNLOCK(vp); 55937731Smckusick vrele(vp); 56037731Smckusick } 56137731Smckusick 56237731Smckusick /* 56337731Smckusick * Noop 56437731Smckusick */ 56537731Smckusick vfs_noop() 56637731Smckusick { 56737731Smckusick 56837731Smckusick return (ENXIO); 56937731Smckusick } 57037731Smckusick 57137731Smckusick /* 57237731Smckusick * Null op 57337731Smckusick */ 57437731Smckusick vfs_nullop() 57537731Smckusick { 57637731Smckusick 57737731Smckusick return (0); 57837731Smckusick } 579