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