123398Smckusick /* 2*37731Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3*37731Smckusick * All rights reserved. 423398Smckusick * 5*37731Smckusick * Redistribution and use in source and binary forms are permitted 6*37731Smckusick * provided that the above copyright notice and this paragraph are 7*37731Smckusick * duplicated in all such forms and that any documentation, 8*37731Smckusick * advertising materials, and other materials related to such 9*37731Smckusick * distribution and use acknowledge that the software was developed 10*37731Smckusick * by the University of California, Berkeley. The name of the 11*37731Smckusick * University may not be used to endorse or promote products derived 12*37731Smckusick * from this software without specific prior written permission. 13*37731Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*37731Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*37731Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*37731Smckusick * 17*37731Smckusick * @(#)vfs_vnops.c 7.4 (Berkeley) 05/09/89 1823398Smckusick */ 1918Sbill 2017099Sbloom #include "param.h" 2117099Sbloom #include "systm.h" 2217099Sbloom #include "user.h" 23*37731Smckusick #include "kernel.h" 2417099Sbloom #include "file.h" 25*37731Smckusick #include "stat.h" 26*37731Smckusick #include "buf.h" 27*37731Smckusick #include "proc.h" 28*37731Smckusick #include "uio.h" 2917099Sbloom #include "socket.h" 3017099Sbloom #include "socketvar.h" 31*37731Smckusick #include "mount.h" 32*37731Smckusick #include "vnode.h" 33*37731Smckusick #include "../ufs/inode.h" 34*37731Smckusick #include "../ufs/fs.h" 35*37731Smckusick #include "../ufs/quota.h" 36*37731Smckusick #include "ioctl.h" 37*37731Smckusick #include "tty.h" 3818Sbill 39*37731Smckusick int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close(); 40*37731Smckusick struct fileops vnops = 41*37731Smckusick { vn_read, vn_write, vn_ioctl, vn_select, vn_close }; 4237520Smckusick 4318Sbill /* 44*37731Smckusick * Common code for vnode open operations. 45*37731Smckusick * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 4618Sbill */ 47*37731Smckusick vn_open(ndp, fmode, cmode) 48*37731Smckusick register struct nameidata *ndp; 49*37731Smckusick int fmode, cmode; 50*37731Smckusick { 51*37731Smckusick register struct vnode *vp; 52*37731Smckusick struct vattr vat; 53*37731Smckusick struct vattr *vap = &vat; 54*37731Smckusick int error; 55*37731Smckusick 56*37731Smckusick if (fmode & FCREAT) { 57*37731Smckusick ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 58*37731Smckusick if ((fmode & FEXCL) == 0) 59*37731Smckusick ndp->ni_nameiop |= FOLLOW; 60*37731Smckusick if (error = namei(ndp)) 61*37731Smckusick return (error); 62*37731Smckusick if (ndp->ni_vp == NULL) { 63*37731Smckusick vattr_null(vap); 64*37731Smckusick vap->va_type = VREG; 65*37731Smckusick vap->va_mode = cmode; 66*37731Smckusick if (error = VOP_CREATE(ndp, vap)) 67*37731Smckusick return (error); 68*37731Smckusick fmode &= ~FTRUNC; 69*37731Smckusick vp = ndp->ni_vp; 70*37731Smckusick } else { 71*37731Smckusick vp = ndp->ni_vp; 72*37731Smckusick ndp->ni_vp = 0; 73*37731Smckusick VOP_ABORTOP(ndp); 74*37731Smckusick ndp->ni_vp = vp; 75*37731Smckusick if (fmode & FEXCL) { 76*37731Smckusick error = EEXIST; 77*37731Smckusick goto bad; 78*37731Smckusick } 79*37731Smckusick fmode &= ~FCREAT; 80*37731Smckusick } 81*37731Smckusick } else { 82*37731Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 83*37731Smckusick if (error = namei(ndp)) 84*37731Smckusick return (error); 85*37731Smckusick vp = ndp->ni_vp; 86*37731Smckusick } 87*37731Smckusick if (vp->v_type == VSOCK) { 88*37731Smckusick error = EOPNOTSUPP; 89*37731Smckusick goto bad; 90*37731Smckusick } 91*37731Smckusick if ((fmode & FCREAT) == 0) { 92*37731Smckusick if (fmode & FREAD) { 93*37731Smckusick if (error = vn_access(vp, VREAD, ndp->ni_cred)) 94*37731Smckusick goto bad; 95*37731Smckusick } 96*37731Smckusick if (fmode & (FWRITE|FTRUNC)) { 97*37731Smckusick if (error = vn_access(vp, VWRITE, ndp->ni_cred)) 98*37731Smckusick goto bad; 99*37731Smckusick if (vp->v_type == VDIR) { 100*37731Smckusick error = EISDIR; 101*37731Smckusick goto bad; 102*37731Smckusick } 103*37731Smckusick } 104*37731Smckusick } 105*37731Smckusick if (fmode & FTRUNC) { 106*37731Smckusick vattr_null(vap); 107*37731Smckusick vap->va_size = 0; 108*37731Smckusick if (error = VOP_SETATTR(vp, vap, ndp->ni_cred)) 109*37731Smckusick goto bad; 110*37731Smckusick } 111*37731Smckusick VOP_UNLOCK(vp); 112*37731Smckusick if (setjmp(&u.u_qsave)) { 113*37731Smckusick if (error == 0) 114*37731Smckusick error = EINTR; 115*37731Smckusick return (error); 116*37731Smckusick } 117*37731Smckusick return (VOP_OPEN(vp, fmode, ndp->ni_cred)); 118*37731Smckusick 119*37731Smckusick bad: 120*37731Smckusick vput(vp); 121*37731Smckusick return(error); 122*37731Smckusick } 123*37731Smckusick 124*37731Smckusick /* 125*37731Smckusick * Check mode permission on vnode pointer. Mode is READ, WRITE or EXEC. 126*37731Smckusick * In the case of WRITE, the read-only status of the file system is 127*37731Smckusick * checked. Also in WRITE, prototype text segments cannot be written. 128*37731Smckusick */ 129*37731Smckusick vn_access(vp, mode, cred) 130*37731Smckusick register struct vnode *vp; 1314817Swnj int mode; 132*37731Smckusick struct ucred *cred; 13318Sbill { 13418Sbill 135*37731Smckusick if (mode & VWRITE) { 13611162Ssam /* 137*37731Smckusick * Disallow write attempts on read-only file systems; 138*37731Smckusick * unless the file is a socket or a block or character 139*37731Smckusick * device resident on the file system. 14011162Ssam */ 141*37731Smckusick if ((vp->v_mount->m_flag & M_RDONLY) && 142*37731Smckusick vp->v_type != VCHR && 143*37731Smckusick vp->v_type != VBLK && 144*37731Smckusick vp->v_type != VSOCK) 145*37731Smckusick 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 */ 151*37731Smckusick if (vp->v_flag & VTEXT) 152*37731Smckusick xrele(vp); 153*37731Smckusick if (vp->v_flag & VTEXT) 154*37731Smckusick return (ETXTBSY); 155*37731Smckusick } 156*37731Smckusick return (VOP_ACCESS(vp, mode, cred)); 157*37731Smckusick } 158*37731Smckusick 159*37731Smckusick /* 160*37731Smckusick * Vnode version of rdwri() for calls on file systems. 161*37731Smckusick */ 162*37731Smckusick vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) 163*37731Smckusick enum uio_rw rw; 164*37731Smckusick struct vnode *vp; 165*37731Smckusick caddr_t base; 166*37731Smckusick int len; 167*37731Smckusick off_t offset; 168*37731Smckusick enum uio_seg segflg; 169*37731Smckusick int ioflg; 170*37731Smckusick struct ucred *cred; 171*37731Smckusick int *aresid; 172*37731Smckusick { 173*37731Smckusick struct uio auio; 174*37731Smckusick struct iovec aiov; 175*37731Smckusick int error; 176*37731Smckusick 177*37731Smckusick auio.uio_iov = &aiov; 178*37731Smckusick auio.uio_iovcnt = 1; 179*37731Smckusick aiov.iov_base = base; 180*37731Smckusick aiov.iov_len = len; 181*37731Smckusick auio.uio_resid = len; 182*37731Smckusick auio.uio_offset = offset; 183*37731Smckusick auio.uio_segflg = segflg; 184*37731Smckusick auio.uio_rw = rw; 185*37731Smckusick if (rw == UIO_READ) 186*37731Smckusick error = VOP_READ(vp, &auio, &offset, ioflg, cred); 187*37731Smckusick else 188*37731Smckusick error = VOP_WRITE(vp, &auio, &offset, ioflg, cred); 189*37731Smckusick if (aresid) 190*37731Smckusick *aresid = auio.uio_resid; 191*37731Smckusick else 192*37731Smckusick if (auio.uio_resid && error == 0) 193*37731Smckusick error = EIO; 194*37731Smckusick return (error); 195*37731Smckusick } 196*37731Smckusick 197*37731Smckusick vn_read(fp, uio, cred) 198*37731Smckusick struct file *fp; 199*37731Smckusick struct uio *uio; 200*37731Smckusick struct ucred *cred; 201*37731Smckusick { 202*37731Smckusick 203*37731Smckusick return (VOP_READ((struct vnode *)fp->f_data, uio, &(fp->f_offset), 204*37731Smckusick (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred)); 205*37731Smckusick } 206*37731Smckusick 207*37731Smckusick vn_write(fp, uio, cred) 208*37731Smckusick struct file *fp; 209*37731Smckusick struct uio *uio; 210*37731Smckusick struct ucred *cred; 211*37731Smckusick { 212*37731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 213*37731Smckusick int ioflag = 0; 214*37731Smckusick 215*37731Smckusick if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) 216*37731Smckusick ioflag |= IO_APPEND; 217*37731Smckusick if (fp->f_flag & FNDELAY) 218*37731Smckusick ioflag |= IO_NDELAY; 219*37731Smckusick return (VOP_WRITE(vp, uio, &(fp->f_offset), ioflag, cred)); 220*37731Smckusick } 221*37731Smckusick 222*37731Smckusick /* 223*37731Smckusick * Get stat info for a vnode. 224*37731Smckusick */ 225*37731Smckusick vn_stat(vp, sb) 226*37731Smckusick struct vnode *vp; 227*37731Smckusick register struct stat *sb; 228*37731Smckusick { 229*37731Smckusick struct vattr vattr; 230*37731Smckusick register struct vattr *vap; 231*37731Smckusick int error; 232*37731Smckusick u_short mode; 233*37731Smckusick 234*37731Smckusick vap = &vattr; 235*37731Smckusick error = VOP_GETATTR(vp, vap, u.u_cred); 236*37731Smckusick if (error) 237*37731Smckusick return (error); 238*37731Smckusick /* 239*37731Smckusick * Copy from vattr table 240*37731Smckusick */ 241*37731Smckusick sb->st_dev = vap->va_fsid; 242*37731Smckusick sb->st_ino = vap->va_fileid; 243*37731Smckusick mode = vap->va_mode; 244*37731Smckusick switch (vp->v_type) { 245*37731Smckusick case VREG: 246*37731Smckusick mode |= IFREG; 247*37731Smckusick break; 248*37731Smckusick case VDIR: 249*37731Smckusick mode |= IFDIR; 250*37731Smckusick break; 251*37731Smckusick case VBLK: 252*37731Smckusick mode |= IFBLK; 253*37731Smckusick break; 254*37731Smckusick case VCHR: 255*37731Smckusick mode |= IFCHR; 256*37731Smckusick break; 257*37731Smckusick case VLNK: 258*37731Smckusick mode |= IFLNK; 259*37731Smckusick break; 260*37731Smckusick case VSOCK: 261*37731Smckusick mode |= IFSOCK; 262*37731Smckusick break; 263*37731Smckusick default: 264*37731Smckusick return (EBADF); 265*37731Smckusick }; 266*37731Smckusick sb->st_mode = mode; 267*37731Smckusick sb->st_nlink = vap->va_nlink; 268*37731Smckusick sb->st_uid = vap->va_uid; 269*37731Smckusick sb->st_gid = vap->va_gid; 270*37731Smckusick sb->st_rdev = vap->va_rdev; 271*37731Smckusick sb->st_size = vap->va_size; 272*37731Smckusick sb->st_atime = vap->va_atime.tv_sec; 273*37731Smckusick sb->st_spare1 = 0; 274*37731Smckusick sb->st_mtime = vap->va_mtime.tv_sec; 275*37731Smckusick sb->st_spare2 = 0; 276*37731Smckusick sb->st_ctime = vap->va_ctime.tv_sec; 277*37731Smckusick sb->st_spare3 = 0; 278*37731Smckusick sb->st_blksize = vap->va_blocksize; 279*37731Smckusick sb->st_spare4[0] = sb->st_spare4[1] = 0; 280*37731Smckusick /* 281*37731Smckusick * XXX THIS IS NOT CORRECT!!, but be sure to change ufs_getattr() 282*37731Smckusick * if you change it. 283*37731Smckusick */ 284*37731Smckusick sb->st_blocks = vap->va_bytes; 285*37731Smckusick return (0); 286*37731Smckusick } 287*37731Smckusick 288*37731Smckusick /* 289*37731Smckusick * Vnode ioctl call 290*37731Smckusick */ 291*37731Smckusick vn_ioctl(fp, com, data) 292*37731Smckusick struct file *fp; 293*37731Smckusick int com; 294*37731Smckusick caddr_t data; 295*37731Smckusick { 296*37731Smckusick register struct vnode *vp = ((struct vnode *)fp->f_data); 297*37731Smckusick struct vattr vattr; 298*37731Smckusick int error; 299*37731Smckusick 300*37731Smckusick switch (vp->v_type) { 301*37731Smckusick 302*37731Smckusick case VREG: 303*37731Smckusick case VDIR: 304*37731Smckusick if (com == FIONREAD) { 305*37731Smckusick if (error = VOP_GETATTR(vp, &vattr, u.u_cred)) 306*37731Smckusick return (error); 307*37731Smckusick *(off_t *)data = vattr.va_size - fp->f_offset; 308*37731Smckusick return (0); 30918Sbill } 310*37731Smckusick if (com == FIONBIO || com == FIOASYNC) /* XXX */ 311*37731Smckusick return (0); /* XXX */ 312*37731Smckusick /* fall into ... */ 313*37731Smckusick 314*37731Smckusick default: 315*37731Smckusick return (ENOTTY); 316*37731Smckusick 317*37731Smckusick case VCHR: 318*37731Smckusick case VBLK: 319*37731Smckusick u.u_r.r_val1 = 0; 320*37731Smckusick if (setjmp(&u.u_qsave)) { 321*37731Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 322*37731Smckusick return(EINTR); 323*37731Smckusick u.u_eosys = RESTARTSYS; 324*37731Smckusick return (0); 325*37731Smckusick } 326*37731Smckusick return (VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred)); 32718Sbill } 328*37731Smckusick } 329*37731Smckusick 330*37731Smckusick /* 331*37731Smckusick * Vnode select call 332*37731Smckusick */ 333*37731Smckusick vn_select(fp, which) 334*37731Smckusick struct file *fp; 335*37731Smckusick int which; 336*37731Smckusick { 337*37731Smckusick return(VOP_SELECT(((struct vnode *)fp->f_data), which, u.u_cred)); 338*37731Smckusick } 339*37731Smckusick 340*37731Smckusick /* 341*37731Smckusick * Vnode close call 342*37731Smckusick */ 343*37731Smckusick vn_close(fp) 344*37731Smckusick register struct file *fp; 345*37731Smckusick { 346*37731Smckusick struct vnode *vp = ((struct vnode *)fp->f_data); 347*37731Smckusick int error; 348*37731Smckusick 349*37731Smckusick if (fp->f_flag & (FSHLOCK|FEXLOCK)) 350*37731Smckusick vn_unlock(fp, FSHLOCK|FEXLOCK); 35111162Ssam /* 352*37731Smckusick * Must delete vnode reference from this file entry 353*37731Smckusick * before VOP_CLOSE, so that only other references 354*37731Smckusick * will prevent close. 35511162Ssam */ 356*37731Smckusick fp->f_data = (caddr_t) 0; 357*37731Smckusick error = VOP_CLOSE(vp, fp->f_flag, u.u_cred); 358*37731Smckusick vrele(vp); 359*37731Smckusick return (error); 360*37731Smckusick } 361*37731Smckusick 362*37731Smckusick /* 363*37731Smckusick * Place an advisory lock on a vnode. 364*37731Smckusick * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries 365*37731Smckusick */ 366*37731Smckusick vn_lock(fp, cmd) 367*37731Smckusick register struct file *fp; 368*37731Smckusick int cmd; 369*37731Smckusick { 370*37731Smckusick register int priority = PLOCK; 371*37731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 372*37731Smckusick 373*37731Smckusick if ((cmd & LOCK_EX) == 0) 374*37731Smckusick priority += 4; 375*37731Smckusick if (setjmp(&u.u_qsave)) { 376*37731Smckusick if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 377*37731Smckusick return(EINTR); 378*37731Smckusick u.u_eosys = RESTARTSYS; 3794817Swnj return (0); 380*37731Smckusick } 38111162Ssam /* 382*37731Smckusick * If there's a exclusive lock currently applied 383*37731Smckusick * to the file, then we've gotta wait for the 384*37731Smckusick * lock with everyone else. 38511162Ssam */ 386*37731Smckusick again: 387*37731Smckusick while (vp->v_flag & VEXLOCK) { 388*37731Smckusick /* 389*37731Smckusick * If we're holding an exclusive 390*37731Smckusick * lock, then release it. 391*37731Smckusick */ 392*37731Smckusick if (fp->f_flag & FEXLOCK) { 393*37731Smckusick vn_unlock(fp, FEXLOCK); 394*37731Smckusick continue; 395*37731Smckusick } 396*37731Smckusick if (cmd & LOCK_NB) 397*37731Smckusick return (EWOULDBLOCK); 398*37731Smckusick vp->v_flag |= VLWAIT; 399*37731Smckusick sleep((caddr_t)&vp->v_exlockc, priority); 40018Sbill } 401*37731Smckusick if ((cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) { 402*37731Smckusick /* 403*37731Smckusick * Must wait for any shared locks to finish 404*37731Smckusick * before we try to apply a exclusive lock. 405*37731Smckusick * 406*37731Smckusick * If we're holding a shared 407*37731Smckusick * lock, then release it. 408*37731Smckusick */ 409*37731Smckusick if (fp->f_flag & FSHLOCK) { 410*37731Smckusick vn_unlock(fp, FSHLOCK); 411*37731Smckusick goto again; 412*37731Smckusick } 413*37731Smckusick if (cmd & LOCK_NB) 414*37731Smckusick return (EWOULDBLOCK); 415*37731Smckusick vp->v_flag |= VLWAIT; 416*37731Smckusick sleep((caddr_t)&vp->v_shlockc, PLOCK); 417*37731Smckusick goto again; 418*37731Smckusick } 419*37731Smckusick if (fp->f_flag & FEXLOCK) 420*37731Smckusick panic("vn_lock"); 421*37731Smckusick if (cmd & LOCK_EX) { 422*37731Smckusick cmd &= ~LOCK_SH; 423*37731Smckusick vp->v_exlockc++; 424*37731Smckusick vp->v_flag |= VEXLOCK; 425*37731Smckusick fp->f_flag |= FEXLOCK; 426*37731Smckusick } 427*37731Smckusick if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { 428*37731Smckusick vp->v_shlockc++; 429*37731Smckusick vp->v_flag |= VSHLOCK; 430*37731Smckusick fp->f_flag |= FSHLOCK; 431*37731Smckusick } 432*37731Smckusick return (0); 43318Sbill } 43418Sbill 43518Sbill /* 436*37731Smckusick * Unlock a file. 43718Sbill */ 438*37731Smckusick vn_unlock(fp, kind) 439*37731Smckusick register struct file *fp; 440*37731Smckusick int kind; 44118Sbill { 442*37731Smckusick register struct vnode *vp = (struct vnode *)fp->f_data; 443*37731Smckusick int flags; 44418Sbill 445*37731Smckusick kind &= fp->f_flag; 446*37731Smckusick if (vp == NULL || kind == 0) 447*37731Smckusick return; 448*37731Smckusick flags = vp->v_flag; 449*37731Smckusick if (kind & FSHLOCK) { 450*37731Smckusick if ((flags & VSHLOCK) == 0) 451*37731Smckusick panic("vn_unlock: SHLOCK"); 452*37731Smckusick if (--vp->v_shlockc == 0) { 453*37731Smckusick vp->v_flag &= ~VSHLOCK; 454*37731Smckusick if (flags & VLWAIT) 455*37731Smckusick wakeup((caddr_t)&vp->v_shlockc); 456*37731Smckusick } 457*37731Smckusick fp->f_flag &= ~FSHLOCK; 45837552Smckusick } 459*37731Smckusick if (kind & FEXLOCK) { 460*37731Smckusick if ((flags & VEXLOCK) == 0) 461*37731Smckusick panic("vn_unlock: EXLOCK"); 462*37731Smckusick if (--vp->v_exlockc == 0) { 463*37731Smckusick vp->v_flag &= ~(VEXLOCK|VLWAIT); 464*37731Smckusick if (flags & VLWAIT) 465*37731Smckusick wakeup((caddr_t)&vp->v_exlockc); 466*37731Smckusick } 467*37731Smckusick fp->f_flag &= ~FEXLOCK; 468*37731Smckusick } 46918Sbill } 47018Sbill 47118Sbill /* 472*37731Smckusick * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 473*37731Smckusick * - look up fsid in mount list (if not found ret error) 474*37731Smckusick * - get vp by calling VFS_FHTOVP() macro 475*37731Smckusick * - if lockflag lock it with VOP_LOCK() 47618Sbill */ 477*37731Smckusick vn_fhtovp(fhp, lockflag, vpp) 478*37731Smckusick fhandle_t *fhp; 479*37731Smckusick int lockflag; 480*37731Smckusick struct vnode **vpp; 48118Sbill { 482*37731Smckusick register struct mount *mp; 483*37731Smckusick int error; 48418Sbill 485*37731Smckusick if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 486*37731Smckusick return (ESTALE); 487*37731Smckusick if (error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 488*37731Smckusick return (error); 489*37731Smckusick if (lockflag) 490*37731Smckusick VOP_LOCK(*vpp); 491*37731Smckusick return (0); 492*37731Smckusick } 493*37731Smckusick 494*37731Smckusick /* 495*37731Smckusick * Revoke access the current tty by all processes. 496*37731Smckusick * Used only by the super-user in init 497*37731Smckusick * to give ``clean'' terminals at login. 498*37731Smckusick */ 499*37731Smckusick vhangup() 500*37731Smckusick { 501*37731Smckusick 502*37731Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 503*37731Smckusick return; 504*37731Smckusick if (u.u_ttyp == NULL) 505*37731Smckusick return; 506*37731Smckusick forceclose(u.u_ttyd); 507*37731Smckusick if ((u.u_ttyp->t_state) & TS_ISOPEN) 508*37731Smckusick gsignal(u.u_ttyp->t_pgid, SIGHUP); 509*37731Smckusick u.u_ttyp->t_session = 0; 510*37731Smckusick u.u_ttyp->t_pgid = 0; 511*37731Smckusick } 512*37731Smckusick 513*37731Smckusick forceclose(dev) 514*37731Smckusick dev_t dev; 515*37731Smckusick { 516*37731Smckusick register struct file *fp; 517*37731Smckusick register struct vnode *vp; 518*37731Smckusick 519*37731Smckusick for (fp = file; fp < fileNFILE; fp++) { 520*37731Smckusick if (fp->f_count == 0) 521*37731Smckusick continue; 522*37731Smckusick if (fp->f_type != DTYPE_VNODE) 523*37731Smckusick continue; 524*37731Smckusick vp = (struct vnode *)fp->f_data; 525*37731Smckusick if (vp == 0) 526*37731Smckusick continue; 527*37731Smckusick if (vp->v_type != VCHR) 528*37731Smckusick continue; 529*37731Smckusick if (vp->v_rdev != dev) 530*37731Smckusick continue; 531*37731Smckusick fp->f_flag &= ~(FREAD|FWRITE); 53218Sbill } 53318Sbill } 534*37731Smckusick 535*37731Smckusick /* 536*37731Smckusick * Vnode release, just decrement the count and call VOP_INACTIVE() 537*37731Smckusick */ 538*37731Smckusick void vrele(vp) 539*37731Smckusick register struct vnode *vp; 540*37731Smckusick { 541*37731Smckusick 542*37731Smckusick if (vp == NULL) 543*37731Smckusick return; 544*37731Smckusick vp->v_count--; 545*37731Smckusick if (vp->v_count < 0) 546*37731Smckusick printf("inode %d, bad ref count %d\n", 547*37731Smckusick VTOI(vp)->i_number, vp->v_count); 548*37731Smckusick if (vp->v_count == 0) 549*37731Smckusick VOP_INACTIVE(vp); 550*37731Smckusick } 551*37731Smckusick 552*37731Smckusick /* 553*37731Smckusick * vput(), just unlock and vrele() 554*37731Smckusick */ 555*37731Smckusick vput(vp) 556*37731Smckusick register struct vnode *vp; 557*37731Smckusick { 558*37731Smckusick VOP_UNLOCK(vp); 559*37731Smckusick vrele(vp); 560*37731Smckusick } 561*37731Smckusick 562*37731Smckusick /* 563*37731Smckusick * Noop 564*37731Smckusick */ 565*37731Smckusick vfs_noop() 566*37731Smckusick { 567*37731Smckusick 568*37731Smckusick return (ENXIO); 569*37731Smckusick } 570*37731Smckusick 571*37731Smckusick /* 572*37731Smckusick * Null op 573*37731Smckusick */ 574*37731Smckusick vfs_nullop() 575*37731Smckusick { 576*37731Smckusick 577*37731Smckusick return (0); 578*37731Smckusick } 579