1 /* $OpenBSD: vfs_vops.c,v 1.29 2020/10/07 12:33:03 mpi 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 KASSERT(p == curproc); 149 150 if (vp->v_op->vop_open == NULL) 151 return (EOPNOTSUPP); 152 153 vp->v_inflight++; 154 r = (vp->v_op->vop_open)(&a); 155 vp->v_inflight--; 156 return r; 157 } 158 159 int 160 VOP_CLOSE(struct vnode *vp, int fflag, struct ucred *cred, struct proc *p) 161 { 162 int r; 163 struct vop_close_args a; 164 a.a_vp = vp; 165 a.a_fflag = fflag; 166 a.a_cred = cred; 167 a.a_p = p; 168 169 KASSERT(p == NULL || p == curproc); 170 ASSERT_VP_ISLOCKED(vp); 171 172 if (vp->v_op->vop_close == NULL) 173 return (EOPNOTSUPP); 174 175 vp->v_inflight++; 176 r = (vp->v_op->vop_close)(&a); 177 vp->v_inflight--; 178 return r; 179 } 180 181 int 182 VOP_ACCESS(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) 183 { 184 struct vop_access_args a; 185 a.a_vp = vp; 186 a.a_mode = mode; 187 a.a_cred = cred; 188 a.a_p = p; 189 190 KASSERT(p == curproc); 191 ASSERT_VP_ISLOCKED(vp); 192 193 if (vp->v_op->vop_access == NULL) 194 return (EOPNOTSUPP); 195 196 return ((vp->v_op->vop_access)(&a)); 197 } 198 199 int 200 VOP_GETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, 201 struct proc *p) 202 { 203 struct vop_getattr_args a; 204 a.a_vp = vp; 205 a.a_vap = vap; 206 a.a_cred = cred; 207 a.a_p = p; 208 209 KASSERT(p == curproc); 210 if (vp->v_op->vop_getattr == NULL) 211 return (EOPNOTSUPP); 212 213 return ((vp->v_op->vop_getattr)(&a)); 214 } 215 216 int 217 VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, 218 struct proc *p) 219 { 220 int r; 221 struct vop_setattr_args a; 222 a.a_vp = vp; 223 a.a_vap = vap; 224 a.a_cred = cred; 225 a.a_p = p; 226 227 KASSERT(p == curproc); 228 ASSERT_VP_ISLOCKED(vp); 229 230 if (vp->v_op->vop_setattr == NULL) 231 return (EOPNOTSUPP); 232 233 vp->v_inflight++; 234 r = (vp->v_op->vop_setattr)(&a); 235 vp->v_inflight--; 236 return r; 237 } 238 239 int 240 VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) 241 { 242 struct vop_read_args a; 243 a.a_vp = vp; 244 a.a_uio = uio; 245 a.a_ioflag = ioflag; 246 a.a_cred = cred; 247 248 ASSERT_VP_ISLOCKED(vp); 249 250 if (vp->v_op->vop_read == NULL) 251 return (EOPNOTSUPP); 252 253 return ((vp->v_op->vop_read)(&a)); 254 } 255 256 int 257 VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, 258 struct ucred *cred) 259 { 260 int r; 261 struct vop_write_args a; 262 a.a_vp = vp; 263 a.a_uio = uio; 264 a.a_ioflag = ioflag; 265 a.a_cred = cred; 266 267 ASSERT_VP_ISLOCKED(vp); 268 269 if (vp->v_op->vop_write == NULL) 270 return (EOPNOTSUPP); 271 272 vp->v_inflight++; 273 r = (vp->v_op->vop_write)(&a); 274 vp->v_inflight--; 275 return r; 276 } 277 278 int 279 VOP_IOCTL(struct vnode *vp, u_long command, void *data, int fflag, 280 struct ucred *cred, struct proc *p) 281 { 282 int r; 283 struct vop_ioctl_args a; 284 a.a_vp = vp; 285 a.a_command = command; 286 a.a_data = data; 287 a.a_fflag = fflag; 288 a.a_cred = cred; 289 a.a_p = p; 290 291 KASSERT(p == curproc); 292 if (vp->v_op->vop_ioctl == NULL) 293 return (EOPNOTSUPP); 294 295 vp->v_inflight++; 296 r = (vp->v_op->vop_ioctl)(&a); 297 vp->v_inflight--; 298 return r; 299 } 300 301 int 302 VOP_POLL(struct vnode *vp, int fflag, int events, struct proc *p) 303 { 304 struct vop_poll_args a; 305 a.a_vp = vp; 306 a.a_fflag = fflag; 307 a.a_events = events; 308 a.a_p = p; 309 310 KASSERT(p == curproc); 311 if (vp->v_op->vop_poll == NULL) 312 return (EOPNOTSUPP); 313 314 return ((vp->v_op->vop_poll)(&a)); 315 } 316 317 int 318 VOP_KQFILTER(struct vnode *vp, int fflag, struct knote *kn) 319 { 320 struct vop_kqfilter_args a; 321 a.a_vp = vp; 322 a.a_fflag = fflag; 323 a.a_kn = kn; 324 325 if (vp->v_op->vop_kqfilter == NULL) 326 return (EOPNOTSUPP); 327 328 return ((vp->v_op->vop_kqfilter)(&a)); 329 } 330 331 int 332 VOP_REVOKE(struct vnode *vp, int flags) 333 { 334 struct vop_revoke_args a; 335 a.a_vp = vp; 336 a.a_flags = flags; 337 338 if (vp->v_op->vop_revoke == NULL) 339 return (EOPNOTSUPP); 340 341 return ((vp->v_op->vop_revoke)(&a)); 342 } 343 344 int 345 VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor, 346 struct proc *p) 347 { 348 int r, s; 349 struct vop_fsync_args a; 350 a.a_vp = vp; 351 a.a_cred = cred; 352 a.a_waitfor = waitfor; 353 a.a_p = p; 354 355 KASSERT(p == curproc); 356 ASSERT_VP_ISLOCKED(vp); 357 358 if (vp->v_op->vop_fsync == NULL) 359 return (EOPNOTSUPP); 360 361 vp->v_inflight++; 362 r = (vp->v_op->vop_fsync)(&a); 363 vp->v_inflight--; 364 s = splbio(); 365 if (r == 0 && vp->v_bioflag & VBIOERROR) 366 r = EIO; 367 splx(s); 368 return r; 369 } 370 371 int 372 VOP_REMOVE(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 373 { 374 int r; 375 struct vop_remove_args a; 376 a.a_dvp = dvp; 377 a.a_vp = vp; 378 a.a_cnp = cnp; 379 380 ASSERT_VP_ISLOCKED(dvp); 381 ASSERT_VP_ISLOCKED(vp); 382 383 if (dvp->v_op->vop_remove == NULL) 384 return (EOPNOTSUPP); 385 386 dvp->v_inflight++; 387 r = (dvp->v_op->vop_remove)(&a); 388 dvp->v_inflight--; 389 return r; 390 } 391 392 int 393 VOP_LINK(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 394 { 395 int r; 396 struct vop_link_args a; 397 a.a_dvp = dvp; 398 a.a_vp = vp; 399 a.a_cnp = cnp; 400 401 ASSERT_VP_ISLOCKED(dvp); 402 403 if (dvp->v_op->vop_link == NULL) 404 return (EOPNOTSUPP); 405 406 dvp->v_inflight++; 407 vp->v_inflight++; 408 r = (dvp->v_op->vop_link)(&a); 409 dvp->v_inflight--; 410 vp->v_inflight--; 411 return r; 412 } 413 414 int 415 VOP_RENAME(struct vnode *fdvp, struct vnode *fvp, 416 struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp, 417 struct componentname *tcnp) 418 { 419 int r; 420 struct vop_rename_args a; 421 a.a_fdvp = fdvp; 422 a.a_fvp = fvp; 423 a.a_fcnp = fcnp; 424 a.a_tdvp = tdvp; 425 a.a_tvp = tvp; 426 a.a_tcnp = tcnp; 427 428 ASSERT_VP_ISLOCKED(tdvp); 429 430 if (fdvp->v_op->vop_rename == NULL) 431 return (EOPNOTSUPP); 432 433 fdvp->v_inflight++; 434 tdvp->v_inflight++; 435 r = (fdvp->v_op->vop_rename)(&a); 436 fdvp->v_inflight--; 437 tdvp->v_inflight--; 438 return r; 439 } 440 441 int 442 VOP_MKDIR(struct vnode *dvp, struct vnode **vpp, 443 struct componentname *cnp, struct vattr *vap) 444 { 445 int r; 446 struct vop_mkdir_args a; 447 a.a_dvp = dvp; 448 a.a_vpp = vpp; 449 a.a_cnp = cnp; 450 a.a_vap = vap; 451 452 ASSERT_VP_ISLOCKED(dvp); 453 454 if (dvp->v_op->vop_mkdir == NULL) 455 return (EOPNOTSUPP); 456 457 dvp->v_inflight++; 458 r = (dvp->v_op->vop_mkdir)(&a); 459 dvp->v_inflight--; 460 return r; 461 } 462 463 int 464 VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 465 { 466 int r; 467 struct vop_rmdir_args a; 468 a.a_dvp = dvp; 469 a.a_vp = vp; 470 a.a_cnp = cnp; 471 472 ASSERT_VP_ISLOCKED(dvp); 473 ASSERT_VP_ISLOCKED(vp); 474 475 KASSERT(dvp != vp); 476 477 if (dvp->v_op->vop_rmdir == NULL) 478 return (EOPNOTSUPP); 479 480 dvp->v_inflight++; 481 vp->v_inflight++; 482 r = (dvp->v_op->vop_rmdir)(&a); 483 dvp->v_inflight--; 484 vp->v_inflight--; 485 return r; 486 } 487 488 int 489 VOP_SYMLINK(struct vnode *dvp, struct vnode **vpp, 490 struct componentname *cnp, struct vattr *vap, char *target) 491 { 492 int r; 493 struct vop_symlink_args a; 494 a.a_dvp = dvp; 495 a.a_vpp = vpp; 496 a.a_cnp = cnp; 497 a.a_vap = vap; 498 a.a_target = target; 499 500 ASSERT_VP_ISLOCKED(dvp); 501 502 if (dvp->v_op->vop_symlink == NULL) 503 return (EOPNOTSUPP); 504 505 dvp->v_inflight++; 506 r = (dvp->v_op->vop_symlink)(&a); 507 dvp->v_inflight--; 508 return r; 509 } 510 511 int 512 VOP_READDIR(struct vnode *vp, struct uio *uio, struct ucred *cred, 513 int *eofflag) 514 { 515 int r; 516 struct vop_readdir_args a; 517 a.a_vp = vp; 518 a.a_uio = uio; 519 a.a_cred = cred; 520 a.a_eofflag = eofflag; 521 522 ASSERT_VP_ISLOCKED(vp); 523 524 if (vp->v_op->vop_readdir == NULL) 525 return (EOPNOTSUPP); 526 527 vp->v_inflight++; 528 r = (vp->v_op->vop_readdir)(&a); 529 vp->v_inflight--; 530 return r; 531 } 532 533 int 534 VOP_READLINK(struct vnode *vp, struct uio *uio, struct ucred *cred) 535 { 536 int r; 537 struct vop_readlink_args a; 538 a.a_vp = vp; 539 a.a_uio = uio; 540 a.a_cred = cred; 541 542 ASSERT_VP_ISLOCKED(vp); 543 544 if (vp->v_op->vop_readlink == NULL) 545 return (EOPNOTSUPP); 546 547 vp->v_inflight++; 548 r = (vp->v_op->vop_readlink)(&a); 549 vp->v_inflight--; 550 return r; 551 } 552 553 int 554 VOP_ABORTOP(struct vnode *dvp, struct componentname *cnp) 555 { 556 int r; 557 struct vop_abortop_args a; 558 a.a_dvp = dvp; 559 a.a_cnp = cnp; 560 561 if (dvp->v_op->vop_abortop == NULL) 562 return (EOPNOTSUPP); 563 564 dvp->v_inflight++; 565 r = (dvp->v_op->vop_abortop)(&a); 566 dvp->v_inflight--; 567 return r; 568 } 569 570 int 571 VOP_INACTIVE(struct vnode *vp, struct proc *p) 572 { 573 struct vop_inactive_args a; 574 a.a_vp = vp; 575 a.a_p = p; 576 577 KASSERT(p == curproc); 578 ASSERT_VP_ISLOCKED(vp); 579 580 if (vp->v_op->vop_inactive == NULL) 581 return (EOPNOTSUPP); 582 583 return ((vp->v_op->vop_inactive)(&a)); 584 } 585 586 int 587 VOP_RECLAIM(struct vnode *vp, struct proc *p) 588 { 589 int r; 590 struct vop_reclaim_args a; 591 a.a_vp = vp; 592 a.a_p = p; 593 594 KASSERT(p == curproc); 595 if (vp->v_op->vop_reclaim == NULL) 596 return (EOPNOTSUPP); 597 598 vp->v_inflight++; 599 r = (vp->v_op->vop_reclaim)(&a); 600 vp->v_inflight--; 601 return r; 602 } 603 604 int 605 VOP_LOCK(struct vnode *vp, int flags) 606 { 607 struct vop_lock_args a; 608 a.a_vp = vp; 609 a.a_flags = flags; 610 611 if (vp->v_op->vop_lock == NULL) 612 return (EOPNOTSUPP); 613 614 return ((vp->v_op->vop_lock)(&a)); 615 } 616 617 int 618 VOP_UNLOCK(struct vnode *vp) 619 { 620 struct vop_unlock_args a; 621 a.a_vp = vp; 622 623 if (vp->v_op->vop_unlock == NULL) 624 return (EOPNOTSUPP); 625 626 return ((vp->v_op->vop_unlock)(&a)); 627 } 628 629 int 630 VOP_BMAP(struct vnode *vp, daddr_t bn, struct vnode **vpp, 631 daddr_t *bnp, int *runp) 632 { 633 struct vop_bmap_args a; 634 a.a_vp = vp; 635 a.a_bn = bn; 636 a.a_vpp = vpp; 637 a.a_bnp = bnp; 638 a.a_runp = runp; 639 640 ASSERT_VP_ISLOCKED(vp); 641 642 if (vp->v_op->vop_bmap == NULL) 643 return (EOPNOTSUPP); 644 645 return ((vp->v_op->vop_bmap)(&a)); 646 } 647 648 int 649 VOP_PRINT(struct vnode *vp) 650 { 651 struct vop_print_args a; 652 a.a_vp = vp; 653 654 if (vp->v_op->vop_print == NULL) 655 return (EOPNOTSUPP); 656 657 return ((vp->v_op->vop_print)(&a)); 658 } 659 660 int 661 VOP_PATHCONF(struct vnode *vp, int name, register_t *retval) 662 { 663 struct vop_pathconf_args a; 664 665 /* 666 * Handle names that are constant across filesystem 667 */ 668 switch (name) { 669 case _PC_PATH_MAX: 670 *retval = PATH_MAX; 671 return (0); 672 case _PC_PIPE_BUF: 673 *retval = PIPE_BUF; 674 return (0); 675 case _PC_ASYNC_IO: 676 case _PC_PRIO_IO: 677 case _PC_SYNC_IO: 678 *retval = 0; 679 return (0); 680 681 } 682 683 a.a_vp = vp; 684 a.a_name = name; 685 a.a_retval = retval; 686 687 ASSERT_VP_ISLOCKED(vp); 688 689 if (vp->v_op->vop_pathconf == NULL) 690 return (EOPNOTSUPP); 691 692 return ((vp->v_op->vop_pathconf)(&a)); 693 } 694 695 int 696 VOP_ADVLOCK(struct vnode *vp, void *id, int op, struct flock *fl, int flags) 697 { 698 struct vop_advlock_args a; 699 a.a_vp = vp; 700 a.a_id = id; 701 a.a_op = op; 702 a.a_fl = fl; 703 a.a_flags = flags; 704 705 if (vp->v_op->vop_advlock == NULL) 706 return (EOPNOTSUPP); 707 708 return (vp->v_op->vop_advlock)(&a); 709 } 710 711 int 712 VOP_STRATEGY(struct buf *bp) 713 { 714 struct vop_strategy_args a; 715 a.a_bp = bp; 716 717 if ((ISSET(bp->b_flags, B_BC)) && (!ISSET(bp->b_flags, B_DMA))) 718 panic("Non dma reachable buffer passed to VOP_STRATEGY"); 719 720 if (bp->b_vp->v_op->vop_strategy == NULL) 721 return (EOPNOTSUPP); 722 723 return ((bp->b_vp->v_op->vop_strategy)(&a)); 724 } 725 726 int 727 VOP_BWRITE(struct buf *bp) 728 { 729 struct vop_bwrite_args a; 730 a.a_bp = bp; 731 732 if (bp->b_vp->v_op->vop_bwrite == NULL) 733 return (EOPNOTSUPP); 734 735 return ((bp->b_vp->v_op->vop_bwrite)(&a)); 736 } 737