1 /* $NetBSD: vfs_vnops.c,v 1.82 2004/11/06 07:34:53 christos 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.82 2004/11/06 07:34:53 christos 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/malloc.h> 52 #include <sys/mount.h> 53 #include <sys/namei.h> 54 #include <sys/vnode.h> 55 #include <sys/ioctl.h> 56 #include <sys/tty.h> 57 #include <sys/poll.h> 58 59 #include <miscfs/specfs/specdev.h> 60 61 #include <uvm/uvm_extern.h> 62 63 #ifdef UNION 64 #include <fs/union/union.h> 65 #endif 66 67 #if defined(LKM) || defined(UNION) 68 int (*vn_union_readdir_hook) (struct vnode **, struct file *, struct proc *); 69 #endif 70 71 #ifdef VERIFIED_EXEC 72 #include <sys/verified_exec.h> 73 74 extern LIST_HEAD(veriexec_devhead, veriexec_dev_list) veriexec_dev_head; 75 extern struct veriexec_devhead veriexec_file_dev_head; 76 #endif 77 78 static int vn_read(struct file *fp, off_t *offset, struct uio *uio, 79 struct ucred *cred, int flags); 80 static int vn_write(struct file *fp, off_t *offset, struct uio *uio, 81 struct ucred *cred, int flags); 82 static int vn_closefile(struct file *fp, struct proc *p); 83 static int vn_poll(struct file *fp, int events, struct proc *p); 84 static int vn_fcntl(struct file *fp, u_int com, void *data, struct proc *p); 85 static int vn_statfile(struct file *fp, struct stat *sb, struct proc *p); 86 static int vn_ioctl(struct file *fp, u_long com, void *data, struct proc *p); 87 88 struct fileops vnops = { 89 vn_read, vn_write, vn_ioctl, vn_fcntl, vn_poll, 90 vn_statfile, vn_closefile, vn_kqfilter 91 }; 92 93 /* 94 * Common code for vnode open operations. 95 * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. 96 */ 97 int 98 vn_open(ndp, fmode, cmode) 99 struct nameidata *ndp; 100 int fmode, cmode; 101 { 102 struct vnode *vp; 103 struct mount *mp; 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 restart: 115 if (fmode & O_CREAT) { 116 ndp->ni_cnd.cn_nameiop = CREATE; 117 ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; 118 if ((fmode & O_EXCL) == 0 && 119 ((fmode & O_NOFOLLOW) == 0)) 120 ndp->ni_cnd.cn_flags |= FOLLOW; 121 if ((error = namei(ndp)) != 0) 122 return (error); 123 if (ndp->ni_vp == NULL) { 124 VATTR_NULL(&va); 125 va.va_type = VREG; 126 va.va_mode = cmode; 127 if (fmode & O_EXCL) 128 va.va_vaflags |= VA_EXCLUSIVE; 129 if (vn_start_write(ndp->ni_dvp, &mp, V_NOWAIT) != 0) { 130 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 131 vput(ndp->ni_dvp); 132 if ((error = vn_start_write(NULL, &mp, 133 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 134 return (error); 135 goto restart; 136 } 137 VOP_LEASE(ndp->ni_dvp, p, cred, LEASE_WRITE); 138 error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, 139 &ndp->ni_cnd, &va); 140 vn_finished_write(mp, 0); 141 if (error) 142 return (error); 143 fmode &= ~O_TRUNC; 144 vp = ndp->ni_vp; 145 } else { 146 VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); 147 if (ndp->ni_dvp == ndp->ni_vp) 148 vrele(ndp->ni_dvp); 149 else 150 vput(ndp->ni_dvp); 151 ndp->ni_dvp = NULL; 152 vp = ndp->ni_vp; 153 if (fmode & O_EXCL) { 154 error = EEXIST; 155 goto bad; 156 } 157 fmode &= ~O_CREAT; 158 } 159 } else { 160 ndp->ni_cnd.cn_nameiop = LOOKUP; 161 ndp->ni_cnd.cn_flags = LOCKLEAF; 162 if ((fmode & O_NOFOLLOW) == 0) 163 ndp->ni_cnd.cn_flags |= FOLLOW; 164 if ((error = namei(ndp)) != 0) 165 return (error); 166 vp = ndp->ni_vp; 167 } 168 if (vp->v_type == VSOCK) { 169 error = EOPNOTSUPP; 170 goto bad; 171 } 172 if (ndp->ni_vp->v_type == VLNK) { 173 error = EFTYPE; 174 goto bad; 175 } 176 177 #ifdef VERIFIED_EXEC 178 veriexec_node = NULL; 179 180 if ((error = VOP_GETATTR(vp, &va, cred, p)) != 0) 181 goto bad; 182 #endif 183 184 if ((fmode & O_CREAT) == 0) { 185 #ifdef VERIFIED_EXEC 186 /* 187 * Look for the file on the fingerprint lists iff 188 * it has not been seen before. 189 */ 190 if ((vp->fp_status == FINGERPRINT_INVALID) || 191 (vp->fp_status == FINGERPRINT_NODEV)) { 192 /* check the file list for the finger print */ 193 veriexec_node = get_veriexec_inode(&veriexec_file_dev_head, 194 va.va_fsid, 195 va.va_fileid, 196 &got_dev); 197 if (veriexec_node == NULL) { 198 /* failing that, check the exec list */ 199 veriexec_node = get_veriexec_inode( 200 &veriexec_dev_head, va.va_fsid, 201 va.va_fileid, &got_dev); 202 } 203 204 if ((veriexec_node == NULL) && (got_dev == 1)) 205 vp->fp_status = FINGERPRINT_NOENTRY; 206 207 if (veriexec_node != NULL) { 208 if ((error = evaluate_fingerprint(vp, 209 veriexec_node, p, va.va_size, 210 fingerprint)) != 0) 211 goto bad; 212 213 if (fingerprintcmp(veriexec_node, 214 fingerprint) == 0) { 215 /* fingerprint ok */ 216 vp->fp_status = FINGERPRINT_VALID; 217 #ifdef VERIFIED_EXEC_DEBUG 218 printf( 219 "file fingerprint matches for dev %lu, file %lu\n", 220 va.va_fsid, va.va_fileid); 221 #endif 222 } else { 223 vp->fp_status = FINGERPRINT_NOMATCH; 224 } 225 } 226 } 227 #endif 228 229 if (fmode & FREAD) { 230 if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0) 231 goto bad; 232 233 #ifdef VERIFIED_EXEC 234 /* file is on finger print list */ 235 if (vp->fp_status == FINGERPRINT_NOMATCH) { 236 /* fingerprint bad */ 237 printf( 238 "file fingerprint does not match on dev %lu, file %lu\n", 239 va.va_fsid, va.va_fileid); 240 if (securelevel > 2) { 241 error = EPERM; 242 goto bad; 243 } 244 } 245 #endif 246 } 247 if (fmode & (FWRITE | O_TRUNC)) { 248 if (vp->v_type == VDIR) { 249 error = EISDIR; 250 goto bad; 251 } 252 if ((error = vn_writechk(vp)) != 0 || 253 (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0) 254 goto bad; 255 #ifdef VERIFIED_EXEC 256 /* 257 * If file has a fingerprint then 258 * deny the write request, otherwise 259 * invalidate the status so we don't 260 * keep checking for the file having 261 * a fingerprint. 262 */ 263 if (vp->fp_status == FINGERPRINT_VALID) { 264 printf( 265 "writing to fingerprinted file for dev %lu, file %lu\n", 266 va.va_fsid, va.va_fileid); 267 if (securelevel > 2) { 268 error = EPERM; 269 goto bad; 270 } else { 271 vp->fp_status = FINGERPRINT_INVALID; 272 } 273 } 274 #endif 275 } 276 } 277 if (fmode & O_TRUNC) { 278 VOP_UNLOCK(vp, 0); /* XXX */ 279 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 280 vput(vp); 281 return (error); 282 } 283 VOP_LEASE(vp, p, cred, LEASE_WRITE); 284 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */ 285 VATTR_NULL(&va); 286 va.va_size = 0; 287 error = VOP_SETATTR(vp, &va, cred, p); 288 vn_finished_write(mp, 0); 289 if (error != 0) 290 goto bad; 291 } 292 if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0) 293 goto bad; 294 if (vp->v_type == VREG && 295 uvn_attach(vp, fmode & FWRITE ? VM_PROT_WRITE : 0) == NULL) { 296 error = EIO; 297 goto bad; 298 } 299 if (fmode & FWRITE) 300 vp->v_writecount++; 301 302 return (0); 303 bad: 304 vput(vp); 305 return (error); 306 } 307 308 /* 309 * Check for write permissions on the specified vnode. 310 * Prototype text segments cannot be written. 311 */ 312 int 313 vn_writechk(vp) 314 struct vnode *vp; 315 { 316 317 /* 318 * If the vnode is in use as a process's text, 319 * we can't allow writing. 320 */ 321 if (vp->v_flag & VTEXT) 322 return (ETXTBSY); 323 return (0); 324 } 325 326 /* 327 * Mark a vnode as having executable mappings. 328 */ 329 void 330 vn_markexec(vp) 331 struct vnode *vp; 332 { 333 if ((vp->v_flag & VEXECMAP) == 0) { 334 uvmexp.filepages -= vp->v_uobj.uo_npages; 335 uvmexp.execpages += vp->v_uobj.uo_npages; 336 } 337 vp->v_flag |= VEXECMAP; 338 } 339 340 /* 341 * Mark a vnode as being the text of a process. 342 * Fail if the vnode is currently writable. 343 */ 344 int 345 vn_marktext(vp) 346 struct vnode *vp; 347 { 348 349 if (vp->v_writecount != 0) { 350 KASSERT((vp->v_flag & VTEXT) == 0); 351 return (ETXTBSY); 352 } 353 vp->v_flag |= VTEXT; 354 vn_markexec(vp); 355 return (0); 356 } 357 358 /* 359 * Vnode close call 360 * 361 * Note: takes an unlocked vnode, while VOP_CLOSE takes a locked node. 362 */ 363 int 364 vn_close(vp, flags, cred, p) 365 struct vnode *vp; 366 int flags; 367 struct ucred *cred; 368 struct proc *p; 369 { 370 int error; 371 372 if (flags & FWRITE) 373 vp->v_writecount--; 374 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 375 error = VOP_CLOSE(vp, flags, cred, p); 376 vput(vp); 377 return (error); 378 } 379 380 /* 381 * Package up an I/O request on a vnode into a uio and do it. 382 */ 383 int 384 vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) 385 enum uio_rw rw; 386 struct vnode *vp; 387 caddr_t base; 388 int len; 389 off_t offset; 390 enum uio_seg segflg; 391 int ioflg; 392 struct ucred *cred; 393 size_t *aresid; 394 struct proc *p; 395 { 396 struct uio auio; 397 struct iovec aiov; 398 struct mount *mp; 399 int error; 400 401 if ((ioflg & IO_NODELOCKED) == 0) { 402 if (rw == UIO_READ) { 403 vn_lock(vp, LK_SHARED | LK_RETRY); 404 } else /* UIO_WRITE */ { 405 if (vp->v_type != VCHR && 406 (error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) 407 != 0) 408 return (error); 409 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 410 } 411 } 412 auio.uio_iov = &aiov; 413 auio.uio_iovcnt = 1; 414 aiov.iov_base = base; 415 aiov.iov_len = len; 416 auio.uio_resid = len; 417 auio.uio_offset = offset; 418 auio.uio_segflg = segflg; 419 auio.uio_rw = rw; 420 auio.uio_procp = p; 421 if (rw == UIO_READ) { 422 error = VOP_READ(vp, &auio, ioflg, cred); 423 } else { 424 error = VOP_WRITE(vp, &auio, ioflg, cred); 425 } 426 if (aresid) 427 *aresid = auio.uio_resid; 428 else 429 if (auio.uio_resid && error == 0) 430 error = EIO; 431 if ((ioflg & IO_NODELOCKED) == 0) { 432 if (rw == UIO_WRITE) 433 vn_finished_write(mp, 0); 434 VOP_UNLOCK(vp, 0); 435 } 436 return (error); 437 } 438 439 int 440 vn_readdir(fp, buf, segflg, count, done, p, cookies, ncookies) 441 struct file *fp; 442 char *buf; 443 int segflg, *done, *ncookies; 444 u_int count; 445 struct proc *p; 446 off_t **cookies; 447 { 448 struct vnode *vp = (struct vnode *)fp->f_data; 449 struct iovec aiov; 450 struct uio auio; 451 int error, eofflag; 452 453 unionread: 454 if (vp->v_type != VDIR) 455 return (EINVAL); 456 aiov.iov_base = buf; 457 aiov.iov_len = count; 458 auio.uio_iov = &aiov; 459 auio.uio_iovcnt = 1; 460 auio.uio_rw = UIO_READ; 461 auio.uio_segflg = segflg; 462 auio.uio_procp = p; 463 auio.uio_resid = count; 464 vn_lock(vp, LK_SHARED | LK_RETRY); 465 auio.uio_offset = fp->f_offset; 466 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookies, 467 ncookies); 468 fp->f_offset = auio.uio_offset; 469 VOP_UNLOCK(vp, 0); 470 if (error) 471 return (error); 472 473 #if defined(UNION) || defined(LKM) 474 if (count == auio.uio_resid && vn_union_readdir_hook) { 475 struct vnode *ovp = vp; 476 477 error = (*vn_union_readdir_hook)(&vp, fp, p); 478 if (error) 479 return (error); 480 if (vp != ovp) 481 goto unionread; 482 } 483 #endif /* UNION || LKM */ 484 485 if (count == auio.uio_resid && (vp->v_flag & VROOT) && 486 (vp->v_mount->mnt_flag & MNT_UNION)) { 487 struct vnode *tvp = vp; 488 vp = vp->v_mount->mnt_vnodecovered; 489 VREF(vp); 490 fp->f_data = vp; 491 fp->f_offset = 0; 492 vrele(tvp); 493 goto unionread; 494 } 495 *done = count - auio.uio_resid; 496 return error; 497 } 498 499 /* 500 * File table vnode read routine. 501 */ 502 static int 503 vn_read(fp, offset, uio, cred, flags) 504 struct file *fp; 505 off_t *offset; 506 struct uio *uio; 507 struct ucred *cred; 508 int flags; 509 { 510 struct vnode *vp = (struct vnode *)fp->f_data; 511 int count, error, ioflag = 0; 512 513 VOP_LEASE(vp, uio->uio_procp, cred, LEASE_READ); 514 if (fp->f_flag & FNONBLOCK) 515 ioflag |= IO_NDELAY; 516 if ((fp->f_flag & (FFSYNC | FRSYNC)) == (FFSYNC | FRSYNC)) 517 ioflag |= IO_SYNC; 518 if (fp->f_flag & FALTIO) 519 ioflag |= IO_ALTSEMANTICS; 520 vn_lock(vp, LK_SHARED | LK_RETRY); 521 uio->uio_offset = *offset; 522 count = uio->uio_resid; 523 error = VOP_READ(vp, uio, ioflag, cred); 524 if (flags & FOF_UPDATE_OFFSET) 525 *offset += count - uio->uio_resid; 526 VOP_UNLOCK(vp, 0); 527 return (error); 528 } 529 530 /* 531 * File table vnode write routine. 532 */ 533 static int 534 vn_write(fp, offset, uio, cred, flags) 535 struct file *fp; 536 off_t *offset; 537 struct uio *uio; 538 struct ucred *cred; 539 int flags; 540 { 541 struct vnode *vp = (struct vnode *)fp->f_data; 542 struct mount *mp; 543 int count, error, ioflag = IO_UNIT; 544 545 if (vp->v_type == VREG && (fp->f_flag & O_APPEND)) 546 ioflag |= IO_APPEND; 547 if (fp->f_flag & FNONBLOCK) 548 ioflag |= IO_NDELAY; 549 if (fp->f_flag & FFSYNC || 550 (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) 551 ioflag |= IO_SYNC; 552 else if (fp->f_flag & FDSYNC) 553 ioflag |= IO_DSYNC; 554 if (fp->f_flag & FALTIO) 555 ioflag |= IO_ALTSEMANTICS; 556 mp = NULL; 557 if (vp->v_type != VCHR && 558 (error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 559 return (error); 560 VOP_LEASE(vp, uio->uio_procp, cred, LEASE_WRITE); 561 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 562 uio->uio_offset = *offset; 563 count = uio->uio_resid; 564 error = VOP_WRITE(vp, uio, ioflag, cred); 565 if (flags & FOF_UPDATE_OFFSET) { 566 if (ioflag & IO_APPEND) 567 *offset = uio->uio_offset; 568 else 569 *offset += count - uio->uio_resid; 570 } 571 VOP_UNLOCK(vp, 0); 572 vn_finished_write(mp, 0); 573 return (error); 574 } 575 576 /* 577 * File table vnode stat routine. 578 */ 579 static int 580 vn_statfile(fp, sb, p) 581 struct file *fp; 582 struct stat *sb; 583 struct proc *p; 584 { 585 struct vnode *vp = (struct vnode *)fp->f_data; 586 587 return vn_stat(vp, sb, p); 588 } 589 590 int 591 vn_stat(vp, sb, p) 592 struct vnode *vp; 593 struct stat *sb; 594 struct proc *p; 595 { 596 struct vattr va; 597 int error; 598 mode_t mode; 599 600 error = VOP_GETATTR(vp, &va, p->p_ucred, p); 601 if (error) 602 return (error); 603 /* 604 * Copy from vattr table 605 */ 606 sb->st_dev = va.va_fsid; 607 sb->st_ino = va.va_fileid; 608 mode = va.va_mode; 609 switch (vp->v_type) { 610 case VREG: 611 mode |= S_IFREG; 612 break; 613 case VDIR: 614 mode |= S_IFDIR; 615 break; 616 case VBLK: 617 mode |= S_IFBLK; 618 break; 619 case VCHR: 620 mode |= S_IFCHR; 621 break; 622 case VLNK: 623 mode |= S_IFLNK; 624 break; 625 case VSOCK: 626 mode |= S_IFSOCK; 627 break; 628 case VFIFO: 629 mode |= S_IFIFO; 630 break; 631 default: 632 return (EBADF); 633 }; 634 sb->st_mode = mode; 635 sb->st_nlink = va.va_nlink; 636 sb->st_uid = va.va_uid; 637 sb->st_gid = va.va_gid; 638 sb->st_rdev = va.va_rdev; 639 sb->st_size = va.va_size; 640 sb->st_atimespec = va.va_atime; 641 sb->st_mtimespec = va.va_mtime; 642 sb->st_ctimespec = va.va_ctime; 643 sb->st_birthtimespec = va.va_birthtime; 644 sb->st_blksize = va.va_blocksize; 645 sb->st_flags = va.va_flags; 646 sb->st_gen = 0; 647 sb->st_blocks = va.va_bytes / S_BLKSIZE; 648 return (0); 649 } 650 651 /* 652 * File table vnode fcntl routine. 653 */ 654 static int 655 vn_fcntl(fp, com, data, p) 656 struct file *fp; 657 u_int com; 658 void *data; 659 struct proc *p; 660 { 661 struct vnode *vp = ((struct vnode *)fp->f_data); 662 int error; 663 664 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 665 error = VOP_FCNTL(vp, com, data, fp->f_flag, p->p_ucred, p); 666 VOP_UNLOCK(vp, 0); 667 return (error); 668 } 669 670 /* 671 * File table vnode ioctl routine. 672 */ 673 static int 674 vn_ioctl(fp, com, data, p) 675 struct file *fp; 676 u_long com; 677 void *data; 678 struct proc *p; 679 { 680 struct vnode *vp = ((struct vnode *)fp->f_data); 681 struct vattr vattr; 682 int error; 683 684 switch (vp->v_type) { 685 686 case VREG: 687 case VDIR: 688 if (com == FIONREAD) { 689 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); 690 if (error) 691 return (error); 692 *(int *)data = vattr.va_size - fp->f_offset; 693 return (0); 694 } 695 if ((com == FIONWRITE) || (com == FIONSPACE)) { 696 /* 697 * Files don't have send queues, so there never 698 * are any bytes in them, nor is there any 699 * open space in them. 700 */ 701 *(int *)data = 0; 702 return (0); 703 } 704 if (com == FIOGETBMAP) { 705 daddr_t *block; 706 707 if (*(daddr_t *)data < 0) 708 return (EINVAL); 709 block = (daddr_t *)data; 710 return (VOP_BMAP(vp, *block, NULL, block, NULL)); 711 } 712 if (com == OFIOGETBMAP) { 713 daddr_t ibn, obn; 714 715 if (*(int32_t *)data < 0) 716 return (EINVAL); 717 ibn = (daddr_t)*(int32_t *)data; 718 error = VOP_BMAP(vp, ibn, NULL, &obn, NULL); 719 *(int32_t *)data = (int32_t)obn; 720 return error; 721 } 722 if (com == FIONBIO || com == FIOASYNC) /* XXX */ 723 return (0); /* XXX */ 724 /* fall into ... */ 725 case VFIFO: 726 case VCHR: 727 case VBLK: 728 error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p); 729 if (error == 0 && com == TIOCSCTTY) { 730 if (p->p_session->s_ttyvp) 731 vrele(p->p_session->s_ttyvp); 732 p->p_session->s_ttyvp = vp; 733 VREF(vp); 734 } 735 return (error); 736 737 default: 738 return (EPASSTHROUGH); 739 } 740 } 741 742 /* 743 * File table vnode poll routine. 744 */ 745 static int 746 vn_poll(fp, events, p) 747 struct file *fp; 748 int events; 749 struct proc *p; 750 { 751 752 return (VOP_POLL(((struct vnode *)fp->f_data), events, p)); 753 } 754 755 /* 756 * File table vnode kqfilter routine. 757 */ 758 int 759 vn_kqfilter(fp, kn) 760 struct file *fp; 761 struct knote *kn; 762 { 763 764 return (VOP_KQFILTER((struct vnode *)fp->f_data, kn)); 765 } 766 767 /* 768 * Check that the vnode is still valid, and if so 769 * acquire requested lock. 770 */ 771 int 772 vn_lock(vp, flags) 773 struct vnode *vp; 774 int flags; 775 { 776 int error; 777 778 KASSERT(vp->v_usecount > 0 || (flags & LK_INTERLOCK) != 0 779 || (vp->v_flag & VONWORKLST) != 0); 780 781 do { 782 if ((flags & LK_INTERLOCK) == 0) 783 simple_lock(&vp->v_interlock); 784 if (vp->v_flag & VXLOCK) { 785 if (flags & LK_NOWAIT) { 786 simple_unlock(&vp->v_interlock); 787 return EBUSY; 788 } 789 vp->v_flag |= VXWANT; 790 ltsleep(vp, PINOD | PNORELOCK, 791 "vn_lock", 0, &vp->v_interlock); 792 error = ENOENT; 793 } else { 794 error = VOP_LOCK(vp, 795 (flags & ~LK_RETRY) | LK_INTERLOCK); 796 if (error == 0 || error == EDEADLK || error == EBUSY) 797 return (error); 798 } 799 flags &= ~LK_INTERLOCK; 800 } while (flags & LK_RETRY); 801 return (error); 802 } 803 804 /* 805 * File table vnode close routine. 806 */ 807 static int 808 vn_closefile(fp, p) 809 struct file *fp; 810 struct proc *p; 811 { 812 813 return (vn_close(((struct vnode *)fp->f_data), fp->f_flag, 814 fp->f_cred, p)); 815 } 816 817 /* 818 * Enable LK_CANRECURSE on lock. Return prior status. 819 */ 820 u_int 821 vn_setrecurse(vp) 822 struct vnode *vp; 823 { 824 struct lock *lkp = &vp->v_lock; 825 u_int retval = lkp->lk_flags & LK_CANRECURSE; 826 827 lkp->lk_flags |= LK_CANRECURSE; 828 return retval; 829 } 830 831 /* 832 * Called when done with locksetrecurse. 833 */ 834 void 835 vn_restorerecurse(vp, flags) 836 struct vnode *vp; 837 u_int flags; 838 { 839 struct lock *lkp = &vp->v_lock; 840 841 lkp->lk_flags &= ~LK_CANRECURSE; 842 lkp->lk_flags |= flags; 843 } 844 845 int 846 vn_cow_establish(struct vnode *vp, 847 int (*func)(void *, struct buf *), void *cookie) 848 { 849 int s; 850 struct spec_cow_entry *e; 851 852 MALLOC(e, struct spec_cow_entry *, sizeof(struct spec_cow_entry), 853 M_DEVBUF, M_WAITOK); 854 e->ce_func = func; 855 e->ce_cookie = cookie; 856 857 SPEC_COW_LOCK(vp->v_specinfo, s); 858 vp->v_spec_cow_req++; 859 while (vp->v_spec_cow_count > 0) 860 ltsleep(&vp->v_spec_cow_req, PRIBIO, "cowlist", 0, 861 &vp->v_spec_cow_slock); 862 863 SLIST_INSERT_HEAD(&vp->v_spec_cow_head, e, ce_list); 864 865 vp->v_spec_cow_req--; 866 if (vp->v_spec_cow_req == 0) 867 wakeup(&vp->v_spec_cow_req); 868 SPEC_COW_UNLOCK(vp->v_specinfo, s); 869 870 return 0; 871 } 872 873 int 874 vn_cow_disestablish(struct vnode *vp, 875 int (*func)(void *, struct buf *), void *cookie) 876 { 877 int s; 878 struct spec_cow_entry *e; 879 880 SPEC_COW_LOCK(vp->v_specinfo, s); 881 vp->v_spec_cow_req++; 882 while (vp->v_spec_cow_count > 0) 883 ltsleep(&vp->v_spec_cow_req, PRIBIO, "cowlist", 0, 884 &vp->v_spec_cow_slock); 885 886 SLIST_FOREACH(e, &vp->v_spec_cow_head, ce_list) 887 if (e->ce_func == func && e->ce_cookie == cookie) { 888 SLIST_REMOVE(&vp->v_spec_cow_head, e, 889 spec_cow_entry, ce_list); 890 FREE(e, M_DEVBUF); 891 break; 892 } 893 894 vp->v_spec_cow_req--; 895 if (vp->v_spec_cow_req == 0) 896 wakeup(&vp->v_spec_cow_req); 897 SPEC_COW_UNLOCK(vp->v_specinfo, s); 898 899 return e ? 0 : EINVAL; 900 } 901