xref: /titanic_50/usr/src/uts/common/fs/autofs/auto_vnops.c (revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/errno.h>
31 #include <sys/proc.h>
32 #include <sys/vnode.h>
33 #include <sys/vfs.h>
34 #include <sys/vfs_opreg.h>
35 #include <sys/uio.h>
36 #include <sys/cred.h>
37 #include <sys/pathname.h>
38 #include <sys/dirent.h>
39 #include <sys/debug.h>
40 #include <sys/sysmacros.h>
41 #include <sys/tiuser.h>
42 #include <sys/cmn_err.h>
43 #include <sys/stat.h>
44 #include <sys/mode.h>
45 #include <sys/policy.h>
46 #include <rpc/types.h>
47 #include <rpc/auth.h>
48 #include <rpc/clnt.h>
49 #include <sys/fs/autofs.h>
50 #include <rpcsvc/autofs_prot.h>
51 #include <fs/fs_subr.h>
52 
53 /*
54  *  Vnode ops for autofs
55  */
56 static int auto_open(vnode_t **, int, cred_t *);
57 static int auto_close(vnode_t *, int, int, offset_t, cred_t *);
58 static int auto_getattr(vnode_t *, vattr_t *, int, cred_t *);
59 static int auto_setattr(vnode_t *, vattr_t *, int, cred_t *,
60 	caller_context_t *);
61 static int auto_access(vnode_t *, int, int, cred_t *);
62 static int auto_lookup(vnode_t *, char *, vnode_t **,
63 	pathname_t *, int, vnode_t *, cred_t *);
64 static int auto_create(vnode_t *, char *, vattr_t *, vcexcl_t,
65 	int, vnode_t **, cred_t *, int);
66 static int auto_remove(vnode_t *, char *, cred_t *);
67 static int auto_link(vnode_t *, vnode_t *, char *, cred_t *);
68 static int auto_rename(vnode_t *, char *, vnode_t *, char *, cred_t *);
69 static int auto_mkdir(vnode_t *, char *, vattr_t *, vnode_t **, cred_t *);
70 static int auto_rmdir(vnode_t *, char *, vnode_t *, cred_t *);
71 static int auto_readdir(vnode_t *, uio_t *, cred_t *, int *);
72 static int auto_symlink(vnode_t *, char *, vattr_t *, char *, cred_t *);
73 static int auto_readlink(vnode_t *, struct uio *, cred_t *);
74 static int auto_fsync(vnode_t *, int, cred_t *);
75 static void auto_inactive(vnode_t *, cred_t *);
76 static int auto_rwlock(vnode_t *, int, caller_context_t *);
77 static void auto_rwunlock(vnode_t *vp, int, caller_context_t *);
78 static int auto_seek(vnode_t *vp, offset_t, offset_t *);
79 
80 static int auto_trigger_mount(vnode_t *, cred_t *, vnode_t **);
81 
82 vnodeops_t *auto_vnodeops;
83 
84 const fs_operation_def_t auto_vnodeops_template[] = {
85 	VOPNAME_OPEN,		{ .vop_open = auto_open },
86 	VOPNAME_CLOSE,		{ .vop_close = auto_close },
87 	VOPNAME_GETATTR,	{ .vop_getattr = auto_getattr },
88 	VOPNAME_SETATTR,	{ .vop_setattr = auto_setattr },
89 	VOPNAME_ACCESS,		{ .vop_access = auto_access },
90 	VOPNAME_LOOKUP,		{ .vop_lookup = auto_lookup },
91 	VOPNAME_CREATE,		{ .vop_create = auto_create },
92 	VOPNAME_REMOVE,		{ .vop_remove = auto_remove },
93 	VOPNAME_LINK,		{ .vop_link = auto_link },
94 	VOPNAME_RENAME,		{ .vop_rename = auto_rename },
95 	VOPNAME_MKDIR,		{ .vop_mkdir = auto_mkdir },
96 	VOPNAME_RMDIR,		{ .vop_rmdir = auto_rmdir },
97 	VOPNAME_READDIR,	{ .vop_readdir = auto_readdir },
98 	VOPNAME_SYMLINK,	{ .vop_symlink = auto_symlink },
99 	VOPNAME_READLINK,	{ .vop_readlink = auto_readlink },
100 	VOPNAME_FSYNC,		{ .vop_fsync = auto_fsync },
101 	VOPNAME_INACTIVE,	{ .vop_inactive = auto_inactive },
102 	VOPNAME_RWLOCK,		{ .vop_rwlock = auto_rwlock },
103 	VOPNAME_RWUNLOCK,	{ .vop_rwunlock = auto_rwunlock },
104 	VOPNAME_SEEK,		{ .vop_seek = auto_seek },
105 	VOPNAME_FRLOCK,		{ .error = fs_error },
106 	VOPNAME_DISPOSE,	{ .error = fs_error },
107 	VOPNAME_SHRLOCK,	{ .error = fs_error },
108 	VOPNAME_VNEVENT,	{ .vop_vnevent = fs_vnevent_support },
109 	NULL,			NULL
110 };
111 
112 
113 
114 /* ARGSUSED */
115 static int
116 auto_open(vnode_t **vpp, int flag, cred_t *cred)
117 {
118 	vnode_t *newvp;
119 	int error;
120 
121 	AUTOFS_DPRINT((4, "auto_open: *vpp=%p\n", (void *)*vpp));
122 
123 	error = auto_trigger_mount(*vpp, cred, &newvp);
124 	if (error)
125 		goto done;
126 
127 	if (newvp != NULL) {
128 		/*
129 		 * Node is now mounted on.
130 		 */
131 		VN_RELE(*vpp);
132 		*vpp = newvp;
133 		error = VOP_ACCESS(*vpp, VREAD, 0, cred);
134 		if (!error)
135 			error = VOP_OPEN(vpp, flag, cred);
136 	}
137 
138 done:
139 	AUTOFS_DPRINT((5, "auto_open: *vpp=%p error=%d\n", (void *)*vpp,
140 	    error));
141 	return (error);
142 }
143 
144 /* ARGSUSED */
145 static int
146 auto_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cred)
147 {
148 	return (0);
149 }
150 
151 static int
152 auto_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cred)
153 {
154 	fnnode_t *fnp = vntofn(vp);
155 	vnode_t *newvp;
156 	vfs_t *vfsp;
157 	int error;
158 
159 	AUTOFS_DPRINT((4, "auto_getattr vp %p\n", (void *)vp));
160 
161 	/*
162 	 * Recursive auto_getattr/mount; go to the vfsp == NULL
163 	 * case.
164 	 */
165 	if (vn_vfswlock_held(vp))
166 		goto defattr;
167 
168 	if (error = vn_vfsrlock_wait(vp))
169 		return (error);
170 
171 	vfsp = vn_mountedvfs(vp);
172 	if (vfsp != NULL) {
173 		/*
174 		 * Node is mounted on.
175 		 */
176 		error = VFS_ROOT(vfsp, &newvp);
177 		vn_vfsunlock(vp);
178 		if (error)
179 			return (error);
180 		mutex_enter(&fnp->fn_lock);
181 		if (fnp->fn_seen == newvp && fnp->fn_thread == curthread) {
182 			/*
183 			 * Recursive auto_getattr(); just release newvp and drop
184 			 * into the vfsp == NULL case.
185 			 */
186 			mutex_exit(&fnp->fn_lock);
187 			VN_RELE(newvp);
188 		} else {
189 			while (fnp->fn_thread && fnp->fn_thread != curthread) {
190 				fnp->fn_flags |= MF_ATTR_WAIT;
191 				cv_wait(&fnp->fn_cv_mount, &fnp->fn_lock);
192 			}
193 			fnp->fn_thread = curthread;
194 			fnp->fn_seen = newvp;
195 			mutex_exit(&fnp->fn_lock);
196 			error = VOP_GETATTR(newvp, vap, flags, cred);
197 			VN_RELE(newvp);
198 			mutex_enter(&fnp->fn_lock);
199 			fnp->fn_seen = 0;
200 			fnp->fn_thread = 0;
201 			if (fnp->fn_flags & MF_ATTR_WAIT) {
202 				fnp->fn_flags &= ~MF_ATTR_WAIT;
203 				cv_broadcast(&fnp->fn_cv_mount);
204 			}
205 			mutex_exit(&fnp->fn_lock);
206 			return (error);
207 		}
208 	} else {
209 		vn_vfsunlock(vp);
210 	}
211 
212 defattr:
213 	ASSERT(vp->v_type == VDIR || vp->v_type == VLNK);
214 	vap->va_uid	= 0;
215 	vap->va_gid	= 0;
216 	vap->va_nlink	= fnp->fn_linkcnt;
217 	vap->va_nodeid	= (u_longlong_t)fnp->fn_nodeid;
218 	vap->va_size	= fnp->fn_size;
219 	vap->va_atime	= fnp->fn_atime;
220 	vap->va_mtime	= fnp->fn_mtime;
221 	vap->va_ctime	= fnp->fn_ctime;
222 	vap->va_type	= vp->v_type;
223 	vap->va_mode	= fnp->fn_mode;
224 	vap->va_fsid	= vp->v_vfsp->vfs_dev;
225 	vap->va_rdev	= 0;
226 	vap->va_blksize	= MAXBSIZE;
227 	vap->va_nblocks	= (fsblkcnt64_t)btod(vap->va_size);
228 	vap->va_seq	= 0;
229 
230 	return (0);
231 }
232 
233 /*ARGSUSED4*/
234 static int
235 auto_setattr(
236 	vnode_t *vp,
237 	struct vattr *vap,
238 	int flags,
239 	cred_t *cred,
240 	caller_context_t *ct)
241 {
242 	vnode_t *newvp;
243 	int error;
244 
245 	AUTOFS_DPRINT((4, "auto_setattr vp %p\n", (void *)vp));
246 
247 	if (error = auto_trigger_mount(vp, cred, &newvp))
248 		goto done;
249 
250 	if (newvp != NULL) {
251 		/*
252 		 * Node is mounted on.
253 		 */
254 		if (vn_is_readonly(newvp))
255 			error = EROFS;
256 		else
257 			error = VOP_SETATTR(newvp, vap, flags, cred, NULL);
258 		VN_RELE(newvp);
259 	} else
260 		error = ENOSYS;
261 
262 done:
263 	AUTOFS_DPRINT((5, "auto_setattr: error=%d\n", error));
264 	return (error);
265 }
266 
267 /* ARGSUSED */
268 static int
269 auto_access(vnode_t *vp, int mode, int flags, cred_t *cred)
270 {
271 	fnnode_t *fnp = vntofn(vp);
272 	vnode_t *newvp;
273 	int error;
274 
275 	AUTOFS_DPRINT((4, "auto_access: vp=%p\n", (void *)vp));
276 
277 	if (error = auto_trigger_mount(vp, cred, &newvp))
278 		goto done;
279 
280 	if (newvp != NULL) {
281 		/*
282 		 * Node is mounted on.
283 		 */
284 		error = VOP_ACCESS(newvp, mode, 0, cred);
285 		VN_RELE(newvp);
286 	} else {
287 		int shift = 0;
288 
289 		/*
290 		 * really interested in the autofs node, check the
291 		 * access on it
292 		 */
293 		ASSERT(error == 0);
294 		if (crgetuid(cred) != fnp->fn_uid) {
295 			shift += 3;
296 			if (groupmember(fnp->fn_gid, cred) == 0)
297 				shift += 3;
298 		}
299 		mode &= ~(fnp->fn_mode << shift);
300 		if (mode != 0)
301 			error = secpolicy_vnode_access(cred, vp, fnp->fn_uid,
302 									mode);
303 	}
304 
305 done:
306 	AUTOFS_DPRINT((5, "auto_access: error=%d\n", error));
307 	return (error);
308 }
309 
310 static int
311 auto_lookup(
312 	vnode_t *dvp,
313 	char *nm,
314 	vnode_t **vpp,
315 	pathname_t *pnp,
316 	int flags,
317 	vnode_t *rdir,
318 	cred_t *cred)
319 {
320 	int error = 0;
321 	vnode_t *newvp = NULL;
322 	vfs_t *vfsp;
323 	fninfo_t *dfnip;
324 	fnnode_t *dfnp = NULL;
325 	fnnode_t *fnp = NULL;
326 	char *searchnm;
327 	int operation;		/* either AUTOFS_LOOKUP or AUTOFS_MOUNT */
328 
329 	dfnip = vfstofni(dvp->v_vfsp);
330 	AUTOFS_DPRINT((3, "auto_lookup: dvp=%p (%s) name=%s\n",
331 	    (void *)dvp, dfnip->fi_map, nm));
332 
333 	if (nm[0] == 0) {
334 		VN_HOLD(dvp);
335 		*vpp = dvp;
336 		return (0);
337 	}
338 
339 	if (error = VOP_ACCESS(dvp, VEXEC, 0, cred))
340 		return (error);
341 
342 	if (nm[0] == '.' && nm[1] == 0) {
343 		VN_HOLD(dvp);
344 		*vpp = dvp;
345 		return (0);
346 	}
347 
348 	if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) {
349 		fnnode_t *pdfnp;
350 
351 		pdfnp = (vntofn(dvp))->fn_parent;
352 		ASSERT(pdfnp != NULL);
353 
354 		/*
355 		 * Since it is legitimate to have the VROOT flag set for the
356 		 * subdirectories of the indirect map in autofs filesystem,
357 		 * rootfnnodep is checked against fnnode of dvp instead of
358 		 * just checking whether VROOT flag is set in dvp
359 		 */
360 
361 		if (pdfnp == pdfnp->fn_globals->fng_rootfnnodep) {
362 			vnode_t *vp;
363 
364 			vfs_rlock_wait(dvp->v_vfsp);
365 			if (dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) {
366 				vfs_unlock(dvp->v_vfsp);
367 				return (EIO);
368 			}
369 			vp = dvp->v_vfsp->vfs_vnodecovered;
370 			VN_HOLD(vp);
371 			vfs_unlock(dvp->v_vfsp);
372 			error = VOP_LOOKUP(vp, nm, vpp, pnp, flags, rdir, cred);
373 			VN_RELE(vp);
374 			return (error);
375 		} else {
376 			*vpp = fntovn(pdfnp);
377 			VN_HOLD(*vpp);
378 			return (0);
379 		}
380 	}
381 
382 top:
383 	dfnp = vntofn(dvp);
384 	searchnm = nm;
385 	operation = 0;
386 
387 	ASSERT(vn_matchops(dvp, auto_vnodeops));
388 
389 	AUTOFS_DPRINT((3, "auto_lookup: dvp=%p dfnp=%p\n", (void *)dvp,
390 	    (void *)dfnp));
391 
392 	/*
393 	 * If a lookup or mount of this node is in progress, wait for it
394 	 * to finish, and return whatever result it got.
395 	 */
396 	mutex_enter(&dfnp->fn_lock);
397 	if (dfnp->fn_flags & (MF_LOOKUP | MF_INPROG)) {
398 		mutex_exit(&dfnp->fn_lock);
399 		error = auto_wait4mount(dfnp);
400 		if (error == AUTOFS_SHUTDOWN)
401 			error = ENOENT;
402 		if (error == EAGAIN)
403 			goto top;
404 		if (error)
405 			return (error);
406 	} else
407 		mutex_exit(&dfnp->fn_lock);
408 
409 
410 	error = vn_vfsrlock_wait(dvp);
411 	if (error)
412 		return (error);
413 	vfsp = vn_mountedvfs(dvp);
414 	if (vfsp != NULL) {
415 		error = VFS_ROOT(vfsp, &newvp);
416 		vn_vfsunlock(dvp);
417 		if (!error) {
418 			error = VOP_LOOKUP(newvp, nm, vpp, pnp,
419 			    flags, rdir, cred);
420 			VN_RELE(newvp);
421 		}
422 		return (error);
423 	}
424 	vn_vfsunlock(dvp);
425 
426 	rw_enter(&dfnp->fn_rwlock, RW_READER);
427 	error = auto_search(dfnp, nm, &fnp, cred);
428 	if (error) {
429 		if (dfnip->fi_flags & MF_DIRECT) {
430 			/*
431 			 * direct map.
432 			 */
433 			if (dfnp->fn_dirents) {
434 				/*
435 				 * Mount previously triggered.
436 				 * 'nm' not found
437 				 */
438 				error = ENOENT;
439 			} else {
440 				/*
441 				 * I need to contact the daemon to trigger
442 				 * the mount. 'dfnp' will be the mountpoint.
443 				 */
444 				operation = AUTOFS_MOUNT;
445 				VN_HOLD(fntovn(dfnp));
446 				fnp = dfnp;
447 				error = 0;
448 			}
449 		} else if (dvp == dfnip->fi_rootvp) {
450 			/*
451 			 * 'dfnp' is the root of the indirect AUTOFS.
452 			 */
453 			if (rw_tryupgrade(&dfnp->fn_rwlock) == 0) {
454 				/*
455 				 * Could not acquire writer lock, release
456 				 * reader, and wait until available. We
457 				 * need to search for 'nm' again, since we
458 				 * had to release the lock before reacquiring
459 				 * it.
460 				 */
461 				rw_exit(&dfnp->fn_rwlock);
462 				rw_enter(&dfnp->fn_rwlock, RW_WRITER);
463 				error = auto_search(dfnp, nm, &fnp, cred);
464 			}
465 
466 			ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock));
467 			if (error) {
468 				/*
469 				 * create node being looked-up and request
470 				 * mount on it.
471 				 */
472 				error = auto_enter(dfnp, nm, &fnp, kcred);
473 				if (!error)
474 					operation = AUTOFS_LOOKUP;
475 			}
476 		} else if ((dfnp->fn_dirents == NULL) &&
477 		    ((dvp->v_flag & VROOT) == 0) &&
478 		    ((fntovn(dfnp->fn_parent))->v_flag & VROOT)) {
479 			/*
480 			 * dfnp is the actual 'mountpoint' of indirect map,
481 			 * it is the equivalent of a direct mount,
482 			 * ie, /home/'user1'
483 			 */
484 			operation = AUTOFS_MOUNT;
485 			VN_HOLD(fntovn(dfnp));
486 			fnp = dfnp;
487 			error = 0;
488 			searchnm = dfnp->fn_name;
489 		}
490 	}
491 
492 	if (error == EAGAIN) {
493 		rw_exit(&dfnp->fn_rwlock);
494 		goto top;
495 	}
496 	if (error) {
497 		rw_exit(&dfnp->fn_rwlock);
498 		return (error);
499 	}
500 
501 	/*
502 	 * We now have the actual fnnode we're interested in.
503 	 * The 'MF_LOOKUP' indicates another thread is currently
504 	 * performing a daemon lookup of this node, therefore we
505 	 * wait for its completion.
506 	 * The 'MF_INPROG' indicates another thread is currently
507 	 * performing a daemon mount of this node, we wait for it
508 	 * to be done if we are performing a MOUNT. We don't
509 	 * wait for it if we are performing a LOOKUP.
510 	 * We can release the reader/writer lock as soon as we acquire
511 	 * the mutex, since the state of the lock can only change by
512 	 * first acquiring the mutex.
513 	 */
514 	mutex_enter(&fnp->fn_lock);
515 	rw_exit(&dfnp->fn_rwlock);
516 	if ((fnp->fn_flags & MF_LOOKUP) ||
517 	    ((operation == AUTOFS_MOUNT) && (fnp->fn_flags & MF_INPROG))) {
518 		mutex_exit(&fnp->fn_lock);
519 		error = auto_wait4mount(fnp);
520 		VN_RELE(fntovn(fnp));
521 		if (error == AUTOFS_SHUTDOWN)
522 			error = ENOENT;
523 		if (error && error != EAGAIN)
524 			return (error);
525 		goto top;
526 	}
527 
528 	if (operation == 0) {
529 		/*
530 		 * got the fnnode, check for any errors
531 		 * on the previous operation on that node.
532 		 */
533 		error = fnp->fn_error;
534 		if ((error == EINTR) || (error == EAGAIN)) {
535 			/*
536 			 * previous operation on this node was
537 			 * not completed, do a lookup now.
538 			 */
539 			operation = AUTOFS_LOOKUP;
540 		} else {
541 			/*
542 			 * previous operation completed. Return
543 			 * a pointer to the node only if there was
544 			 * no error.
545 			 */
546 			mutex_exit(&fnp->fn_lock);
547 			if (!error)
548 				*vpp = fntovn(fnp);
549 			else
550 				VN_RELE(fntovn(fnp));
551 			return (error);
552 		}
553 	}
554 
555 	/*
556 	 * Since I got to this point, it means I'm the one
557 	 * responsible for triggering the mount/look-up of this node.
558 	 */
559 	switch (operation) {
560 	case AUTOFS_LOOKUP:
561 		AUTOFS_BLOCK_OTHERS(fnp, MF_LOOKUP);
562 		fnp->fn_error = 0;
563 		mutex_exit(&fnp->fn_lock);
564 		error = auto_lookup_aux(fnp, searchnm, cred);
565 		if (!error) {
566 			/*
567 			 * Return this vnode
568 			 */
569 			*vpp = fntovn(fnp);
570 		} else {
571 			/*
572 			 * release our reference to this vnode
573 			 * and return error
574 			 */
575 			VN_RELE(fntovn(fnp));
576 		}
577 		break;
578 	case AUTOFS_MOUNT:
579 		AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG);
580 		fnp->fn_error = 0;
581 		mutex_exit(&fnp->fn_lock);
582 		/*
583 		 * auto_new_mount_thread fires up a new thread which
584 		 * calls automountd finishing up the work
585 		 */
586 		auto_new_mount_thread(fnp, searchnm, cred);
587 
588 		/*
589 		 * At this point, we are simply another thread
590 		 * waiting for the mount to complete
591 		 */
592 		error = auto_wait4mount(fnp);
593 		if (error == AUTOFS_SHUTDOWN)
594 			error = ENOENT;
595 
596 		/*
597 		 * now release our reference to this vnode
598 		 */
599 		VN_RELE(fntovn(fnp));
600 		if (!error)
601 			goto top;
602 		break;
603 	default:
604 		auto_log(dfnp->fn_globals->fng_verbose,
605 			dfnp->fn_globals->fng_zoneid, CE_WARN,
606 			"auto_lookup: unknown "
607 		    "operation %d", operation);
608 	}
609 
610 	AUTOFS_DPRINT((5, "auto_lookup: name=%s *vpp=%p return=%d\n",
611 	    nm, (void *)*vpp, error));
612 
613 	return (error);
614 }
615 
616 static int
617 auto_create(
618 	vnode_t *dvp,
619 	char *nm,
620 	vattr_t *va,
621 	vcexcl_t excl,
622 	int mode,
623 	vnode_t **vpp,
624 	cred_t *cred,
625 	int flag)
626 {
627 	vnode_t *newvp;
628 	int error;
629 
630 	AUTOFS_DPRINT((4, "auto_create dvp %p nm %s\n", (void *)dvp, nm));
631 
632 	if (error = auto_trigger_mount(dvp, cred, &newvp))
633 		goto done;
634 
635 	if (newvp != NULL) {
636 		/*
637 		 * Node is now mounted on.
638 		 */
639 		if (vn_is_readonly(newvp))
640 			error = EROFS;
641 		else
642 			error = VOP_CREATE(newvp, nm, va, excl,
643 			    mode, vpp, cred, flag);
644 		VN_RELE(newvp);
645 	} else
646 		error = ENOSYS;
647 
648 done:
649 	AUTOFS_DPRINT((5, "auto_create: error=%d\n", error));
650 	return (error);
651 }
652 
653 static int
654 auto_remove(vnode_t *dvp, char *nm, cred_t *cred)
655 {
656 	vnode_t *newvp;
657 	int error;
658 
659 	AUTOFS_DPRINT((4, "auto_remove dvp %p nm %s\n", (void *)dvp, nm));
660 
661 	if (error = auto_trigger_mount(dvp, cred, &newvp))
662 		goto done;
663 
664 	if (newvp != NULL) {
665 		/*
666 		 * Node is now mounted on.
667 		 */
668 		if (vn_is_readonly(newvp))
669 			error = EROFS;
670 		else
671 			error = VOP_REMOVE(newvp, nm, cred);
672 		VN_RELE(newvp);
673 	} else
674 		error = ENOSYS;
675 
676 done:
677 	AUTOFS_DPRINT((5, "auto_remove: error=%d\n", error));
678 	return (error);
679 }
680 
681 static int
682 auto_link(vnode_t *tdvp, vnode_t *svp, char *nm, cred_t *cred)
683 {
684 	vnode_t *newvp;
685 	int error;
686 
687 	AUTOFS_DPRINT((4, "auto_link tdvp %p svp %p nm %s\n", (void *)tdvp,
688 	    (void *)svp, nm));
689 
690 	if (error = auto_trigger_mount(tdvp, cred, &newvp))
691 		goto done;
692 
693 	if (newvp == NULL) {
694 		/*
695 		 * an autonode can not be a link to another node
696 		 */
697 		error = ENOSYS;
698 		goto done;
699 	}
700 
701 	if (vn_is_readonly(newvp)) {
702 		error = EROFS;
703 		VN_RELE(newvp);
704 		goto done;
705 	}
706 
707 	if (vn_matchops(svp, auto_vnodeops)) {
708 		/*
709 		 * source vp can't be an autonode
710 		 */
711 		error = ENOSYS;
712 		VN_RELE(newvp);
713 		goto done;
714 	}
715 
716 	error = VOP_LINK(newvp, svp, nm, cred);
717 	VN_RELE(newvp);
718 
719 done:
720 	AUTOFS_DPRINT((5, "auto_link error=%d\n", error));
721 	return (error);
722 }
723 
724 static int
725 auto_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr)
726 {
727 	vnode_t *o_newvp, *n_newvp;
728 	int error;
729 
730 	AUTOFS_DPRINT((4, "auto_rename odvp %p onm %s to ndvp %p nnm %s\n",
731 	    (void *)odvp, onm, (void *)ndvp, nnm));
732 
733 	/*
734 	 * we know odvp is an autonode, otherwise this function
735 	 * could not have ever been called.
736 	 */
737 	ASSERT(vn_matchops(odvp, auto_vnodeops));
738 
739 	if (error = auto_trigger_mount(odvp, cr, &o_newvp))
740 		goto done;
741 
742 	if (o_newvp == NULL) {
743 		/*
744 		 * can't rename an autonode
745 		 */
746 		error = ENOSYS;
747 		goto done;
748 	}
749 
750 	if (vn_matchops(ndvp, auto_vnodeops)) {
751 		/*
752 		 * directory is AUTOFS, need to trigger the
753 		 * mount of the real filesystem.
754 		 */
755 		if (error = auto_trigger_mount(ndvp, cr, &n_newvp)) {
756 			VN_RELE(o_newvp);
757 			goto done;
758 		}
759 
760 		if (n_newvp == NULL) {
761 			/*
762 			 * target can't be an autonode
763 			 */
764 			error = ENOSYS;
765 			VN_RELE(o_newvp);
766 			goto done;
767 		}
768 	} else {
769 		/*
770 		 * destination directory mount had been
771 		 * triggered prior to the call to this function.
772 		 */
773 		n_newvp = ndvp;
774 	}
775 
776 	ASSERT(!vn_matchops(n_newvp, auto_vnodeops));
777 
778 	if (vn_is_readonly(n_newvp)) {
779 		error = EROFS;
780 		VN_RELE(o_newvp);
781 		if (n_newvp != ndvp)
782 			VN_RELE(n_newvp);
783 		goto done;
784 	}
785 
786 	error = VOP_RENAME(o_newvp, onm, n_newvp, nnm, cr);
787 	VN_RELE(o_newvp);
788 	if (n_newvp != ndvp)
789 		VN_RELE(n_newvp);
790 
791 done:
792 	AUTOFS_DPRINT((5, "auto_rename error=%d\n", error));
793 	return (error);
794 }
795 
796 static int
797 auto_mkdir(vnode_t *dvp, char *nm, vattr_t *va, vnode_t **vpp, cred_t *cred)
798 {
799 	vnode_t *newvp;
800 	int error;
801 
802 	AUTOFS_DPRINT((4, "auto_mkdir dvp %p nm %s\n", (void *)dvp, nm));
803 
804 	if (error = auto_trigger_mount(dvp, cred, &newvp))
805 		goto done;
806 
807 	if (newvp != NULL) {
808 		/*
809 		 * Node is now mounted on.
810 		 */
811 		if (vn_is_readonly(newvp))
812 			error = EROFS;
813 		else
814 			error = VOP_MKDIR(newvp, nm, va, vpp, cred);
815 		VN_RELE(newvp);
816 	} else
817 		error = ENOSYS;
818 
819 done:
820 	AUTOFS_DPRINT((5, "auto_mkdir: error=%d\n", error));
821 	return (error);
822 }
823 
824 static int
825 auto_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cred)
826 {
827 	vnode_t *newvp;
828 	int error;
829 
830 	AUTOFS_DPRINT((4, "auto_rmdir: vp=%p nm=%s\n", (void *)dvp, nm));
831 
832 	if (error = auto_trigger_mount(dvp, cred, &newvp))
833 		goto done;
834 
835 	if (newvp != NULL) {
836 		/*
837 		 * Node is now mounted on.
838 		 */
839 		if (vn_is_readonly(newvp))
840 			error = EROFS;
841 		else
842 			error = VOP_RMDIR(newvp, nm, cdir, cred);
843 		VN_RELE(newvp);
844 	} else
845 		error = ENOSYS;
846 
847 done:
848 	AUTOFS_DPRINT((5, "auto_rmdir: error=%d\n", error));
849 	return (error);
850 }
851 
852 static int autofs_nobrowse = 0;
853 
854 #ifdef nextdp
855 #undef nextdp
856 #endif
857 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
858 
859 static int
860 auto_readdir(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp)
861 {
862 	struct autofs_rddirargs	rda;
863 	autofs_rddirres rd;
864 	fnnode_t *fnp = vntofn(vp);
865 	fnnode_t *cfnp, *nfnp;
866 	dirent64_t *dp;
867 	ulong_t offset;
868 	ulong_t outcount = 0, count = 0;
869 	size_t namelen;
870 	ulong_t alloc_count;
871 	void *outbuf = NULL;
872 	fninfo_t *fnip = vfstofni(vp->v_vfsp);
873 	struct iovec *iovp;
874 	int error = 0;
875 	int reached_max = 0;
876 	int myeof = 0;
877 	int this_reclen;
878 	struct autofs_globals *fngp = vntofn(fnip->fi_rootvp)->fn_globals;
879 
880 	AUTOFS_DPRINT((4, "auto_readdir vp=%p offset=%lld\n",
881 	    (void *)vp, uiop->uio_loffset));
882 
883 	if (eofp != NULL)
884 		*eofp = 0;
885 
886 	if (uiop->uio_iovcnt != 1)
887 		return (EINVAL);
888 
889 	iovp = uiop->uio_iov;
890 	alloc_count = iovp->iov_len;
891 
892 	gethrestime(&fnp->fn_atime);
893 	fnp->fn_ref_time = fnp->fn_atime.tv_sec;
894 
895 	dp = outbuf = kmem_zalloc(alloc_count, KM_SLEEP);
896 
897 	/*
898 	 * Held when getdents calls VOP_RWLOCK....
899 	 */
900 	ASSERT(RW_READ_HELD(&fnp->fn_rwlock));
901 	if (uiop->uio_offset >= AUTOFS_DAEMONCOOKIE) {
902 again:
903 		/*
904 		 * Do readdir of daemon contents only
905 		 * Drop readers lock and reacquire after reply.
906 		 */
907 		rw_exit(&fnp->fn_rwlock);
908 		bzero(&rd, sizeof (struct autofs_rddirres));
909 		count = 0;
910 		rda.rda_map = fnip->fi_map;
911 		rda.rda_offset = (uint_t)uiop->uio_offset;
912 		rd.rd_rddir.rddir_entries = dp;
913 		rda.rda_count = rd.rd_rddir.rddir_size = (uint_t)alloc_count;
914 		rda.uid = crgetuid(cred);
915 
916 		error = auto_calldaemon(fngp->fng_zoneid,
917 			AUTOFS_READDIR,
918 			xdr_autofs_rddirargs,
919 			&rda,
920 			xdr_autofs_rddirres,
921 			(void *)&rd,
922 			sizeof (autofs_rddirres),
923 			TRUE);
924 
925 		/*
926 		 * reacquire previously dropped lock
927 		 */
928 		rw_enter(&fnp->fn_rwlock, RW_READER);
929 
930 		if (!error) {
931 			error = rd.rd_status;
932 			dp = rd.rd_rddir.rddir_entries;
933 		}
934 
935 		if (error) {
936 			if (error == AUTOFS_SHUTDOWN) {
937 				/*
938 				 * treat as empty directory
939 				 */
940 				error = 0;
941 				myeof = 1;
942 				if (eofp)
943 					*eofp = 1;
944 			}
945 			goto done;
946 		}
947 		if (rd.rd_rddir.rddir_size) {
948 			dirent64_t *odp = dp;   /* next in output buffer */
949 			dirent64_t *cdp = dp;   /* current examined entry */
950 
951 			/*
952 			 * Check for duplicates here
953 			 */
954 			do {
955 				this_reclen = cdp->d_reclen;
956 				if (auto_search(fnp, cdp->d_name,
957 					NULL, cred)) {
958 					/*
959 					 * entry not found in kernel list,
960 					 * include it in readdir output.
961 					 *
962 					 * If we are skipping entries. then
963 					 * we need to copy this entry to the
964 					 * correct position in the buffer
965 					 * to be copied out.
966 					 */
967 					if (cdp != odp)
968 						bcopy(cdp, odp,
969 							(size_t)this_reclen);
970 					odp = nextdp(odp);
971 					outcount += this_reclen;
972 				} else {
973 					/*
974 					 * Entry was found in the kernel
975 					 * list. If it is the first entry
976 					 * in this buffer, then just skip it
977 					 */
978 					if (odp == dp) {
979 						dp = nextdp(dp);
980 						odp = dp;
981 					}
982 				}
983 				count += this_reclen;
984 				cdp = (struct dirent64 *)
985 					((char *)cdp + this_reclen);
986 			} while (count < rd.rd_rddir.rddir_size);
987 
988 			if (outcount)
989 				error = uiomove(dp, outcount, UIO_READ, uiop);
990 			uiop->uio_offset = rd.rd_rddir.rddir_offset;
991 		} else {
992 			if (rd.rd_rddir.rddir_eof == 0) {
993 				/*
994 				 * alloc_count not large enough for one
995 				 * directory entry
996 				 */
997 				error = EINVAL;
998 			}
999 		}
1000 		if (rd.rd_rddir.rddir_eof && !error) {
1001 			myeof = 1;
1002 			if (eofp)
1003 				*eofp = 1;
1004 		}
1005 		if (!error && !myeof && outcount == 0) {
1006 			/*
1007 			 * call daemon with new cookie, all previous
1008 			 * elements happened to be duplicates
1009 			 */
1010 			dp = outbuf;
1011 			goto again;
1012 		}
1013 		goto done;
1014 	}
1015 
1016 	if (uiop->uio_offset == 0) {
1017 		/*
1018 		 * first time: so fudge the . and ..
1019 		 */
1020 		this_reclen = DIRENT64_RECLEN(1);
1021 		if (alloc_count < this_reclen) {
1022 			error = EINVAL;
1023 			goto done;
1024 		}
1025 		dp->d_ino = (ino64_t)fnp->fn_nodeid;
1026 		dp->d_off = (off64_t)1;
1027 		dp->d_reclen = (ushort_t)this_reclen;
1028 
1029 		/* use strncpy(9f) to zero out uninitialized bytes */
1030 
1031 		(void) strncpy(dp->d_name, ".",
1032 			DIRENT64_NAMELEN(this_reclen));
1033 		outcount += dp->d_reclen;
1034 		dp = nextdp(dp);
1035 
1036 		this_reclen = DIRENT64_RECLEN(2);
1037 		if (alloc_count < outcount + this_reclen) {
1038 			error = EINVAL;
1039 			goto done;
1040 		}
1041 		dp->d_reclen = (ushort_t)this_reclen;
1042 		dp->d_ino = (ino64_t)fnp->fn_parent->fn_nodeid;
1043 		dp->d_off = (off64_t)2;
1044 
1045 		/* use strncpy(9f) to zero out uninitialized bytes */
1046 
1047 		(void) strncpy(dp->d_name, "..",
1048 			DIRENT64_NAMELEN(this_reclen));
1049 		outcount += dp->d_reclen;
1050 		dp = nextdp(dp);
1051 	}
1052 
1053 	offset = 2;
1054 	cfnp = fnp->fn_dirents;
1055 	while (cfnp != NULL) {
1056 		nfnp = cfnp->fn_next;
1057 		offset = cfnp->fn_offset;
1058 		if ((offset >= uiop->uio_offset) &&
1059 			(!(cfnp->fn_flags & MF_LOOKUP))) {
1060 			int reclen;
1061 
1062 			/*
1063 			 * include node only if its offset is greater or
1064 			 * equal to the one required and it is not in
1065 			 * transient state (not being looked-up)
1066 			 */
1067 			namelen = strlen(cfnp->fn_name);
1068 			reclen = (int)DIRENT64_RECLEN(namelen);
1069 			if (outcount + reclen > alloc_count) {
1070 				reached_max = 1;
1071 				break;
1072 			}
1073 			dp->d_reclen = (ushort_t)reclen;
1074 			dp->d_ino = (ino64_t)cfnp->fn_nodeid;
1075 			if (nfnp != NULL) {
1076 				/*
1077 				 * get the offset of the next element
1078 				 */
1079 				dp->d_off = (off64_t)nfnp->fn_offset;
1080 			} else {
1081 				/*
1082 				 * This is the last element, make
1083 				 * offset one plus the current
1084 				 */
1085 				dp->d_off = (off64_t)cfnp->fn_offset + 1;
1086 			}
1087 
1088 			/* use strncpy(9f) to zero out uninitialized bytes */
1089 
1090 			(void) strncpy(dp->d_name, cfnp->fn_name,
1091 				DIRENT64_NAMELEN(reclen));
1092 			outcount += dp->d_reclen;
1093 			dp = nextdp(dp);
1094 		}
1095 		cfnp = nfnp;
1096 	}
1097 
1098 	if (outcount)
1099 		error = uiomove(outbuf, outcount, UIO_READ, uiop);
1100 	if (!error) {
1101 		if (reached_max) {
1102 			/*
1103 			 * This entry did not get added to the buffer on this,
1104 			 * call. We need to add it on the next call therefore
1105 			 * set uio_offset to this entry's offset.  If there
1106 			 * wasn't enough space for one dirent, return EINVAL.
1107 			 */
1108 			uiop->uio_offset = offset;
1109 			if (outcount == 0)
1110 				error = EINVAL;
1111 		} else if (autofs_nobrowse ||
1112 			auto_nobrowse_option(fnip->fi_opts) ||
1113 			(fnip->fi_flags & MF_DIRECT) ||
1114 			(fnp->fn_trigger != NULL) ||
1115 			(((vp->v_flag & VROOT) == 0) &&
1116 				((fntovn(fnp->fn_parent))->v_flag & VROOT) &&
1117 				(fnp->fn_dirents == NULL))) {
1118 			/*
1119 			 * done reading directory entries
1120 			 */
1121 			uiop->uio_offset = offset + 1;
1122 			if (eofp)
1123 				*eofp = 1;
1124 		} else {
1125 			/*
1126 			 * Need to get the rest of the entries from the daemon.
1127 			 */
1128 			uiop->uio_offset = AUTOFS_DAEMONCOOKIE;
1129 		}
1130 	}
1131 
1132 done:
1133 	kmem_free(outbuf, alloc_count);
1134 	AUTOFS_DPRINT((5, "auto_readdir vp=%p offset=%lld eof=%d\n",
1135 		(void *)vp, uiop->uio_loffset, myeof));
1136 	return (error);
1137 }
1138 
1139 static int
1140 auto_symlink(
1141 	vnode_t *dvp,
1142 	char *lnknm,		/* new entry */
1143 	vattr_t *tva,
1144 	char *tnm,		/* existing entry */
1145 	cred_t *cred)
1146 {
1147 	vnode_t *newvp;
1148 	int error;
1149 
1150 	AUTOFS_DPRINT((4, "auto_symlink: dvp=%p lnknm=%s tnm=%s\n",
1151 	    (void *)dvp, lnknm, tnm));
1152 
1153 	if (error = auto_trigger_mount(dvp, cred, &newvp))
1154 		goto done;
1155 
1156 	if (newvp != NULL) {
1157 		/*
1158 		 * Node is mounted on.
1159 		 */
1160 		if (vn_is_readonly(newvp))
1161 			error = EROFS;
1162 		else
1163 			error = VOP_SYMLINK(newvp, lnknm, tva, tnm, cred);
1164 		VN_RELE(newvp);
1165 	} else
1166 		error = ENOSYS;
1167 
1168 done:
1169 	AUTOFS_DPRINT((5, "auto_symlink: error=%d\n", error));
1170 	return (error);
1171 }
1172 
1173 /* ARGSUSED */
1174 static int
1175 auto_readlink(vnode_t *vp, struct uio *uiop, cred_t *cr)
1176 {
1177 	fnnode_t *fnp = vntofn(vp);
1178 	int error;
1179 	timestruc_t now;
1180 
1181 	AUTOFS_DPRINT((4, "auto_readlink: vp=%p\n", (void *)vp));
1182 
1183 	gethrestime(&now);
1184 	fnp->fn_ref_time = now.tv_sec;
1185 
1186 	if (vp->v_type != VLNK)
1187 		error = EINVAL;
1188 	else {
1189 		ASSERT(!(fnp->fn_flags & (MF_INPROG | MF_LOOKUP)));
1190 		fnp->fn_atime = now;
1191 		error = uiomove(fnp->fn_symlink, MIN(fnp->fn_symlinklen,
1192 		    uiop->uio_resid), UIO_READ, uiop);
1193 	}
1194 
1195 	AUTOFS_DPRINT((5, "auto_readlink: error=%d\n", error));
1196 	return (error);
1197 }
1198 
1199 /* ARGSUSED */
1200 static int
1201 auto_fsync(vnode_t *cp, int syncflag, cred_t *cred)
1202 {
1203 	return (0);
1204 }
1205 
1206 /* ARGSUSED */
1207 static void
1208 auto_inactive(vnode_t *vp, cred_t *cred)
1209 {
1210 	fnnode_t *fnp = vntofn(vp);
1211 	fnnode_t *dfnp = fnp->fn_parent;
1212 	int count;
1213 
1214 	AUTOFS_DPRINT((4, "auto_inactive: vp=%p v_count=%u fn_link=%d\n",
1215 	    (void *)vp, vp->v_count, fnp->fn_linkcnt));
1216 
1217 	/*
1218 	 * The rwlock should not be already held by this thread.
1219 	 * The assert relies on the fact that the owner field is cleared
1220 	 * when the lock is released.
1221 	 */
1222 	ASSERT(dfnp != NULL);
1223 	ASSERT(rw_owner(&dfnp->fn_rwlock) != curthread);
1224 	rw_enter(&dfnp->fn_rwlock, RW_WRITER);
1225 	mutex_enter(&vp->v_lock);
1226 	ASSERT(vp->v_count > 0);
1227 	count = --vp->v_count;
1228 	mutex_exit(&vp->v_lock);
1229 	if (count == 0) {
1230 		/*
1231 		 * Free only if node has no subdirectories.
1232 		 */
1233 		if (fnp->fn_linkcnt == 1) {
1234 			auto_disconnect(dfnp, fnp);
1235 			rw_exit(&dfnp->fn_rwlock);
1236 			auto_freefnnode(fnp);
1237 			AUTOFS_DPRINT((5, "auto_inactive: (exit) vp=%p freed\n",
1238 			    (void *)vp));
1239 			return;
1240 		}
1241 	}
1242 	rw_exit(&dfnp->fn_rwlock);
1243 
1244 	AUTOFS_DPRINT((5, "auto_inactive: (exit) vp=%p v_count=%u fn_link=%d\n",
1245 	    (void *)vp, vp->v_count, fnp->fn_linkcnt));
1246 }
1247 
1248 /* ARGSUSED2 */
1249 static int
1250 auto_rwlock(vnode_t *vp, int write_lock, caller_context_t *ct)
1251 {
1252 	fnnode_t *fnp = vntofn(vp);
1253 	if (write_lock)
1254 		rw_enter(&fnp->fn_rwlock, RW_WRITER);
1255 	else
1256 		rw_enter(&fnp->fn_rwlock, RW_READER);
1257 	return (write_lock);
1258 }
1259 
1260 /* ARGSUSED */
1261 static void
1262 auto_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ct)
1263 {
1264 	fnnode_t *fnp = vntofn(vp);
1265 	rw_exit(&fnp->fn_rwlock);
1266 }
1267 
1268 
1269 /* ARGSUSED */
1270 static int
1271 auto_seek(struct vnode *vp, offset_t ooff, offset_t *noffp)
1272 {
1273 	/*
1274 	 * Return 0 unconditionally, since we expect
1275 	 * a VDIR all the time
1276 	 */
1277 	return (0);
1278 }
1279 
1280 /*
1281  * Triggers the mount if needed. If the mount has been triggered by
1282  * another thread, it will wait for its return status, and return it.
1283  * Whether the mount is triggered by this thread, another thread, or
1284  * if the vnode was already covered, '*newvp' is a
1285  * VN_HELD vnode pointing to the root of the filesystem covering 'vp'.
1286  * If the node is not mounted on, and should not be mounted on, '*newvp'
1287  * will be NULL.
1288  * The calling routine may use '*newvp' to do the filesystem jump.
1289  */
1290 static int
1291 auto_trigger_mount(vnode_t *vp, cred_t *cred, vnode_t **newvp)
1292 {
1293 	fnnode_t *fnp = vntofn(vp);
1294 	fninfo_t *fnip = vfstofni(vp->v_vfsp);
1295 	vnode_t *dvp;
1296 	vfs_t *vfsp;
1297 	int delayed_ind;
1298 	char name[AUTOFS_MAXPATHLEN];
1299 	int error;
1300 
1301 	AUTOFS_DPRINT((4, "auto_trigger_mount: vp=%p\n", (void *)vp));
1302 
1303 	*newvp = NULL;
1304 
1305 	/*
1306 	 * Cross-zone mount triggering is disallowed.
1307 	 */
1308 	if (fnip->fi_zoneid != getzoneid())
1309 		return (EPERM);	/* Not owner of mount */
1310 
1311 retry:
1312 	error = 0;
1313 	delayed_ind = 0;
1314 	mutex_enter(&fnp->fn_lock);
1315 	while (fnp->fn_flags & (MF_LOOKUP | MF_INPROG)) {
1316 		/*
1317 		 * Mount or lookup in progress,
1318 		 * wait for it before proceeding.
1319 		 */
1320 		mutex_exit(&fnp->fn_lock);
1321 		error = auto_wait4mount(fnp);
1322 		if (error == AUTOFS_SHUTDOWN) {
1323 			error = 0;
1324 			goto done;
1325 		}
1326 		if (error && error != EAGAIN)
1327 			goto done;
1328 		error = 0;
1329 		mutex_enter(&fnp->fn_lock);
1330 	}
1331 
1332 	/*
1333 	 * If the vfslock can't be acquired for the first time.
1334 	 * drop the fn_lock and retry next time in blocking mode.
1335 	 */
1336 	if (vn_vfswlock(vp)) {
1337 		/*
1338 		 * Lock held by another thread.
1339 		 * Perform blocking by dropping the
1340 		 * fn_lock.
1341 		 */
1342 		mutex_exit(&fnp->fn_lock);
1343 		error = vn_vfswlock_wait(vp);
1344 		if (error)
1345 			goto done;
1346 		/*
1347 		 * Because fn_lock wasn't held, the state
1348 		 * of the trigger node might have changed.
1349 		 * Need to run through the checks on trigger
1350 		 * node again.
1351 		 */
1352 		vn_vfsunlock(vp);
1353 		goto retry;
1354 	}
1355 
1356 	vfsp = vn_mountedvfs(vp);
1357 	if (vfsp != NULL) {
1358 		mutex_exit(&fnp->fn_lock);
1359 		error = VFS_ROOT(vfsp, newvp);
1360 		vn_vfsunlock(vp);
1361 		goto done;
1362 	} else {
1363 		vn_vfsunlock(vp);
1364 		if ((fnp->fn_flags & MF_MOUNTPOINT) &&
1365 		    fnp->fn_trigger != NULL) {
1366 			ASSERT(fnp->fn_dirents == NULL);
1367 			/*
1368 			 * The filesystem that used to sit here has been
1369 			 * forcibly unmounted.
1370 			 */
1371 			mutex_exit(&fnp->fn_lock);
1372 			error = EIO;
1373 			goto done;
1374 		}
1375 	}
1376 
1377 	ASSERT(vp->v_type == VDIR);
1378 	dvp = fntovn(fnp->fn_parent);
1379 
1380 	if ((fnp->fn_dirents == NULL) &&
1381 	    ((fnip->fi_flags & MF_DIRECT) == 0) &&
1382 	    ((vp->v_flag & VROOT) == 0) &&
1383 	    (dvp->v_flag & VROOT)) {
1384 		/*
1385 		 * If the parent of this node is the root of an indirect
1386 		 * AUTOFS filesystem, this node is remountable.
1387 		 */
1388 		delayed_ind = 1;
1389 	}
1390 
1391 	if (delayed_ind ||
1392 	    ((fnip->fi_flags & MF_DIRECT) && (fnp->fn_dirents == NULL))) {
1393 		/*
1394 		 * Trigger mount since:
1395 		 * direct mountpoint with no subdirs or
1396 		 * delayed indirect.
1397 		 */
1398 		AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG);
1399 		fnp->fn_error = 0;
1400 		mutex_exit(&fnp->fn_lock);
1401 		if (delayed_ind)
1402 			(void) strcpy(name, fnp->fn_name);
1403 		else
1404 			(void) strcpy(name, ".");
1405 		fnp->fn_ref_time = gethrestime_sec();
1406 		auto_new_mount_thread(fnp, name, cred);
1407 		/*
1408 		 * At this point we're simply another thread waiting
1409 		 * for the mount to finish.
1410 		 */
1411 		error = auto_wait4mount(fnp);
1412 		if (error == EAGAIN)
1413 			goto retry;
1414 		if (error == AUTOFS_SHUTDOWN) {
1415 			error = 0;
1416 			goto done;
1417 		}
1418 		if (error == 0) {
1419 			if (error = vn_vfsrlock_wait(vp))
1420 				goto done;
1421 			/* Reacquire after dropping locks */
1422 			vfsp = vn_mountedvfs(vp);
1423 			if (vfsp != NULL) {
1424 				error = VFS_ROOT(vfsp, newvp);
1425 				vn_vfsunlock(vp);
1426 			} else {
1427 				vn_vfsunlock(vp);
1428 				goto retry;
1429 			}
1430 		}
1431 	} else
1432 		mutex_exit(&fnp->fn_lock);
1433 
1434 done:
1435 	AUTOFS_DPRINT((5, "auto_trigger_mount: error=%d\n", error));
1436 	return (error);
1437 }
1438