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