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