1 /* $OpenBSD: vfs_vops.c,v 1.17 2018/02/10 05:24:23 deraadt Exp $ */ 2 /* 3 * Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * Copyright (c) 1992, 1993 18 * The Regents of the University of California. All rights reserved. 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 3. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 */ 44 45 #include <sys/param.h> 46 #include <sys/vnode.h> 47 #include <sys/unistd.h> 48 #include <sys/systm.h> 49 50 #ifdef VFSLCKDEBUG 51 #include <sys/systm.h> /* for panic() */ 52 53 #define ASSERT_VP_ISLOCKED(vp) do { \ 54 if (((vp)->v_flag & VLOCKSWORK) && !VOP_ISLOCKED(vp)) { \ 55 VOP_PRINT(vp); \ 56 panic("vp not locked"); \ 57 } \ 58 } while (0) 59 #else 60 #define ASSERT_VP_ISLOCKED(vp) /* nothing */ 61 #endif 62 63 int 64 VOP_ISLOCKED(struct vnode *vp) 65 { 66 struct vop_islocked_args a; 67 a.a_vp = vp; 68 69 if (vp->v_op->vop_islocked == NULL) 70 return (EOPNOTSUPP); 71 72 return ((vp->v_op->vop_islocked)(&a)); 73 } 74 75 int 76 VOP_LOOKUP(struct vnode *dvp, struct vnode **vpp, 77 struct componentname *cnp) 78 { 79 int r; 80 struct vop_lookup_args a; 81 a.a_dvp = dvp; 82 a.a_vpp = vpp; 83 a.a_cnp = cnp; 84 85 if (dvp->v_op->vop_lookup == NULL) 86 return (EOPNOTSUPP); 87 88 dvp->v_inflight++; 89 r = (dvp->v_op->vop_lookup)(&a); 90 dvp->v_inflight--; 91 return r; 92 } 93 94 int 95 VOP_CREATE(struct vnode *dvp, struct vnode **vpp, 96 struct componentname *cnp, struct vattr *vap) 97 { 98 int r; 99 struct vop_create_args a; 100 a.a_dvp = dvp; 101 a.a_vpp = vpp; 102 a.a_cnp = cnp; 103 a.a_vap = vap; 104 105 ASSERT_VP_ISLOCKED(dvp); 106 107 if (dvp->v_op->vop_create == NULL) 108 return (EOPNOTSUPP); 109 110 dvp->v_inflight++; 111 r = (dvp->v_op->vop_create)(&a); 112 dvp->v_inflight--; 113 return r; 114 } 115 116 int 117 VOP_MKNOD(struct vnode *dvp, struct vnode **vpp, 118 struct componentname *cnp, struct vattr *vap) 119 { 120 int r; 121 struct vop_mknod_args a; 122 a.a_dvp = dvp; 123 a.a_vpp = vpp; 124 a.a_cnp = cnp; 125 a.a_vap = vap; 126 127 ASSERT_VP_ISLOCKED(dvp); 128 129 if (dvp->v_op->vop_mknod == NULL) 130 return (EOPNOTSUPP); 131 132 dvp->v_inflight++; 133 r = (dvp->v_op->vop_mknod)(&a); 134 dvp->v_inflight--; 135 return r; 136 } 137 138 int 139 VOP_OPEN(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) 140 { 141 int r; 142 struct vop_open_args a; 143 a.a_vp = vp; 144 a.a_mode = mode; 145 a.a_cred = cred; 146 a.a_p = p; 147 148 if (vp->v_op->vop_open == NULL) 149 return (EOPNOTSUPP); 150 151 vp->v_inflight++; 152 r = (vp->v_op->vop_open)(&a); 153 vp->v_inflight--; 154 return r; 155 } 156 157 int 158 VOP_CLOSE(struct vnode *vp, int fflag, struct ucred *cred, struct proc *p) 159 { 160 int r; 161 struct vop_close_args a; 162 a.a_vp = vp; 163 a.a_fflag = fflag; 164 a.a_cred = cred; 165 a.a_p = p; 166 167 ASSERT_VP_ISLOCKED(vp); 168 169 if (vp->v_op->vop_close == NULL) 170 return (EOPNOTSUPP); 171 172 vp->v_inflight++; 173 r = (vp->v_op->vop_close)(&a); 174 vp->v_inflight--; 175 return r; 176 } 177 178 int 179 VOP_ACCESS(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) 180 { 181 struct vop_access_args a; 182 a.a_vp = vp; 183 a.a_mode = mode; 184 a.a_cred = cred; 185 a.a_p = p; 186 187 ASSERT_VP_ISLOCKED(vp); 188 189 if (vp->v_op->vop_access == NULL) 190 return (EOPNOTSUPP); 191 192 return ((vp->v_op->vop_access)(&a)); 193 } 194 195 int 196 VOP_GETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, 197 struct proc *p) 198 { 199 struct vop_getattr_args a; 200 a.a_vp = vp; 201 a.a_vap = vap; 202 a.a_cred = cred; 203 a.a_p = p; 204 205 if (vp->v_op->vop_getattr == NULL) 206 return (EOPNOTSUPP); 207 208 return ((vp->v_op->vop_getattr)(&a)); 209 } 210 211 int 212 VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, 213 struct proc *p) 214 { 215 int r; 216 struct vop_setattr_args a; 217 a.a_vp = vp; 218 a.a_vap = vap; 219 a.a_cred = cred; 220 a.a_p = p; 221 222 ASSERT_VP_ISLOCKED(vp); 223 224 if (vp->v_op->vop_setattr == NULL) 225 return (EOPNOTSUPP); 226 227 vp->v_inflight++; 228 r = (vp->v_op->vop_setattr)(&a); 229 vp->v_inflight--; 230 return r; 231 } 232 233 int 234 VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) 235 { 236 struct vop_read_args a; 237 a.a_vp = vp; 238 a.a_uio = uio; 239 a.a_ioflag = ioflag; 240 a.a_cred = cred; 241 242 ASSERT_VP_ISLOCKED(vp); 243 244 if (vp->v_op->vop_read == NULL) 245 return (EOPNOTSUPP); 246 247 return ((vp->v_op->vop_read)(&a)); 248 } 249 250 int 251 VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, 252 struct ucred *cred) 253 { 254 int r; 255 struct vop_write_args a; 256 a.a_vp = vp; 257 a.a_uio = uio; 258 a.a_ioflag = ioflag; 259 a.a_cred = cred; 260 261 ASSERT_VP_ISLOCKED(vp); 262 263 if (vp->v_op->vop_write == NULL) 264 return (EOPNOTSUPP); 265 266 vp->v_inflight++; 267 r = (vp->v_op->vop_write)(&a); 268 vp->v_inflight--; 269 return r; 270 } 271 272 int 273 VOP_IOCTL(struct vnode *vp, u_long command, void *data, int fflag, 274 struct ucred *cred, struct proc *p) 275 { 276 int r; 277 struct vop_ioctl_args a; 278 a.a_vp = vp; 279 a.a_command = command; 280 a.a_data = data; 281 a.a_fflag = fflag; 282 a.a_cred = cred; 283 a.a_p = p; 284 285 if (vp->v_op->vop_ioctl == NULL) 286 return (EOPNOTSUPP); 287 288 vp->v_inflight++; 289 r = (vp->v_op->vop_ioctl)(&a); 290 vp->v_inflight--; 291 return r; 292 } 293 294 int 295 VOP_POLL(struct vnode *vp, int fflag, int events, struct proc *p) 296 { 297 struct vop_poll_args a; 298 a.a_vp = vp; 299 a.a_fflag = fflag; 300 a.a_events = events; 301 a.a_p = p; 302 303 if (vp->v_op->vop_poll == NULL) 304 return (EOPNOTSUPP); 305 306 return ((vp->v_op->vop_poll)(&a)); 307 } 308 309 int 310 VOP_KQFILTER(struct vnode *vp, struct knote *kn) 311 { 312 struct vop_kqfilter_args a; 313 a.a_vp = vp; 314 a.a_kn = kn; 315 316 if (vp->v_op->vop_kqfilter == NULL) 317 return (EOPNOTSUPP); 318 319 return ((vp->v_op->vop_kqfilter)(&a)); 320 } 321 322 int 323 VOP_REVOKE(struct vnode *vp, int flags) 324 { 325 struct vop_revoke_args a; 326 a.a_vp = vp; 327 a.a_flags = flags; 328 329 if (vp->v_op->vop_revoke == NULL) 330 return (EOPNOTSUPP); 331 332 return ((vp->v_op->vop_revoke)(&a)); 333 } 334 335 int 336 VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor, 337 struct proc *p) 338 { 339 int r; 340 struct vop_fsync_args a; 341 a.a_vp = vp; 342 a.a_cred = cred; 343 a.a_waitfor = waitfor; 344 a.a_p = p; 345 346 ASSERT_VP_ISLOCKED(vp); 347 348 if (vp->v_op->vop_fsync == NULL) 349 return (EOPNOTSUPP); 350 351 vp->v_inflight++; 352 r = (vp->v_op->vop_fsync)(&a); 353 vp->v_inflight--; 354 return r; 355 } 356 357 int 358 VOP_REMOVE(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 359 { 360 int r; 361 struct vop_remove_args a; 362 a.a_dvp = dvp; 363 a.a_vp = vp; 364 a.a_cnp = cnp; 365 366 ASSERT_VP_ISLOCKED(dvp); 367 ASSERT_VP_ISLOCKED(vp); 368 369 if (dvp->v_op->vop_remove == NULL) 370 return (EOPNOTSUPP); 371 372 dvp->v_inflight++; 373 r = (dvp->v_op->vop_remove)(&a); 374 dvp->v_inflight--; 375 return r; 376 } 377 378 int 379 VOP_LINK(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 380 { 381 int r; 382 struct vop_link_args a; 383 a.a_dvp = dvp; 384 a.a_vp = vp; 385 a.a_cnp = cnp; 386 387 ASSERT_VP_ISLOCKED(dvp); 388 389 if (dvp->v_op->vop_link == NULL) 390 return (EOPNOTSUPP); 391 392 dvp->v_inflight++; 393 vp->v_inflight++; 394 r = (dvp->v_op->vop_link)(&a); 395 dvp->v_inflight--; 396 vp->v_inflight--; 397 return r; 398 } 399 400 int 401 VOP_RENAME(struct vnode *fdvp, struct vnode *fvp, 402 struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp, 403 struct componentname *tcnp) 404 { 405 int r; 406 struct vop_rename_args a; 407 a.a_fdvp = fdvp; 408 a.a_fvp = fvp; 409 a.a_fcnp = fcnp; 410 a.a_tdvp = tdvp; 411 a.a_tvp = tvp; 412 a.a_tcnp = tcnp; 413 414 ASSERT_VP_ISLOCKED(tdvp); 415 416 if (fdvp->v_op->vop_rename == NULL) 417 return (EOPNOTSUPP); 418 419 fdvp->v_inflight++; 420 tdvp->v_inflight++; 421 r = (fdvp->v_op->vop_rename)(&a); 422 fdvp->v_inflight--; 423 tdvp->v_inflight--; 424 return r; 425 } 426 427 int 428 VOP_MKDIR(struct vnode *dvp, struct vnode **vpp, 429 struct componentname *cnp, struct vattr *vap) 430 { 431 int r; 432 struct vop_mkdir_args a; 433 a.a_dvp = dvp; 434 a.a_vpp = vpp; 435 a.a_cnp = cnp; 436 a.a_vap = vap; 437 438 ASSERT_VP_ISLOCKED(dvp); 439 440 if (dvp->v_op->vop_mkdir == NULL) 441 return (EOPNOTSUPP); 442 443 dvp->v_inflight++; 444 r = (dvp->v_op->vop_mkdir)(&a); 445 dvp->v_inflight--; 446 return r; 447 } 448 449 int 450 VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 451 { 452 int r; 453 struct vop_rmdir_args a; 454 a.a_dvp = dvp; 455 a.a_vp = vp; 456 a.a_cnp = cnp; 457 458 ASSERT_VP_ISLOCKED(dvp); 459 ASSERT_VP_ISLOCKED(vp); 460 461 if (dvp->v_op->vop_rmdir == NULL) 462 return (EOPNOTSUPP); 463 464 dvp->v_inflight++; 465 vp->v_inflight++; 466 r = (dvp->v_op->vop_rmdir)(&a); 467 dvp->v_inflight--; 468 vp->v_inflight--; 469 return r; 470 } 471 472 int 473 VOP_SYMLINK(struct vnode *dvp, struct vnode **vpp, 474 struct componentname *cnp, struct vattr *vap, char *target) 475 { 476 int r; 477 struct vop_symlink_args a; 478 a.a_dvp = dvp; 479 a.a_vpp = vpp; 480 a.a_cnp = cnp; 481 a.a_vap = vap; 482 a.a_target = target; 483 484 ASSERT_VP_ISLOCKED(dvp); 485 486 if (dvp->v_op->vop_symlink == NULL) 487 return (EOPNOTSUPP); 488 489 dvp->v_inflight++; 490 r = (dvp->v_op->vop_symlink)(&a); 491 dvp->v_inflight--; 492 return r; 493 } 494 495 int 496 VOP_READDIR(struct vnode *vp, struct uio *uio, struct ucred *cred, 497 int *eofflag) 498 { 499 int r; 500 struct vop_readdir_args a; 501 a.a_vp = vp; 502 a.a_uio = uio; 503 a.a_cred = cred; 504 a.a_eofflag = eofflag; 505 506 ASSERT_VP_ISLOCKED(vp); 507 508 if (vp->v_op->vop_readdir == NULL) 509 return (EOPNOTSUPP); 510 511 vp->v_inflight++; 512 r = (vp->v_op->vop_readdir)(&a); 513 vp->v_inflight--; 514 return r; 515 } 516 517 int 518 VOP_READLINK(struct vnode *vp, struct uio *uio, struct ucred *cred) 519 { 520 int r; 521 struct vop_readlink_args a; 522 a.a_vp = vp; 523 a.a_uio = uio; 524 a.a_cred = cred; 525 526 ASSERT_VP_ISLOCKED(vp); 527 528 if (vp->v_op->vop_readlink == NULL) 529 return (EOPNOTSUPP); 530 531 vp->v_inflight++; 532 r = (vp->v_op->vop_readlink)(&a); 533 vp->v_inflight--; 534 return r; 535 } 536 537 int 538 VOP_ABORTOP(struct vnode *dvp, struct componentname *cnp) 539 { 540 int r; 541 struct vop_abortop_args a; 542 a.a_dvp = dvp; 543 a.a_cnp = cnp; 544 545 if (dvp->v_op->vop_abortop == NULL) 546 return (EOPNOTSUPP); 547 548 dvp->v_inflight++; 549 r = (dvp->v_op->vop_abortop)(&a); 550 dvp->v_inflight--; 551 return r; 552 } 553 554 int 555 VOP_INACTIVE(struct vnode *vp, struct proc *p) 556 { 557 struct vop_inactive_args a; 558 a.a_vp = vp; 559 a.a_p = p; 560 561 ASSERT_VP_ISLOCKED(vp); 562 563 if (vp->v_op->vop_inactive == NULL) 564 return (EOPNOTSUPP); 565 566 return ((vp->v_op->vop_inactive)(&a)); 567 } 568 569 int 570 VOP_RECLAIM(struct vnode *vp, struct proc *p) 571 { 572 int r; 573 struct vop_reclaim_args a; 574 a.a_vp = vp; 575 a.a_p = p; 576 577 if (vp->v_op->vop_reclaim == NULL) 578 return (EOPNOTSUPP); 579 580 vp->v_inflight++; 581 r = (vp->v_op->vop_reclaim)(&a); 582 vp->v_inflight--; 583 return r; 584 } 585 586 int 587 VOP_LOCK(struct vnode *vp, int flags, struct proc *p) 588 { 589 struct vop_lock_args a; 590 a.a_vp = vp; 591 a.a_flags = flags; 592 a.a_p = p; 593 594 if (vp->v_op->vop_lock == NULL) 595 return (EOPNOTSUPP); 596 597 return ((vp->v_op->vop_lock)(&a)); 598 } 599 600 int 601 VOP_UNLOCK(struct vnode *vp, struct proc *p) 602 { 603 int r; 604 struct vop_unlock_args a; 605 a.a_vp = vp; 606 a.a_p = p; 607 608 if (vp->v_op->vop_unlock == NULL) 609 return (EOPNOTSUPP); 610 611 vp->v_inflight++; 612 r = (vp->v_op->vop_unlock)(&a); 613 vp->v_inflight--; 614 return r; 615 } 616 617 int 618 VOP_BMAP(struct vnode *vp, daddr_t bn, struct vnode **vpp, 619 daddr_t *bnp, int *runp) 620 { 621 struct vop_bmap_args a; 622 a.a_vp = vp; 623 a.a_bn = bn; 624 a.a_vpp = vpp; 625 a.a_bnp = bnp; 626 a.a_runp = runp; 627 628 ASSERT_VP_ISLOCKED(vp); 629 630 if (vp->v_op->vop_bmap == NULL) 631 return (EOPNOTSUPP); 632 633 return ((vp->v_op->vop_bmap)(&a)); 634 } 635 636 int 637 VOP_PRINT(struct vnode *vp) 638 { 639 struct vop_print_args a; 640 a.a_vp = vp; 641 642 if (vp->v_op->vop_print == NULL) 643 return (EOPNOTSUPP); 644 645 return ((vp->v_op->vop_print)(&a)); 646 } 647 648 int 649 VOP_PATHCONF(struct vnode *vp, int name, register_t *retval) 650 { 651 struct vop_pathconf_args a; 652 653 /* 654 * Handle names that are constant across filesystem 655 */ 656 switch (name) { 657 case _PC_PATH_MAX: 658 *retval = PATH_MAX; 659 return (0); 660 case _PC_PIPE_BUF: 661 *retval = PIPE_BUF; 662 return (0); 663 case _PC_ASYNC_IO: 664 case _PC_PRIO_IO: 665 case _PC_SYNC_IO: 666 *retval = 0; 667 return (0); 668 669 } 670 671 a.a_vp = vp; 672 a.a_name = name; 673 a.a_retval = retval; 674 675 ASSERT_VP_ISLOCKED(vp); 676 677 if (vp->v_op->vop_pathconf == NULL) 678 return (EOPNOTSUPP); 679 680 return ((vp->v_op->vop_pathconf)(&a)); 681 } 682 683 int 684 VOP_ADVLOCK(struct vnode *vp, void *id, int op, struct flock *fl, int flags) 685 { 686 int r; 687 struct vop_advlock_args a; 688 a.a_vp = vp; 689 a.a_id = id; 690 a.a_op = op; 691 a.a_fl = fl; 692 a.a_flags = flags; 693 694 if (vp->v_op->vop_advlock == NULL) 695 return (EOPNOTSUPP); 696 697 vp->v_inflight++; 698 r = (vp->v_op->vop_advlock)(&a); 699 vp->v_inflight--; 700 return r; 701 } 702 703 int 704 VOP_STRATEGY(struct buf *bp) 705 { 706 struct vop_strategy_args a; 707 a.a_bp = bp; 708 709 if ((ISSET(bp->b_flags, B_BC)) && (!ISSET(bp->b_flags, B_DMA))) 710 panic("Non dma reachable buffer passed to VOP_STRATEGY"); 711 712 if (bp->b_vp->v_op->vop_strategy == NULL) 713 return (EOPNOTSUPP); 714 715 return ((bp->b_vp->v_op->vop_strategy)(&a)); 716 } 717 718 int 719 VOP_BWRITE(struct buf *bp) 720 { 721 struct vop_bwrite_args a; 722 a.a_bp = bp; 723 724 if (bp->b_vp->v_op->vop_bwrite == NULL) 725 return (EOPNOTSUPP); 726 727 return ((bp->b_vp->v_op->vop_bwrite)(&a)); 728 } 729