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
lofs_lookup(ap)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
lofs_mknod(ap)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
lofs_create(ap)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
lofs_open(ap)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
lofs_close(ap)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
lofs_access(ap)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
lofs_getattr(ap)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
lofs_setattr(ap)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
lofs_read(ap)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
lofs_write(ap)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
lofs_ioctl(ap)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
lofs_select(ap)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
lofs_mmap(ap)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
lofs_fsync(ap)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
lofs_seek(ap)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
lofs_remove(ap)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
lofs_link(ap)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
lofs_rename(ap)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
lofs_mkdir(ap)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
lofs_rmdir(ap)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
lofs_symlink(ap)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
lofs_readdir(ap)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
lofs_readlink(ap)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
lofs_abortop(ap)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
lofs_inactive(ap)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
lofs_reclaim(ap)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
lofs_lock(ap)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
lofs_unlock(ap)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
lofs_bmap(ap)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
lofs_strategy(ap)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
lofs_print(ap)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
lofs_islocked(ap)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
lofs_pathconf(ap)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
lofs_advlock(ap)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
lofs_blkatoff(ap)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
lofs_valloc(ap)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
lofs_vfree(ap)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
lofs_truncate(ap)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
lofs_update(ap)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
lofs_bwrite(ap)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