1b5970980Smckusick /* 2760e73c7Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3760e73c7Smckusick * All rights reserved. 4b5970980Smckusick * 573a8e095Sbostic * %sccs.include.redist.c% 6760e73c7Smckusick * 7*9fc842b5Smckusick * @(#)vfs_vnops.c 7.24 (Berkeley) 08/22/90 8b5970980Smckusick */ 982e77ef7Ssam 10ecd0bebeSbloom #include "param.h" 11ecd0bebeSbloom #include "systm.h" 12ecd0bebeSbloom #include "user.h" 13760e73c7Smckusick #include "kernel.h" 14ecd0bebeSbloom #include "file.h" 15760e73c7Smckusick #include "stat.h" 16760e73c7Smckusick #include "buf.h" 17760e73c7Smckusick #include "proc.h" 18760e73c7Smckusick #include "uio.h" 19ecd0bebeSbloom #include "socket.h" 20ecd0bebeSbloom #include "socketvar.h" 21760e73c7Smckusick #include "mount.h" 22760e73c7Smckusick #include "vnode.h" 23760e73c7Smckusick #include "ioctl.h" 24760e73c7Smckusick #include "tty.h" 251d37f34bSbill 26760e73c7Smckusick int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close(); 27760e73c7Smckusick struct fileops vnops = 28760e73c7Smckusick { vn_read, vn_write, vn_ioctl, vn_select, vn_close }; 29ae1aeb7bSmckusick 301d37f34bSbill /* 31760e73c7Smckusick * Common code for vnode open operations. 32760e73c7Smckusick * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 331d37f34bSbill */ 34760e73c7Smckusick vn_open(ndp, fmode, cmode) 35760e73c7Smckusick register struct nameidata *ndp; 36760e73c7Smckusick int fmode, cmode; 371d37f34bSbill { 38760e73c7Smckusick register struct vnode *vp; 39760e73c7Smckusick struct vattr vat; 40760e73c7Smckusick struct vattr *vap = &vat; 41760e73c7Smckusick int error; 421d37f34bSbill 43760e73c7Smckusick if (fmode & FCREAT) { 44760e73c7Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 45760e73c7Smckusick if ((fmode & FEXCL) == 0) 46760e73c7Smckusick ndp->ni_nameiop |= FOLLOW; 47760e73c7Smckusick if (error = namei(ndp)) 48760e73c7Smckusick return (error); 49760e73c7Smckusick if (ndp->ni_vp == NULL) { 509a8d5e2aSmckusick VATTR_NULL(vap); 51760e73c7Smckusick vap->va_type = VREG; 52760e73c7Smckusick vap->va_mode = cmode; 53760e73c7Smckusick if (error = VOP_CREATE(ndp, vap)) 54760e73c7Smckusick return (error); 55760e73c7Smckusick fmode &= ~FTRUNC; 56760e73c7Smckusick vp = ndp->ni_vp; 57760e73c7Smckusick } else { 5883225eaeSmckusick if (ndp->ni_dvp == ndp->ni_vp) 5983225eaeSmckusick vrele(ndp->ni_dvp); 60e8a20c25Smckusick else 6183225eaeSmckusick vput(ndp->ni_dvp); 6283225eaeSmckusick ndp->ni_dvp = NULL; 63760e73c7Smckusick vp = ndp->ni_vp; 64760e73c7Smckusick if (fmode & FEXCL) { 65760e73c7Smckusick error = EEXIST; 66760e73c7Smckusick goto bad; 67760e73c7Smckusick } 68760e73c7Smckusick fmode &= ~FCREAT; 69760e73c7Smckusick } 70760e73c7Smckusick } else { 71760e73c7Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 72760e73c7Smckusick if (error = namei(ndp)) 73760e73c7Smckusick return (error); 74760e73c7Smckusick vp = ndp->ni_vp; 75760e73c7Smckusick } 76760e73c7Smckusick if (vp->v_type == VSOCK) { 77760e73c7Smckusick error = EOPNOTSUPP; 78760e73c7Smckusick goto bad; 79760e73c7Smckusick } 80760e73c7Smckusick if ((fmode & FCREAT) == 0) { 81760e73c7Smckusick if (fmode & FREAD) { 82a597f5e9Smckusick if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred)) 83760e73c7Smckusick goto bad; 84760e73c7Smckusick } 85760e73c7Smckusick if (fmode & (FWRITE|FTRUNC)) { 86760e73c7Smckusick if (vp->v_type == VDIR) { 87760e73c7Smckusick error = EISDIR; 88760e73c7Smckusick goto bad; 89760e73c7Smckusick } 90a597f5e9Smckusick if ((error = vn_writechk(vp)) || 91a597f5e9Smckusick (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred))) 92a597f5e9Smckusick goto bad; 93760e73c7Smckusick } 94760e73c7Smckusick } 95760e73c7Smckusick if (fmode & FTRUNC) { 969a8d5e2aSmckusick VATTR_NULL(vap); 97760e73c7Smckusick vap->va_size = 0; 98760e73c7Smckusick if (error = VOP_SETATTR(vp, vap, ndp->ni_cred)) 99760e73c7Smckusick goto bad; 100760e73c7Smckusick } 101760e73c7Smckusick VOP_UNLOCK(vp); 102a25d0e59Smckusick error = VOP_OPEN(vp, fmode, ndp->ni_cred); 103a25d0e59Smckusick if (error) 104a25d0e59Smckusick vrele(vp); 105a25d0e59Smckusick return (error); 106760e73c7Smckusick 107760e73c7Smckusick bad: 108760e73c7Smckusick vput(vp); 109760e73c7Smckusick return (error); 110760e73c7Smckusick } 111760e73c7Smckusick 11245db6fc1Ssam /* 113a597f5e9Smckusick * Check for write permissions on the specified vnode. 114a597f5e9Smckusick * The read-only status of the file system is checked. 115a597f5e9Smckusick * Also, prototype text segments cannot be written. 11645db6fc1Ssam */ 117a597f5e9Smckusick vn_writechk(vp) 118760e73c7Smckusick register struct vnode *vp; 119760e73c7Smckusick { 120760e73c7Smckusick 121760e73c7Smckusick /* 122760e73c7Smckusick * Disallow write attempts on read-only file systems; 123760e73c7Smckusick * unless the file is a socket or a block or character 124760e73c7Smckusick * device resident on the file system. 125760e73c7Smckusick */ 126*9fc842b5Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) { 127*9fc842b5Smckusick switch (vp->v_type) { 128*9fc842b5Smckusick case VREG: case VDIR: case VLNK: 129760e73c7Smckusick return (EROFS); 130*9fc842b5Smckusick } 131*9fc842b5Smckusick } 13245db6fc1Ssam /* 13345db6fc1Ssam * If there's shared text associated with 134a597f5e9Smckusick * the vnode, try to free it up once. If 13545db6fc1Ssam * we fail, we can't allow writing. 13645db6fc1Ssam */ 137760e73c7Smckusick if (vp->v_flag & VTEXT) 138760e73c7Smckusick xrele(vp); 139760e73c7Smckusick if (vp->v_flag & VTEXT) 140760e73c7Smckusick return (ETXTBSY); 141a597f5e9Smckusick return (0); 1421d37f34bSbill } 1431d37f34bSbill 1441d37f34bSbill /* 145760e73c7Smckusick * Vnode version of rdwri() for calls on file systems. 1461d37f34bSbill */ 147760e73c7Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) 148760e73c7Smckusick enum uio_rw rw; 149760e73c7Smckusick struct vnode *vp; 150760e73c7Smckusick caddr_t base; 151760e73c7Smckusick int len; 152760e73c7Smckusick off_t offset; 153760e73c7Smckusick enum uio_seg segflg; 154760e73c7Smckusick int ioflg; 155760e73c7Smckusick struct ucred *cred; 156760e73c7Smckusick int *aresid; 1571d37f34bSbill { 158760e73c7Smckusick struct uio auio; 159760e73c7Smckusick struct iovec aiov; 160760e73c7Smckusick int error; 1611d37f34bSbill 1622a601dc3Smckusick if ((ioflg & IO_NODELOCKED) == 0) 1632a601dc3Smckusick VOP_LOCK(vp); 164760e73c7Smckusick auio.uio_iov = &aiov; 165760e73c7Smckusick auio.uio_iovcnt = 1; 166760e73c7Smckusick aiov.iov_base = base; 167760e73c7Smckusick aiov.iov_len = len; 168760e73c7Smckusick auio.uio_resid = len; 169760e73c7Smckusick auio.uio_offset = offset; 170760e73c7Smckusick auio.uio_segflg = segflg; 171760e73c7Smckusick auio.uio_rw = rw; 172760e73c7Smckusick if (rw == UIO_READ) 1732a601dc3Smckusick error = VOP_READ(vp, &auio, ioflg, cred); 174760e73c7Smckusick else 1752a601dc3Smckusick error = VOP_WRITE(vp, &auio, ioflg, cred); 176760e73c7Smckusick if (aresid) 177760e73c7Smckusick *aresid = auio.uio_resid; 178760e73c7Smckusick else 179760e73c7Smckusick if (auio.uio_resid && error == 0) 180760e73c7Smckusick error = EIO; 1812a601dc3Smckusick if ((ioflg & IO_NODELOCKED) == 0) 1822a601dc3Smckusick VOP_UNLOCK(vp); 183760e73c7Smckusick return (error); 1842510f0cdSmckusick } 1851d37f34bSbill 186760e73c7Smckusick vn_read(fp, uio, cred) 187760e73c7Smckusick struct file *fp; 188760e73c7Smckusick struct uio *uio; 189760e73c7Smckusick struct ucred *cred; 1901d37f34bSbill { 1912a601dc3Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 1922a601dc3Smckusick int count, error; 1931d37f34bSbill 1942a601dc3Smckusick VOP_LOCK(vp); 1952a601dc3Smckusick uio->uio_offset = fp->f_offset; 1962a601dc3Smckusick count = uio->uio_resid; 1972a601dc3Smckusick error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred); 1982a601dc3Smckusick fp->f_offset += count - uio->uio_resid; 1992a601dc3Smckusick VOP_UNLOCK(vp); 2002a601dc3Smckusick return (error); 201760e73c7Smckusick } 202760e73c7Smckusick 203760e73c7Smckusick vn_write(fp, uio, cred) 204760e73c7Smckusick struct file *fp; 205760e73c7Smckusick struct uio *uio; 206760e73c7Smckusick struct ucred *cred; 207760e73c7Smckusick { 208760e73c7Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 2092a601dc3Smckusick int count, error, ioflag = 0; 210760e73c7Smckusick 211760e73c7Smckusick if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) 212760e73c7Smckusick ioflag |= IO_APPEND; 213760e73c7Smckusick if (fp->f_flag & FNDELAY) 214760e73c7Smckusick ioflag |= IO_NDELAY; 2152a601dc3Smckusick VOP_LOCK(vp); 2162a601dc3Smckusick uio->uio_offset = fp->f_offset; 2172a601dc3Smckusick count = uio->uio_resid; 2182a601dc3Smckusick error = VOP_WRITE(vp, uio, ioflag, cred); 2192a601dc3Smckusick if (ioflag & IO_APPEND) 2202a601dc3Smckusick fp->f_offset = uio->uio_offset; 2212a601dc3Smckusick else 2222a601dc3Smckusick fp->f_offset += count - uio->uio_resid; 2232a601dc3Smckusick VOP_UNLOCK(vp); 2242a601dc3Smckusick return (error); 225760e73c7Smckusick } 226760e73c7Smckusick 227760e73c7Smckusick /* 228760e73c7Smckusick * Get stat info for a vnode. 229760e73c7Smckusick */ 230760e73c7Smckusick vn_stat(vp, sb) 231760e73c7Smckusick struct vnode *vp; 232760e73c7Smckusick register struct stat *sb; 233760e73c7Smckusick { 234760e73c7Smckusick struct vattr vattr; 235760e73c7Smckusick register struct vattr *vap; 236760e73c7Smckusick int error; 237760e73c7Smckusick u_short mode; 238760e73c7Smckusick 239760e73c7Smckusick vap = &vattr; 240760e73c7Smckusick error = VOP_GETATTR(vp, vap, u.u_cred); 241760e73c7Smckusick if (error) 242760e73c7Smckusick return (error); 243760e73c7Smckusick /* 244760e73c7Smckusick * Copy from vattr table 245760e73c7Smckusick */ 246760e73c7Smckusick sb->st_dev = vap->va_fsid; 247760e73c7Smckusick sb->st_ino = vap->va_fileid; 248760e73c7Smckusick mode = vap->va_mode; 249760e73c7Smckusick switch (vp->v_type) { 250760e73c7Smckusick case VREG: 2516357f7baSmckusick mode |= S_IFREG; 252760e73c7Smckusick break; 253760e73c7Smckusick case VDIR: 2546357f7baSmckusick mode |= S_IFDIR; 255760e73c7Smckusick break; 256760e73c7Smckusick case VBLK: 2576357f7baSmckusick mode |= S_IFBLK; 258760e73c7Smckusick break; 259760e73c7Smckusick case VCHR: 2606357f7baSmckusick mode |= S_IFCHR; 261760e73c7Smckusick break; 262760e73c7Smckusick case VLNK: 2636357f7baSmckusick mode |= S_IFLNK; 264760e73c7Smckusick break; 265760e73c7Smckusick case VSOCK: 2666357f7baSmckusick mode |= S_IFSOCK; 267760e73c7Smckusick break; 268920ab10fSmckusick case VFIFO: 269920ab10fSmckusick mode |= S_IFIFO; 270920ab10fSmckusick break; 271760e73c7Smckusick default: 272760e73c7Smckusick return (EBADF); 273760e73c7Smckusick }; 274760e73c7Smckusick sb->st_mode = mode; 275760e73c7Smckusick sb->st_nlink = vap->va_nlink; 276760e73c7Smckusick sb->st_uid = vap->va_uid; 277760e73c7Smckusick sb->st_gid = vap->va_gid; 278760e73c7Smckusick sb->st_rdev = vap->va_rdev; 279760e73c7Smckusick sb->st_size = vap->va_size; 280760e73c7Smckusick sb->st_atime = vap->va_atime.tv_sec; 281760e73c7Smckusick sb->st_spare1 = 0; 282760e73c7Smckusick sb->st_mtime = vap->va_mtime.tv_sec; 283760e73c7Smckusick sb->st_spare2 = 0; 284760e73c7Smckusick sb->st_ctime = vap->va_ctime.tv_sec; 285760e73c7Smckusick sb->st_spare3 = 0; 286760e73c7Smckusick sb->st_blksize = vap->va_blocksize; 28718b27549Smckusick sb->st_flags = vap->va_flags; 28818b27549Smckusick sb->st_gen = vap->va_gen; 289aa6f7503Smckusick sb->st_blocks = vap->va_bytes / S_BLKSIZE; 2901d37f34bSbill return (0); 2911d37f34bSbill } 292760e73c7Smckusick 293760e73c7Smckusick /* 294760e73c7Smckusick * Vnode ioctl call 295760e73c7Smckusick */ 296760e73c7Smckusick vn_ioctl(fp, com, data) 297760e73c7Smckusick struct file *fp; 298760e73c7Smckusick int com; 299760e73c7Smckusick caddr_t data; 300760e73c7Smckusick { 301760e73c7Smckusick register struct vnode *vp = ((struct vnode *)fp->f_data); 302760e73c7Smckusick struct vattr vattr; 303760e73c7Smckusick int error; 304760e73c7Smckusick 305760e73c7Smckusick switch (vp->v_type) { 306760e73c7Smckusick 307760e73c7Smckusick case VREG: 308760e73c7Smckusick case VDIR: 309760e73c7Smckusick if (com == FIONREAD) { 310760e73c7Smckusick if (error = VOP_GETATTR(vp, &vattr, u.u_cred)) 311760e73c7Smckusick return (error); 312760e73c7Smckusick *(off_t *)data = vattr.va_size - fp->f_offset; 313760e73c7Smckusick return (0); 314760e73c7Smckusick } 315760e73c7Smckusick if (com == FIONBIO || com == FIOASYNC) /* XXX */ 316760e73c7Smckusick return (0); /* XXX */ 317760e73c7Smckusick /* fall into ... */ 318760e73c7Smckusick 319760e73c7Smckusick default: 320760e73c7Smckusick return (ENOTTY); 321760e73c7Smckusick 322920ab10fSmckusick case VFIFO: 323760e73c7Smckusick case VCHR: 324760e73c7Smckusick case VBLK: 325e79e4887Smarc error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred); 326e79e4887Smarc if (error == 0 && com == TIOCSCTTY) { 327e79e4887Smarc u.u_procp->p_session->s_ttyvp = vp; 328e79e4887Smarc VREF(vp); 329e79e4887Smarc } 330e79e4887Smarc return (error); 331760e73c7Smckusick } 332760e73c7Smckusick } 333760e73c7Smckusick 334760e73c7Smckusick /* 335760e73c7Smckusick * Vnode select call 336760e73c7Smckusick */ 337760e73c7Smckusick vn_select(fp, which) 338760e73c7Smckusick struct file *fp; 339760e73c7Smckusick int which; 340760e73c7Smckusick { 341920ab10fSmckusick return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 342920ab10fSmckusick u.u_cred)); 343760e73c7Smckusick } 344760e73c7Smckusick 345760e73c7Smckusick /* 346760e73c7Smckusick * Vnode close call 347760e73c7Smckusick */ 348760e73c7Smckusick vn_close(fp) 349760e73c7Smckusick register struct file *fp; 350760e73c7Smckusick { 351760e73c7Smckusick struct vnode *vp = ((struct vnode *)fp->f_data); 352760e73c7Smckusick int error; 353760e73c7Smckusick 354760e73c7Smckusick if (fp->f_flag & (FSHLOCK|FEXLOCK)) 355760e73c7Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 356760e73c7Smckusick /* 357760e73c7Smckusick * Must delete vnode reference from this file entry 358760e73c7Smckusick * before VOP_CLOSE, so that only other references 359760e73c7Smckusick * will prevent close. 360760e73c7Smckusick */ 361760e73c7Smckusick fp->f_data = (caddr_t) 0; 362760e73c7Smckusick error = VOP_CLOSE(vp, fp->f_flag, u.u_cred); 363760e73c7Smckusick vrele(vp); 364760e73c7Smckusick return (error); 365760e73c7Smckusick } 366760e73c7Smckusick 367760e73c7Smckusick /* 368760e73c7Smckusick * Place an advisory lock on a vnode. 369760e73c7Smckusick * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries 370760e73c7Smckusick */ 371760e73c7Smckusick vn_lock(fp, cmd) 372760e73c7Smckusick register struct file *fp; 373760e73c7Smckusick int cmd; 374760e73c7Smckusick { 375760e73c7Smckusick register int priority = PLOCK; 376760e73c7Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 377bad83f78Skarels int error = 0; 378bad83f78Skarels static char lockstr[] = "flock"; 379760e73c7Smckusick 380760e73c7Smckusick if ((cmd & LOCK_EX) == 0) 381760e73c7Smckusick priority += 4; 382bad83f78Skarels priority |= PCATCH; 383bad83f78Skarels 384760e73c7Smckusick /* 385760e73c7Smckusick * If there's a exclusive lock currently applied 386760e73c7Smckusick * to the file, then we've gotta wait for the 387760e73c7Smckusick * lock with everyone else. 388760e73c7Smckusick */ 389760e73c7Smckusick again: 390760e73c7Smckusick while (vp->v_flag & VEXLOCK) { 391760e73c7Smckusick /* 392760e73c7Smckusick * If we're holding an exclusive 393760e73c7Smckusick * lock, then release it. 394760e73c7Smckusick */ 395760e73c7Smckusick if (fp->f_flag & FEXLOCK) { 396760e73c7Smckusick vn_unlock(fp, FEXLOCK); 397760e73c7Smckusick continue; 398760e73c7Smckusick } 399760e73c7Smckusick if (cmd & LOCK_NB) 400760e73c7Smckusick return (EWOULDBLOCK); 401760e73c7Smckusick vp->v_flag |= VLWAIT; 402bad83f78Skarels if (error = tsleep((caddr_t)&vp->v_exlockc, priority, 403bad83f78Skarels lockstr, 0)) 404bad83f78Skarels return (error); 405760e73c7Smckusick } 406*9fc842b5Smckusick if (error == 0 && (cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) { 407760e73c7Smckusick /* 408760e73c7Smckusick * Must wait for any shared locks to finish 409760e73c7Smckusick * before we try to apply a exclusive lock. 410760e73c7Smckusick * 411760e73c7Smckusick * If we're holding a shared 412760e73c7Smckusick * lock, then release it. 413760e73c7Smckusick */ 414760e73c7Smckusick if (fp->f_flag & FSHLOCK) { 415760e73c7Smckusick vn_unlock(fp, FSHLOCK); 416760e73c7Smckusick goto again; 417760e73c7Smckusick } 418760e73c7Smckusick if (cmd & LOCK_NB) 419760e73c7Smckusick return (EWOULDBLOCK); 420760e73c7Smckusick vp->v_flag |= VLWAIT; 421bad83f78Skarels if (error = tsleep((caddr_t)&vp->v_shlockc, PLOCK | PCATCH, 422*9fc842b5Smckusick lockstr, 0)) 423bad83f78Skarels return (error); 424760e73c7Smckusick } 425760e73c7Smckusick if (fp->f_flag & FEXLOCK) 426760e73c7Smckusick panic("vn_lock"); 427760e73c7Smckusick if (cmd & LOCK_EX) { 428760e73c7Smckusick cmd &= ~LOCK_SH; 429760e73c7Smckusick vp->v_exlockc++; 430760e73c7Smckusick vp->v_flag |= VEXLOCK; 431760e73c7Smckusick fp->f_flag |= FEXLOCK; 432760e73c7Smckusick } 433760e73c7Smckusick if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { 434760e73c7Smckusick vp->v_shlockc++; 435760e73c7Smckusick vp->v_flag |= VSHLOCK; 436760e73c7Smckusick fp->f_flag |= FSHLOCK; 437760e73c7Smckusick } 438760e73c7Smckusick return (0); 439760e73c7Smckusick } 440760e73c7Smckusick 441760e73c7Smckusick /* 442760e73c7Smckusick * Unlock a file. 443760e73c7Smckusick */ 444760e73c7Smckusick vn_unlock(fp, kind) 445760e73c7Smckusick register struct file *fp; 446760e73c7Smckusick int kind; 447760e73c7Smckusick { 448760e73c7Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 449760e73c7Smckusick int flags; 450760e73c7Smckusick 451760e73c7Smckusick kind &= fp->f_flag; 452760e73c7Smckusick if (vp == NULL || kind == 0) 453760e73c7Smckusick return; 454760e73c7Smckusick flags = vp->v_flag; 455760e73c7Smckusick if (kind & FSHLOCK) { 456760e73c7Smckusick if ((flags & VSHLOCK) == 0) 457760e73c7Smckusick panic("vn_unlock: SHLOCK"); 458760e73c7Smckusick if (--vp->v_shlockc == 0) { 459760e73c7Smckusick vp->v_flag &= ~VSHLOCK; 460760e73c7Smckusick if (flags & VLWAIT) 461760e73c7Smckusick wakeup((caddr_t)&vp->v_shlockc); 462760e73c7Smckusick } 463760e73c7Smckusick fp->f_flag &= ~FSHLOCK; 464760e73c7Smckusick } 465760e73c7Smckusick if (kind & FEXLOCK) { 466760e73c7Smckusick if ((flags & VEXLOCK) == 0) 467760e73c7Smckusick panic("vn_unlock: EXLOCK"); 468760e73c7Smckusick if (--vp->v_exlockc == 0) { 469760e73c7Smckusick vp->v_flag &= ~(VEXLOCK|VLWAIT); 470760e73c7Smckusick if (flags & VLWAIT) 471760e73c7Smckusick wakeup((caddr_t)&vp->v_exlockc); 472760e73c7Smckusick } 473760e73c7Smckusick fp->f_flag &= ~FEXLOCK; 474760e73c7Smckusick } 475760e73c7Smckusick } 476760e73c7Smckusick 477760e73c7Smckusick /* 478760e73c7Smckusick * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 479760e73c7Smckusick * - look up fsid in mount list (if not found ret error) 480760e73c7Smckusick * - get vp by calling VFS_FHTOVP() macro 481760e73c7Smckusick * - if lockflag lock it with VOP_LOCK() 482760e73c7Smckusick */ 483760e73c7Smckusick vn_fhtovp(fhp, lockflag, vpp) 484760e73c7Smckusick fhandle_t *fhp; 485760e73c7Smckusick int lockflag; 486760e73c7Smckusick struct vnode **vpp; 487760e73c7Smckusick { 488760e73c7Smckusick register struct mount *mp; 489760e73c7Smckusick 490760e73c7Smckusick if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 491760e73c7Smckusick return (ESTALE); 492229daf47Smckusick if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 493229daf47Smckusick return (ESTALE); 494229daf47Smckusick if (!lockflag) 495229daf47Smckusick VOP_UNLOCK(*vpp); 496760e73c7Smckusick return (0); 497760e73c7Smckusick } 498760e73c7Smckusick 499760e73c7Smckusick /* 500760e73c7Smckusick * Noop 501760e73c7Smckusick */ 502760e73c7Smckusick vfs_noop() 503760e73c7Smckusick { 504760e73c7Smckusick 505760e73c7Smckusick return (ENXIO); 506760e73c7Smckusick } 507760e73c7Smckusick 508760e73c7Smckusick /* 509760e73c7Smckusick * Null op 510760e73c7Smckusick */ 511760e73c7Smckusick vfs_nullop() 512760e73c7Smckusick { 513760e73c7Smckusick 514760e73c7Smckusick return (0); 5152510f0cdSmckusick } 516