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