1 /* $NetBSD: vfs_vnops.c,v 1.76 2004/01/10 17:16:38 hannken Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.76 2004/01/10 17:16:38 hannken Exp $"); 41 42 #include "fs_union.h" 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/file.h> 48 #include <sys/stat.h> 49 #include <sys/buf.h> 50 #include <sys/proc.h> 51 #include <sys/mount.h> 52 #include <sys/namei.h> 53 #include <sys/vnode.h> 54 #include <sys/ioctl.h> 55 #include <sys/tty.h> 56 #include <sys/poll.h> 57 58 #include <uvm/uvm_extern.h> 59 60 #ifdef UNION 61 #include <fs/union/union.h> 62 #endif 63 64 #if defined(LKM) || defined(UNION) 65 int (*vn_union_readdir_hook) (struct vnode **, struct file *, struct proc *); 66 #endif 67 68 #ifdef VERIFIED_EXEC 69 #include <sys/verified_exec.h> 70 71 extern LIST_HEAD(veriexec_devhead, veriexec_dev_list) veriexec_dev_head; 72 extern struct veriexec_devhead veriexec_file_dev_head; 73 #endif 74 75 static int vn_read(struct file *fp, off_t *offset, struct uio *uio, 76 struct ucred *cred, int flags); 77 static int vn_write(struct file *fp, off_t *offset, struct uio *uio, 78 struct ucred *cred, int flags); 79 static int vn_closefile(struct file *fp, struct proc *p); 80 static int vn_poll(struct file *fp, int events, struct proc *p); 81 static int vn_fcntl(struct file *fp, u_int com, void *data, struct proc *p); 82 static int vn_statfile(struct file *fp, struct stat *sb, struct proc *p); 83 static int vn_ioctl(struct file *fp, u_long com, void *data, struct proc *p); 84 85 struct fileops vnops = { 86 vn_read, vn_write, vn_ioctl, vn_fcntl, vn_poll, 87 vn_statfile, vn_closefile, vn_kqfilter 88 }; 89 90 /* 91 * Common code for vnode open operations. 92 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 93 */ 94 int 95 vn_open(ndp, fmode, cmode) 96 struct nameidata *ndp; 97 int fmode, cmode; 98 { 99 struct vnode *vp; 100 struct mount *mp; 101 struct proc *p = ndp->ni_cnd.cn_proc; 102 struct ucred *cred = p->p_ucred; 103 struct vattr va; 104 int error; 105 #ifdef VERIFIED_EXEC 106 char got_dev; 107 struct veriexec_inode_list *veriexec_node; 108 char fingerprint[MAXFINGERPRINTLEN]; 109 #endif 110 111 restart: 112 if (fmode & O_CREAT) { 113 ndp->ni_cnd.cn_nameiop = CREATE; 114 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 115 if ((fmode & O_EXCL) == 0 && 116 ((fmode & O_NOFOLLOW) == 0)) 117 ndp->ni_cnd.cn_flags |= FOLLOW; 118 if ((error = namei(ndp)) != 0) 119 return (error); 120 if (ndp->ni_vp == NULL) { 121 VATTR_NULL(&va); 122 va.va_type = VREG; 123 va.va_mode = cmode; 124 if (fmode & O_EXCL) 125 va.va_vaflags |= VA_EXCLUSIVE; 126 if (vn_start_write(ndp->ni_dvp, &mp, V_NOWAIT) != 0) { 127 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 128 vput(ndp->ni_dvp); 129 if ((error = vn_start_write(NULL, &mp, 130 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 131 return (error); 132 goto restart; 133 } 134 VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE); 135 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 136 &ndp->ni_cnd, &va); 137 vn_finished_write(mp, 0); 138 if (error) 139 return (error); 140 fmode &= ~O_TRUNC; 141 vp = ndp->ni_vp; 142 } else { 143 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 144 if (ndp->ni_dvp == ndp->ni_vp) 145 vrele(ndp->ni_dvp); 146 else 147 vput(ndp->ni_dvp); 148 ndp->ni_dvp = NULL; 149 vp = ndp->ni_vp; 150 if (fmode & O_EXCL) { 151 error = EEXIST; 152 goto bad; 153 } 154 fmode &= ~O_CREAT; 155 } 156 } else { 157 ndp->ni_cnd.cn_nameiop = LOOKUP; 158 ndp->ni_cnd.cn_flags = LOCKLEAF; 159 if ((fmode & O_NOFOLLOW) == 0) 160 ndp->ni_cnd.cn_flags |= FOLLOW; 161 if ((error = namei(ndp)) != 0) 162 return (error); 163 vp = ndp->ni_vp; 164 } 165 if (vp->v_type == VSOCK) { 166 error = EOPNOTSUPP; 167 goto bad; 168 } 169 if (ndp->ni_vp->v_type == VLNK) { 170 error = EFTYPE; 171 goto bad; 172 } 173 174 #ifdef VERIFIED_EXEC 175 veriexec_node = NULL; 176 177 if ((error = VOP_GETATTR(vp, &va, cred, p)) != 0) 178 goto bad; 179 #endif 180 181 if ((fmode & O_CREAT) == 0) { 182 #ifdef VERIFIED_EXEC 183 /* 184 * Look for the file on the fingerprint lists iff 185 * it has not been seen before. 186 */ 187 if ((vp->fp_status == FINGERPRINT_INVALID) || 188 (vp->fp_status == FINGERPRINT_NODEV)) { 189 /* check the file list for the finger print */ 190 veriexec_node = get_veriexec_inode(&veriexec_file_dev_head, 191 va.va_fsid, 192 va.va_fileid, 193 &got_dev); 194 if (veriexec_node == NULL) { 195 /* failing that, check the exec list */ 196 veriexec_node = get_veriexec_inode( 197 &veriexec_dev_head, va.va_fsid, 198 va.va_fileid, &got_dev); 199 } 200 201 if ((veriexec_node == NULL) && (got_dev == 1)) 202 vp->fp_status = FINGERPRINT_NOENTRY; 203 204 if (veriexec_node != NULL) { 205 if ((error = evaluate_fingerprint(vp, 206 veriexec_node, p, va.va_size, 207 fingerprint)) != 0) 208 goto bad; 209 210 if (fingerprintcmp(veriexec_node, 211 fingerprint) == 0) { 212 /* fingerprint ok */ 213 vp->fp_status = FINGERPRINT_VALID; 214 #ifdef VERIFIED_EXEC_DEBUG 215 printf( 216 "file fingerprint matches for dev %lu, file %lu\n", 217 va.va_fsid, va.va_fileid); 218 #endif 219 } else { 220 vp->fp_status = FINGERPRINT_NOMATCH; 221 } 222 } 223 } 224 #endif 225 226 if (fmode & FREAD) { 227 if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0) 228 goto bad; 229 230 #ifdef VERIFIED_EXEC 231 /* file is on finger print list */ 232 if (vp->fp_status == FINGERPRINT_NOMATCH) { 233 /* fingerprint bad */ 234 printf( 235 "file fingerprint does not match on dev %lu, file %lu\n", 236 va.va_fsid, va.va_fileid); 237 if (securelevel > 2) { 238 error = EPERM; 239 goto bad; 240 } 241 } 242 #endif 243 } 244 if (fmode & (FWRITE | O_TRUNC)) { 245 if (vp->v_type == VDIR) { 246 error = EISDIR; 247 goto bad; 248 } 249 if ((error = vn_writechk(vp)) != 0 || 250 (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0) 251 goto bad; 252 #ifdef VERIFIED_EXEC 253 /* 254 * If file has a fingerprint then 255 * deny the write request, otherwise 256 * invalidate the status so we don't 257 * keep checking for the file having 258 * a fingerprint. 259 */ 260 if (vp->fp_status == FINGERPRINT_VALID) { 261 printf( 262 "writing to fingerprinted file for dev %lu, file %lu\n", 263 va.va_fsid, va.va_fileid); 264 if (securelevel > 2) { 265 error = EPERM; 266 goto bad; 267 } else { 268 vp->fp_status = FINGERPRINT_INVALID; 269 } 270 } 271 #endif 272 } 273 } 274 if (fmode & O_TRUNC) { 275 VOP_UNLOCK(vp, 0); /* XXX */ 276 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 277 vput(vp); 278 return (error); 279 } 280 VOP_LEASE(vp, p, cred, LEASE_WRITE); 281 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */ 282 VATTR_NULL(&va); 283 va.va_size = 0; 284 error = VOP_SETATTR(vp, &va, cred, p); 285 vn_finished_write(mp, 0); 286 if (error != 0) 287 goto bad; 288 } 289 if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0) 290 goto bad; 291 if (vp->v_type == VREG && 292 uvn_attach(vp, fmode & FWRITE ? VM_PROT_WRITE : 0) == NULL) { 293 error = EIO; 294 goto bad; 295 } 296 if (fmode & FWRITE) 297 vp->v_writecount++; 298 299 return (0); 300 bad: 301 vput(vp); 302 return (error); 303 } 304 305 /* 306 * Check for write permissions on the specified vnode. 307 * Prototype text segments cannot be written. 308 */ 309 int 310 vn_writechk(vp) 311 struct vnode *vp; 312 { 313 314 /* 315 * If the vnode is in use as a process's text, 316 * we can't allow writing. 317 */ 318 if (vp->v_flag & VTEXT) 319 return (ETXTBSY); 320 return (0); 321 } 322 323 /* 324 * Mark a vnode as having executable mappings. 325 */ 326 void 327 vn_markexec(vp) 328 struct vnode *vp; 329 { 330 if ((vp->v_flag & VEXECMAP) == 0) { 331 uvmexp.filepages -= vp->v_uobj.uo_npages; 332 uvmexp.execpages += vp->v_uobj.uo_npages; 333 } 334 vp->v_flag |= VEXECMAP; 335 } 336 337 /* 338 * Mark a vnode as being the text of a process. 339 * Fail if the vnode is currently writable. 340 */ 341 int 342 vn_marktext(vp) 343 struct vnode *vp; 344 { 345 346 if (vp->v_writecount != 0) { 347 KASSERT((vp->v_flag & VTEXT) == 0); 348 return (ETXTBSY); 349 } 350 vp->v_flag |= VTEXT; 351 vn_markexec(vp); 352 return (0); 353 } 354 355 /* 356 * Vnode close call 357 * 358 * Note: takes an unlocked vnode, while VOP_CLOSE takes a locked node. 359 */ 360 int 361 vn_close(vp, flags, cred, p) 362 struct vnode *vp; 363 int flags; 364 struct ucred *cred; 365 struct proc *p; 366 { 367 int error; 368 369 if (flags & FWRITE) 370 vp->v_writecount--; 371 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 372 error = VOP_CLOSE(vp, flags, cred, p); 373 vput(vp); 374 return (error); 375 } 376 377 /* 378 * Package up an I/O request on a vnode into a uio and do it. 379 */ 380 int 381 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) 382 enum uio_rw rw; 383 struct vnode *vp; 384 caddr_t base; 385 int len; 386 off_t offset; 387 enum uio_seg segflg; 388 int ioflg; 389 struct ucred *cred; 390 size_t *aresid; 391 struct proc *p; 392 { 393 struct uio auio; 394 struct iovec aiov; 395 struct mount *mp; 396 int error; 397 398 if ((ioflg & IO_NODELOCKED) == 0) { 399 if (rw == UIO_READ) { 400 vn_lock(vp, LK_SHARED | LK_RETRY); 401 } else /* UIO_WRITE */ { 402 if (vp->v_type != VCHR && 403 (error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) 404 != 0) 405 return (error); 406 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 407 } 408 } 409 auio.uio_iov = &aiov; 410 auio.uio_iovcnt = 1; 411 aiov.iov_base = base; 412 aiov.iov_len = len; 413 auio.uio_resid = len; 414 auio.uio_offset = offset; 415 auio.uio_segflg = segflg; 416 auio.uio_rw = rw; 417 auio.uio_procp = p; 418 if (rw == UIO_READ) { 419 error = VOP_READ(vp, &auio, ioflg, cred); 420 } else { 421 error = VOP_WRITE(vp, &auio, ioflg, cred); 422 } 423 if (aresid) 424 *aresid = auio.uio_resid; 425 else 426 if (auio.uio_resid && error == 0) 427 error = EIO; 428 if ((ioflg & IO_NODELOCKED) == 0) { 429 if (rw == UIO_WRITE) 430 vn_finished_write(mp, 0); 431 VOP_UNLOCK(vp, 0); 432 } 433 return (error); 434 } 435 436 int 437 vn_readdir(fp, buf, segflg, count, done, p, cookies, ncookies) 438 struct file *fp; 439 char *buf; 440 int segflg, *done, *ncookies; 441 u_int count; 442 struct proc *p; 443 off_t **cookies; 444 { 445 struct vnode *vp = (struct vnode *)fp->f_data; 446 struct iovec aiov; 447 struct uio auio; 448 int error, eofflag; 449 450 unionread: 451 if (vp->v_type != VDIR) 452 return (EINVAL); 453 aiov.iov_base = buf; 454 aiov.iov_len = count; 455 auio.uio_iov = &aiov; 456 auio.uio_iovcnt = 1; 457 auio.uio_rw = UIO_READ; 458 auio.uio_segflg = segflg; 459 auio.uio_procp = p; 460 auio.uio_resid = count; 461 vn_lock(vp, LK_SHARED | LK_RETRY); 462 auio.uio_offset = fp->f_offset; 463 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookies, 464 ncookies); 465 fp->f_offset = auio.uio_offset; 466 VOP_UNLOCK(vp, 0); 467 if (error) 468 return (error); 469 470 #if defined(UNION) || defined(LKM) 471 if (count == auio.uio_resid && vn_union_readdir_hook) { 472 struct vnode *ovp = vp; 473 474 error = (*vn_union_readdir_hook)(&vp, fp, p); 475 if (error) 476 return (error); 477 if (vp != ovp) 478 goto unionread; 479 } 480 #endif /* UNION || LKM */ 481 482 if (count == auio.uio_resid && (vp->v_flag & VROOT) && 483 (vp->v_mount->mnt_flag & MNT_UNION)) { 484 struct vnode *tvp = vp; 485 vp = vp->v_mount->mnt_vnodecovered; 486 VREF(vp); 487 fp->f_data = vp; 488 fp->f_offset = 0; 489 vrele(tvp); 490 goto unionread; 491 } 492 *done = count - auio.uio_resid; 493 return error; 494 } 495 496 /* 497 * File table vnode read routine. 498 */ 499 static int 500 vn_read(fp, offset, uio, cred, flags) 501 struct file *fp; 502 off_t *offset; 503 struct uio *uio; 504 struct ucred *cred; 505 int flags; 506 { 507 struct vnode *vp = (struct vnode *)fp->f_data; 508 int count, error, ioflag = 0; 509 510 VOP_LEASE(vp, uio->uio_procp, cred, LEASE_READ); 511 if (fp->f_flag & FNONBLOCK) 512 ioflag |= IO_NDELAY; 513 if ((fp->f_flag & (FFSYNC | FRSYNC)) == (FFSYNC | FRSYNC)) 514 ioflag |= IO_SYNC; 515 if (fp->f_flag & FALTIO) 516 ioflag |= IO_ALTSEMANTICS; 517 vn_lock(vp, LK_SHARED | LK_RETRY); 518 uio->uio_offset = *offset; 519 count = uio->uio_resid; 520 error = VOP_READ(vp, uio, ioflag, cred); 521 if (flags & FOF_UPDATE_OFFSET) 522 *offset += count - uio->uio_resid; 523 VOP_UNLOCK(vp, 0); 524 return (error); 525 } 526 527 /* 528 * File table vnode write routine. 529 */ 530 static int 531 vn_write(fp, offset, uio, cred, flags) 532 struct file *fp; 533 off_t *offset; 534 struct uio *uio; 535 struct ucred *cred; 536 int flags; 537 { 538 struct vnode *vp = (struct vnode *)fp->f_data; 539 struct mount *mp; 540 int count, error, ioflag = IO_UNIT; 541 542 if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) 543 ioflag |= IO_APPEND; 544 if (fp->f_flag & FNONBLOCK) 545 ioflag |= IO_NDELAY; 546 if (fp->f_flag & FFSYNC || 547 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) 548 ioflag |= IO_SYNC; 549 else if (fp->f_flag & FDSYNC) 550 ioflag |= IO_DSYNC; 551 if (fp->f_flag & FALTIO) 552 ioflag |= IO_ALTSEMANTICS; 553 mp = NULL; 554 if (vp->v_type != VCHR && 555 (error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 556 return (error); 557 VOP_LEASE(vp, uio->uio_procp, cred, LEASE_WRITE); 558 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 559 uio->uio_offset = *offset; 560 count = uio->uio_resid; 561 error = VOP_WRITE(vp, uio, ioflag, cred); 562 if (flags & FOF_UPDATE_OFFSET) { 563 if (ioflag & IO_APPEND) 564 *offset = uio->uio_offset; 565 else 566 *offset += count - uio->uio_resid; 567 } 568 VOP_UNLOCK(vp, 0); 569 vn_finished_write(mp, 0); 570 return (error); 571 } 572 573 /* 574 * File table vnode stat routine. 575 */ 576 static int 577 vn_statfile(fp, sb, p) 578 struct file *fp; 579 struct stat *sb; 580 struct proc *p; 581 { 582 struct vnode *vp = (struct vnode *)fp->f_data; 583 584 return vn_stat(vp, sb, p); 585 } 586 587 int 588 vn_stat(vp, sb, p) 589 struct vnode *vp; 590 struct stat *sb; 591 struct proc *p; 592 { 593 struct vattr va; 594 int error; 595 mode_t mode; 596 597 error = VOP_GETATTR(vp, &va, p->p_ucred, p); 598 if (error) 599 return (error); 600 /* 601 * Copy from vattr table 602 */ 603 sb->st_dev = va.va_fsid; 604 sb->st_ino = va.va_fileid; 605 mode = va.va_mode; 606 switch (vp->v_type) { 607 case VREG: 608 mode |= S_IFREG; 609 break; 610 case VDIR: 611 mode |= S_IFDIR; 612 break; 613 case VBLK: 614 mode |= S_IFBLK; 615 break; 616 case VCHR: 617 mode |= S_IFCHR; 618 break; 619 case VLNK: 620 mode |= S_IFLNK; 621 break; 622 case VSOCK: 623 mode |= S_IFSOCK; 624 break; 625 case VFIFO: 626 mode |= S_IFIFO; 627 break; 628 default: 629 return (EBADF); 630 }; 631 sb->st_mode = mode; 632 sb->st_nlink = va.va_nlink; 633 sb->st_uid = va.va_uid; 634 sb->st_gid = va.va_gid; 635 sb->st_rdev = va.va_rdev; 636 sb->st_size = va.va_size; 637 sb->st_atimespec = va.va_atime; 638 sb->st_mtimespec = va.va_mtime; 639 sb->st_ctimespec = va.va_ctime; 640 sb->st_birthtimespec = va.va_birthtime; 641 sb->st_blksize = va.va_blocksize; 642 sb->st_flags = va.va_flags; 643 sb->st_gen = 0; 644 sb->st_blocks = va.va_bytes / S_BLKSIZE; 645 return (0); 646 } 647 648 /* 649 * File table vnode fcntl routine. 650 */ 651 static int 652 vn_fcntl(fp, com, data, p) 653 struct file *fp; 654 u_int com; 655 void *data; 656 struct proc *p; 657 { 658 struct vnode *vp = ((struct vnode *)fp->f_data); 659 int error; 660 661 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 662 error = VOP_FCNTL(vp, com, data, fp->f_flag, p->p_ucred, p); 663 VOP_UNLOCK(vp, 0); 664 return (error); 665 } 666 667 /* 668 * File table vnode ioctl routine. 669 */ 670 static int 671 vn_ioctl(fp, com, data, p) 672 struct file *fp; 673 u_long com; 674 void *data; 675 struct proc *p; 676 { 677 struct vnode *vp = ((struct vnode *)fp->f_data); 678 struct vattr vattr; 679 int error; 680 681 switch (vp->v_type) { 682 683 case VREG: 684 case VDIR: 685 if (com == FIONREAD) { 686 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); 687 if (error) 688 return (error); 689 *(int *)data = vattr.va_size - fp->f_offset; 690 return (0); 691 } 692 if (com == FIOGETBMAP) { 693 daddr_t *block; 694 695 if (*(daddr_t *)data < 0) 696 return (EINVAL); 697 block = (daddr_t *)data; 698 return (VOP_BMAP(vp, *block, NULL, block, NULL)); 699 } 700 if (com == OFIOGETBMAP) { 701 daddr_t ibn, obn; 702 703 if (*(int32_t *)data < 0) 704 return (EINVAL); 705 ibn = (daddr_t)*(int32_t *)data; 706 error = VOP_BMAP(vp, ibn, NULL, &obn, NULL); 707 *(int32_t *)data = (int32_t)obn; 708 return error; 709 } 710 if (com == FIONBIO || com == FIOASYNC) /* XXX */ 711 return (0); /* XXX */ 712 /* fall into ... */ 713 case VFIFO: 714 case VCHR: 715 case VBLK: 716 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); 717 if (error == 0 && com == TIOCSCTTY) { 718 if (p->p_session->s_ttyvp) 719 vrele(p->p_session->s_ttyvp); 720 p->p_session->s_ttyvp = vp; 721 VREF(vp); 722 } 723 return (error); 724 725 default: 726 return (EPASSTHROUGH); 727 } 728 } 729 730 /* 731 * File table vnode poll routine. 732 */ 733 static int 734 vn_poll(fp, events, p) 735 struct file *fp; 736 int events; 737 struct proc *p; 738 { 739 740 return (VOP_POLL(((struct vnode *)fp->f_data), events, p)); 741 } 742 743 /* 744 * File table vnode kqfilter routine. 745 */ 746 int 747 vn_kqfilter(fp, kn) 748 struct file *fp; 749 struct knote *kn; 750 { 751 752 return (VOP_KQFILTER((struct vnode *)fp->f_data, kn)); 753 } 754 755 /* 756 * Check that the vnode is still valid, and if so 757 * acquire requested lock. 758 */ 759 int 760 vn_lock(vp, flags) 761 struct vnode *vp; 762 int flags; 763 { 764 int error; 765 766 do { 767 if ((flags & LK_INTERLOCK) == 0) 768 simple_lock(&vp->v_interlock); 769 if (vp->v_flag & VXLOCK) { 770 if (flags & LK_NOWAIT) { 771 simple_unlock(&vp->v_interlock); 772 return EBUSY; 773 } 774 vp->v_flag |= VXWANT; 775 ltsleep(vp, PINOD | PNORELOCK, 776 "vn_lock", 0, &vp->v_interlock); 777 error = ENOENT; 778 } else { 779 error = VOP_LOCK(vp, flags | LK_INTERLOCK); 780 if (error == 0 || error == EDEADLK || error == EBUSY) 781 return (error); 782 } 783 flags &= ~LK_INTERLOCK; 784 } while (flags & LK_RETRY); 785 return (error); 786 } 787 788 /* 789 * File table vnode close routine. 790 */ 791 static int 792 vn_closefile(fp, p) 793 struct file *fp; 794 struct proc *p; 795 { 796 797 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, 798 fp->f_cred, p)); 799 } 800 801 /* 802 * Enable LK_CANRECURSE on lock. Return prior status. 803 */ 804 u_int 805 vn_setrecurse(vp) 806 struct vnode *vp; 807 { 808 struct lock *lkp = &vp->v_lock; 809 u_int retval = lkp->lk_flags & LK_CANRECURSE; 810 811 lkp->lk_flags |= LK_CANRECURSE; 812 return retval; 813 } 814 815 /* 816 * Called when done with locksetrecurse. 817 */ 818 void 819 vn_restorerecurse(vp, flags) 820 struct vnode *vp; 821 u_int flags; 822 { 823 struct lock *lkp = &vp->v_lock; 824 825 lkp->lk_flags &= ~LK_CANRECURSE; 826 lkp->lk_flags |= flags; 827 } 828