xref: /titanic_52/usr/src/uts/common/fs/lofs/lofs_vnops.c (revision 749f21d359d8fbd020c974a1a5227316221bfc9c)
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 2006 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), 0);
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.  Whichever
282  * directory is then looked up in "/net/jurassic/net/jurassic"
283  * the vnode returned is the vnode covered by the autonode
284  * "net" and this 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 autoloop = 0;
310 	int doingdotdot = 0;
311 	int nosub = 0;
312 	int mkflag = 0;
313 
314 	/*
315 	 * If name is empty and no XATTR flags are set, then return
316 	 * dvp (empty name == lookup ".").  If an XATTR flag is set
317 	 * then we need to call VOP_LOOKUP to get the xattr dir.
318 	 */
319 	if (nm[0] == '\0' && ! (flags & (CREATE_XATTR_DIR|LOOKUP_XATTR))) {
320 		VN_HOLD(dvp);
321 		*vpp = dvp;
322 		return (0);
323 	}
324 
325 	if (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0') {
326 		doingdotdot++;
327 		/*
328 		 * Handle ".." out of mounted filesystem
329 		 */
330 		while ((realdvp->v_flag & VROOT) && realdvp != rootdir) {
331 			realdvp = realdvp->v_vfsp->vfs_vnodecovered;
332 			ASSERT(realdvp != NULL);
333 		}
334 	}
335 
336 	*vpp = NULL;	/* default(error) case */
337 
338 	/*
339 	 * Do the normal lookup
340 	 */
341 	if (error = VOP_LOOKUP(realdvp, nm, &vp, pnp, flags, rdir, cr)) {
342 		vp = NULL;
343 		goto out;
344 	}
345 
346 	/*
347 	 * We do this check here to avoid returning a stale file handle to the
348 	 * caller.
349 	 */
350 	if (nm[0] == '.' && nm[1] == '\0') {
351 		ASSERT(vp == realdvp);
352 		VN_HOLD(dvp);
353 		VN_RELE(vp);
354 		*vpp = dvp;
355 		return (0);
356 	}
357 
358 	if (doingdotdot) {
359 		if ((vtol(dvp))->lo_looping & LO_LOOPING) {
360 			vfs_t *vfsp;
361 
362 			error = vn_vfsrlock_wait(realdvp);
363 			if (error)
364 				goto out;
365 			vfsp = vn_mountedvfs(realdvp);
366 			/*
367 			 * In the standard case if the looping flag is set and
368 			 * performing dotdot we would be returning from a
369 			 * covered vnode, implying vfsp could not be null. The
370 			 * exceptions being if we have looping and overlay
371 			 * mounts or looping and covered file systems.
372 			 */
373 			if (vfsp == NULL) {
374 				/*
375 				 * Overlay mount or covered file system,
376 				 * so just make the shadow node.
377 				 */
378 				vn_vfsunlock(realdvp);
379 				*vpp = makelonode(vp, li, 0);
380 				(vtol(*vpp))->lo_looping |= LO_LOOPING;
381 				return (0);
382 			}
383 			/*
384 			 * When looping get the actual found vnode
385 			 * instead of the vnode covered.
386 			 * Here we have to hold the lock for realdvp
387 			 * since an unmount during the traversal to the
388 			 * root vnode would turn *vfsp into garbage
389 			 * which would be fatal.
390 			 */
391 			error = VFS_ROOT(vfsp, &tvp);
392 			vn_vfsunlock(realdvp);
393 
394 			if (error)
395 				goto out;
396 
397 			if ((tvp == li->li_rootvp) && (vp == realvp(tvp))) {
398 				/*
399 				 * we're back at the real vnode
400 				 * of the rootvp
401 				 *
402 				 * return the rootvp
403 				 * Ex: /mnt/mnt/..
404 				 * where / has been lofs-mounted
405 				 * onto /mnt.  Return the lofs
406 				 * node mounted at /mnt.
407 				 */
408 				*vpp = tvp;
409 				VN_RELE(vp);
410 				return (0);
411 			} else {
412 				/*
413 				 * We are returning from a covered
414 				 * node whose vfs_mountedhere is
415 				 * not pointing to vfs of the current
416 				 * root vnode.
417 				 * This is a condn where in we
418 				 * returned a covered node say Zc
419 				 * but Zc is not the cover of current
420 				 * root.
421 				 * i.e.., if X is the root vnode
422 				 * lookup(Zc,"..") is taking us to
423 				 * X.
424 				 * Ex: /net/X/net/X/Y
425 				 *
426 				 * If LO_AUTOLOOP (autofs/lofs looping detected)
427 				 * has been set then we are encountering the
428 				 * cover of Y (Y being any directory vnode
429 				 * under /net/X/net/X/).
430 				 * When performing a dotdot set the
431 				 * returned vp to the vnode covered
432 				 * by the mounted lofs, ie /net/X/net/X
433 				 */
434 				VN_RELE(tvp);
435 				if ((vtol(dvp))->lo_looping & LO_AUTOLOOP) {
436 					VN_RELE(vp);
437 					vp = li->li_rootvp;
438 					vp = vp->v_vfsp->vfs_vnodecovered;
439 					VN_HOLD(vp);
440 					*vpp = makelonode(vp, li, 0);
441 					(vtol(*vpp))->lo_looping |= LO_LOOPING;
442 					return (0);
443 				}
444 			}
445 		} else {
446 			/*
447 			 * No frills just make the shadow node.
448 			 */
449 			*vpp = makelonode(vp, li, 0);
450 			return (0);
451 		}
452 	}
453 
454 	nosub = (vtoli(dvp->v_vfsp)->li_flag & LO_NOSUB);
455 
456 	/*
457 	 * If this vnode is mounted on, then we
458 	 * traverse to the vnode which is the root of
459 	 * the mounted file system.
460 	 */
461 	if (!nosub && (error = traverse(&vp)))
462 		goto out;
463 
464 	/*
465 	 * Make a lnode for the real vnode.
466 	 */
467 	if (vp->v_type != VDIR || nosub) {
468 		*vpp = makelonode(vp, li, 0);
469 		if (IS_DEVVP(*vpp)) {
470 			vnode_t *svp;
471 
472 			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
473 			VN_RELE(*vpp);
474 			if (svp == NULL)
475 				error = ENOSYS;
476 			else
477 				*vpp = svp;
478 		}
479 		return (error);
480 	}
481 
482 	/*
483 	 * if the found vnode (vp) is not of type lofs
484 	 * then we're just going to make a shadow of that
485 	 * vp and get out.
486 	 *
487 	 * If the found vnode (vp) is of lofs type, and
488 	 * we're not doing dotdot, check if we are
489 	 * looping.
490 	 */
491 	if (!doingdotdot && vfs_matchops(vp->v_vfsp, lo_vfsops)) {
492 		/*
493 		 * Check if we're looping, i.e.
494 		 * vp equals the root vp of the lofs, directly
495 		 * or indirectly, return the covered node.
496 		 */
497 
498 		if (!((vtol(dvp))->lo_looping & LO_LOOPING)) {
499 			if (vp == li->li_rootvp) {
500 				/*
501 				 * Direct looping condn.
502 				 * Ex:- X is / mounted directory so lookup of
503 				 * /X/X is a direct looping condn.
504 				 */
505 				tvp = vp;
506 				vp = vp->v_vfsp->vfs_vnodecovered;
507 				VN_HOLD(vp);
508 				VN_RELE(tvp);
509 				looping++;
510 			} else {
511 				/*
512 				 * Indirect looping can be defined as
513 				 * real lookup returning rootvp of the current
514 				 * tree in any level of recursion.
515 				 *
516 				 * This check is useful if there are multiple
517 				 * levels of lofs indirections. Suppose vnode X
518 				 * in the current lookup has as its real vnode
519 				 * another lofs node. Y = realvp(X) Y should be
520 				 * a lofs node for the check to continue or Y
521 				 * is not the rootvp of X.
522 				 * Ex:- say X and Y are two vnodes
523 				 * say real(Y) is X and real(X) is Z
524 				 * parent vnode for X and Y is Z
525 				 * lookup(Y,"path") say we are looking for Y
526 				 * again under Y and we have to return Yc.
527 				 * but the lookup of Y under Y doesnot return
528 				 * Y the root vnode again here is why.
529 				 * 1. lookup(Y,"path of Y") will go to
530 				 * 2. lookup(real(Y),"path of Y") and then to
531 				 * 3. lookup(real(X),"path of Y").
532 				 * and now what lookup level 1 sees is the
533 				 * outcome of 2 but the vnode Y is due to
534 				 * lookup(Z,"path of Y") so we have to skip
535 				 * intermediate levels to find if in any level
536 				 * there is a looping.
537 				 */
538 				is_indirectloop = 0;
539 				nonlovp = vp;
540 				while (
541 				    vfs_matchops(nonlovp->v_vfsp, lo_vfsops) &&
542 				    !(is_indirectloop)) {
543 					if (li->li_rootvp  == nonlovp) {
544 						is_indirectloop++;
545 						break;
546 					}
547 					nonlovp = realvp(nonlovp);
548 				}
549 
550 				if (is_indirectloop) {
551 					VN_RELE(vp);
552 					vp = nonlovp;
553 					vp = vp->v_vfsp->vfs_vnodecovered;
554 					VN_HOLD(vp);
555 					looping++;
556 				}
557 			}
558 		} else {
559 			/*
560 			 * come here only because of the interaction between
561 			 * the autofs and lofs.
562 			 *
563 			 * Lookup of "/net/X/net/X" will return a shadow of
564 			 * an autonode X_a which we call X_l.
565 			 *
566 			 * Lookup of anything under X_l, will trigger a call to
567 			 * auto_lookup(X_a,nm) which will eventually call
568 			 * lo_lookup(X_lr,nm) where X_lr is the root vnode of
569 			 * the current lofs.
570 			 *
571 			 * We come here only when we are called with X_l as dvp
572 			 * and look for something underneath.
573 			 *
574 			 * Now that an autofs/lofs looping condition has been
575 			 * identified any directory vnode contained within
576 			 * dvp will be set to the vnode covered by the
577 			 * mounted autofs. Thus all directories within dvp
578 			 * will appear empty hence teminating the looping.
579 			 * The LO_AUTOLOOP flag is set on the returned lonode
580 			 * to indicate the termination of the autofs/lofs
581 			 * looping. This is required for the correct behaviour
582 			 * when performing a dotdot.
583 			 */
584 			realdvp = realvp(dvp);
585 			while (vfs_matchops(realdvp->v_vfsp, lo_vfsops)) {
586 				realdvp = realvp(realdvp);
587 			}
588 
589 			error = VFS_ROOT(realdvp->v_vfsp, &tvp);
590 			if (error)
591 				goto out;
592 			/*
593 			 * tvp now contains the rootvp of the vfs of the
594 			 * real vnode of dvp. The directory vnode vp is set
595 			 * to the covered vnode to terminate looping. No
596 			 * distinction is made between any vp as all directory
597 			 * vnodes contained in dvp are returned as the covered
598 			 * vnode.
599 			 */
600 			VN_RELE(vp);
601 			vp = tvp;	/* this is an autonode */
602 
603 			/*
604 			 * Need to find the covered vnode
605 			 */
606 			vp = vp->v_vfsp->vfs_vnodecovered;
607 			ASSERT(vp);
608 			VN_HOLD(vp);
609 			VN_RELE(tvp);
610 			/*
611 			 * Force the creation of a new lnode even if the hash
612 			 * table contains a lnode that references this vnode.
613 			 */
614 			mkflag = LOF_FORCE;
615 			autoloop++;
616 		}
617 	}
618 	*vpp = makelonode(vp, li, mkflag);
619 
620 	if ((looping) ||
621 	    (((vtol(dvp))->lo_looping & LO_LOOPING) && !doingdotdot)) {
622 		(vtol(*vpp))->lo_looping |= LO_LOOPING;
623 	}
624 
625 	if (autoloop) {
626 		(vtol(*vpp))->lo_looping |= LO_AUTOLOOP;
627 	}
628 
629 out:
630 	if (error != 0 && vp != NULL)
631 		VN_RELE(vp);
632 #ifdef LODEBUG
633 	lo_dprint(4,
634 	"lo_lookup dvp %x realdvp %x nm '%s' newvp %x real vp %x error %d\n",
635 		dvp, realvp(dvp), nm, *vpp, vp, error);
636 #endif
637 	return (error);
638 }
639 
640 /*ARGSUSED*/
641 static int
642 lo_create(
643 	vnode_t *dvp,
644 	char *nm,
645 	struct vattr *va,
646 	enum vcexcl exclusive,
647 	int mode,
648 	vnode_t **vpp,
649 	struct cred *cr,
650 	int flag)
651 {
652 	int error;
653 	vnode_t *vp = NULL;
654 	vnode_t *tvp = NULL;
655 
656 #ifdef LODEBUG
657 	lo_dprint(4, "lo_create vp %p realvp %p\n", dvp, realvp(dvp));
658 #endif
659 	if (*nm == '\0') {
660 		ASSERT(vpp && dvp == *vpp);
661 		vp = realvp(*vpp);
662 	}
663 
664 	if (IS_ZONEDEVFS(dvp)) {
665 
666 		/*
667 		 * In the case of an exclusive create, *vpp will not
668 		 * be populated.  We must check to see if the file exists.
669 		 */
670 		if ((exclusive == EXCL) && (*nm != '\0')) {
671 			(void) VOP_LOOKUP(dvp, nm, &tvp, NULL, 0, NULL, cr);
672 		}
673 
674 		/* Is this truly a create?  If so, fail */
675 		if ((*vpp == NULL) && (tvp == NULL))
676 			return (EACCES);
677 
678 		if (tvp != NULL)
679 			VN_RELE(tvp);
680 
681 		/* Is this an open of a non-special for writing?  If so, fail */
682 		if (*vpp != NULL && (mode & VWRITE) && !IS_DEVVP(*vpp))
683 			return (EACCES);
684 	}
685 
686 	error = VOP_CREATE(realvp(dvp), nm, va, exclusive, mode, &vp, cr, flag);
687 	if (!error) {
688 		*vpp = makelonode(vp, vtoli(dvp->v_vfsp), 0);
689 		if (IS_DEVVP(*vpp)) {
690 			vnode_t *svp;
691 
692 			svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
693 			VN_RELE(*vpp);
694 			if (svp == NULL)
695 				error = ENOSYS;
696 			else
697 				*vpp = svp;
698 		}
699 	}
700 	return (error);
701 }
702 
703 static int
704 lo_remove(vnode_t *dvp, char *nm, struct cred *cr)
705 {
706 #ifdef LODEBUG
707 	lo_dprint(4, "lo_remove vp %p realvp %p\n", dvp, realvp(dvp));
708 #endif
709 	if (IS_ZONEDEVFS(dvp))
710 		return (EACCES);
711 	dvp = realvp(dvp);
712 	return (VOP_REMOVE(dvp, nm, cr));
713 }
714 
715 static int
716 lo_link(vnode_t *tdvp, vnode_t *vp, char *tnm, struct cred *cr)
717 {
718 #ifdef LODEBUG
719 	lo_dprint(4, "lo_link vp %p realvp %p\n", vp, realvp(vp));
720 #endif
721 	while (vn_matchops(vp, lo_vnodeops)) {
722 		if (IS_ZONEDEVFS(vp))
723 			return (EACCES);
724 		vp = realvp(vp);
725 	}
726 	while (vn_matchops(tdvp, lo_vnodeops)) {
727 		if (IS_ZONEDEVFS(tdvp))
728 			return (EACCES);
729 		tdvp = realvp(tdvp);
730 	}
731 	if (vp->v_vfsp != tdvp->v_vfsp)
732 		return (EXDEV);
733 	return (VOP_LINK(tdvp, vp, tnm, cr));
734 }
735 
736 static int
737 lo_rename(
738 	vnode_t *odvp,
739 	char *onm,
740 	vnode_t *ndvp,
741 	char *nnm,
742 	struct cred *cr)
743 {
744 	vnode_t *tnvp;
745 
746 #ifdef LODEBUG
747 	lo_dprint(4, "lo_rename vp %p realvp %p\n", odvp, realvp(odvp));
748 #endif
749 	if (IS_ZONEDEVFS(odvp))
750 		return (EACCES);
751 	/*
752 	 * We need to make sure we're not trying to remove a mount point for a
753 	 * filesystem mounted on top of lofs, which only we know about.
754 	 */
755 	if (vn_matchops(ndvp, lo_vnodeops))	/* Not our problem. */
756 		goto rename;
757 	if (VOP_LOOKUP(ndvp, nnm, &tnvp, NULL, 0, NULL, cr) != 0)
758 		goto rename;
759 	if (tnvp->v_type != VDIR) {
760 		VN_RELE(tnvp);
761 		goto rename;
762 	}
763 	if (vn_mountedvfs(tnvp)) {
764 		VN_RELE(tnvp);
765 		return (EBUSY);
766 	}
767 	VN_RELE(tnvp);
768 rename:
769 	/*
770 	 * Since the case we're dealing with above can happen at any layer in
771 	 * the stack of lofs filesystems, we need to recurse down the stack,
772 	 * checking to see if there are any instances of a filesystem mounted on
773 	 * top of lofs. In order to keep on using the lofs version of
774 	 * VOP_RENAME(), we make sure that while the target directory is of type
775 	 * lofs, the source directory (the one used for getting the fs-specific
776 	 * version of VOP_RENAME()) is also of type lofs.
777 	 */
778 	if (vn_matchops(ndvp, lo_vnodeops)) {
779 		if (IS_ZONEDEVFS(ndvp))
780 			return (EACCES);
781 		ndvp = realvp(ndvp);	/* Check the next layer */
782 	} else {
783 		/*
784 		 * We can go fast here
785 		 */
786 		while (vn_matchops(odvp, lo_vnodeops)) {
787 			if (IS_ZONEDEVFS(odvp))
788 				return (EACCES);
789 			odvp = realvp(odvp);
790 		}
791 		if (odvp->v_vfsp != ndvp->v_vfsp)
792 			return (EXDEV);
793 	}
794 	return (VOP_RENAME(odvp, onm, ndvp, nnm, cr));
795 }
796 
797 static int
798 lo_mkdir(
799 	vnode_t *dvp,
800 	char *nm,
801 	struct vattr *va,
802 	vnode_t **vpp,
803 	struct cred *cr)
804 {
805 	int error;
806 
807 #ifdef LODEBUG
808 	lo_dprint(4, "lo_mkdir vp %p realvp %p\n", dvp, realvp(dvp));
809 #endif
810 	if (IS_ZONEDEVFS(dvp))
811 		return (EACCES);
812 	error = VOP_MKDIR(realvp(dvp), nm, va, vpp, cr);
813 	if (!error)
814 		*vpp = makelonode(*vpp, vtoli(dvp->v_vfsp), 0);
815 	return (error);
816 }
817 
818 static int
819 lo_realvp(vnode_t *vp, vnode_t **vpp)
820 {
821 #ifdef LODEBUG
822 	lo_dprint(4, "lo_realvp %p\n", vp);
823 #endif
824 	while (vn_matchops(vp, lo_vnodeops))
825 		vp = realvp(vp);
826 
827 	if (VOP_REALVP(vp, vpp) != 0)
828 		*vpp = vp;
829 	return (0);
830 }
831 
832 static int
833 lo_rmdir(
834 	vnode_t *dvp,
835 	char *nm,
836 	vnode_t *cdir,
837 	struct cred *cr)
838 {
839 	vnode_t *rvp = cdir;
840 
841 #ifdef LODEBUG
842 	lo_dprint(4, "lo_rmdir vp %p realvp %p\n", dvp, realvp(dvp));
843 #endif
844 	if (IS_ZONEDEVFS(dvp))
845 		return (EACCES);
846 	/* if cdir is lofs vnode ptr get its real vnode ptr */
847 	if (vn_matchops(dvp, vn_getops(rvp)))
848 		(void) lo_realvp(cdir, &rvp);
849 	dvp = realvp(dvp);
850 	return (VOP_RMDIR(dvp, nm, rvp, cr));
851 }
852 
853 static int
854 lo_symlink(
855 	vnode_t *dvp,
856 	char *lnm,
857 	struct vattr *tva,
858 	char *tnm,
859 	struct cred *cr)
860 {
861 #ifdef LODEBUG
862 	lo_dprint(4, "lo_symlink vp %p realvp %p\n", dvp, realvp(dvp));
863 #endif
864 	if (IS_ZONEDEVFS(dvp))
865 		return (EACCES);
866 	dvp = realvp(dvp);
867 	return (VOP_SYMLINK(dvp, lnm, tva, tnm, cr));
868 }
869 
870 static int
871 lo_readlink(vnode_t *vp, struct uio *uiop, struct cred *cr)
872 {
873 	vp = realvp(vp);
874 	return (VOP_READLINK(vp, uiop, cr));
875 }
876 
877 static int
878 lo_readdir(vnode_t *vp, struct uio *uiop, struct cred *cr, int *eofp)
879 {
880 #ifdef LODEBUG
881 	lo_dprint(4, "lo_readdir vp %p realvp %p\n", vp, realvp(vp));
882 #endif
883 	vp = realvp(vp);
884 	return (VOP_READDIR(vp, uiop, cr, eofp));
885 }
886 
887 static int
888 lo_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct)
889 {
890 	vp = realvp(vp);
891 	return (VOP_RWLOCK(vp, write_lock, ct));
892 }
893 
894 static void
895 lo_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct)
896 {
897 	vp = realvp(vp);
898 	VOP_RWUNLOCK(vp, write_lock, ct);
899 }
900 
901 static int
902 lo_seek(vnode_t *vp, offset_t ooff, offset_t *noffp)
903 {
904 	vp = realvp(vp);
905 	return (VOP_SEEK(vp, ooff, noffp));
906 }
907 
908 static int
909 lo_cmp(vnode_t *vp1, vnode_t *vp2)
910 {
911 	while (vn_matchops(vp1, lo_vnodeops))
912 		vp1 = realvp(vp1);
913 	while (vn_matchops(vp2, lo_vnodeops))
914 		vp2 = realvp(vp2);
915 	return (VOP_CMP(vp1, vp2));
916 }
917 
918 static int
919 lo_frlock(
920 	vnode_t *vp,
921 	int cmd,
922 	struct flock64 *bfp,
923 	int flag,
924 	offset_t offset,
925 	struct flk_callback *flk_cbp,
926 	cred_t *cr)
927 {
928 	vp = realvp(vp);
929 	return (VOP_FRLOCK(vp, cmd, bfp, flag, offset, flk_cbp, cr));
930 }
931 
932 static int
933 lo_space(
934 	vnode_t *vp,
935 	int cmd,
936 	struct flock64 *bfp,
937 	int flag,
938 	offset_t offset,
939 	struct cred *cr,
940 	caller_context_t *ct)
941 {
942 	vp = realvp(vp);
943 	return (VOP_SPACE(vp, cmd, bfp, flag, offset, cr, ct));
944 }
945 
946 static int
947 lo_getpage(
948 	vnode_t *vp,
949 	offset_t off,
950 	size_t len,
951 	uint_t *prot,
952 	struct page *parr[],
953 	size_t psz,
954 	struct seg *seg,
955 	caddr_t addr,
956 	enum seg_rw rw,
957 	struct cred *cr)
958 {
959 	vp = realvp(vp);
960 	return (VOP_GETPAGE(vp, off, len, prot, parr, psz, seg, addr, rw, cr));
961 }
962 
963 static int
964 lo_putpage(vnode_t *vp, offset_t off, size_t len, int flags, struct cred *cr)
965 {
966 	vp = realvp(vp);
967 	return (VOP_PUTPAGE(vp, off, len, flags, cr));
968 }
969 
970 static int
971 lo_map(
972 	vnode_t *vp,
973 	offset_t off,
974 	struct as *as,
975 	caddr_t *addrp,
976 	size_t len,
977 	uchar_t prot,
978 	uchar_t maxprot,
979 	uint_t flags,
980 	struct cred *cr)
981 {
982 	vp = realvp(vp);
983 	return (VOP_MAP(vp, off, as, addrp, len, prot, maxprot, flags, cr));
984 }
985 
986 static int
987 lo_addmap(
988 	vnode_t *vp,
989 	offset_t off,
990 	struct as *as,
991 	caddr_t addr,
992 	size_t len,
993 	uchar_t prot,
994 	uchar_t maxprot,
995 	uint_t flags,
996 	struct cred *cr)
997 {
998 	vp = realvp(vp);
999 	return (VOP_ADDMAP(vp, off, as, addr, len, prot, maxprot, flags, cr));
1000 }
1001 
1002 static int
1003 lo_delmap(
1004 	vnode_t *vp,
1005 	offset_t off,
1006 	struct as *as,
1007 	caddr_t addr,
1008 	size_t len,
1009 	uint_t prot,
1010 	uint_t maxprot,
1011 	uint_t flags,
1012 	struct cred *cr)
1013 {
1014 	vp = realvp(vp);
1015 	return (VOP_DELMAP(vp, off, as, addr, len, prot, maxprot, flags, cr));
1016 }
1017 
1018 static int
1019 lo_poll(
1020 	vnode_t *vp,
1021 	short events,
1022 	int anyyet,
1023 	short *reventsp,
1024 	struct pollhead **phpp)
1025 {
1026 	vp = realvp(vp);
1027 	return (VOP_POLL(vp, events, anyyet, reventsp, phpp));
1028 }
1029 
1030 static int
1031 lo_dump(vnode_t *vp, caddr_t addr, int bn, int count)
1032 {
1033 	vp = realvp(vp);
1034 	return (VOP_DUMP(vp, addr, bn, count));
1035 }
1036 
1037 static int
1038 lo_pathconf(vnode_t *vp, int cmd, ulong_t *valp, struct cred *cr)
1039 {
1040 	vp = realvp(vp);
1041 	return (VOP_PATHCONF(vp, cmd, valp, cr));
1042 }
1043 
1044 static int
1045 lo_pageio(
1046 	vnode_t *vp,
1047 	struct page *pp,
1048 	u_offset_t io_off,
1049 	size_t io_len,
1050 	int flags,
1051 	cred_t *cr)
1052 {
1053 	vp = realvp(vp);
1054 	return (VOP_PAGEIO(vp, pp, io_off, io_len, flags, cr));
1055 }
1056 
1057 static void
1058 lo_dispose(vnode_t *vp, page_t *pp, int fl, int dn, cred_t *cr)
1059 {
1060 	vp = realvp(vp);
1061 	if (vp != NULL && vp != &kvp)
1062 		VOP_DISPOSE(vp, pp, fl, dn, cr);
1063 }
1064 
1065 static int
1066 lo_setsecattr(vnode_t *vp, vsecattr_t *secattr, int flags, struct cred *cr)
1067 {
1068 	if (vn_is_readonly(vp))
1069 		return (EROFS);
1070 	vp = realvp(vp);
1071 	return (VOP_SETSECATTR(vp, secattr, flags, cr));
1072 }
1073 
1074 static int
1075 lo_getsecattr(vnode_t *vp, vsecattr_t *secattr, int flags, struct cred *cr)
1076 {
1077 	vp = realvp(vp);
1078 	return (VOP_GETSECATTR(vp, secattr, flags, cr));
1079 }
1080 
1081 static int
1082 lo_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr)
1083 {
1084 	vp = realvp(vp);
1085 	return (VOP_SHRLOCK(vp, cmd, shr, flag, cr));
1086 }
1087 
1088 /*
1089  * Loopback vnode operations vector.
1090  */
1091 
1092 struct vnodeops *lo_vnodeops;
1093 
1094 const fs_operation_def_t lo_vnodeops_template[] = {
1095 	VOPNAME_OPEN, lo_open,
1096 	VOPNAME_CLOSE, lo_close,
1097 	VOPNAME_READ, lo_read,
1098 	VOPNAME_WRITE, lo_write,
1099 	VOPNAME_IOCTL, lo_ioctl,
1100 	VOPNAME_SETFL, lo_setfl,
1101 	VOPNAME_GETATTR, lo_getattr,
1102 	VOPNAME_SETATTR, lo_setattr,
1103 	VOPNAME_ACCESS, lo_access,
1104 	VOPNAME_LOOKUP, lo_lookup,
1105 	VOPNAME_CREATE, lo_create,
1106 	VOPNAME_REMOVE, lo_remove,
1107 	VOPNAME_LINK, lo_link,
1108 	VOPNAME_RENAME, lo_rename,
1109 	VOPNAME_MKDIR, lo_mkdir,
1110 	VOPNAME_RMDIR, lo_rmdir,
1111 	VOPNAME_READDIR, lo_readdir,
1112 	VOPNAME_SYMLINK, lo_symlink,
1113 	VOPNAME_READLINK, lo_readlink,
1114 	VOPNAME_FSYNC, lo_fsync,
1115 	VOPNAME_INACTIVE, (fs_generic_func_p) lo_inactive,
1116 	VOPNAME_FID, lo_fid,
1117 	VOPNAME_RWLOCK, lo_rwlock,
1118 	VOPNAME_RWUNLOCK, (fs_generic_func_p) lo_rwunlock,
1119 	VOPNAME_SEEK, lo_seek,
1120 	VOPNAME_CMP, lo_cmp,
1121 	VOPNAME_FRLOCK, lo_frlock,
1122 	VOPNAME_SPACE, lo_space,
1123 	VOPNAME_REALVP, lo_realvp,
1124 	VOPNAME_GETPAGE, lo_getpage,
1125 	VOPNAME_PUTPAGE, lo_putpage,
1126 	VOPNAME_MAP, (fs_generic_func_p) lo_map,
1127 	VOPNAME_ADDMAP, (fs_generic_func_p) lo_addmap,
1128 	VOPNAME_DELMAP, lo_delmap,
1129 	VOPNAME_POLL, (fs_generic_func_p) lo_poll,
1130 	VOPNAME_DUMP, lo_dump,
1131 	VOPNAME_DUMPCTL, fs_error,		/* XXX - why? */
1132 	VOPNAME_PATHCONF, lo_pathconf,
1133 	VOPNAME_PAGEIO, lo_pageio,
1134 	VOPNAME_DISPOSE, (fs_generic_func_p) lo_dispose,
1135 	VOPNAME_SETSECATTR, lo_setsecattr,
1136 	VOPNAME_GETSECATTR, lo_getsecattr,
1137 	VOPNAME_SHRLOCK, lo_shrlock,
1138 	NULL, NULL
1139 };
1140