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