xref: /titanic_44/usr/src/uts/common/fs/lofs/lofs_vnops.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/errno.h>
32 #include <sys/vnode.h>
33 #include <sys/vfs.h>
34 #include <sys/uio.h>
35 #include <sys/cred.h>
36 #include <sys/pathname.h>
37 #include <sys/debug.h>
38 #include <sys/fs/lofs_node.h>
39 #include <sys/fs/lofs_info.h>
40 #include <fs/fs_subr.h>
41 #include <vm/as.h>
42 #include <vm/seg.h>
43 
44 #define	IS_ZONEDEVFS(vp) \
45 	(vtoli((vp)->v_vfsp)->li_flag & LO_ZONEDEVFS)
46 
47 /*
48  * These are the vnode ops routines which implement the vnode interface to
49  * the looped-back file system.  These routines just take their parameters,
50  * and then calling the appropriate real vnode routine(s) to do the work.
51  */
52 
53 static int
54 lo_open(vnode_t **vpp, int flag, struct cred *cr)
55 {
56 	vnode_t *vp = *vpp;
57 	vnode_t *rvp;
58 	vnode_t *oldvp;
59 	int error;
60 
61 #ifdef LODEBUG
62 	lo_dprint(4, "lo_open vp %p cnt=%d realvp %p cnt=%d\n",
63 		vp, vp->v_count, realvp(vp), realvp(vp)->v_count);
64 #endif
65 
66 	oldvp = vp;
67 	vp = rvp = realvp(vp);
68 	/*
69 	 * Need to hold new reference to vp since VOP_OPEN() may
70 	 * decide to release it.
71 	 */
72 	VN_HOLD(vp);
73 	error = VOP_OPEN(&rvp, flag, cr);
74 
75 	if (!error && rvp != vp) {
76 		/*
77 		 * the FS which we called should have released the
78 		 * new reference on vp
79 		 */
80 		*vpp = makelonode(rvp, vtoli(oldvp->v_vfsp));
81 		if (IS_DEVVP(*vpp)) {
82 			vnode_t *svp;
83 
84 			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
85 			VN_RELE(*vpp);
86 			if (svp == NULL)
87 				error = ENOSYS;
88 			else
89 				*vpp = svp;
90 		}
91 		VN_RELE(oldvp);
92 	} else {
93 		ASSERT(rvp->v_count > 1);
94 		VN_RELE(rvp);
95 	}
96 
97 	return (error);
98 }
99 
100 static int
101 lo_close(
102 	vnode_t *vp,
103 	int flag,
104 	int count,
105 	offset_t offset,
106 	struct cred *cr)
107 {
108 #ifdef LODEBUG
109 	lo_dprint(4, "lo_close vp %p realvp %p\n", vp, realvp(vp));
110 #endif
111 	vp = realvp(vp);
112 	return (VOP_CLOSE(vp, flag, count, offset, cr));
113 }
114 
115 static int
116 lo_read(vnode_t *vp, struct uio *uiop, int ioflag, struct cred *cr,
117 	caller_context_t *ct)
118 {
119 #ifdef LODEBUG
120 	lo_dprint(4, "lo_read vp %p realvp %p\n", vp, realvp(vp));
121 #endif
122 	vp = realvp(vp);
123 	return (VOP_READ(vp, uiop, ioflag, cr, ct));
124 }
125 
126 static int
127 lo_write(vnode_t *vp, struct uio *uiop, int ioflag, struct cred *cr,
128 	caller_context_t *ct)
129 {
130 #ifdef LODEBUG
131 	lo_dprint(4, "lo_write vp %p realvp %p\n", vp, realvp(vp));
132 #endif
133 	vp = realvp(vp);
134 	return (VOP_WRITE(vp, uiop, ioflag, cr, ct));
135 }
136 
137 static int
138 lo_ioctl(
139 	vnode_t *vp,
140 	int cmd,
141 	intptr_t arg,
142 	int flag,
143 	struct cred *cr,
144 	int *rvalp)
145 {
146 #ifdef LODEBUG
147 	lo_dprint(4, "lo_ioctl vp %p realvp %p\n", vp, realvp(vp));
148 #endif
149 	vp = realvp(vp);
150 	return (VOP_IOCTL(vp, cmd, arg, flag, cr, rvalp));
151 }
152 
153 static int
154 lo_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr)
155 {
156 	vp = realvp(vp);
157 	return (VOP_SETFL(vp, oflags, nflags, cr));
158 }
159 
160 static int
161 lo_getattr(
162 	vnode_t *vp,
163 	struct vattr *vap,
164 	int flags,
165 	struct cred *cr)
166 {
167 	int error;
168 
169 #ifdef LODEBUG
170 	lo_dprint(4, "lo_getattr vp %p realvp %p\n", vp, realvp(vp));
171 #endif
172 	if (error = VOP_GETATTR(realvp(vp), vap, flags, cr))
173 		return (error);
174 
175 	/*
176 	 * In zonedevfs mode, we pull a nasty trick; we make sure that
177 	 * the dev_t does *not* reflect the underlying device, so that
178 	 * no renames can occur to or from the /dev hierarchy.
179 	 */
180 	if (IS_ZONEDEVFS(vp)) {
181 		vap->va_fsid = expldev(vp->v_vfsp->vfs_fsid.val[0]);
182 	}
183 
184 	return (0);
185 }
186 
187 static int
188 lo_setattr(
189 	vnode_t *vp,
190 	struct vattr *vap,
191 	int flags,
192 	struct cred *cr,
193 	caller_context_t *ct)
194 {
195 #ifdef LODEBUG
196 	lo_dprint(4, "lo_setattr vp %p realvp %p\n", vp, realvp(vp));
197 #endif
198 	if (IS_ZONEDEVFS(vp) && !IS_DEVVP(vp)) {
199 		return (EACCES);
200 	}
201 	vp = realvp(vp);
202 	return (VOP_SETATTR(vp, vap, flags, cr, ct));
203 }
204 
205 static int
206 lo_access(vnode_t *vp, int mode, int flags, struct cred *cr)
207 {
208 #ifdef LODEBUG
209 	lo_dprint(4, "lo_access vp %p realvp %p\n", vp, realvp(vp));
210 #endif
211 	if (mode & VWRITE) {
212 		if (vp->v_type == VREG && vn_is_readonly(vp))
213 			return (EROFS);
214 		if (IS_ZONEDEVFS(vp) && !IS_DEVVP(vp))
215 			return (EACCES);
216 	}
217 	vp = realvp(vp);
218 	return (VOP_ACCESS(vp, mode, flags, cr));
219 }
220 
221 static int
222 lo_fsync(vnode_t *vp, int syncflag, struct cred *cr)
223 {
224 #ifdef LODEBUG
225 	lo_dprint(4, "lo_fsync vp %p realvp %p\n", vp, realvp(vp));
226 #endif
227 	vp = realvp(vp);
228 	return (VOP_FSYNC(vp, syncflag, cr));
229 }
230 
231 /*ARGSUSED*/
232 static void
233 lo_inactive(vnode_t *vp, struct cred *cr)
234 {
235 #ifdef LODEBUG
236 	lo_dprint(4, "lo_inactive %p, realvp %p\n", vp, realvp(vp));
237 #endif
238 	freelonode(vtol(vp));
239 }
240 
241 /* ARGSUSED */
242 static int
243 lo_fid(vnode_t *vp, struct fid *fidp)
244 {
245 #ifdef LODEBUG
246 	lo_dprint(4, "lo_fid %p, realvp %p\n", vp, realvp(vp));
247 #endif
248 	vp = realvp(vp);
249 	return (VOP_FID(vp, fidp));
250 }
251 
252 /*
253  * Given a vnode of lofs type, lookup nm name and
254  * return a shadow vnode (of lofs type) of the
255  * real vnode found.
256  *
257  * Due to the nature of lofs, there is a potential
258  * looping in path traversal.
259  *
260  * starting from the mount point of an lofs;
261  * a loop is defined to be a traversal path
262  * where the mount point or the real vnode of
263  * the root of this lofs is encountered twice.
264  * Once at the start of traversal and second
265  * when the looping is found.
266  *
267  * When a loop is encountered, a shadow of the
268  * covered vnode is returned to stop the looping.
269  *
270  * This normally works, but with the advent of
271  * the new automounter, returning the shadow of the
272  * covered vnode (autonode, in this case) does not
273  * stop the loop.  Because further lookup on this
274  * lonode will cause the autonode to call lo_lookup()
275  * on the lonode covering it.
276  *
277  * example "/net/jurassic/net/jurassic" is a loop.
278  * returning the shadow of the autonode corresponding to
279  * "/net/jurassic/net/jurassic" will not terminate the
280  * loop.   To solve this problem we allow the loop to go
281  * through one more level component lookup.  If it hit
282  * "net" after the loop as in "/net/jurassic/net/jurassic/net",
283  * then returning the vnode covered by the autonode "net"
284  * will terminate the loop.
285  *
286  * Lookup for dot dot has to be dealt with separately.
287  * It will be nice to have a "one size fits all" kind
288  * of solution, so that we don't have so many ifs statement
289  * in the lo_lookup() to handle dotdot.  But, since
290  * there are so many special cases to handle different
291  * kinds looping above, we need special codes to handle
292  * dotdot lookup as well.
293  */
294 static int
295 lo_lookup(
296 	vnode_t *dvp,
297 	char *nm,
298 	vnode_t **vpp,
299 	struct pathname *pnp,
300 	int flags,
301 	vnode_t *rdir,
302 	struct cred *cr)
303 {
304 	vnode_t *vp = NULL, *tvp = NULL, *nonlovp;
305 	int error, is_indirectloop;
306 	vnode_t *realdvp = realvp(dvp);
307 	struct loinfo *li = vtoli(dvp->v_vfsp);
308 	int looping = 0;
309 	int doingdotdot = 0;
310 	int nosub = 0;
311 
312 	/*
313 	 * If name is empty and no XATTR flags are set, then return
314 	 * dvp (empty name == lookup ".").  If an XATTR flag is set
315 	 * then we need to call VOP_LOOKUP to get the xattr dir.
316 	 */
317 	if (nm[0] == '\0' && ! (flags & (CREATE_XATTR_DIR|LOOKUP_XATTR))) {
318 		VN_HOLD(dvp);
319 		*vpp = dvp;
320 		return (0);
321 	}
322 
323 	if (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0') {
324 		doingdotdot++;
325 		/*
326 		 * Handle ".." out of mounted filesystem
327 		 */
328 		while ((realdvp->v_flag & VROOT) && realdvp != rootdir) {
329 			realdvp = realdvp->v_vfsp->vfs_vnodecovered;
330 			ASSERT(realdvp != NULL);
331 		}
332 	}
333 
334 	*vpp = NULL;	/* default(error) case */
335 
336 	/*
337 	 * Do the normal lookup
338 	 */
339 	if (error = VOP_LOOKUP(realdvp, nm, &vp, pnp, flags, rdir, cr))
340 		goto out;
341 
342 	/*
343 	 * We do this check here to avoid returning a stale file handle to the
344 	 * caller.
345 	 */
346 	if (nm[0] == '.' && nm[1] == '\0') {
347 		ASSERT(vp == realdvp);
348 		VN_HOLD(dvp);
349 		VN_RELE(vp);
350 		*vpp = dvp;
351 		return (0);
352 	}
353 
354 	if (doingdotdot) {
355 		if ((vtol(dvp))->lo_looping) {
356 			vfs_t *vfsp;
357 
358 			error = vn_vfswlock_wait(realdvp);
359 			if (error)
360 				goto out;
361 			vfsp = vn_mountedvfs(realdvp);
362 			if (vfsp != NULL) {
363 				/*
364 				 * if looping get the actual found vnode
365 				 * instead of the vnode covered
366 				 * Here we have to hold the lock for realdvp
367 				 * since an unmount during the traversal to the
368 				 * root vnode would turn *vfsp into garbage
369 				 * which would be fatal.
370 				 */
371 				vfs_lock_wait(vfsp);
372 				vn_vfsunlock(realdvp);
373 
374 				error = VFS_ROOT(vfsp, &tvp);
375 
376 				vfs_unlock(vfsp);
377 				if (error)
378 					goto out;
379 				if ((tvp == li->li_rootvp)&&
380 				    (vp == realvp(tvp))) {
381 					/*
382 					 * we're back at the real vnode
383 					 * of the rootvp
384 					 *
385 					 * return the rootvp
386 					 * Ex: /mnt/mnt/..
387 					 * where / has been lofs-mounted
388 					 * onto /mnt.  Return the lofs
389 					 * node mounted at /mnt.
390 					 */
391 					*vpp = tvp;
392 					VN_RELE(vp);
393 					return (0);
394 				} else {
395 					/*
396 					 * We are returning from a covered
397 					 * node whose vfs_mountedhere is
398 					 * not pointing to vfs of the current
399 					 * root vnode.
400 					 * This is a condn where in we
401 					 * returned a covered node say Zc
402 					 * but Zc is not the cover of current
403 					 * root.
404 					 * i.e.., if X is the root vnode
405 					 * lookup(Zc,"..") is taking us to
406 					 * X.
407 					 * Ex: /net/X/net/X/net
408 					 * We are encountering cover of net.
409 					 * doing a dotdot from here means we
410 					 * to take the lookup to the same state
411 					 * that would have happened when we do
412 					 * lookup of any Y under /net/X/net/X
413 					 */
414 					VN_RELE(tvp);
415 					if (vp == realvp(li->li_rootvp)) {
416 						VN_RELE(vp);
417 						vp = li->li_rootvp;
418 						vp = vp->v_vfsp->
419 							vfs_vnodecovered;
420 						VN_HOLD(vp);
421 						*vpp = makelonode(vp, li);
422 						(vtol(*vpp))->lo_looping = 1;
423 						return (0);
424 					}
425 				}
426 			} else {
427 				/*
428 				 * We are returning from a looping dvp.
429 				 * If we are returning to rootvp return
430 				 * the covered node with looping bit set.
431 				 *
432 				 * This means we are not returning from cover
433 				 * but we should return to the root node by
434 				 * giving the covered node with looping flag
435 				 * set. We are returning from a non-covernode
436 				 * with looping bit set means we couldn't stop
437 				 * by giving the cover of root vnode.
438 				 *
439 				 *	Say X is the root vnode and lookup of
440 				 * X again under X returns Xc(due to looping
441 				 * condn). let Z=lookup(Xc,"path") and
442 				 * if lookup(Z,"..") returns  the root vp X
443 				 * return Xc with looping bit set or if a new
444 				 * node Z.. is returned make a shadow with a
445 				 * looping flag.
446 				 *
447 				 * Ex:- lookup of /net/X/net/X/Y/.. or
448 				 * lookup of /net/X/net/X/Y/Z/.. .
449 				 * In the first case we are returning to root
450 				 * we will return the cover of root with
451 				 * looping bit set.
452 				 */
453 				vn_vfsunlock(realdvp);
454 				if (vp == li->li_rootvp) {
455 					tvp = vp;
456 					vp = (vp)->v_vfsp->vfs_vnodecovered;
457 					VN_RELE(tvp);
458 					VN_HOLD(vp);
459 				}
460 				*vpp = makelonode(vp, li);
461 				(vtol(*vpp))->lo_looping = 1;
462 				return (0);
463 			}
464 		} else {
465 			/*
466 			 * No frills just make the shadow node.
467 			 */
468 			*vpp = makelonode(vp, li);
469 			return (0);
470 		}
471 	}
472 
473 	nosub = (vtoli(dvp->v_vfsp)->li_flag & LO_NOSUB);
474 
475 	/*
476 	 * If this vnode is mounted on, then we
477 	 * traverse to the vnode which is the root of
478 	 * the mounted file system.
479 	 */
480 	if (!nosub && (error = traverse(&vp)))
481 		goto out;
482 
483 	/*
484 	 * Make a lnode for the real vnode.
485 	 */
486 	if (vp->v_type != VDIR || nosub) {
487 		*vpp = makelonode(vp, li);
488 		if (IS_DEVVP(*vpp)) {
489 			vnode_t *svp;
490 
491 			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
492 			VN_RELE(*vpp);
493 			if (svp == NULL)
494 				error = ENOSYS;
495 			else
496 				*vpp = svp;
497 		}
498 		return (error);
499 	}
500 
501 	/*
502 	 * if the found vnode (vp) is not of type lofs
503 	 * then we're just going to make a shadow of that
504 	 * vp and get out.
505 	 *
506 	 * If the found vnode (vp) is of lofs type, and
507 	 * we're not doing dotdot, check if we are
508 	 * looping.
509 	 */
510 	if (!doingdotdot && vfs_matchops(vp->v_vfsp, lo_vfsops)) {
511 		/*
512 		 * Check if we're looping, i.e.
513 		 * vp equals the root vp of the lofs, directly
514 		 * or indirectly, return the covered node.
515 		 */
516 
517 		if (!(vtol(dvp))->lo_looping) {
518 			if (vp == li->li_rootvp) {
519 				/*
520 				 * Direct looping condn.
521 				 * Ex:- X is / mounted directory so lookup of
522 				 * /X/X is a direct looping condn.
523 				 */
524 				tvp = vp;
525 				vp = vp->v_vfsp->vfs_vnodecovered;
526 				VN_HOLD(vp);
527 				VN_RELE(tvp);
528 				looping++;
529 			} else {
530 				/*
531 				 * Indirect looping can be defined as
532 				 * real lookup returning rootvp of the current
533 				 * tree in any level of recursion.
534 				 *
535 				 * This check is useful if there are multiple
536 				 * levels of lofs indirections. Suppose vnode X
537 				 * in the current lookup has as its real vnode
538 				 * another lofs node. Y = realvp(X) Y should be
539 				 * a lofs node for the check to continue or Y
540 				 * is not the rootvp of X.
541 				 * Ex:- say X and Y are two vnodes
542 				 * say real(Y) is X and real(X) is Z
543 				 * parent vnode for X and Y is Z
544 				 * lookup(Y,"path") say we are looking for Y
545 				 * again under Y and we have to return Yc.
546 				 * but the lookup of Y under Y doesnot return
547 				 * Y the root vnode again here is why.
548 				 * 1. lookup(Y,"path of Y") will go to
549 				 * 2. lookup(real(Y),"path of Y") and then to
550 				 * 3. lookup(real(X),"path of Y").
551 				 * and now what lookup level 1 sees is the
552 				 * outcome of 2 but the vnode Y is due to
553 				 * lookup(Z,"path of Y") so we have to skip
554 				 * intermediate levels to find if in any level
555 				 * there is a looping.
556 				 */
557 				is_indirectloop = 0;
558 				nonlovp = vp;
559 				while (
560 				    vfs_matchops(nonlovp->v_vfsp, lo_vfsops) &&
561 				    !(is_indirectloop)) {
562 					if (li->li_rootvp  == nonlovp) {
563 						is_indirectloop++;
564 						break;
565 					}
566 					nonlovp = realvp(nonlovp);
567 				}
568 
569 				if (is_indirectloop) {
570 					VN_RELE(vp);
571 					vp = nonlovp;
572 					vp = vp->v_vfsp->vfs_vnodecovered;
573 					VN_HOLD(vp);
574 					looping++;
575 				}
576 			}
577 		} else {
578 			/*
579 			 * come here only because of the interaction between
580 			 * the autofs and lofs.
581 			 *
582 			 * Lookup of "/net/X/net/X" will return a shadow of
583 			 * an autonode X_a which we call X_l.
584 			 *
585 			 * Lookup of anything under X_l, will trigger a call to
586 			 * auto_lookup(X_a,nm) which will eventually call
587 			 * lo_lookup(X_lr,nm) where X_lr is the root vnode of
588 			 * the current lofs.
589 			 *
590 			 * We come here only when we are called with X_l as dvp
591 			 * and look for something underneath.
592 			 *
593 			 * We need to find out if the vnode, which vp is
594 			 * shadowing, is the rootvp of the autofs.
595 			 *
596 			 */
597 			realdvp = realvp(dvp);
598 			while (vfs_matchops(realdvp->v_vfsp, lo_vfsops)) {
599 				realdvp = realvp(realdvp);
600 			}
601 
602 			error = VFS_ROOT(realdvp->v_vfsp, &tvp);
603 			if (error)
604 				goto out;
605 			/*
606 			 * tvp now contains the rootvp of the vfs of the
607 			 * real vnode of dvp
608 			 */
609 
610 			if (realvp(dvp)->v_vfsp == realvp(vp)->v_vfsp &&
611 			    tvp == realvp(vp)) {
612 				/*
613 				 * vp is the shadow of "net",
614 				 * the rootvp of autofs
615 				 */
616 				VN_RELE(vp);
617 				vp = tvp;	/* this is an autonode */
618 
619 				/*
620 				 * Need to find the covered vnode
621 				 */
622 				vp = vp->v_vfsp->vfs_vnodecovered;
623 				ASSERT(vp);
624 				VN_HOLD(vp);
625 				VN_RELE(tvp);
626 			} else {
627 				VN_RELE(tvp);
628 			}
629 		}
630 	}
631 	*vpp = makelonode(vp, li);
632 
633 	if ((looping) || ((vtol(dvp))->lo_looping && !doingdotdot)) {
634 		(vtol(*vpp))->lo_looping = 1;
635 	}
636 
637 out:
638 	if (error != 0 && vp != NULL)
639 		VN_RELE(vp);
640 #ifdef LODEBUG
641 	lo_dprint(4,
642 	"lo_lookup dvp %x realdvp %x nm '%s' newvp %x real vp %x error %d\n",
643 		dvp, realvp(dvp), nm, *vpp, vp, error);
644 #endif
645 	return (error);
646 }
647 
648 /*ARGSUSED*/
649 static int
650 lo_create(
651 	vnode_t *dvp,
652 	char *nm,
653 	struct vattr *va,
654 	enum vcexcl exclusive,
655 	int mode,
656 	vnode_t **vpp,
657 	struct cred *cr,
658 	int flag)
659 {
660 	int error;
661 	vnode_t *vp = NULL;
662 
663 #ifdef LODEBUG
664 	lo_dprint(4, "lo_create vp %p realvp %p\n", dvp, realvp(dvp));
665 #endif
666 	if (*nm == '\0') {
667 		ASSERT(vpp && dvp == *vpp);
668 		vp = realvp(*vpp);
669 	}
670 
671 	if (IS_ZONEDEVFS(dvp)) {
672 		/* Is this truly a create?  If so, fail */
673 		if (*vpp == NULL)
674 			return (EACCES);
675 
676 		/* Is this an open of a non-special for writing?  If so, fail */
677 		if (*vpp != NULL && (mode & VWRITE) && !IS_DEVVP(*vpp))
678 			return (EACCES);
679 	}
680 
681 	error = VOP_CREATE(realvp(dvp), nm, va, exclusive, mode, &vp, cr, flag);
682 	if (!error) {
683 		*vpp = makelonode(vp, vtoli(dvp->v_vfsp));
684 		if (IS_DEVVP(*vpp)) {
685 			vnode_t *svp;
686 
687 			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
688 			VN_RELE(*vpp);
689 			if (svp == NULL)
690 				error = ENOSYS;
691 			else
692 				*vpp = svp;
693 		}
694 	}
695 	return (error);
696 }
697 
698 static int
699 lo_remove(vnode_t *dvp, char *nm, struct cred *cr)
700 {
701 #ifdef LODEBUG
702 	lo_dprint(4, "lo_remove vp %p realvp %p\n", dvp, realvp(dvp));
703 #endif
704 	if (IS_ZONEDEVFS(dvp))
705 		return (EACCES);
706 	dvp = realvp(dvp);
707 	return (VOP_REMOVE(dvp, nm, cr));
708 }
709 
710 static int
711 lo_link(vnode_t *tdvp, vnode_t *vp, char *tnm, struct cred *cr)
712 {
713 #ifdef LODEBUG
714 	lo_dprint(4, "lo_link vp %p realvp %p\n", vp, realvp(vp));
715 #endif
716 	while (vn_matchops(vp, lo_vnodeops)) {
717 		if (IS_ZONEDEVFS(vp))
718 			return (EACCES);
719 		vp = realvp(vp);
720 	}
721 	while (vn_matchops(tdvp, lo_vnodeops)) {
722 		if (IS_ZONEDEVFS(tdvp))
723 			return (EACCES);
724 		tdvp = realvp(tdvp);
725 	}
726 	if (vp->v_vfsp != tdvp->v_vfsp)
727 		return (EXDEV);
728 	return (VOP_LINK(tdvp, vp, tnm, cr));
729 }
730 
731 static int
732 lo_rename(
733 	vnode_t *odvp,
734 	char *onm,
735 	vnode_t *ndvp,
736 	char *nnm,
737 	struct cred *cr)
738 {
739 	vnode_t *tnvp;
740 
741 #ifdef LODEBUG
742 	lo_dprint(4, "lo_rename vp %p realvp %p\n", odvp, realvp(odvp));
743 #endif
744 	if (IS_ZONEDEVFS(odvp))
745 		return (EACCES);
746 	/*
747 	 * We need to make sure we're not trying to remove a mount point for a
748 	 * filesystem mounted on top of lofs, which only we know about.
749 	 */
750 	if (vn_matchops(ndvp, lo_vnodeops))	/* Not our problem. */
751 		goto rename;
752 	if (VOP_LOOKUP(ndvp, nnm, &tnvp, NULL, 0, NULL, cr) != 0)
753 		goto rename;
754 	if (tnvp->v_type != VDIR) {
755 		VN_RELE(tnvp);
756 		goto rename;
757 	}
758 	if (vn_mountedvfs(tnvp)) {
759 		VN_RELE(tnvp);
760 		return (EBUSY);
761 	}
762 	VN_RELE(tnvp);
763 rename:
764 	/*
765 	 * Since the case we're dealing with above can happen at any layer in
766 	 * the stack of lofs filesystems, we need to recurse down the stack,
767 	 * checking to see if there are any instances of a filesystem mounted on
768 	 * top of lofs. In order to keep on using the lofs version of
769 	 * VOP_RENAME(), we make sure that while the target directory is of type
770 	 * lofs, the source directory (the one used for getting the fs-specific
771 	 * version of VOP_RENAME()) is also of type lofs.
772 	 */
773 	if (vn_matchops(ndvp, lo_vnodeops)) {
774 		if (IS_ZONEDEVFS(ndvp))
775 			return (EACCES);
776 		ndvp = realvp(ndvp);	/* Check the next layer */
777 	} else {
778 		/*
779 		 * We can go fast here
780 		 */
781 		while (vn_matchops(odvp, lo_vnodeops)) {
782 			if (IS_ZONEDEVFS(odvp))
783 				return (EACCES);
784 			odvp = realvp(odvp);
785 		}
786 		if (odvp->v_vfsp != ndvp->v_vfsp)
787 			return (EXDEV);
788 	}
789 	return (VOP_RENAME(odvp, onm, ndvp, nnm, cr));
790 }
791 
792 static int
793 lo_mkdir(
794 	vnode_t *dvp,
795 	char *nm,
796 	struct vattr *va,
797 	vnode_t **vpp,
798 	struct cred *cr)
799 {
800 	int error;
801 
802 #ifdef LODEBUG
803 	lo_dprint(4, "lo_mkdir vp %p realvp %p\n", dvp, realvp(dvp));
804 #endif
805 	if (IS_ZONEDEVFS(dvp))
806 		return (EACCES);
807 	error = VOP_MKDIR(realvp(dvp), nm, va, vpp, cr);
808 	if (!error)
809 		*vpp = makelonode(*vpp, vtoli(dvp->v_vfsp));
810 	return (error);
811 }
812 
813 static int
814 lo_realvp(vnode_t *vp, vnode_t **vpp)
815 {
816 #ifdef LODEBUG
817 	lo_dprint(4, "lo_realvp %p\n", vp);
818 #endif
819 	while (vn_matchops(vp, lo_vnodeops))
820 		vp = realvp(vp);
821 
822 	if (VOP_REALVP(vp, vpp) != 0)
823 		*vpp = vp;
824 	return (0);
825 }
826 
827 static int
828 lo_rmdir(
829 	vnode_t *dvp,
830 	char *nm,
831 	vnode_t *cdir,
832 	struct cred *cr)
833 {
834 	vnode_t *rvp = cdir;
835 
836 #ifdef LODEBUG
837 	lo_dprint(4, "lo_rmdir vp %p realvp %p\n", dvp, realvp(dvp));
838 #endif
839 	if (IS_ZONEDEVFS(dvp))
840 		return (EACCES);
841 	/* if cdir is lofs vnode ptr get its real vnode ptr */
842 	if (vn_matchops(dvp, vn_getops(rvp)))
843 		(void) lo_realvp(cdir, &rvp);
844 	dvp = realvp(dvp);
845 	return (VOP_RMDIR(dvp, nm, rvp, cr));
846 }
847 
848 static int
849 lo_symlink(
850 	vnode_t *dvp,
851 	char *lnm,
852 	struct vattr *tva,
853 	char *tnm,
854 	struct cred *cr)
855 {
856 #ifdef LODEBUG
857 	lo_dprint(4, "lo_symlink vp %p realvp %p\n", dvp, realvp(dvp));
858 #endif
859 	if (IS_ZONEDEVFS(dvp))
860 		return (EACCES);
861 	dvp = realvp(dvp);
862 	return (VOP_SYMLINK(dvp, lnm, tva, tnm, cr));
863 }
864 
865 static int
866 lo_readlink(vnode_t *vp, struct uio *uiop, struct cred *cr)
867 {
868 	vp = realvp(vp);
869 	return (VOP_READLINK(vp, uiop, cr));
870 }
871 
872 static int
873 lo_readdir(vnode_t *vp, struct uio *uiop, struct cred *cr, int *eofp)
874 {
875 #ifdef LODEBUG
876 	lo_dprint(4, "lo_readdir vp %p realvp %p\n", vp, realvp(vp));
877 #endif
878 	vp = realvp(vp);
879 	return (VOP_READDIR(vp, uiop, cr, eofp));
880 }
881 
882 static int
883 lo_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct)
884 {
885 	vp = realvp(vp);
886 	return (VOP_RWLOCK(vp, write_lock, ct));
887 }
888 
889 static void
890 lo_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct)
891 {
892 	vp = realvp(vp);
893 	VOP_RWUNLOCK(vp, write_lock, ct);
894 }
895 
896 static int
897 lo_seek(vnode_t *vp, offset_t ooff, offset_t *noffp)
898 {
899 	vp = realvp(vp);
900 	return (VOP_SEEK(vp, ooff, noffp));
901 }
902 
903 static int
904 lo_cmp(vnode_t *vp1, vnode_t *vp2)
905 {
906 	while (vn_matchops(vp1, lo_vnodeops))
907 		vp1 = realvp(vp1);
908 	while (vn_matchops(vp2, lo_vnodeops))
909 		vp2 = realvp(vp2);
910 	return (VOP_CMP(vp1, vp2));
911 }
912 
913 static int
914 lo_frlock(
915 	vnode_t *vp,
916 	int cmd,
917 	struct flock64 *bfp,
918 	int flag,
919 	offset_t offset,
920 	struct flk_callback *flk_cbp,
921 	cred_t *cr)
922 {
923 	vp = realvp(vp);
924 	return (VOP_FRLOCK(vp, cmd, bfp, flag, offset, flk_cbp, cr));
925 }
926 
927 static int
928 lo_space(
929 	vnode_t *vp,
930 	int cmd,
931 	struct flock64 *bfp,
932 	int flag,
933 	offset_t offset,
934 	struct cred *cr,
935 	caller_context_t *ct)
936 {
937 	vp = realvp(vp);
938 	return (VOP_SPACE(vp, cmd, bfp, flag, offset, cr, ct));
939 }
940 
941 static int
942 lo_getpage(
943 	vnode_t *vp,
944 	offset_t off,
945 	size_t len,
946 	uint_t *prot,
947 	struct page *parr[],
948 	size_t psz,
949 	struct seg *seg,
950 	caddr_t addr,
951 	enum seg_rw rw,
952 	struct cred *cr)
953 {
954 	vp = realvp(vp);
955 	return (VOP_GETPAGE(vp, off, len, prot, parr, psz, seg, addr, rw, cr));
956 }
957 
958 static int
959 lo_putpage(vnode_t *vp, offset_t off, size_t len, int flags, struct cred *cr)
960 {
961 	vp = realvp(vp);
962 	return (VOP_PUTPAGE(vp, off, len, flags, cr));
963 }
964 
965 static int
966 lo_map(
967 	vnode_t *vp,
968 	offset_t off,
969 	struct as *as,
970 	caddr_t *addrp,
971 	size_t len,
972 	uchar_t prot,
973 	uchar_t maxprot,
974 	uint_t flags,
975 	struct cred *cr)
976 {
977 	vp = realvp(vp);
978 	return (VOP_MAP(vp, off, as, addrp, len, prot, maxprot, flags, cr));
979 }
980 
981 static int
982 lo_addmap(
983 	vnode_t *vp,
984 	offset_t off,
985 	struct as *as,
986 	caddr_t addr,
987 	size_t len,
988 	uchar_t prot,
989 	uchar_t maxprot,
990 	uint_t flags,
991 	struct cred *cr)
992 {
993 	vp = realvp(vp);
994 	return (VOP_ADDMAP(vp, off, as, addr, len, prot, maxprot, flags, cr));
995 }
996 
997 static int
998 lo_delmap(
999 	vnode_t *vp,
1000 	offset_t off,
1001 	struct as *as,
1002 	caddr_t addr,
1003 	size_t len,
1004 	uint_t prot,
1005 	uint_t maxprot,
1006 	uint_t flags,
1007 	struct cred *cr)
1008 {
1009 	vp = realvp(vp);
1010 	return (VOP_DELMAP(vp, off, as, addr, len, prot, maxprot, flags, cr));
1011 }
1012 
1013 static int
1014 lo_poll(
1015 	vnode_t *vp,
1016 	short events,
1017 	int anyyet,
1018 	short *reventsp,
1019 	struct pollhead **phpp)
1020 {
1021 	vp = realvp(vp);
1022 	return (VOP_POLL(vp, events, anyyet, reventsp, phpp));
1023 }
1024 
1025 static int
1026 lo_dump(vnode_t *vp, caddr_t addr, int bn, int count)
1027 {
1028 	vp = realvp(vp);
1029 	return (VOP_DUMP(vp, addr, bn, count));
1030 }
1031 
1032 static int
1033 lo_pathconf(vnode_t *vp, int cmd, ulong_t *valp, struct cred *cr)
1034 {
1035 	vp = realvp(vp);
1036 	return (VOP_PATHCONF(vp, cmd, valp, cr));
1037 }
1038 
1039 static int
1040 lo_pageio(
1041 	vnode_t *vp,
1042 	struct page *pp,
1043 	u_offset_t io_off,
1044 	size_t io_len,
1045 	int flags,
1046 	cred_t *cr)
1047 {
1048 	vp = realvp(vp);
1049 	return (VOP_PAGEIO(vp, pp, io_off, io_len, flags, cr));
1050 }
1051 
1052 static void
1053 lo_dispose(vnode_t *vp, page_t *pp, int fl, int dn, cred_t *cr)
1054 {
1055 	vp = realvp(vp);
1056 	if (vp != NULL && vp != &kvp)
1057 		VOP_DISPOSE(vp, pp, fl, dn, cr);
1058 }
1059 
1060 static int
1061 lo_setsecattr(vnode_t *vp, vsecattr_t *secattr, int flags, struct cred *cr)
1062 {
1063 	if (vn_is_readonly(vp))
1064 		return (EROFS);
1065 	vp = realvp(vp);
1066 	return (VOP_SETSECATTR(vp, secattr, flags, cr));
1067 }
1068 
1069 static int
1070 lo_getsecattr(vnode_t *vp, vsecattr_t *secattr, int flags, struct cred *cr)
1071 {
1072 	vp = realvp(vp);
1073 	return (VOP_GETSECATTR(vp, secattr, flags, cr));
1074 }
1075 
1076 static int
1077 lo_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr)
1078 {
1079 	vp = realvp(vp);
1080 	return (VOP_SHRLOCK(vp, cmd, shr, flag, cr));
1081 }
1082 
1083 /*
1084  * Loopback vnode operations vector.
1085  */
1086 
1087 struct vnodeops *lo_vnodeops;
1088 
1089 const fs_operation_def_t lo_vnodeops_template[] = {
1090 	VOPNAME_OPEN, lo_open,
1091 	VOPNAME_CLOSE, lo_close,
1092 	VOPNAME_READ, lo_read,
1093 	VOPNAME_WRITE, lo_write,
1094 	VOPNAME_IOCTL, lo_ioctl,
1095 	VOPNAME_SETFL, lo_setfl,
1096 	VOPNAME_GETATTR, lo_getattr,
1097 	VOPNAME_SETATTR, lo_setattr,
1098 	VOPNAME_ACCESS, lo_access,
1099 	VOPNAME_LOOKUP, lo_lookup,
1100 	VOPNAME_CREATE, lo_create,
1101 	VOPNAME_REMOVE, lo_remove,
1102 	VOPNAME_LINK, lo_link,
1103 	VOPNAME_RENAME, lo_rename,
1104 	VOPNAME_MKDIR, lo_mkdir,
1105 	VOPNAME_RMDIR, lo_rmdir,
1106 	VOPNAME_READDIR, lo_readdir,
1107 	VOPNAME_SYMLINK, lo_symlink,
1108 	VOPNAME_READLINK, lo_readlink,
1109 	VOPNAME_FSYNC, lo_fsync,
1110 	VOPNAME_INACTIVE, (fs_generic_func_p) lo_inactive,
1111 	VOPNAME_FID, lo_fid,
1112 	VOPNAME_RWLOCK, lo_rwlock,
1113 	VOPNAME_RWUNLOCK, (fs_generic_func_p) lo_rwunlock,
1114 	VOPNAME_SEEK, lo_seek,
1115 	VOPNAME_CMP, lo_cmp,
1116 	VOPNAME_FRLOCK, lo_frlock,
1117 	VOPNAME_SPACE, lo_space,
1118 	VOPNAME_REALVP, lo_realvp,
1119 	VOPNAME_GETPAGE, lo_getpage,
1120 	VOPNAME_PUTPAGE, lo_putpage,
1121 	VOPNAME_MAP, (fs_generic_func_p) lo_map,
1122 	VOPNAME_ADDMAP, (fs_generic_func_p) lo_addmap,
1123 	VOPNAME_DELMAP, lo_delmap,
1124 	VOPNAME_POLL, (fs_generic_func_p) lo_poll,
1125 	VOPNAME_DUMP, lo_dump,
1126 	VOPNAME_DUMPCTL, fs_error,		/* XXX - why? */
1127 	VOPNAME_PATHCONF, lo_pathconf,
1128 	VOPNAME_PAGEIO, lo_pageio,
1129 	VOPNAME_DISPOSE, (fs_generic_func_p) lo_dispose,
1130 	VOPNAME_SETSECATTR, lo_setsecattr,
1131 	VOPNAME_GETSECATTR, lo_getsecattr,
1132 	VOPNAME_SHRLOCK, lo_shrlock,
1133 	NULL, NULL
1134 };
1135