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*38351Smckusick * @(#)vfs_vnops.c 7.7 (Berkeley) 06/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 } 117*38351Smckusick error = VOP_OPEN(vp, fmode, ndp->ni_cred); 118*38351Smckusick if (error) 119*38351Smckusick vrele(vp); 120*38351Smckusick return (error); 12137731Smckusick 12237731Smckusick bad: 12337731Smckusick vput(vp); 12437731Smckusick return(error); 12537731Smckusick } 12637731Smckusick 12737731Smckusick /* 12837731Smckusick * Check mode permission on vnode pointer. Mode is READ, WRITE or EXEC. 12937731Smckusick * In the case of WRITE, the read-only status of the file system is 13037731Smckusick * checked. Also in WRITE, prototype text segments cannot be written. 13137731Smckusick */ 13237731Smckusick vn_access(vp, mode, cred) 13337731Smckusick register struct vnode *vp; 1344817Swnj int mode; 13537731Smckusick struct ucred *cred; 13618Sbill { 13718Sbill 13837731Smckusick if (mode & VWRITE) { 13911162Ssam /* 14037731Smckusick * Disallow write attempts on read-only file systems; 14137731Smckusick * unless the file is a socket or a block or character 14237731Smckusick * device resident on the file system. 14311162Ssam */ 14437731Smckusick if ((vp->v_mount->m_flag & M_RDONLY) && 14537731Smckusick vp->v_type != VCHR && 14637731Smckusick vp->v_type != VBLK && 14737731Smckusick vp->v_type != VSOCK) 14837731Smckusick return (EROFS); 14911162Ssam /* 15011162Ssam * If there's shared text associated with 15111162Ssam * the inode, try to free it up once. If 15211162Ssam * we fail, we can't allow writing. 15311162Ssam */ 15437731Smckusick if (vp->v_flag & VTEXT) 15537731Smckusick xrele(vp); 15637731Smckusick if (vp->v_flag & VTEXT) 15737731Smckusick return (ETXTBSY); 15837731Smckusick } 15937731Smckusick return (VOP_ACCESS(vp, mode, cred)); 16037731Smckusick } 16137731Smckusick 16237731Smckusick /* 16337731Smckusick * Vnode version of rdwri() for calls on file systems. 16437731Smckusick */ 16537731Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) 16637731Smckusick enum uio_rw rw; 16737731Smckusick struct vnode *vp; 16837731Smckusick caddr_t base; 16937731Smckusick int len; 17037731Smckusick off_t offset; 17137731Smckusick enum uio_seg segflg; 17237731Smckusick int ioflg; 17337731Smckusick struct ucred *cred; 17437731Smckusick int *aresid; 17537731Smckusick { 17637731Smckusick struct uio auio; 17737731Smckusick struct iovec aiov; 17837731Smckusick int error; 17937731Smckusick 18037731Smckusick auio.uio_iov = &aiov; 18137731Smckusick auio.uio_iovcnt = 1; 18237731Smckusick aiov.iov_base = base; 18337731Smckusick aiov.iov_len = len; 18437731Smckusick auio.uio_resid = len; 18537731Smckusick auio.uio_offset = offset; 18637731Smckusick auio.uio_segflg = segflg; 18737731Smckusick auio.uio_rw = rw; 18837731Smckusick if (rw == UIO_READ) 18937731Smckusick error = VOP_READ(vp, &auio, &offset, ioflg, cred); 19037731Smckusick else 19137731Smckusick error = VOP_WRITE(vp, &auio, &offset, ioflg, cred); 19237731Smckusick if (aresid) 19337731Smckusick *aresid = auio.uio_resid; 19437731Smckusick else 19537731Smckusick if (auio.uio_resid && error == 0) 19637731Smckusick error = EIO; 19737731Smckusick return (error); 19837731Smckusick } 19937731Smckusick 20037731Smckusick vn_read(fp, uio, cred) 20137731Smckusick struct file *fp; 20237731Smckusick struct uio *uio; 20337731Smckusick struct ucred *cred; 20437731Smckusick { 20537731Smckusick 20637731Smckusick return (VOP_READ((struct vnode *)fp->f_data, uio, &(fp->f_offset), 20737731Smckusick (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred)); 20837731Smckusick } 20937731Smckusick 21037731Smckusick vn_write(fp, uio, cred) 21137731Smckusick struct file *fp; 21237731Smckusick struct uio *uio; 21337731Smckusick struct ucred *cred; 21437731Smckusick { 21537731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 21637731Smckusick int ioflag = 0; 21737731Smckusick 21837731Smckusick if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) 21937731Smckusick ioflag |= IO_APPEND; 22037731Smckusick if (fp->f_flag & FNDELAY) 22137731Smckusick ioflag |= IO_NDELAY; 22237731Smckusick return (VOP_WRITE(vp, uio, &(fp->f_offset), ioflag, cred)); 22337731Smckusick } 22437731Smckusick 22537731Smckusick /* 22637731Smckusick * Get stat info for a vnode. 22737731Smckusick */ 22837731Smckusick vn_stat(vp, sb) 22937731Smckusick struct vnode *vp; 23037731Smckusick register struct stat *sb; 23137731Smckusick { 23237731Smckusick struct vattr vattr; 23337731Smckusick register struct vattr *vap; 23437731Smckusick int error; 23537731Smckusick u_short mode; 23637731Smckusick 23737731Smckusick vap = &vattr; 23837731Smckusick error = VOP_GETATTR(vp, vap, u.u_cred); 23937731Smckusick if (error) 24037731Smckusick return (error); 24137731Smckusick /* 24237731Smckusick * Copy from vattr table 24337731Smckusick */ 24437731Smckusick sb->st_dev = vap->va_fsid; 24537731Smckusick sb->st_ino = vap->va_fileid; 24637731Smckusick mode = vap->va_mode; 24737731Smckusick switch (vp->v_type) { 24837731Smckusick case VREG: 24937731Smckusick mode |= IFREG; 25037731Smckusick break; 25137731Smckusick case VDIR: 25237731Smckusick mode |= IFDIR; 25337731Smckusick break; 25437731Smckusick case VBLK: 25537731Smckusick mode |= IFBLK; 25637731Smckusick break; 25737731Smckusick case VCHR: 25837731Smckusick mode |= IFCHR; 25937731Smckusick break; 26037731Smckusick case VLNK: 26137731Smckusick mode |= IFLNK; 26237731Smckusick break; 26337731Smckusick case VSOCK: 26437731Smckusick mode |= IFSOCK; 26537731Smckusick break; 26637731Smckusick default: 26737731Smckusick return (EBADF); 26837731Smckusick }; 26937731Smckusick sb->st_mode = mode; 27037731Smckusick sb->st_nlink = vap->va_nlink; 27137731Smckusick sb->st_uid = vap->va_uid; 27237731Smckusick sb->st_gid = vap->va_gid; 27337731Smckusick sb->st_rdev = vap->va_rdev; 27437731Smckusick sb->st_size = vap->va_size; 27537731Smckusick sb->st_atime = vap->va_atime.tv_sec; 27637731Smckusick sb->st_spare1 = 0; 27737731Smckusick sb->st_mtime = vap->va_mtime.tv_sec; 27837731Smckusick sb->st_spare2 = 0; 27937731Smckusick sb->st_ctime = vap->va_ctime.tv_sec; 28037731Smckusick sb->st_spare3 = 0; 28137731Smckusick sb->st_blksize = vap->va_blocksize; 28238257Smckusick sb->st_flags = vap->va_flags; 28338257Smckusick sb->st_gen = vap->va_gen; 28437731Smckusick /* 28537731Smckusick * XXX THIS IS NOT CORRECT!!, but be sure to change ufs_getattr() 28637731Smckusick * if you change it. 28737731Smckusick */ 28837731Smckusick sb->st_blocks = vap->va_bytes; 28937731Smckusick return (0); 29037731Smckusick } 29137731Smckusick 29237731Smckusick /* 29337731Smckusick * Vnode ioctl call 29437731Smckusick */ 29537731Smckusick vn_ioctl(fp, com, data) 29637731Smckusick struct file *fp; 29737731Smckusick int com; 29837731Smckusick caddr_t data; 29937731Smckusick { 30037731Smckusick register struct vnode *vp = ((struct vnode *)fp->f_data); 30137731Smckusick struct vattr vattr; 30237731Smckusick int error; 30337731Smckusick 30437731Smckusick switch (vp->v_type) { 30537731Smckusick 30637731Smckusick case VREG: 30737731Smckusick case VDIR: 30837731Smckusick if (com == FIONREAD) { 30937731Smckusick if (error = VOP_GETATTR(vp, &vattr, u.u_cred)) 31037731Smckusick return (error); 31137731Smckusick *(off_t *)data = vattr.va_size - fp->f_offset; 31237731Smckusick return (0); 31318Sbill } 31437731Smckusick if (com == FIONBIO || com == FIOASYNC) /* XXX */ 31537731Smckusick return (0); /* XXX */ 31637731Smckusick /* fall into ... */ 31737731Smckusick 31837731Smckusick default: 31937731Smckusick return (ENOTTY); 32037731Smckusick 32137731Smckusick case VCHR: 32237731Smckusick case VBLK: 32337731Smckusick u.u_r.r_val1 = 0; 32437731Smckusick if (setjmp(&u.u_qsave)) { 32537731Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 32637731Smckusick return(EINTR); 32737731Smckusick u.u_eosys = RESTARTSYS; 32837731Smckusick return (0); 32937731Smckusick } 33037731Smckusick return (VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred)); 33118Sbill } 33237731Smckusick } 33337731Smckusick 33437731Smckusick /* 33537731Smckusick * Vnode select call 33637731Smckusick */ 33737731Smckusick vn_select(fp, which) 33837731Smckusick struct file *fp; 33937731Smckusick int which; 34037731Smckusick { 34137731Smckusick return(VOP_SELECT(((struct vnode *)fp->f_data), which, u.u_cred)); 34237731Smckusick } 34337731Smckusick 34437731Smckusick /* 34537731Smckusick * Vnode close call 34637731Smckusick */ 34737731Smckusick vn_close(fp) 34837731Smckusick register struct file *fp; 34937731Smckusick { 35037731Smckusick struct vnode *vp = ((struct vnode *)fp->f_data); 35137731Smckusick int error; 35237731Smckusick 35337731Smckusick if (fp->f_flag & (FSHLOCK|FEXLOCK)) 35437731Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 35511162Ssam /* 35637731Smckusick * Must delete vnode reference from this file entry 35737731Smckusick * before VOP_CLOSE, so that only other references 35837731Smckusick * will prevent close. 35911162Ssam */ 36037731Smckusick fp->f_data = (caddr_t) 0; 36137731Smckusick error = VOP_CLOSE(vp, fp->f_flag, u.u_cred); 36237731Smckusick vrele(vp); 36337731Smckusick return (error); 36437731Smckusick } 36537731Smckusick 36637731Smckusick /* 36737731Smckusick * Place an advisory lock on a vnode. 36837731Smckusick * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries 36937731Smckusick */ 37037731Smckusick vn_lock(fp, cmd) 37137731Smckusick register struct file *fp; 37237731Smckusick int cmd; 37337731Smckusick { 37437731Smckusick register int priority = PLOCK; 37537731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 37637731Smckusick 37737731Smckusick if ((cmd & LOCK_EX) == 0) 37837731Smckusick priority += 4; 37937731Smckusick if (setjmp(&u.u_qsave)) { 38037731Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 38137731Smckusick return(EINTR); 38237731Smckusick u.u_eosys = RESTARTSYS; 3834817Swnj return (0); 38437731Smckusick } 38511162Ssam /* 38637731Smckusick * If there's a exclusive lock currently applied 38737731Smckusick * to the file, then we've gotta wait for the 38837731Smckusick * lock with everyone else. 38911162Ssam */ 39037731Smckusick again: 39137731Smckusick while (vp->v_flag & VEXLOCK) { 39237731Smckusick /* 39337731Smckusick * If we're holding an exclusive 39437731Smckusick * lock, then release it. 39537731Smckusick */ 39637731Smckusick if (fp->f_flag & FEXLOCK) { 39737731Smckusick vn_unlock(fp, FEXLOCK); 39837731Smckusick continue; 39937731Smckusick } 40037731Smckusick if (cmd & LOCK_NB) 40137731Smckusick return (EWOULDBLOCK); 40237731Smckusick vp->v_flag |= VLWAIT; 40337731Smckusick sleep((caddr_t)&vp->v_exlockc, priority); 40418Sbill } 40537731Smckusick if ((cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) { 40637731Smckusick /* 40737731Smckusick * Must wait for any shared locks to finish 40837731Smckusick * before we try to apply a exclusive lock. 40937731Smckusick * 41037731Smckusick * If we're holding a shared 41137731Smckusick * lock, then release it. 41237731Smckusick */ 41337731Smckusick if (fp->f_flag & FSHLOCK) { 41437731Smckusick vn_unlock(fp, FSHLOCK); 41537731Smckusick goto again; 41637731Smckusick } 41737731Smckusick if (cmd & LOCK_NB) 41837731Smckusick return (EWOULDBLOCK); 41937731Smckusick vp->v_flag |= VLWAIT; 42037731Smckusick sleep((caddr_t)&vp->v_shlockc, PLOCK); 42137731Smckusick goto again; 42237731Smckusick } 42337731Smckusick if (fp->f_flag & FEXLOCK) 42437731Smckusick panic("vn_lock"); 42537731Smckusick if (cmd & LOCK_EX) { 42637731Smckusick cmd &= ~LOCK_SH; 42737731Smckusick vp->v_exlockc++; 42837731Smckusick vp->v_flag |= VEXLOCK; 42937731Smckusick fp->f_flag |= FEXLOCK; 43037731Smckusick } 43137731Smckusick if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { 43237731Smckusick vp->v_shlockc++; 43337731Smckusick vp->v_flag |= VSHLOCK; 43437731Smckusick fp->f_flag |= FSHLOCK; 43537731Smckusick } 43637731Smckusick return (0); 43718Sbill } 43818Sbill 43918Sbill /* 44037731Smckusick * Unlock a file. 44118Sbill */ 44237731Smckusick vn_unlock(fp, kind) 44337731Smckusick register struct file *fp; 44437731Smckusick int kind; 44518Sbill { 44637731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 44737731Smckusick int flags; 44818Sbill 44937731Smckusick kind &= fp->f_flag; 45037731Smckusick if (vp == NULL || kind == 0) 45137731Smckusick return; 45237731Smckusick flags = vp->v_flag; 45337731Smckusick if (kind & FSHLOCK) { 45437731Smckusick if ((flags & VSHLOCK) == 0) 45537731Smckusick panic("vn_unlock: SHLOCK"); 45637731Smckusick if (--vp->v_shlockc == 0) { 45737731Smckusick vp->v_flag &= ~VSHLOCK; 45837731Smckusick if (flags & VLWAIT) 45937731Smckusick wakeup((caddr_t)&vp->v_shlockc); 46037731Smckusick } 46137731Smckusick fp->f_flag &= ~FSHLOCK; 46237552Smckusick } 46337731Smckusick if (kind & FEXLOCK) { 46437731Smckusick if ((flags & VEXLOCK) == 0) 46537731Smckusick panic("vn_unlock: EXLOCK"); 46637731Smckusick if (--vp->v_exlockc == 0) { 46737731Smckusick vp->v_flag &= ~(VEXLOCK|VLWAIT); 46837731Smckusick if (flags & VLWAIT) 46937731Smckusick wakeup((caddr_t)&vp->v_exlockc); 47037731Smckusick } 47137731Smckusick fp->f_flag &= ~FEXLOCK; 47237731Smckusick } 47318Sbill } 47418Sbill 47518Sbill /* 47637731Smckusick * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 47737731Smckusick * - look up fsid in mount list (if not found ret error) 47837731Smckusick * - get vp by calling VFS_FHTOVP() macro 47937731Smckusick * - if lockflag lock it with VOP_LOCK() 48018Sbill */ 48137731Smckusick vn_fhtovp(fhp, lockflag, vpp) 48237731Smckusick fhandle_t *fhp; 48337731Smckusick int lockflag; 48437731Smckusick struct vnode **vpp; 48518Sbill { 48637731Smckusick register struct mount *mp; 48737731Smckusick int error; 48818Sbill 48937731Smckusick if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 49037731Smckusick return (ESTALE); 49138146Smckusick if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 49238146Smckusick return (ESTALE); 49338146Smckusick if (!lockflag) 49438146Smckusick VOP_UNLOCK(*vpp); 49537731Smckusick return (0); 49637731Smckusick } 49737731Smckusick 49837731Smckusick /* 49937731Smckusick * Revoke access the current tty by all processes. 50037731Smckusick * Used only by the super-user in init 50137731Smckusick * to give ``clean'' terminals at login. 50237731Smckusick */ 50337731Smckusick vhangup() 50437731Smckusick { 50537731Smckusick 50637731Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 50737731Smckusick return; 50837731Smckusick if (u.u_ttyp == NULL) 50937731Smckusick return; 51037731Smckusick forceclose(u.u_ttyd); 51137731Smckusick if ((u.u_ttyp->t_state) & TS_ISOPEN) 51237731Smckusick gsignal(u.u_ttyp->t_pgid, SIGHUP); 51337731Smckusick u.u_ttyp->t_session = 0; 51437731Smckusick u.u_ttyp->t_pgid = 0; 51537731Smckusick } 51637731Smckusick 51737731Smckusick forceclose(dev) 51837731Smckusick dev_t dev; 51937731Smckusick { 52037731Smckusick register struct file *fp; 52137731Smckusick register struct vnode *vp; 52237731Smckusick 52337731Smckusick for (fp = file; fp < fileNFILE; fp++) { 52437731Smckusick if (fp->f_count == 0) 52537731Smckusick continue; 52637731Smckusick if (fp->f_type != DTYPE_VNODE) 52737731Smckusick continue; 52837731Smckusick vp = (struct vnode *)fp->f_data; 52937731Smckusick if (vp == 0) 53037731Smckusick continue; 53137731Smckusick if (vp->v_type != VCHR) 53237731Smckusick continue; 53337731Smckusick if (vp->v_rdev != dev) 53437731Smckusick continue; 53537731Smckusick fp->f_flag &= ~(FREAD|FWRITE); 53618Sbill } 53718Sbill } 53837731Smckusick 53937731Smckusick /* 540*38351Smckusick * Vnode reference, just increment the count 541*38351Smckusick */ 542*38351Smckusick void vref(vp) 543*38351Smckusick struct vnode *vp; 544*38351Smckusick { 545*38351Smckusick 546*38351Smckusick vp->v_count++; 547*38351Smckusick } 548*38351Smckusick 549*38351Smckusick /* 55037731Smckusick * Vnode release, just decrement the count and call VOP_INACTIVE() 55137731Smckusick */ 55237731Smckusick void vrele(vp) 55337731Smckusick register struct vnode *vp; 55437731Smckusick { 55537731Smckusick 55637731Smckusick if (vp == NULL) 55737731Smckusick return; 55837731Smckusick vp->v_count--; 55937731Smckusick if (vp->v_count < 0) 56037731Smckusick printf("inode %d, bad ref count %d\n", 56137731Smckusick VTOI(vp)->i_number, vp->v_count); 56237731Smckusick if (vp->v_count == 0) 56337731Smckusick VOP_INACTIVE(vp); 56437731Smckusick } 56537731Smckusick 56637731Smckusick /* 56737731Smckusick * vput(), just unlock and vrele() 56837731Smckusick */ 56937731Smckusick vput(vp) 57037731Smckusick register struct vnode *vp; 57137731Smckusick { 57237731Smckusick VOP_UNLOCK(vp); 57337731Smckusick vrele(vp); 57437731Smckusick } 57537731Smckusick 57637731Smckusick /* 57737731Smckusick * Noop 57837731Smckusick */ 57937731Smckusick vfs_noop() 58037731Smckusick { 58137731Smckusick 58237731Smckusick return (ENXIO); 58337731Smckusick } 58437731Smckusick 58537731Smckusick /* 58637731Smckusick * Null op 58737731Smckusick */ 58837731Smckusick vfs_nullop() 58937731Smckusick { 59037731Smckusick 59137731Smckusick return (0); 59237731Smckusick } 593