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