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