1 /* 2 * Copyright (c) 1992 The Regents of the University of California 3 * Copyright (c) 1990, 1992 Jan-Simon Pendry 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 7.4 (Berkeley) 11/14/92 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 382 #ifdef LOFS_DIAGNOSTIC 383 printf("lofs_fsync(ap->a_vp = %x->%x)\n", ap->a_vp, LOFSVP(ap->a_vp)); 384 #endif 385 386 return VOP_FSYNC(LOFSVP(ap->a_vp), ap->a_cred, ap->a_waitfor, ap->a_p); 387 } 388 389 lofs_seek(ap) 390 struct vop_seek_args /* { 391 struct vnode *a_vp; 392 off_t a_oldoff; 393 off_t a_newoff; 394 struct ucred *a_cred; 395 } */ *ap; 396 { 397 398 #ifdef LOFS_DIAGNOSTIC 399 printf("lofs_seek(ap->a_vp = %x->%x)\n", ap->a_vp, LOFSVP(ap->a_vp)); 400 #endif 401 402 return VOP_SEEK(LOFSVP(ap->a_vp), ap->a_oldoff, ap->a_newoff, ap->a_cred); 403 } 404 405 lofs_remove(ap) 406 struct vop_remove_args /* { 407 struct vnode *a_dvp; 408 struct vnode *a_vp; 409 struct componentname *a_cnp; 410 } */ *ap; 411 { 412 int error; 413 414 #ifdef LOFS_DIAGNOSTIC 415 printf("lofs_remove(ap->a_vp = %x->%x)\n", ap->a_dvp, LOFSVP(ap->a_dvp)); 416 #endif 417 418 PUSHREF(xdvp, ap->a_dvp); 419 VREF(ap->a_dvp); 420 PUSHREF(xvp, ap->a_vp); 421 VREF(ap->a_vp); 422 423 error = VOP_REMOVE(ap->a_dvp, ap->a_vp, ap->a_cnp); 424 425 POP(xvp, ap->a_vp); 426 vrele(ap->a_vp); 427 POP(xdvp, ap->a_dvp); 428 vrele(ap->a_dvp); 429 430 return (error); 431 } 432 433 /* 434 * vp is this. 435 * ni_dvp is the locked parent of the target. 436 * ni_vp is NULL. 437 */ 438 lofs_link(ap) 439 struct vop_link_args /* { 440 struct vnode *a_vp; 441 struct vnode *a_tdvp; 442 struct componentname *a_cnp; 443 } */ *ap; 444 { 445 int error; 446 447 #ifdef LOFS_DIAGNOSTIC 448 printf("lofs_link(ap->a_tdvp = %x->%x)\n", ap->a_vp, LOFSVP(ap->a_vp)); 449 #endif 450 451 PUSHREF(xdvp, ap->a_vp); 452 VREF(ap->a_vp); 453 454 error = VOP_LINK(ap->a_vp, LOFSVP(ap->a_tdvp), ap->a_cnp); 455 456 POP(xdvp, ap->a_vp); 457 vrele(ap->a_vp); 458 459 return (error); 460 } 461 462 lofs_rename(ap) 463 struct vop_rename_args /* { 464 struct vnode *a_fdvp; 465 struct vnode *a_fvp; 466 struct componentname *a_fcnp; 467 struct vnode *a_tdvp; 468 struct vnode *a_tvp; 469 struct componentname *a_tcnp; 470 } */ *ap; 471 { 472 struct vnode *fvp, *tvp; 473 struct vnode *tdvp; 474 #ifdef notdef 475 struct vnode *fsvp, *tsvp; 476 #endif 477 int error; 478 479 #ifdef LOFS_DIAGNOSTIC 480 printf("lofs_rename(fdvp = %x->%x)\n", ap->a_fdvp, LOFSVP(ap->a_fdvp)); 481 /*printf("lofs_rename(tdvp = %x->%x)\n", tndp->ni_dvp, LOFSVP(tndp->ni_dvp));*/ 482 #endif 483 484 #ifdef LOFS_DIAGNOSTIC 485 printf("lofs_rename - switch source dvp\n"); 486 #endif 487 /* 488 * Switch source directory to point to lofsed vnode 489 */ 490 PUSHREF(fdvp, ap->a_fdvp); 491 VREF(ap->a_fdvp); 492 493 #ifdef LOFS_DIAGNOSTIC 494 printf("lofs_rename - switch source vp\n"); 495 #endif 496 /* 497 * And source object if it is lofsed... 498 */ 499 fvp = ap->a_fvp; 500 if (fvp && fvp->v_op == lofs_vnodeop_p) { 501 ap->a_fvp = LOFSVP(fvp); 502 VREF(ap->a_fvp); 503 } else { 504 fvp = 0; 505 } 506 507 #ifdef notdef 508 #ifdef LOFS_DIAGNOSTIC 509 printf("lofs_rename - switch source start vp\n"); 510 #endif 511 /* 512 * And source startdir object if it is lofsed... 513 */ 514 fsvp = fndp->ni_startdir; 515 if (fsvp && fsvp->v_op == lofs_vnodeop_p) { 516 fndp->ni_startdir = LOFSVP(fsvp); 517 VREF(fndp->ni_startdir); 518 } else { 519 fsvp = 0; 520 } 521 #endif 522 523 #ifdef LOFS_DIAGNOSTIC 524 printf("lofs_rename - switch target dvp\n"); 525 #endif 526 /* 527 * Switch target directory to point to lofsed vnode 528 */ 529 tdvp = ap->a_tdvp; 530 if (tdvp && tdvp->v_op == lofs_vnodeop_p) { 531 ap->a_tdvp = LOFSVP(tdvp); 532 VREF(ap->a_tdvp); 533 } else { 534 tdvp = 0; 535 } 536 537 #ifdef LOFS_DIAGNOSTIC 538 printf("lofs_rename - switch target vp\n"); 539 #endif 540 /* 541 * And target object if it is lofsed... 542 */ 543 tvp = ap->a_tvp; 544 if (tvp && tvp->v_op == lofs_vnodeop_p) { 545 ap->a_tvp = LOFSVP(tvp); 546 VREF(ap->a_tvp); 547 } else { 548 tvp = 0; 549 } 550 551 #ifdef notdef 552 #ifdef LOFS_DIAGNOSTIC 553 printf("lofs_rename - switch target start vp\n"); 554 #endif 555 /* 556 * And target startdir object if it is lofsed... 557 */ 558 tsvp = tndp->ni_startdir; 559 if (tsvp && tsvp->v_op == lofs_vnodeop_p) { 560 tndp->ni_startdir = LOFSVP(fsvp); 561 VREF(tndp->ni_startdir); 562 } else { 563 tsvp = 0; 564 } 565 #endif 566 567 #ifdef LOFS_DIAGNOSTIC 568 printf("lofs_rename - VOP_RENAME(%x, %x, %x, %x)\n", 569 ap->a_fdvp, ap->a_fvp, ap->a_tdvp, ap->a_tvp); 570 vprint("ap->a_fdvp", ap->a_fdvp); 571 vprint("ap->a_fvp", ap->a_fvp); 572 vprint("ap->a_tdvp", ap->a_tdvp); 573 if (ap->a_tvp) vprint("ap->a_tvp", ap->a_tvp); 574 DELAY(16000000); 575 #endif 576 577 error = VOP_RENAME(ap->a_fdvp, ap->a_fvp, ap->a_fcnp, ap->a_tdvp, ap->a_tvp, ap->a_tcnp); 578 579 /* 580 * Put everything back... 581 */ 582 583 #ifdef notdef 584 #ifdef LOFS_DIAGNOSTIC 585 printf("lofs_rename - restore target startdir\n"); 586 #endif 587 588 if (tsvp) { 589 if (tndp->ni_startdir) 590 vrele(tndp->ni_startdir); 591 tndp->ni_startdir = tsvp; 592 } 593 #endif 594 595 #ifdef LOFS_DIAGNOSTIC 596 printf("lofs_rename - restore target vp\n"); 597 #endif 598 599 if (tvp) { 600 ap->a_tvp = tvp; 601 vrele(ap->a_tvp); 602 } 603 604 #ifdef LOFS_DIAGNOSTIC 605 printf("lofs_rename - restore target dvp\n"); 606 #endif 607 608 if (tdvp) { 609 ap->a_tdvp = tdvp; 610 vrele(ap->a_tdvp); 611 } 612 613 #ifdef notdef 614 #ifdef LOFS_DIAGNOSTIC 615 printf("lofs_rename - restore source startdir\n"); 616 #endif 617 618 if (fsvp) { 619 if (fndp->ni_startdir) 620 vrele(fndp->ni_startdir); 621 fndp->ni_startdir = fsvp; 622 } 623 #endif 624 625 #ifdef LOFS_DIAGNOSTIC 626 printf("lofs_rename - restore source vp\n"); 627 #endif 628 629 630 if (fvp) { 631 ap->a_fvp = fvp; 632 vrele(ap->a_fvp); 633 } 634 635 #ifdef LOFS_DIAGNOSTIC 636 printf("lofs_rename - restore source dvp\n"); 637 #endif 638 639 POP(fdvp, ap->a_fdvp); 640 vrele(ap->a_fdvp); 641 642 return (error); 643 } 644 645 /* 646 * ni_dvp is the locked (alias) parent. 647 * ni_vp is NULL. 648 */ 649 lofs_mkdir(ap) 650 struct vop_mkdir_args /* { 651 struct vnode *a_dvp; 652 struct vnode **a_vpp; 653 struct componentname *a_cnp; 654 struct vattr *a_vap; 655 } */ *ap; 656 { 657 int error; 658 struct vnode *dvp = ap->a_dvp; 659 struct vnode *xdvp; 660 struct vnode *newvp; 661 662 #ifdef LOFS_DIAGNOSTIC 663 printf("lofs_mkdir(vp = %x->%x)\n", dvp, LOFSVP(dvp)); 664 #endif 665 666 xdvp = dvp; 667 dvp = LOFSVP(xdvp); 668 VREF(dvp); 669 670 error = VOP_MKDIR(dvp, &newvp, ap->a_cnp, ap->a_vap); 671 672 if (error) { 673 *ap->a_vpp = NULLVP; 674 vrele(xdvp); 675 return (error); 676 } 677 678 /* 679 * Make a new lofs node 680 */ 681 /*VREF(dvp);*/ 682 683 error = make_lofs(dvp->v_mount, &newvp); 684 685 *ap->a_vpp = newvp; 686 687 return (error); 688 } 689 690 /* 691 * ni_dvp is the locked parent. 692 * ni_vp is the entry to be removed. 693 */ 694 lofs_rmdir(ap) 695 struct vop_rmdir_args /* { 696 struct vnode *a_dvp; 697 struct vnode *a_vp; 698 struct componentname *a_cnp; 699 } */ *ap; 700 { 701 struct vnode *vp = ap->a_vp; 702 struct vnode *dvp = ap->a_dvp; 703 int error; 704 705 #ifdef LOFS_DIAGNOSTIC 706 printf("lofs_rmdir(dvp = %x->%x)\n", dvp, LOFSVP(dvp)); 707 #endif 708 709 PUSHREF(xdvp, dvp); 710 VREF(dvp); 711 PUSHREF(xvp, vp); 712 VREF(vp); 713 714 error = VOP_RMDIR(dvp, vp, ap->a_cnp); 715 716 POP(xvp, vp); 717 vrele(vp); 718 POP(xdvp, dvp); 719 vrele(dvp); 720 721 return (error); 722 } 723 724 /* 725 * ni_dvp is the locked parent. 726 * ni_vp is NULL. 727 */ 728 lofs_symlink(ap) 729 struct vop_symlink_args /* { 730 struct vnode *a_dvp; 731 struct vnode **a_vpp; 732 struct componentname *a_cnp; 733 struct vattr *a_vap; 734 char *a_target; 735 } */ *ap; 736 { 737 int error; 738 739 #ifdef LOFS_DIAGNOSTIC 740 printf("VOP_SYMLINK(vp = %x->%x)\n", ap->a_dvp, LOFSVP(ap->a_dvp)); 741 #endif 742 743 PUSHREF(xdvp, ap->a_dvp); 744 VREF(ap->a_dvp); 745 746 error = VOP_SYMLINK(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap, ap->a_target); 747 748 POP(xdvp, ap->a_dvp); 749 vrele(ap->a_dvp); 750 751 return (error); 752 } 753 754 lofs_readdir(ap) 755 struct vop_readdir_args /* { 756 struct vnode *a_vp; 757 struct uio *a_uio; 758 struct ucred *a_cred; 759 } */ *ap; 760 { 761 762 #ifdef LOFS_DIAGNOSTIC 763 printf("lofs_readdir(ap->a_vp = %x->%x)\n", ap->a_vp, LOFSVP(ap->a_vp)); 764 #endif 765 766 return VOP_READDIR(LOFSVP(ap->a_vp), ap->a_uio, ap->a_cred); 767 } 768 769 lofs_readlink(ap) 770 struct vop_readlink_args /* { 771 struct vnode *a_vp; 772 struct uio *a_uio; 773 struct ucred *a_cred; 774 } */ *ap; 775 { 776 777 #ifdef LOFS_DIAGNOSTIC 778 printf("lofs_readlink(ap->a_vp = %x->%x)\n", ap->a_vp, LOFSVP(ap->a_vp)); 779 #endif 780 781 return VOP_READLINK(LOFSVP(ap->a_vp), ap->a_uio, ap->a_cred); 782 } 783 784 /* 785 * Anyone's guess... 786 */ 787 lofs_abortop(ap) 788 struct vop_abortop_args /* { 789 struct vnode *a_dvp; 790 struct componentname *a_cnp; 791 } */ *ap; 792 { 793 int error; 794 795 PUSHREF(xdvp, ap->a_dvp); 796 797 error = VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 798 799 POP(xdvp, ap->a_dvp); 800 801 return (error); 802 } 803 804 lofs_inactive(ap) 805 struct vop_inactive_args /* { 806 struct vnode *a_vp; 807 } */ *ap; 808 { 809 struct vnode *targetvp = LOFSVP(ap->a_vp); 810 811 #ifdef LOFS_DIAGNOSTIC 812 printf("lofs_inactive(ap->a_vp = %x->%x)\n", ap->a_vp, targetvp); 813 #endif 814 815 #ifdef DIAGNOSTIC 816 { extern int prtactive; 817 if (prtactive && ap->a_vp->v_usecount != 0) 818 vprint("lofs_inactive: pushing active", ap->a_vp); 819 } 820 #endif 821 822 if (targetvp) { 823 vrele(targetvp); 824 LOFSP(ap->a_vp)->a_lofsvp = 0; 825 } 826 } 827 828 lofs_reclaim(ap) 829 struct vop_reclaim_args /* { 830 struct vnode *a_vp; 831 } */ *ap; 832 { 833 struct vnode *targetvp; 834 835 #ifdef LOFS_DIAGNOSTIC 836 printf("lofs_reclaim(ap->a_vp = %x->%x)\n", ap->a_vp, LOFSVP(ap->a_vp)); 837 #endif 838 remque(LOFSP(ap->a_vp)); 839 targetvp = LOFSVP(ap->a_vp); 840 if (targetvp) { 841 printf("lofs: delayed vrele of %x\n", targetvp); 842 vrele(targetvp); /* XXX should never happen */ 843 } 844 FREE(ap->a_vp->v_data, M_TEMP); 845 ap->a_vp->v_data = 0; 846 return (0); 847 } 848 849 lofs_lock(ap) 850 struct vop_lock_args /* { 851 struct vnode *a_vp; 852 } */ *ap; 853 { 854 int error; 855 register struct vnode *vp = ap->a_vp; 856 struct vnode *targetvp; 857 858 while (vp->v_flag & VXLOCK) { 859 vp->v_flag |= VXWANT; 860 sleep((caddr_t)vp, PINOD); 861 } 862 if (vp->v_tag == VT_NON) 863 return (ENOENT); 864 targetvp = LOFSVP(ap->a_vp); 865 866 #ifdef LOFS_DIAGNOSTIC 867 printf("lofs_lock(ap->a_vp = %x->%x)\n", ap->a_vp, targetvp); 868 /*vprint("lofs_lock ap->a_vp", ap->a_vp); 869 if (targetvp) 870 vprint("lofs_lock ->ap->a_vp", targetvp); 871 else 872 printf("lofs_lock ->ap->a_vp = NIL\n");*/ 873 #endif 874 875 if (targetvp && (error = VOP_LOCK(targetvp))) 876 return (error); 877 return (0); 878 } 879 880 lofs_unlock(ap) 881 struct vop_unlock_args /* { 882 struct vnode *a_vp; 883 } */ *ap; 884 { 885 struct vnode *targetvp = LOFSVP(ap->a_vp); 886 887 #ifdef LOFS_DIAGNOSTIC 888 printf("lofs_unlock(ap->a_vp = %x->%x)\n", ap->a_vp, targetvp); 889 #endif 890 891 if (targetvp) 892 return (VOP_UNLOCK(targetvp)); 893 return (0); 894 } 895 896 lofs_bmap(ap) 897 struct vop_bmap_args /* { 898 struct vnode *a_vp; 899 daddr_t a_bn; 900 struct vnode **a_vpp; 901 daddr_t *a_bnp; 902 int *a_runp; 903 } */ *ap; 904 { 905 906 #ifdef LOFS_DIAGNOSTIC 907 printf("lofs_bmap(ap->a_vp = %x->%x)\n", ap->a_vp, LOFSVP(ap->a_vp)); 908 #endif 909 910 return VOP_BMAP(LOFSVP(ap->a_vp), ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp); 911 } 912 913 lofs_strategy(ap) 914 struct vop_strategy_args /* { 915 struct buf *a_bp; 916 } */ *ap; 917 { 918 int error; 919 920 #ifdef LOFS_DIAGNOSTIC 921 printf("lofs_strategy(vp = %x->%x)\n", ap->a_bp->b_vp, LOFSVP(ap->a_bp->b_vp)); 922 #endif 923 924 PUSHREF(vp, ap->a_bp->b_vp); 925 926 error = VOP_STRATEGY(ap->a_bp); 927 928 POP(vp, ap->a_bp->b_vp); 929 930 return (error); 931 } 932 933 lofs_print(ap) 934 struct vop_print_args /* { 935 struct vnode *a_vp; 936 } */ *ap; 937 { 938 939 struct vnode *targetvp = LOFSVP(ap->a_vp); 940 printf("tag VT_LOFS ref "); 941 if (targetvp) 942 return (VOP_PRINT(targetvp)); 943 printf("NULLVP\n"); 944 return (0); 945 } 946 947 lofs_islocked(ap) 948 struct vop_islocked_args /* { 949 struct vnode *a_vp; 950 } */ *ap; 951 { 952 953 struct vnode *targetvp = LOFSVP(ap->a_vp); 954 if (targetvp) 955 return (VOP_ISLOCKED(targetvp)); 956 return (0); 957 } 958 959 lofs_advlock(ap) 960 struct vop_advlock_args /* { 961 struct vnode *a_vp; 962 caddr_t a_id; 963 int a_op; 964 struct flock *a_fl; 965 int a_flags; 966 } */ *ap; 967 { 968 969 return VOP_ADVLOCK(LOFSVP(ap->a_vp), ap->a_id, ap->a_op, ap->a_fl, ap->a_flags); 970 } 971 972 /* 973 * LOFS directory offset lookup. 974 * Currently unsupported. 975 */ 976 lofs_blkatoff(ap) 977 struct vop_blkatoff_args /* { 978 struct vnode *a_vp; 979 off_t a_offset; 980 char **a_res; 981 struct buf **a_bpp; 982 } */ *ap; 983 { 984 985 return (EOPNOTSUPP); 986 } 987 988 /* 989 * LOFS flat namespace allocation. 990 * Currently unsupported. 991 */ 992 lofs_valloc(ap) 993 struct vop_valloc_args /* { 994 struct vnode *a_pvp; 995 int a_mode; 996 struct ucred *a_cred; 997 struct vnode **a_vpp; 998 } */ *ap; 999 { 1000 1001 return (EOPNOTSUPP); 1002 } 1003 1004 /* 1005 * LOFS flat namespace free. 1006 * Currently unsupported. 1007 */ 1008 /*void*/ 1009 lofs_vfree(ap) 1010 struct vop_vfree_args /* { 1011 struct vnode *a_pvp; 1012 ino_t a_ino; 1013 int a_mode; 1014 } */ *ap; 1015 { 1016 1017 return (0); 1018 } 1019 1020 /* 1021 * LOFS file truncation. 1022 */ 1023 lofs_truncate(ap) 1024 struct vop_truncate_args /* { 1025 struct vnode *a_vp; 1026 off_t a_length; 1027 int a_flags; 1028 struct ucred *a_cred; 1029 struct proc *a_p; 1030 } */ *ap; 1031 { 1032 1033 /* Use lofs_setattr */ 1034 printf("lofs_truncate: need to implement!!"); 1035 return (EOPNOTSUPP); 1036 } 1037 1038 /* 1039 * LOFS update. 1040 */ 1041 lofs_update(ap) 1042 struct vop_update_args /* { 1043 struct vnode *a_vp; 1044 struct timeval *a_ta; 1045 struct timeval *a_tm; 1046 int a_waitfor; 1047 } */ *ap; 1048 { 1049 1050 /* Use lofs_setattr */ 1051 printf("lofs_update: need to implement!!"); 1052 return (EOPNOTSUPP); 1053 } 1054 1055 /* 1056 * LOFS bwrite 1057 */ 1058 lofs_bwrite(ap) 1059 struct vop_bwrite_args /* { 1060 struct buf *a_bp; 1061 } */ *ap; 1062 { 1063 1064 return (EOPNOTSUPP); 1065 } 1066 1067 /* 1068 * Global vfs data structures for ufs 1069 */ 1070 int (**lofs_vnodeop_p)(); 1071 struct vnodeopv_entry_desc lofs_vnodeop_entries[] = { 1072 { &vop_default_desc, vn_default_error }, 1073 { &vop_lookup_desc, lofs_lookup }, /* lookup */ 1074 { &vop_create_desc, lofs_create }, /* create */ 1075 { &vop_mknod_desc, lofs_mknod }, /* mknod */ 1076 { &vop_open_desc, lofs_open }, /* open */ 1077 { &vop_close_desc, lofs_close }, /* close */ 1078 { &vop_access_desc, lofs_access }, /* access */ 1079 { &vop_getattr_desc, lofs_getattr }, /* getattr */ 1080 { &vop_setattr_desc, lofs_setattr }, /* setattr */ 1081 { &vop_read_desc, lofs_read }, /* read */ 1082 { &vop_write_desc, lofs_write }, /* write */ 1083 { &vop_ioctl_desc, lofs_ioctl }, /* ioctl */ 1084 { &vop_select_desc, lofs_select }, /* select */ 1085 { &vop_mmap_desc, lofs_mmap }, /* mmap */ 1086 { &vop_fsync_desc, lofs_fsync }, /* fsync */ 1087 { &vop_seek_desc, lofs_seek }, /* seek */ 1088 { &vop_remove_desc, lofs_remove }, /* remove */ 1089 { &vop_link_desc, lofs_link }, /* link */ 1090 { &vop_rename_desc, lofs_rename }, /* rename */ 1091 { &vop_mkdir_desc, lofs_mkdir }, /* mkdir */ 1092 { &vop_rmdir_desc, lofs_rmdir }, /* rmdir */ 1093 { &vop_symlink_desc, lofs_symlink }, /* symlink */ 1094 { &vop_readdir_desc, lofs_readdir }, /* readdir */ 1095 { &vop_readlink_desc, lofs_readlink }, /* readlink */ 1096 { &vop_abortop_desc, lofs_abortop }, /* abortop */ 1097 { &vop_inactive_desc, lofs_inactive }, /* inactive */ 1098 { &vop_reclaim_desc, lofs_reclaim }, /* reclaim */ 1099 { &vop_lock_desc, lofs_lock }, /* lock */ 1100 { &vop_unlock_desc, lofs_unlock }, /* unlock */ 1101 { &vop_bmap_desc, lofs_bmap }, /* bmap */ 1102 { &vop_strategy_desc, lofs_strategy }, /* strategy */ 1103 { &vop_print_desc, lofs_print }, /* print */ 1104 { &vop_islocked_desc, lofs_islocked }, /* islocked */ 1105 { &vop_advlock_desc, lofs_advlock }, /* advlock */ 1106 { &vop_blkatoff_desc, lofs_blkatoff }, /* blkatoff */ 1107 { &vop_valloc_desc, lofs_valloc }, /* valloc */ 1108 { &vop_vfree_desc, lofs_vfree }, /* vfree */ 1109 { &vop_truncate_desc, lofs_truncate }, /* truncate */ 1110 { &vop_update_desc, lofs_update }, /* update */ 1111 { &vop_bwrite_desc, lofs_bwrite }, /* bwrite */ 1112 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1113 }; 1114 struct vnodeopv_desc lofs_vnodeop_opv_desc = 1115 { &lofs_vnodeop_p, lofs_vnodeop_entries }; 1116