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