1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)vfs_vnops.c 7.16 (Berkeley) 03/05/90 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "user.h" 23 #include "kernel.h" 24 #include "file.h" 25 #include "stat.h" 26 #include "buf.h" 27 #include "proc.h" 28 #include "uio.h" 29 #include "socket.h" 30 #include "socketvar.h" 31 #include "mount.h" 32 #include "vnode.h" 33 #include "../ufs/fs.h" 34 #include "../ufs/quota.h" 35 #include "ioctl.h" 36 #include "tty.h" 37 #include "tsleep.h" 38 39 int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close(); 40 struct fileops vnops = 41 { vn_read, vn_write, vn_ioctl, vn_select, vn_close }; 42 43 /* 44 * Common code for vnode open operations. 45 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 46 */ 47 vn_open(ndp, fmode, cmode) 48 register struct nameidata *ndp; 49 int fmode, cmode; 50 { 51 register struct vnode *vp; 52 struct vattr vat; 53 struct vattr *vap = &vat; 54 int error; 55 56 if (fmode & FCREAT) { 57 ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; 58 if ((fmode & FEXCL) == 0) 59 ndp->ni_nameiop |= FOLLOW; 60 if (error = namei(ndp)) 61 return (error); 62 if (ndp->ni_vp == NULL) { 63 vattr_null(vap); 64 vap->va_type = VREG; 65 vap->va_mode = cmode; 66 if (error = VOP_CREATE(ndp, vap)) 67 return (error); 68 fmode &= ~FTRUNC; 69 vp = ndp->ni_vp; 70 } else { 71 if (ndp->ni_dvp == ndp->ni_vp) 72 vrele(ndp->ni_dvp); 73 else if (ndp->ni_dvp != NULL) 74 vput(ndp->ni_dvp); 75 ndp->ni_dvp = NULL; 76 vp = ndp->ni_vp; 77 if (fmode & FEXCL) { 78 error = EEXIST; 79 goto bad; 80 } 81 fmode &= ~FCREAT; 82 } 83 } else { 84 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 85 if (error = namei(ndp)) 86 return (error); 87 vp = ndp->ni_vp; 88 } 89 if (vp->v_type == VSOCK) { 90 error = EOPNOTSUPP; 91 goto bad; 92 } 93 if ((fmode & FCREAT) == 0) { 94 if (fmode & FREAD) { 95 if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred)) 96 goto bad; 97 } 98 if (fmode & (FWRITE|FTRUNC)) { 99 if (vp->v_type == VDIR) { 100 error = EISDIR; 101 goto bad; 102 } 103 if ((error = vn_writechk(vp)) || 104 (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred))) 105 goto bad; 106 } 107 } 108 if (fmode & FTRUNC) { 109 vattr_null(vap); 110 vap->va_size = 0; 111 if (error = VOP_SETATTR(vp, vap, ndp->ni_cred)) 112 goto bad; 113 } 114 VOP_UNLOCK(vp); 115 if (setjmp(&u.u_qsave)) { 116 if (error == 0) 117 error = EINTR; 118 return (error); 119 } 120 error = VOP_OPEN(vp, fmode, ndp->ni_cred); 121 if (error) 122 vrele(vp); 123 return (error); 124 125 bad: 126 vput(vp); 127 return(error); 128 } 129 130 /* 131 * Check for write permissions on the specified vnode. 132 * The read-only status of the file system is checked. 133 * Also, prototype text segments cannot be written. 134 */ 135 vn_writechk(vp) 136 register struct vnode *vp; 137 { 138 139 /* 140 * Disallow write attempts on read-only file systems; 141 * unless the file is a socket or a block or character 142 * device resident on the file system. 143 */ 144 if ((vp->v_mount->m_flag & M_RDONLY) && vp->v_type != VCHR && 145 vp->v_type != VBLK && vp->v_type != VSOCK) 146 return (EROFS); 147 /* 148 * If there's shared text associated with 149 * the vnode, try to free it up once. If 150 * we fail, we can't allow writing. 151 */ 152 if (vp->v_flag & VTEXT) 153 xrele(vp); 154 if (vp->v_flag & VTEXT) 155 return (ETXTBSY); 156 return (0); 157 } 158 159 /* 160 * Vnode version of rdwri() for calls on file systems. 161 */ 162 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid) 163 enum uio_rw rw; 164 struct vnode *vp; 165 caddr_t base; 166 int len; 167 off_t offset; 168 enum uio_seg segflg; 169 int ioflg; 170 struct ucred *cred; 171 int *aresid; 172 { 173 struct uio auio; 174 struct iovec aiov; 175 int error; 176 177 if ((ioflg & IO_NODELOCKED) == 0) 178 VOP_LOCK(vp); 179 auio.uio_iov = &aiov; 180 auio.uio_iovcnt = 1; 181 aiov.iov_base = base; 182 aiov.iov_len = len; 183 auio.uio_resid = len; 184 auio.uio_offset = offset; 185 auio.uio_segflg = segflg; 186 auio.uio_rw = rw; 187 if (rw == UIO_READ) 188 error = VOP_READ(vp, &auio, ioflg, cred); 189 else 190 error = VOP_WRITE(vp, &auio, ioflg, cred); 191 if (aresid) 192 *aresid = auio.uio_resid; 193 else 194 if (auio.uio_resid && error == 0) 195 error = EIO; 196 if ((ioflg & IO_NODELOCKED) == 0) 197 VOP_UNLOCK(vp); 198 return (error); 199 } 200 201 vn_read(fp, uio, cred) 202 struct file *fp; 203 struct uio *uio; 204 struct ucred *cred; 205 { 206 register struct vnode *vp = (struct vnode *)fp->f_data; 207 int count, error; 208 209 VOP_LOCK(vp); 210 uio->uio_offset = fp->f_offset; 211 count = uio->uio_resid; 212 error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred); 213 fp->f_offset += count - uio->uio_resid; 214 VOP_UNLOCK(vp); 215 return (error); 216 } 217 218 vn_write(fp, uio, cred) 219 struct file *fp; 220 struct uio *uio; 221 struct ucred *cred; 222 { 223 register struct vnode *vp = (struct vnode *)fp->f_data; 224 int count, error, ioflag = 0; 225 226 if (vp->v_type == VREG && (fp->f_flag & FAPPEND)) 227 ioflag |= IO_APPEND; 228 if (fp->f_flag & FNDELAY) 229 ioflag |= IO_NDELAY; 230 VOP_LOCK(vp); 231 uio->uio_offset = fp->f_offset; 232 count = uio->uio_resid; 233 error = VOP_WRITE(vp, uio, ioflag, cred); 234 if (ioflag & IO_APPEND) 235 fp->f_offset = uio->uio_offset; 236 else 237 fp->f_offset += count - uio->uio_resid; 238 VOP_UNLOCK(vp); 239 return (error); 240 } 241 242 /* 243 * Get stat info for a vnode. 244 */ 245 vn_stat(vp, sb) 246 struct vnode *vp; 247 register struct stat *sb; 248 { 249 struct vattr vattr; 250 register struct vattr *vap; 251 int error; 252 u_short mode; 253 254 vap = &vattr; 255 error = VOP_GETATTR(vp, vap, u.u_cred); 256 if (error) 257 return (error); 258 /* 259 * Copy from vattr table 260 */ 261 sb->st_dev = vap->va_fsid; 262 sb->st_ino = vap->va_fileid; 263 mode = vap->va_mode; 264 switch (vp->v_type) { 265 case VREG: 266 mode |= S_IFREG; 267 break; 268 case VDIR: 269 mode |= S_IFDIR; 270 break; 271 case VBLK: 272 mode |= S_IFBLK; 273 break; 274 case VCHR: 275 mode |= S_IFCHR; 276 break; 277 case VLNK: 278 mode |= S_IFLNK; 279 break; 280 case VSOCK: 281 mode |= S_IFSOCK; 282 break; 283 case VFIFO: 284 mode |= S_IFIFO; 285 break; 286 default: 287 return (EBADF); 288 }; 289 sb->st_mode = mode; 290 sb->st_nlink = vap->va_nlink; 291 sb->st_uid = vap->va_uid; 292 sb->st_gid = vap->va_gid; 293 sb->st_rdev = vap->va_rdev; 294 sb->st_size = vap->va_size; 295 sb->st_atime = vap->va_atime.tv_sec; 296 sb->st_spare1 = 0; 297 sb->st_mtime = vap->va_mtime.tv_sec; 298 sb->st_spare2 = 0; 299 sb->st_ctime = vap->va_ctime.tv_sec; 300 sb->st_spare3 = 0; 301 sb->st_blksize = vap->va_blocksize; 302 sb->st_flags = vap->va_flags; 303 sb->st_gen = vap->va_gen; 304 sb->st_blocks = vap->va_bytes / S_BLKSIZE; 305 return (0); 306 } 307 308 /* 309 * Vnode ioctl call 310 */ 311 vn_ioctl(fp, com, data) 312 struct file *fp; 313 int com; 314 caddr_t data; 315 { 316 register struct vnode *vp = ((struct vnode *)fp->f_data); 317 struct vattr vattr; 318 int error; 319 320 switch (vp->v_type) { 321 322 case VREG: 323 case VDIR: 324 if (com == FIONREAD) { 325 if (error = VOP_GETATTR(vp, &vattr, u.u_cred)) 326 return (error); 327 *(off_t *)data = vattr.va_size - fp->f_offset; 328 return (0); 329 } 330 if (com == FIONBIO || com == FIOASYNC) /* XXX */ 331 return (0); /* XXX */ 332 /* fall into ... */ 333 334 default: 335 return (ENOTTY); 336 337 case VFIFO: 338 case VCHR: 339 case VBLK: 340 u.u_r.r_val1 = 0; 341 if (setjmp(&u.u_qsave)) { 342 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 343 return(EINTR); 344 u.u_eosys = RESTARTSYS; 345 return (0); 346 } 347 error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred); 348 if (error == 0 && com == TIOCSCTTY) { 349 u.u_procp->p_session->s_ttyvp = vp; 350 VREF(vp); 351 } 352 return (error); 353 } 354 } 355 356 /* 357 * Vnode select call 358 */ 359 vn_select(fp, which) 360 struct file *fp; 361 int which; 362 { 363 return(VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, 364 u.u_cred)); 365 } 366 367 /* 368 * Vnode close call 369 */ 370 vn_close(fp) 371 register struct file *fp; 372 { 373 struct vnode *vp = ((struct vnode *)fp->f_data); 374 int error; 375 376 if (fp->f_flag & (FSHLOCK|FEXLOCK)) 377 vn_unlock(fp, FSHLOCK|FEXLOCK); 378 /* 379 * Must delete vnode reference from this file entry 380 * before VOP_CLOSE, so that only other references 381 * will prevent close. 382 */ 383 fp->f_data = (caddr_t) 0; 384 error = VOP_CLOSE(vp, fp->f_flag, u.u_cred); 385 vrele(vp); 386 return (error); 387 } 388 389 /* 390 * Place an advisory lock on a vnode. 391 * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries 392 */ 393 vn_lock(fp, cmd) 394 register struct file *fp; 395 int cmd; 396 { 397 register int priority = PLOCK; 398 register struct vnode *vp = (struct vnode *)fp->f_data; 399 400 if ((cmd & LOCK_EX) == 0) 401 priority += 4; 402 if (setjmp(&u.u_qsave)) { 403 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0) 404 return(EINTR); 405 u.u_eosys = RESTARTSYS; 406 return (0); 407 } 408 /* 409 * If there's a exclusive lock currently applied 410 * to the file, then we've gotta wait for the 411 * lock with everyone else. 412 */ 413 again: 414 while (vp->v_flag & VEXLOCK) { 415 /* 416 * If we're holding an exclusive 417 * lock, then release it. 418 */ 419 if (fp->f_flag & FEXLOCK) { 420 vn_unlock(fp, FEXLOCK); 421 continue; 422 } 423 if (cmd & LOCK_NB) 424 return (EWOULDBLOCK); 425 vp->v_flag |= VLWAIT; 426 tsleep((caddr_t)&vp->v_exlockc, priority, SLP_EXLCK, 0); 427 } 428 if ((cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) { 429 /* 430 * Must wait for any shared locks to finish 431 * before we try to apply a exclusive lock. 432 * 433 * If we're holding a shared 434 * lock, then release it. 435 */ 436 if (fp->f_flag & FSHLOCK) { 437 vn_unlock(fp, FSHLOCK); 438 goto again; 439 } 440 if (cmd & LOCK_NB) 441 return (EWOULDBLOCK); 442 vp->v_flag |= VLWAIT; 443 tsleep((caddr_t)&vp->v_shlockc, PLOCK, SLP_SHLCK, 0); 444 goto again; 445 } 446 if (fp->f_flag & FEXLOCK) 447 panic("vn_lock"); 448 if (cmd & LOCK_EX) { 449 cmd &= ~LOCK_SH; 450 vp->v_exlockc++; 451 vp->v_flag |= VEXLOCK; 452 fp->f_flag |= FEXLOCK; 453 } 454 if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) { 455 vp->v_shlockc++; 456 vp->v_flag |= VSHLOCK; 457 fp->f_flag |= FSHLOCK; 458 } 459 return (0); 460 } 461 462 /* 463 * Unlock a file. 464 */ 465 vn_unlock(fp, kind) 466 register struct file *fp; 467 int kind; 468 { 469 register struct vnode *vp = (struct vnode *)fp->f_data; 470 int flags; 471 472 kind &= fp->f_flag; 473 if (vp == NULL || kind == 0) 474 return; 475 flags = vp->v_flag; 476 if (kind & FSHLOCK) { 477 if ((flags & VSHLOCK) == 0) 478 panic("vn_unlock: SHLOCK"); 479 if (--vp->v_shlockc == 0) { 480 vp->v_flag &= ~VSHLOCK; 481 if (flags & VLWAIT) 482 wakeup((caddr_t)&vp->v_shlockc); 483 } 484 fp->f_flag &= ~FSHLOCK; 485 } 486 if (kind & FEXLOCK) { 487 if ((flags & VEXLOCK) == 0) 488 panic("vn_unlock: EXLOCK"); 489 if (--vp->v_exlockc == 0) { 490 vp->v_flag &= ~(VEXLOCK|VLWAIT); 491 if (flags & VLWAIT) 492 wakeup((caddr_t)&vp->v_exlockc); 493 } 494 fp->f_flag &= ~FEXLOCK; 495 } 496 } 497 498 /* 499 * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked) 500 * - look up fsid in mount list (if not found ret error) 501 * - get vp by calling VFS_FHTOVP() macro 502 * - if lockflag lock it with VOP_LOCK() 503 */ 504 vn_fhtovp(fhp, lockflag, vpp) 505 fhandle_t *fhp; 506 int lockflag; 507 struct vnode **vpp; 508 { 509 register struct mount *mp; 510 511 if ((mp = getvfs(&fhp->fh_fsid)) == NULL) 512 return (ESTALE); 513 if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp)) 514 return (ESTALE); 515 if (!lockflag) 516 VOP_UNLOCK(*vpp); 517 return (0); 518 } 519 520 /* 521 * Noop 522 */ 523 vfs_noop() 524 { 525 526 return (ENXIO); 527 } 528 529 /* 530 * Null op 531 */ 532 vfs_nullop() 533 { 534 535 return (0); 536 } 537