1 /* $OpenBSD: vfs_vops.c,v 1.30 2021/04/28 09:53:53 claudio 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 #define ASSERT_VP_ISLOCKED(vp) do { \ 52 if (((vp)->v_flag & VLOCKSWORK) && !VOP_ISLOCKED(vp)) { \ 53 VOP_PRINT(vp); \ 54 panic("vp not locked"); \ 55 } \ 56 } while (0) 57 #else 58 #define ASSERT_VP_ISLOCKED(vp) /* nothing */ 59 #endif 60 61 int 62 VOP_ISLOCKED(struct vnode *vp) 63 { 64 struct vop_islocked_args a; 65 a.a_vp = vp; 66 67 if (vp->v_op->vop_islocked == NULL) 68 return (EOPNOTSUPP); 69 70 return ((vp->v_op->vop_islocked)(&a)); 71 } 72 73 int 74 VOP_LOOKUP(struct vnode *dvp, struct vnode **vpp, 75 struct componentname *cnp) 76 { 77 int r; 78 struct vop_lookup_args a; 79 a.a_dvp = dvp; 80 a.a_vpp = vpp; 81 a.a_cnp = cnp; 82 83 if (dvp->v_op->vop_lookup == NULL) 84 return (EOPNOTSUPP); 85 86 dvp->v_inflight++; 87 r = (dvp->v_op->vop_lookup)(&a); 88 dvp->v_inflight--; 89 return r; 90 } 91 92 int 93 VOP_CREATE(struct vnode *dvp, struct vnode **vpp, 94 struct componentname *cnp, struct vattr *vap) 95 { 96 int r; 97 struct vop_create_args a; 98 a.a_dvp = dvp; 99 a.a_vpp = vpp; 100 a.a_cnp = cnp; 101 a.a_vap = vap; 102 103 ASSERT_VP_ISLOCKED(dvp); 104 105 if (dvp->v_op->vop_create == NULL) 106 return (EOPNOTSUPP); 107 108 dvp->v_inflight++; 109 r = (dvp->v_op->vop_create)(&a); 110 dvp->v_inflight--; 111 return r; 112 } 113 114 int 115 VOP_MKNOD(struct vnode *dvp, struct vnode **vpp, 116 struct componentname *cnp, struct vattr *vap) 117 { 118 int r; 119 struct vop_mknod_args a; 120 a.a_dvp = dvp; 121 a.a_vpp = vpp; 122 a.a_cnp = cnp; 123 a.a_vap = vap; 124 125 ASSERT_VP_ISLOCKED(dvp); 126 127 if (dvp->v_op->vop_mknod == NULL) 128 return (EOPNOTSUPP); 129 130 dvp->v_inflight++; 131 r = (dvp->v_op->vop_mknod)(&a); 132 dvp->v_inflight--; 133 return r; 134 } 135 136 int 137 VOP_OPEN(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) 138 { 139 int r; 140 struct vop_open_args a; 141 a.a_vp = vp; 142 a.a_mode = mode; 143 a.a_cred = cred; 144 a.a_p = p; 145 146 KASSERT(p == curproc); 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 KASSERT(p == NULL || p == curproc); 168 ASSERT_VP_ISLOCKED(vp); 169 170 if (vp->v_op->vop_close == NULL) 171 return (EOPNOTSUPP); 172 173 vp->v_inflight++; 174 r = (vp->v_op->vop_close)(&a); 175 vp->v_inflight--; 176 return r; 177 } 178 179 int 180 VOP_ACCESS(struct vnode *vp, int mode, struct ucred *cred, struct proc *p) 181 { 182 struct vop_access_args a; 183 a.a_vp = vp; 184 a.a_mode = mode; 185 a.a_cred = cred; 186 a.a_p = p; 187 188 KASSERT(p == curproc); 189 ASSERT_VP_ISLOCKED(vp); 190 191 if (vp->v_op->vop_access == NULL) 192 return (EOPNOTSUPP); 193 194 return ((vp->v_op->vop_access)(&a)); 195 } 196 197 int 198 VOP_GETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, 199 struct proc *p) 200 { 201 struct vop_getattr_args a; 202 a.a_vp = vp; 203 a.a_vap = vap; 204 a.a_cred = cred; 205 a.a_p = p; 206 207 KASSERT(p == curproc); 208 if (vp->v_op->vop_getattr == NULL) 209 return (EOPNOTSUPP); 210 211 return ((vp->v_op->vop_getattr)(&a)); 212 } 213 214 int 215 VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct ucred *cred, 216 struct proc *p) 217 { 218 int r; 219 struct vop_setattr_args a; 220 a.a_vp = vp; 221 a.a_vap = vap; 222 a.a_cred = cred; 223 a.a_p = p; 224 225 KASSERT(p == curproc); 226 ASSERT_VP_ISLOCKED(vp); 227 228 if (vp->v_op->vop_setattr == NULL) 229 return (EOPNOTSUPP); 230 231 vp->v_inflight++; 232 r = (vp->v_op->vop_setattr)(&a); 233 vp->v_inflight--; 234 return r; 235 } 236 237 int 238 VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) 239 { 240 struct vop_read_args a; 241 a.a_vp = vp; 242 a.a_uio = uio; 243 a.a_ioflag = ioflag; 244 a.a_cred = cred; 245 246 ASSERT_VP_ISLOCKED(vp); 247 248 if (vp->v_op->vop_read == NULL) 249 return (EOPNOTSUPP); 250 251 return ((vp->v_op->vop_read)(&a)); 252 } 253 254 int 255 VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, 256 struct ucred *cred) 257 { 258 int r; 259 struct vop_write_args a; 260 a.a_vp = vp; 261 a.a_uio = uio; 262 a.a_ioflag = ioflag; 263 a.a_cred = cred; 264 265 ASSERT_VP_ISLOCKED(vp); 266 267 if (vp->v_op->vop_write == NULL) 268 return (EOPNOTSUPP); 269 270 vp->v_inflight++; 271 r = (vp->v_op->vop_write)(&a); 272 vp->v_inflight--; 273 return r; 274 } 275 276 int 277 VOP_IOCTL(struct vnode *vp, u_long command, void *data, int fflag, 278 struct ucred *cred, struct proc *p) 279 { 280 int r; 281 struct vop_ioctl_args a; 282 a.a_vp = vp; 283 a.a_command = command; 284 a.a_data = data; 285 a.a_fflag = fflag; 286 a.a_cred = cred; 287 a.a_p = p; 288 289 KASSERT(p == curproc); 290 if (vp->v_op->vop_ioctl == NULL) 291 return (EOPNOTSUPP); 292 293 vp->v_inflight++; 294 r = (vp->v_op->vop_ioctl)(&a); 295 vp->v_inflight--; 296 return r; 297 } 298 299 int 300 VOP_POLL(struct vnode *vp, int fflag, int events, struct proc *p) 301 { 302 struct vop_poll_args a; 303 a.a_vp = vp; 304 a.a_fflag = fflag; 305 a.a_events = events; 306 a.a_p = p; 307 308 KASSERT(p == curproc); 309 if (vp->v_op->vop_poll == NULL) 310 return (EOPNOTSUPP); 311 312 return ((vp->v_op->vop_poll)(&a)); 313 } 314 315 int 316 VOP_KQFILTER(struct vnode *vp, int fflag, struct knote *kn) 317 { 318 struct vop_kqfilter_args a; 319 a.a_vp = vp; 320 a.a_fflag = fflag; 321 a.a_kn = kn; 322 323 if (vp->v_op->vop_kqfilter == NULL) 324 return (EOPNOTSUPP); 325 326 return ((vp->v_op->vop_kqfilter)(&a)); 327 } 328 329 int 330 VOP_REVOKE(struct vnode *vp, int flags) 331 { 332 struct vop_revoke_args a; 333 a.a_vp = vp; 334 a.a_flags = flags; 335 336 if (vp->v_op->vop_revoke == NULL) 337 return (EOPNOTSUPP); 338 339 return ((vp->v_op->vop_revoke)(&a)); 340 } 341 342 int 343 VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor, 344 struct proc *p) 345 { 346 int r, s; 347 struct vop_fsync_args a; 348 a.a_vp = vp; 349 a.a_cred = cred; 350 a.a_waitfor = waitfor; 351 a.a_p = p; 352 353 KASSERT(p == curproc); 354 ASSERT_VP_ISLOCKED(vp); 355 356 if (vp->v_op->vop_fsync == NULL) 357 return (EOPNOTSUPP); 358 359 vp->v_inflight++; 360 r = (vp->v_op->vop_fsync)(&a); 361 vp->v_inflight--; 362 s = splbio(); 363 if (r == 0 && vp->v_bioflag & VBIOERROR) 364 r = EIO; 365 splx(s); 366 return r; 367 } 368 369 int 370 VOP_REMOVE(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 371 { 372 int r; 373 struct vop_remove_args a; 374 a.a_dvp = dvp; 375 a.a_vp = vp; 376 a.a_cnp = cnp; 377 378 ASSERT_VP_ISLOCKED(dvp); 379 ASSERT_VP_ISLOCKED(vp); 380 381 if (dvp->v_op->vop_remove == NULL) 382 return (EOPNOTSUPP); 383 384 dvp->v_inflight++; 385 r = (dvp->v_op->vop_remove)(&a); 386 dvp->v_inflight--; 387 return r; 388 } 389 390 int 391 VOP_LINK(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 392 { 393 int r; 394 struct vop_link_args a; 395 a.a_dvp = dvp; 396 a.a_vp = vp; 397 a.a_cnp = cnp; 398 399 ASSERT_VP_ISLOCKED(dvp); 400 401 if (dvp->v_op->vop_link == NULL) 402 return (EOPNOTSUPP); 403 404 dvp->v_inflight++; 405 vp->v_inflight++; 406 r = (dvp->v_op->vop_link)(&a); 407 dvp->v_inflight--; 408 vp->v_inflight--; 409 return r; 410 } 411 412 int 413 VOP_RENAME(struct vnode *fdvp, struct vnode *fvp, 414 struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp, 415 struct componentname *tcnp) 416 { 417 int r; 418 struct vop_rename_args a; 419 a.a_fdvp = fdvp; 420 a.a_fvp = fvp; 421 a.a_fcnp = fcnp; 422 a.a_tdvp = tdvp; 423 a.a_tvp = tvp; 424 a.a_tcnp = tcnp; 425 426 ASSERT_VP_ISLOCKED(tdvp); 427 428 if (fdvp->v_op->vop_rename == NULL) 429 return (EOPNOTSUPP); 430 431 fdvp->v_inflight++; 432 tdvp->v_inflight++; 433 r = (fdvp->v_op->vop_rename)(&a); 434 fdvp->v_inflight--; 435 tdvp->v_inflight--; 436 return r; 437 } 438 439 int 440 VOP_MKDIR(struct vnode *dvp, struct vnode **vpp, 441 struct componentname *cnp, struct vattr *vap) 442 { 443 int r; 444 struct vop_mkdir_args a; 445 a.a_dvp = dvp; 446 a.a_vpp = vpp; 447 a.a_cnp = cnp; 448 a.a_vap = vap; 449 450 ASSERT_VP_ISLOCKED(dvp); 451 452 if (dvp->v_op->vop_mkdir == NULL) 453 return (EOPNOTSUPP); 454 455 dvp->v_inflight++; 456 r = (dvp->v_op->vop_mkdir)(&a); 457 dvp->v_inflight--; 458 return r; 459 } 460 461 int 462 VOP_RMDIR(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 463 { 464 int r; 465 struct vop_rmdir_args a; 466 a.a_dvp = dvp; 467 a.a_vp = vp; 468 a.a_cnp = cnp; 469 470 ASSERT_VP_ISLOCKED(dvp); 471 ASSERT_VP_ISLOCKED(vp); 472 473 KASSERT(dvp != vp); 474 475 if (dvp->v_op->vop_rmdir == NULL) 476 return (EOPNOTSUPP); 477 478 dvp->v_inflight++; 479 vp->v_inflight++; 480 r = (dvp->v_op->vop_rmdir)(&a); 481 dvp->v_inflight--; 482 vp->v_inflight--; 483 return r; 484 } 485 486 int 487 VOP_SYMLINK(struct vnode *dvp, struct vnode **vpp, 488 struct componentname *cnp, struct vattr *vap, char *target) 489 { 490 int r; 491 struct vop_symlink_args a; 492 a.a_dvp = dvp; 493 a.a_vpp = vpp; 494 a.a_cnp = cnp; 495 a.a_vap = vap; 496 a.a_target = target; 497 498 ASSERT_VP_ISLOCKED(dvp); 499 500 if (dvp->v_op->vop_symlink == NULL) 501 return (EOPNOTSUPP); 502 503 dvp->v_inflight++; 504 r = (dvp->v_op->vop_symlink)(&a); 505 dvp->v_inflight--; 506 return r; 507 } 508 509 int 510 VOP_READDIR(struct vnode *vp, struct uio *uio, struct ucred *cred, 511 int *eofflag) 512 { 513 int r; 514 struct vop_readdir_args a; 515 a.a_vp = vp; 516 a.a_uio = uio; 517 a.a_cred = cred; 518 a.a_eofflag = eofflag; 519 520 ASSERT_VP_ISLOCKED(vp); 521 522 if (vp->v_op->vop_readdir == NULL) 523 return (EOPNOTSUPP); 524 525 vp->v_inflight++; 526 r = (vp->v_op->vop_readdir)(&a); 527 vp->v_inflight--; 528 return r; 529 } 530 531 int 532 VOP_READLINK(struct vnode *vp, struct uio *uio, struct ucred *cred) 533 { 534 int r; 535 struct vop_readlink_args a; 536 a.a_vp = vp; 537 a.a_uio = uio; 538 a.a_cred = cred; 539 540 ASSERT_VP_ISLOCKED(vp); 541 542 if (vp->v_op->vop_readlink == NULL) 543 return (EOPNOTSUPP); 544 545 vp->v_inflight++; 546 r = (vp->v_op->vop_readlink)(&a); 547 vp->v_inflight--; 548 return r; 549 } 550 551 int 552 VOP_ABORTOP(struct vnode *dvp, struct componentname *cnp) 553 { 554 int r; 555 struct vop_abortop_args a; 556 a.a_dvp = dvp; 557 a.a_cnp = cnp; 558 559 if (dvp->v_op->vop_abortop == NULL) 560 return (EOPNOTSUPP); 561 562 dvp->v_inflight++; 563 r = (dvp->v_op->vop_abortop)(&a); 564 dvp->v_inflight--; 565 return r; 566 } 567 568 int 569 VOP_INACTIVE(struct vnode *vp, struct proc *p) 570 { 571 struct vop_inactive_args a; 572 a.a_vp = vp; 573 a.a_p = p; 574 575 KASSERT(p == curproc); 576 ASSERT_VP_ISLOCKED(vp); 577 578 if (vp->v_op->vop_inactive == NULL) 579 return (EOPNOTSUPP); 580 581 return ((vp->v_op->vop_inactive)(&a)); 582 } 583 584 int 585 VOP_RECLAIM(struct vnode *vp, struct proc *p) 586 { 587 int r; 588 struct vop_reclaim_args a; 589 a.a_vp = vp; 590 a.a_p = p; 591 592 KASSERT(p == curproc); 593 if (vp->v_op->vop_reclaim == NULL) 594 return (EOPNOTSUPP); 595 596 vp->v_inflight++; 597 r = (vp->v_op->vop_reclaim)(&a); 598 vp->v_inflight--; 599 return r; 600 } 601 602 int 603 VOP_LOCK(struct vnode *vp, int flags) 604 { 605 struct vop_lock_args a; 606 a.a_vp = vp; 607 a.a_flags = flags; 608 609 MUTEX_ASSERT_UNLOCKED(&vnode_mtx); 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