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