1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * All rights reserved. 5 * 6 * This code is derived from software donated to Berkeley by 7 * Jan-Simon Pendry. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)lofs_vnops.c 8.3 (Berkeley) 01/14/94 12 * 13 * $Id: lofs_vnops.c,v 1.11 1992/05/30 10:05:43 jsp Exp jsp $ 14 */ 15 16 /* 17 * Loopback Filesystem 18 */ 19 20 #include <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/proc.h> 23 #include <sys/time.h> 24 #include <sys/types.h> 25 #include <sys/vnode.h> 26 #include <sys/mount.h> 27 #include <sys/namei.h> 28 #include <sys/malloc.h> 29 #include <sys/buf.h> 30 #include <miscfs/lofs/lofs.h> 31 32 /* 33 * Basic strategy: as usual, do as little work as possible. 34 * Nothing is ever locked in the lofs'ed filesystem, all 35 * locks are held in the underlying filesystems. 36 */ 37 38 /* 39 * Save a vnode and replace with 40 * the lofs'ed one 41 */ 42 #define PUSHREF(v, nd) \ 43 { \ 44 struct { struct vnode *vnp; } v; \ 45 v.vnp = (nd); \ 46 (nd) = LOFSVP(v.vnp) 47 48 /* 49 * Undo the PUSHREF 50 */ 51 #define POP(v, nd) \ 52 \ 53 (nd) = v.vnp; \ 54 } 55 56 /* 57 * vp is the current namei directory 58 * ndp is the name to locate in that directory... 59 */ 60 int 61 lofs_lookup(ap) 62 struct vop_lookup_args /* { 63 struct vnode * a_dvp; 64 struct vnode ** a_vpp; 65 struct componentname * a_cnp; 66 } */ *ap; 67 { 68 struct vnode *dvp = ap->a_dvp; 69 struct vnode *newvp; 70 struct vnode *targetdvp; 71 int error; 72 int flag = ap->a_cnp->cn_nameiop /*& OPMASK*/; 73 74 /* 75 * (ap->a_dvp) was locked when passed in, and it will be replaced 76 * with the target vnode, BUT that will already have been 77 * locked when (ap->a_dvp) was locked [see lofs_lock]. all that 78 * must be done here is to keep track of reference counts. 79 */ 80 targetdvp = LOFSVP(dvp); 81 /*VREF(targetdvp);*/ 82 83 /* 84 * Call lookup on the looped vnode 85 */ 86 error = VOP_LOOKUP(targetdvp, &newvp, ap->a_cnp); 87 /*vrele(targetdvp);*/ 88 89 if (error) { 90 *ap->a_vpp = NULLVP; 91 return (error); 92 } 93 94 *ap->a_vpp = newvp; 95 96 /* 97 * If we just found a directory then make 98 * a loopback node for it and return the loopback 99 * instead of the real vnode. Otherwise simply 100 * return the aliased directory and vnode. 101 */ 102 if (newvp && newvp->v_type == VDIR && flag == LOOKUP) { 103 /* 104 * At this point, newvp is the vnode to be looped. 105 * Activate a loopback and return the looped vnode. 106 */ 107 return (make_lofs(dvp->v_mount, ap->a_vpp)); 108 } 109 110 return (0); 111 } 112 113 /* 114 * this = ni_dvp 115 * ni_dvp references the locked directory. 116 * ni_vp is NULL. 117 */ 118 int 119 lofs_mknod(ap) 120 struct vop_mknod_args /* { 121 struct vnode *a_dvp; 122 struct vnode **a_vpp; 123 struct componentname *a_cnp; 124 struct vattr *a_vap; 125 } */ *ap; 126 { 127 int error; 128 129 PUSHREF(xdvp, ap->a_dvp); 130 VREF(ap->a_dvp); 131 132 error = VOP_MKNOD(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap); 133 134 POP(xdvp, ap->a_dvp); 135 vrele(ap->a_dvp); 136 137 return (error); 138 } 139 140 /* 141 * this = ni_dvp; 142 * ni_dvp references the locked directory 143 * ni_vp is NULL. 144 */ 145 int 146 lofs_create(ap) 147 struct vop_create_args /* { 148 struct vnode *a_dvp; 149 struct vnode **a_vpp; 150 struct componentname *a_cnp; 151 struct vattr *a_vap; 152 } */ *ap; 153 { 154 int error; 155 156 PUSHREF(xdvp, ap->a_dvp); 157 VREF(ap->a_dvp); 158 159 error = VOP_CREATE(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap); 160 161 POP(xdvp, ap->a_dvp); 162 vrele(ap->a_dvp); 163 164 return (error); 165 } 166 167 int 168 lofs_open(ap) 169 struct vop_open_args /* { 170 struct vnode *a_vp; 171 int a_mode; 172 struct ucred *a_cred; 173 struct proc *a_p; 174 } */ *ap; 175 { 176 177 return (VOP_OPEN(LOFSVP(ap->a_vp), ap->a_mode, ap->a_cred, ap->a_p)); 178 } 179 180 int 181 lofs_close(ap) 182 struct vop_close_args /* { 183 struct vnode *a_vp; 184 int a_fflag; 185 struct ucred *a_cred; 186 struct proc *a_p; 187 } */ *ap; 188 { 189 190 return (VOP_CLOSE(LOFSVP(ap->a_vp), ap->a_fflag, ap->a_cred, ap->a_p)); 191 } 192 193 int 194 lofs_access(ap) 195 struct vop_access_args /* { 196 struct vnode *a_vp; 197 int a_mode; 198 struct ucred *a_cred; 199 struct proc *a_p; 200 } */ *ap; 201 { 202 203 return (VOP_ACCESS(LOFSVP(ap->a_vp), ap->a_mode, ap->a_cred, ap->a_p)); 204 } 205 206 int 207 lofs_getattr(ap) 208 struct vop_getattr_args /* { 209 struct vnode *a_vp; 210 struct vattr *a_vap; 211 struct ucred *a_cred; 212 struct proc *a_p; 213 } */ *ap; 214 { 215 int error; 216 217 /* 218 * Get the stats from the underlying filesystem 219 */ 220 error = VOP_GETATTR(LOFSVP(ap->a_vp), ap->a_vap, ap->a_cred, ap->a_p); 221 if (error) 222 return (error); 223 /* 224 * and replace the fsid field with the loopback number 225 * to preserve the namespace. 226 */ 227 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 228 return (0); 229 } 230 231 int 232 lofs_setattr(ap) 233 struct vop_setattr_args /* { 234 struct vnode *a_vp; 235 struct vattr *a_vap; 236 struct ucred *a_cred; 237 struct proc *a_p; 238 } */ *ap; 239 { 240 241 return (VOP_SETATTR(LOFSVP(ap->a_vp), ap->a_vap, ap->a_cred, ap->a_p)); 242 } 243 244 int 245 lofs_read(ap) 246 struct vop_read_args /* { 247 struct vnode *a_vp; 248 struct uio *a_uio; 249 int a_ioflag; 250 struct ucred *a_cred; 251 } */ *ap; 252 { 253 254 return (VOP_READ(LOFSVP(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred)); 255 } 256 257 int 258 lofs_write(ap) 259 struct vop_write_args /* { 260 struct vnode *a_vp; 261 struct uio *a_uio; 262 int a_ioflag; 263 struct ucred *a_cred; 264 } */ *ap; 265 { 266 267 return (VOP_WRITE(LOFSVP(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred)); 268 } 269 270 int 271 lofs_ioctl(ap) 272 struct vop_ioctl_args /* { 273 struct vnode *a_vp; 274 int a_command; 275 caddr_t a_data; 276 int a_fflag; 277 struct ucred *a_cred; 278 struct proc *a_p; 279 } */ *ap; 280 { 281 282 return (VOP_IOCTL(LOFSVP(ap->a_vp), ap->a_command, ap->a_data, ap->a_fflag, ap->a_cred, ap->a_p)); 283 } 284 285 int 286 lofs_select(ap) 287 struct vop_select_args /* { 288 struct vnode *a_vp; 289 int a_which; 290 int a_fflags; 291 struct ucred *a_cred; 292 struct proc *a_p; 293 } */ *ap; 294 { 295 296 return (VOP_SELECT(LOFSVP(ap->a_vp), ap->a_which, ap->a_fflags, ap->a_cred, ap->a_p)); 297 } 298 299 int 300 lofs_mmap(ap) 301 struct vop_mmap_args /* { 302 struct vnode *a_vp; 303 int a_fflags; 304 struct ucred *a_cred; 305 struct proc *a_p; 306 } */ *ap; 307 { 308 309 return (VOP_MMAP(LOFSVP(ap->a_vp), ap->a_fflags, ap->a_cred, ap->a_p)); 310 } 311 312 int 313 lofs_fsync(ap) 314 struct vop_fsync_args /* { 315 struct vnode *a_vp; 316 struct ucred *a_cred; 317 int a_waitfor; 318 struct proc *a_p; 319 } */ *ap; 320 { 321 struct vnode *targetvp = LOFSVP(ap->a_vp); 322 323 if (targetvp) 324 return (VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, ap->a_p)); 325 return (0); 326 } 327 328 int 329 lofs_seek(ap) 330 struct vop_seek_args /* { 331 struct vnode *a_vp; 332 off_t a_oldoff; 333 off_t a_newoff; 334 struct ucred *a_cred; 335 } */ *ap; 336 { 337 338 return (VOP_SEEK(LOFSVP(ap->a_vp), ap->a_oldoff, ap->a_newoff, ap->a_cred)); 339 } 340 341 int 342 lofs_remove(ap) 343 struct vop_remove_args /* { 344 struct vnode *a_dvp; 345 struct vnode *a_vp; 346 struct componentname *a_cnp; 347 } */ *ap; 348 { 349 int error; 350 351 PUSHREF(xdvp, ap->a_dvp); 352 VREF(ap->a_dvp); 353 PUSHREF(xvp, ap->a_vp); 354 VREF(ap->a_vp); 355 356 error = VOP_REMOVE(ap->a_dvp, ap->a_vp, ap->a_cnp); 357 358 POP(xvp, ap->a_vp); 359 vrele(ap->a_vp); 360 POP(xdvp, ap->a_dvp); 361 vrele(ap->a_dvp); 362 363 return (error); 364 } 365 366 /* 367 * vp is this. 368 * ni_dvp is the locked parent of the target. 369 * ni_vp is NULL. 370 */ 371 int 372 lofs_link(ap) 373 struct vop_link_args /* { 374 struct vnode *a_vp; 375 struct vnode *a_tdvp; 376 struct componentname *a_cnp; 377 } */ *ap; 378 { 379 int error; 380 381 PUSHREF(xdvp, ap->a_vp); 382 VREF(ap->a_vp); 383 384 error = VOP_LINK(ap->a_vp, LOFSVP(ap->a_tdvp), ap->a_cnp); 385 386 POP(xdvp, ap->a_vp); 387 vrele(ap->a_vp); 388 389 return (error); 390 } 391 392 int 393 lofs_rename(ap) 394 struct vop_rename_args /* { 395 struct vnode *a_fdvp; 396 struct vnode *a_fvp; 397 struct componentname *a_fcnp; 398 struct vnode *a_tdvp; 399 struct vnode *a_tvp; 400 struct componentname *a_tcnp; 401 } */ *ap; 402 { 403 struct vnode *fvp, *tvp; 404 struct vnode *tdvp; 405 #ifdef notdef 406 struct vnode *fsvp, *tsvp; 407 #endif 408 int error; 409 410 /* 411 * Switch source directory to point to lofsed vnode 412 */ 413 PUSHREF(fdvp, ap->a_fdvp); 414 VREF(ap->a_fdvp); 415 416 /* 417 * And source object if it is lofsed... 418 */ 419 fvp = ap->a_fvp; 420 if (fvp && fvp->v_op == lofs_vnodeop_p) { 421 ap->a_fvp = LOFSVP(fvp); 422 VREF(ap->a_fvp); 423 } else { 424 fvp = 0; 425 } 426 427 #ifdef notdef 428 /* 429 * And source startdir object if it is lofsed... 430 */ 431 fsvp = fndp->ni_startdir; 432 if (fsvp && fsvp->v_op == lofs_vnodeop_p) { 433 fndp->ni_startdir = LOFSVP(fsvp); 434 VREF(fndp->ni_startdir); 435 } else { 436 fsvp = 0; 437 } 438 #endif 439 440 /* 441 * Switch target directory to point to lofsed vnode 442 */ 443 tdvp = ap->a_tdvp; 444 if (tdvp && tdvp->v_op == lofs_vnodeop_p) { 445 ap->a_tdvp = LOFSVP(tdvp); 446 VREF(ap->a_tdvp); 447 } else { 448 tdvp = 0; 449 } 450 451 /* 452 * And target object if it is lofsed... 453 */ 454 tvp = ap->a_tvp; 455 if (tvp && tvp->v_op == lofs_vnodeop_p) { 456 ap->a_tvp = LOFSVP(tvp); 457 VREF(ap->a_tvp); 458 } else { 459 tvp = 0; 460 } 461 462 #ifdef notdef 463 /* 464 * And target startdir object if it is lofsed... 465 */ 466 tsvp = tndp->ni_startdir; 467 if (tsvp && tsvp->v_op == lofs_vnodeop_p) { 468 tndp->ni_startdir = LOFSVP(fsvp); 469 VREF(tndp->ni_startdir); 470 } else { 471 tsvp = 0; 472 } 473 #endif 474 475 error = VOP_RENAME(ap->a_fdvp, ap->a_fvp, ap->a_fcnp, ap->a_tdvp, ap->a_tvp, ap->a_tcnp); 476 477 /* 478 * Put everything back... 479 */ 480 481 #ifdef notdef 482 483 if (tsvp) { 484 if (tndp->ni_startdir) 485 vrele(tndp->ni_startdir); 486 tndp->ni_startdir = tsvp; 487 } 488 #endif 489 490 if (tvp) { 491 ap->a_tvp = tvp; 492 vrele(ap->a_tvp); 493 } 494 495 if (tdvp) { 496 ap->a_tdvp = tdvp; 497 vrele(ap->a_tdvp); 498 } 499 500 #ifdef notdef 501 502 if (fsvp) { 503 if (fndp->ni_startdir) 504 vrele(fndp->ni_startdir); 505 fndp->ni_startdir = fsvp; 506 } 507 #endif 508 509 if (fvp) { 510 ap->a_fvp = fvp; 511 vrele(ap->a_fvp); 512 } 513 514 POP(fdvp, ap->a_fdvp); 515 vrele(ap->a_fdvp); 516 517 return (error); 518 } 519 520 /* 521 * ni_dvp is the locked (alias) parent. 522 * ni_vp is NULL. 523 */ 524 int 525 lofs_mkdir(ap) 526 struct vop_mkdir_args /* { 527 struct vnode *a_dvp; 528 struct vnode **a_vpp; 529 struct componentname *a_cnp; 530 struct vattr *a_vap; 531 } */ *ap; 532 { 533 int error; 534 struct vnode *dvp = ap->a_dvp; 535 struct vnode *xdvp; 536 struct vnode *newvp; 537 538 xdvp = dvp; 539 dvp = LOFSVP(xdvp); 540 VREF(dvp); 541 542 error = VOP_MKDIR(dvp, &newvp, ap->a_cnp, ap->a_vap); 543 544 if (error) { 545 *ap->a_vpp = NULLVP; 546 vrele(xdvp); 547 return (error); 548 } 549 550 /* 551 * Make a new lofs node 552 */ 553 /*VREF(dvp);*/ 554 555 error = make_lofs(dvp->v_mount, &newvp); 556 557 *ap->a_vpp = newvp; 558 559 return (error); 560 } 561 562 /* 563 * ni_dvp is the locked parent. 564 * ni_vp is the entry to be removed. 565 */ 566 int 567 lofs_rmdir(ap) 568 struct vop_rmdir_args /* { 569 struct vnode *a_dvp; 570 struct vnode *a_vp; 571 struct componentname *a_cnp; 572 } */ *ap; 573 { 574 struct vnode *vp = ap->a_vp; 575 struct vnode *dvp = ap->a_dvp; 576 int error; 577 578 PUSHREF(xdvp, dvp); 579 VREF(dvp); 580 PUSHREF(xvp, vp); 581 VREF(vp); 582 583 error = VOP_RMDIR(dvp, vp, ap->a_cnp); 584 585 POP(xvp, vp); 586 vrele(vp); 587 POP(xdvp, dvp); 588 vrele(dvp); 589 590 return (error); 591 } 592 593 /* 594 * ni_dvp is the locked parent. 595 * ni_vp is NULL. 596 */ 597 int 598 lofs_symlink(ap) 599 struct vop_symlink_args /* { 600 struct vnode *a_dvp; 601 struct vnode **a_vpp; 602 struct componentname *a_cnp; 603 struct vattr *a_vap; 604 char *a_target; 605 } */ *ap; 606 { 607 int error; 608 609 PUSHREF(xdvp, ap->a_dvp); 610 VREF(ap->a_dvp); 611 612 error = VOP_SYMLINK(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap, ap->a_target); 613 614 POP(xdvp, ap->a_dvp); 615 vrele(ap->a_dvp); 616 617 return (error); 618 } 619 620 int 621 lofs_readdir(ap) 622 struct vop_readdir_args /* { 623 struct vnode *a_vp; 624 struct uio *a_uio; 625 struct ucred *a_cred; 626 } */ *ap; 627 { 628 629 return (VOP_READDIR(LOFSVP(ap->a_vp), ap->a_uio, ap->a_cred)); 630 } 631 632 int 633 lofs_readlink(ap) 634 struct vop_readlink_args /* { 635 struct vnode *a_vp; 636 struct uio *a_uio; 637 struct ucred *a_cred; 638 } */ *ap; 639 { 640 641 return (VOP_READLINK(LOFSVP(ap->a_vp), ap->a_uio, ap->a_cred)); 642 } 643 644 /* 645 * Anyone's guess... 646 */ 647 int 648 lofs_abortop(ap) 649 struct vop_abortop_args /* { 650 struct vnode *a_dvp; 651 struct componentname *a_cnp; 652 } */ *ap; 653 { 654 int error; 655 656 PUSHREF(xdvp, ap->a_dvp); 657 658 error = VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 659 660 POP(xdvp, ap->a_dvp); 661 662 return (error); 663 } 664 665 int 666 lofs_inactive(ap) 667 struct vop_inactive_args /* { 668 struct vnode *a_vp; 669 } */ *ap; 670 { 671 struct vnode *targetvp = LOFSVP(ap->a_vp); 672 673 #ifdef DIAGNOSTIC 674 { extern int prtactive; 675 if (prtactive && ap->a_vp->v_usecount != 0) 676 vprint("lofs_inactive: pushing active", ap->a_vp); 677 } 678 #endif 679 680 if (targetvp) { 681 vrele(targetvp); 682 LOFSP(ap->a_vp)->a_lofsvp = 0; 683 } 684 } 685 686 int 687 lofs_reclaim(ap) 688 struct vop_reclaim_args /* { 689 struct vnode *a_vp; 690 } */ *ap; 691 { 692 struct vnode *targetvp; 693 694 remque(LOFSP(ap->a_vp)); 695 targetvp = LOFSVP(ap->a_vp); 696 if (targetvp) { 697 printf("lofs: delayed vrele of %x\n", targetvp); 698 vrele(targetvp); /* XXX should never happen */ 699 } 700 FREE(ap->a_vp->v_data, M_TEMP); 701 ap->a_vp->v_data = 0; 702 return (0); 703 } 704 705 int 706 lofs_lock(ap) 707 struct vop_lock_args /* { 708 struct vnode *a_vp; 709 } */ *ap; 710 { 711 int error; 712 register struct vnode *vp = ap->a_vp; 713 struct vnode *targetvp; 714 715 while (vp->v_flag & VXLOCK) { 716 vp->v_flag |= VXWANT; 717 sleep((caddr_t)vp, PINOD); 718 } 719 if (vp->v_tag == VT_NON) 720 return (ENOENT); 721 targetvp = LOFSVP(ap->a_vp); 722 723 if (targetvp && (error = VOP_LOCK(targetvp))) 724 return (error); 725 return (0); 726 } 727 728 int 729 lofs_unlock(ap) 730 struct vop_unlock_args /* { 731 struct vnode *a_vp; 732 } */ *ap; 733 { 734 struct vnode *targetvp = LOFSVP(ap->a_vp); 735 736 if (targetvp) 737 return (VOP_UNLOCK(targetvp)); 738 return (0); 739 } 740 741 int 742 lofs_bmap(ap) 743 struct vop_bmap_args /* { 744 struct vnode *a_vp; 745 daddr_t a_bn; 746 struct vnode **a_vpp; 747 daddr_t *a_bnp; 748 int *a_runp; 749 } */ *ap; 750 { 751 752 return (VOP_BMAP(LOFSVP(ap->a_vp), ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp)); 753 } 754 755 int 756 lofs_strategy(ap) 757 struct vop_strategy_args /* { 758 struct buf *a_bp; 759 } */ *ap; 760 { 761 int error; 762 763 PUSHREF(vp, ap->a_bp->b_vp); 764 765 error = VOP_STRATEGY(ap->a_bp); 766 767 POP(vp, ap->a_bp->b_vp); 768 769 return (error); 770 } 771 772 int 773 lofs_print(ap) 774 struct vop_print_args /* { 775 struct vnode *a_vp; 776 } */ *ap; 777 { 778 779 struct vnode *targetvp = LOFSVP(ap->a_vp); 780 printf("tag VT_LOFS ref "); 781 if (targetvp) 782 return (VOP_PRINT(targetvp)); 783 printf("NULLVP\n"); 784 return (0); 785 } 786 787 int 788 lofs_islocked(ap) 789 struct vop_islocked_args /* { 790 struct vnode *a_vp; 791 } */ *ap; 792 { 793 794 struct vnode *targetvp = LOFSVP(ap->a_vp); 795 if (targetvp) 796 return (VOP_ISLOCKED(targetvp)); 797 return (0); 798 } 799 800 int 801 lofs_pathconf(ap) 802 struct vop_pathconf_args *ap; 803 { 804 805 return (VOP_PATHCONF(LOFSVP(ap->a_vp), ap->a_name, ap->a_retval)); 806 } 807 808 int 809 lofs_advlock(ap) 810 struct vop_advlock_args /* { 811 struct vnode *a_vp; 812 caddr_t a_id; 813 int a_op; 814 struct flock *a_fl; 815 int a_flags; 816 } */ *ap; 817 { 818 819 return (VOP_ADVLOCK(LOFSVP(ap->a_vp), ap->a_id, ap->a_op, ap->a_fl, ap->a_flags)); 820 } 821 822 /* 823 * LOFS directory offset lookup. 824 * Currently unsupported. 825 */ 826 int 827 lofs_blkatoff(ap) 828 struct vop_blkatoff_args /* { 829 struct vnode *a_vp; 830 off_t a_offset; 831 char **a_res; 832 struct buf **a_bpp; 833 } */ *ap; 834 { 835 836 return (EOPNOTSUPP); 837 } 838 839 /* 840 * LOFS flat namespace allocation. 841 * Currently unsupported. 842 */ 843 int 844 lofs_valloc(ap) 845 struct vop_valloc_args /* { 846 struct vnode *a_pvp; 847 int a_mode; 848 struct ucred *a_cred; 849 struct vnode **a_vpp; 850 } */ *ap; 851 { 852 853 return (EOPNOTSUPP); 854 } 855 856 /* 857 * LOFS flat namespace free. 858 * Currently unsupported. 859 */ 860 /*void*/ 861 int 862 lofs_vfree(ap) 863 struct vop_vfree_args /* { 864 struct vnode *a_pvp; 865 ino_t a_ino; 866 int a_mode; 867 } */ *ap; 868 { 869 870 return (0); 871 } 872 873 /* 874 * LOFS file truncation. 875 */ 876 int 877 lofs_truncate(ap) 878 struct vop_truncate_args /* { 879 struct vnode *a_vp; 880 off_t a_length; 881 int a_flags; 882 struct ucred *a_cred; 883 struct proc *a_p; 884 } */ *ap; 885 { 886 887 /* Use lofs_setattr */ 888 printf("lofs_truncate: need to implement!!"); 889 return (EOPNOTSUPP); 890 } 891 892 /* 893 * LOFS update. 894 */ 895 int 896 lofs_update(ap) 897 struct vop_update_args /* { 898 struct vnode *a_vp; 899 struct timeval *a_ta; 900 struct timeval *a_tm; 901 int a_waitfor; 902 } */ *ap; 903 { 904 905 /* Use lofs_setattr */ 906 printf("lofs_update: need to implement!!"); 907 return (EOPNOTSUPP); 908 } 909 910 /* 911 * LOFS bwrite 912 */ 913 int 914 lofs_bwrite(ap) 915 struct vop_bwrite_args /* { 916 struct buf *a_bp; 917 } */ *ap; 918 { 919 920 return (EOPNOTSUPP); 921 } 922 923 /* 924 * Global vfs data structures for ufs 925 */ 926 int (**lofs_vnodeop_p)(); 927 struct vnodeopv_entry_desc lofs_vnodeop_entries[] = { 928 { &vop_default_desc, vn_default_error }, 929 { &vop_lookup_desc, lofs_lookup }, /* lookup */ 930 { &vop_create_desc, lofs_create }, /* create */ 931 { &vop_mknod_desc, lofs_mknod }, /* mknod */ 932 { &vop_open_desc, lofs_open }, /* open */ 933 { &vop_close_desc, lofs_close }, /* close */ 934 { &vop_access_desc, lofs_access }, /* access */ 935 { &vop_getattr_desc, lofs_getattr }, /* getattr */ 936 { &vop_setattr_desc, lofs_setattr }, /* setattr */ 937 { &vop_read_desc, lofs_read }, /* read */ 938 { &vop_write_desc, lofs_write }, /* write */ 939 { &vop_ioctl_desc, lofs_ioctl }, /* ioctl */ 940 { &vop_select_desc, lofs_select }, /* select */ 941 { &vop_mmap_desc, lofs_mmap }, /* mmap */ 942 { &vop_fsync_desc, lofs_fsync }, /* fsync */ 943 { &vop_seek_desc, lofs_seek }, /* seek */ 944 { &vop_remove_desc, lofs_remove }, /* remove */ 945 { &vop_link_desc, lofs_link }, /* link */ 946 { &vop_rename_desc, lofs_rename }, /* rename */ 947 { &vop_mkdir_desc, lofs_mkdir }, /* mkdir */ 948 { &vop_rmdir_desc, lofs_rmdir }, /* rmdir */ 949 { &vop_symlink_desc, lofs_symlink }, /* symlink */ 950 { &vop_readdir_desc, lofs_readdir }, /* readdir */ 951 { &vop_readlink_desc, lofs_readlink }, /* readlink */ 952 { &vop_abortop_desc, lofs_abortop }, /* abortop */ 953 { &vop_inactive_desc, lofs_inactive }, /* inactive */ 954 { &vop_reclaim_desc, lofs_reclaim }, /* reclaim */ 955 { &vop_lock_desc, lofs_lock }, /* lock */ 956 { &vop_unlock_desc, lofs_unlock }, /* unlock */ 957 { &vop_bmap_desc, lofs_bmap }, /* bmap */ 958 { &vop_strategy_desc, lofs_strategy }, /* strategy */ 959 { &vop_print_desc, lofs_print }, /* print */ 960 { &vop_islocked_desc, lofs_islocked }, /* islocked */ 961 { &vop_pathconf_desc, lofs_pathconf }, /* pathconf */ 962 { &vop_advlock_desc, lofs_advlock }, /* advlock */ 963 { &vop_blkatoff_desc, lofs_blkatoff }, /* blkatoff */ 964 { &vop_valloc_desc, lofs_valloc }, /* valloc */ 965 { &vop_vfree_desc, lofs_vfree }, /* vfree */ 966 { &vop_truncate_desc, lofs_truncate }, /* truncate */ 967 { &vop_update_desc, lofs_update }, /* update */ 968 { &vop_bwrite_desc, lofs_bwrite }, /* bwrite */ 969 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 970 }; 971 struct vnodeopv_desc lofs_vnodeop_opv_desc = 972 { &lofs_vnodeop_p, lofs_vnodeop_entries }; 973