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