xref: /illumos-gate/usr/src/uts/common/fs/autofs/auto_subr.c (revision 95b97885737f6c068bf0c5187e14f4441fd48acd)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/param.h>
30 #include <sys/kmem.h>
31 #include <sys/errno.h>
32 #include <sys/proc.h>
33 #include <sys/disp.h>
34 #include <sys/vfs.h>
35 #include <sys/vnode.h>
36 #include <sys/pathname.h>
37 #include <sys/cred.h>
38 #include <sys/mount.h>
39 #include <sys/cmn_err.h>
40 #include <sys/debug.h>
41 #include <sys/systm.h>
42 #include <rpc/types.h>
43 #include <rpc/xdr.h>
44 #include <rpc/auth.h>
45 #include <rpc/clnt.h>
46 #include <sys/ticotsord.h>
47 #include <sys/dirent.h>
48 #include <fs/fs_subr.h>
49 #include <rpcsvc/autofs_prot.h>
50 #include <sys/fs/autofs.h>
51 #include <sys/callb.h>
52 #include <sys/sysmacros.h>
53 #include <sys/zone.h>
54 #include <sys/fs/mntdata.h>
55 
56 /*
57  * Autofs and Zones:
58  *
59  * Zones are delegated the responsibility of managing their own autofs mounts
60  * and maps.  Each zone runs its own copy of automountd, with its own timeouts,
61  * and other logically "global" parameters.  kRPC and virtualization in the
62  * loopback transport (tl) will prevent a zone from communicating with another
63  * zone's automountd.
64  *
65  * Each zone has its own "rootfnnode" and associated tree of auto nodes.
66  *
67  * Each zone also has its own set of "unmounter" kernel threads; these are
68  * created and run within the zone's context (ie, they are created via
69  * zthread_create()).
70  *
71  * Cross-zone mount triggers are disallowed.  There is a check in
72  * auto_trigger_mount() to this effect; EPERM is returned to indicate that the
73  * mount is not owned by the caller.
74  *
75  * autofssys() enables a caller in the global zone to clean up in-kernel (as
76  * well as regular) autofs mounts via the unmount_tree() mechanism.  This is
77  * routinely done when all mounts are removed as part of zone shutdown.
78  */
79 #define	TYPICALMAXPATHLEN	64
80 
81 static kmutex_t autofs_nodeid_lock;
82 
83 static int auto_perform_link(fnnode_t *, struct linka *, cred_t *);
84 static int auto_perform_actions(fninfo_t *, fnnode_t *,
85     action_list *, cred_t *);
86 static int auto_getmntpnt(vnode_t *, char *, vnode_t **, cred_t *);
87 static int auto_lookup_request(fninfo_t *, char *, struct linka *,
88     cred_t *, bool_t, bool_t *);
89 static int auto_mount_request(fninfo_t *, char *, action_list **,
90     cred_t *, bool_t);
91 
92 /*
93  * Clears the MF_INPROG flag, and wakes up those threads sleeping on
94  * fn_cv_mount if MF_WAITING is set.
95  */
96 void
97 auto_unblock_others(
98 	fnnode_t *fnp,
99 	uint_t operation)		/* either MF_INPROG or MF_LOOKUP */
100 {
101 	ASSERT(operation & (MF_INPROG | MF_LOOKUP));
102 	fnp->fn_flags &= ~operation;
103 	if (fnp->fn_flags & MF_WAITING) {
104 		fnp->fn_flags &= ~MF_WAITING;
105 		cv_broadcast(&fnp->fn_cv_mount);
106 	}
107 }
108 
109 int
110 auto_wait4mount(fnnode_t *fnp)
111 {
112 	int error;
113 	k_sigset_t smask;
114 
115 	AUTOFS_DPRINT((4, "auto_wait4mount: fnp=%p\n", (void *)fnp));
116 
117 	mutex_enter(&fnp->fn_lock);
118 	while (fnp->fn_flags & (MF_INPROG | MF_LOOKUP)) {
119 		/*
120 		 * There is a mount or a lookup in progress.
121 		 */
122 		fnp->fn_flags |= MF_WAITING;
123 		sigintr(&smask, 1);
124 		if (!cv_wait_sig(&fnp->fn_cv_mount, &fnp->fn_lock)) {
125 			/*
126 			 * Decided not to wait for operation to
127 			 * finish after all.
128 			 */
129 			sigunintr(&smask);
130 			mutex_exit(&fnp->fn_lock);
131 			return (EINTR);
132 		}
133 		sigunintr(&smask);
134 	}
135 	error = fnp->fn_error;
136 
137 	if (error == EINTR) {
138 		/*
139 		 * The thread doing the mount got interrupted, we need to
140 		 * try again, by returning EAGAIN.
141 		 */
142 		error = EAGAIN;
143 	}
144 	mutex_exit(&fnp->fn_lock);
145 
146 	AUTOFS_DPRINT((5, "auto_wait4mount: fnp=%p error=%d\n", (void *)fnp,
147 	    error));
148 	return (error);
149 }
150 
151 int
152 auto_lookup_aux(fnnode_t *fnp, char *name, cred_t *cred)
153 {
154 	struct fninfo *fnip;
155 	struct linka link;
156 	bool_t mountreq = FALSE;
157 	int error = 0;
158 
159 	fnip = vfstofni(fntovn(fnp)->v_vfsp);
160 	bzero(&link, sizeof (link));
161 	error = auto_lookup_request(fnip, name, &link, cred, TRUE, &mountreq);
162 	if (!error) {
163 		if (link.link != NULL) {
164 			/*
165 			 * This node should be a symlink
166 			 */
167 			error = auto_perform_link(fnp, &link, cred);
168 			kmem_free(link.dir, strlen(link.dir) + 1);
169 			kmem_free(link.link, strlen(link.link) + 1);
170 		} else if (mountreq) {
171 			/*
172 			 * The automount daemon is requesting a mount,
173 			 * implying this entry must be a wildcard match and
174 			 * therefore in need of verification that the entry
175 			 * exists on the server.
176 			 */
177 			mutex_enter(&fnp->fn_lock);
178 			AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG);
179 			fnp->fn_error = 0;
180 
181 			/*
182 			 * Unblock other lookup requests on this node,
183 			 * this is needed to let the lookup generated by
184 			 * the mount call to complete. The caveat is
185 			 * other lookups on this node can also get by,
186 			 * i.e., another lookup on this node that occurs
187 			 * while this lookup is attempting the mount
188 			 * would return a positive result no matter what.
189 			 * Therefore two lookups on the this node could
190 			 * potentially get disparate results.
191 			 */
192 			AUTOFS_UNBLOCK_OTHERS(fnp, MF_LOOKUP);
193 			mutex_exit(&fnp->fn_lock);
194 			/*
195 			 * auto_new_mount_thread fires up a new thread which
196 			 * calls automountd finishing up the work
197 			 */
198 			auto_new_mount_thread(fnp, name, cred);
199 
200 			/*
201 			 * At this point, we are simply another thread
202 			 * waiting for the mount to complete
203 			 */
204 			error = auto_wait4mount(fnp);
205 			if (error == AUTOFS_SHUTDOWN)
206 				error = ENOENT;
207 		}
208 	}
209 
210 	mutex_enter(&fnp->fn_lock);
211 	fnp->fn_error = error;
212 
213 	/*
214 	 * Notify threads waiting for lookup/mount that
215 	 * it's done.
216 	 */
217 	if (mountreq) {
218 		AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
219 	} else {
220 		AUTOFS_UNBLOCK_OTHERS(fnp, MF_LOOKUP);
221 	}
222 	mutex_exit(&fnp->fn_lock);
223 	return (error);
224 }
225 
226 /*
227  * Starting point for thread to handle mount requests with automountd.
228  * XXX auto_mount_thread() is not suspend-safe within the scope of
229  * the present model defined for cpr to suspend the system. Calls
230  * made by the auto_mount_thread() that have been identified to be unsafe
231  * are (1) RPC client handle setup and client calls to automountd which
232  * can block deep down in the RPC library, (2) kmem_alloc() calls with the
233  * KM_SLEEP flag which can block if memory is low, and (3) VFS_*(), and
234  * lookuppnvp() calls which can result in over the wire calls to servers.
235  * The thread should be completely reevaluated to make it suspend-safe in
236  * case of future updates to the cpr model.
237  */
238 static void
239 auto_mount_thread(struct autofs_callargs *argsp)
240 {
241 	struct fninfo *fnip;
242 	fnnode_t *fnp;
243 	vnode_t *vp;
244 	char *name;
245 	size_t namelen;
246 	cred_t *cred;
247 	action_list *alp = NULL;
248 	int error;
249 	callb_cpr_t cprinfo;
250 	kmutex_t auto_mount_thread_cpr_lock;
251 
252 	mutex_init(&auto_mount_thread_cpr_lock, NULL, MUTEX_DEFAULT, NULL);
253 	CALLB_CPR_INIT(&cprinfo, &auto_mount_thread_cpr_lock, callb_generic_cpr,
254 		"auto_mount_thread");
255 
256 	fnp = argsp->fnc_fnp;
257 	vp = fntovn(fnp);
258 	fnip = vfstofni(vp->v_vfsp);
259 	name = argsp->fnc_name;
260 	cred = argsp->fnc_cred;
261 	ASSERT(crgetzoneid(argsp->fnc_cred) == fnip->fi_zoneid);
262 
263 	error = auto_mount_request(fnip, name, &alp, cred, TRUE);
264 	if (!error)
265 		error = auto_perform_actions(fnip, fnp, alp, cred);
266 	mutex_enter(&fnp->fn_lock);
267 	fnp->fn_error = error;
268 
269 	/*
270 	 * Notify threads waiting for mount that
271 	 * it's done.
272 	 */
273 	AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
274 	mutex_exit(&fnp->fn_lock);
275 
276 	VN_RELE(vp);
277 	crfree(argsp->fnc_cred);
278 	namelen = strlen(argsp->fnc_name) + 1;
279 	kmem_free(argsp->fnc_name, namelen);
280 	kmem_free(argsp, sizeof (*argsp));
281 
282 	mutex_enter(&auto_mount_thread_cpr_lock);
283 	CALLB_CPR_EXIT(&cprinfo);
284 	mutex_destroy(&auto_mount_thread_cpr_lock);
285 	zthread_exit();
286 	/* NOTREACHED */
287 }
288 
289 static int autofs_thr_success = 0;
290 
291 /*
292  * Creates new thread which calls auto_mount_thread which does
293  * the bulk of the work calling automountd, via 'auto_perform_actions'.
294  */
295 void
296 auto_new_mount_thread(fnnode_t *fnp, char *name, cred_t *cred)
297 {
298 	struct autofs_callargs *argsp;
299 
300 	argsp = kmem_alloc(sizeof (*argsp), KM_SLEEP);
301 	VN_HOLD(fntovn(fnp));
302 	argsp->fnc_fnp = fnp;
303 	argsp->fnc_name = kmem_alloc(strlen(name) + 1, KM_SLEEP);
304 	(void) strcpy(argsp->fnc_name, name);
305 	argsp->fnc_origin = curthread;
306 	crhold(cred);
307 	argsp->fnc_cred = cred;
308 
309 	(void) zthread_create(NULL, 0, auto_mount_thread, argsp, 0,
310 	    minclsyspri);
311 	autofs_thr_success++;
312 }
313 
314 int
315 auto_calldaemon(
316 	fninfo_t *fnip,
317 	rpcproc_t which,
318 	xdrproc_t xdrargs,
319 	void *argsp,
320 	xdrproc_t xdrres,
321 	void *resp,
322 	cred_t *cred,
323 	bool_t hard)				/* retry forever? */
324 {
325 	CLIENT *client;
326 	enum clnt_stat status;
327 	struct rpc_err rpcerr;
328 	struct timeval wait;
329 	bool_t tryagain;
330 	int error = 0;
331 	k_sigset_t smask;
332 	struct autofs_globals *fngp = vntofn(fnip->fi_rootvp)->fn_globals;
333 
334 	AUTOFS_DPRINT((4, "auto_calldaemon\n"));
335 
336 	error = clnt_tli_kcreate(&fnip->fi_knconf, &fnip->fi_addr,
337 	    AUTOFS_PROG, AUTOFS_VERS, 0, INT_MAX, cred, &client);
338 
339 	if (error) {
340 		auto_log(fngp, CE_WARN, "autofs: clnt_tli_kcreate: error %d",
341 		    error);
342 		goto done;
343 	}
344 
345 	/*
346 	 * Release the old authentication handle.  It was probably
347 	 * AUTH_UNIX.
348 	 */
349 	auth_destroy(client->cl_auth);
350 
351 	/*
352 	 * Create a new authentication handle for AUTH_LOOPBACK.  This
353 	 * will allow us to correctly handle the entire groups list.
354 	 */
355 	client->cl_auth = authloopback_create();
356 	if (client->cl_auth == NULL) {
357 		clnt_destroy(client);
358 		error = EINTR;
359 		auto_log(fngp, CE_WARN,
360 		    "autofs: authloopback_create: error %d", error);
361 		goto done;
362 	}
363 
364 	wait.tv_sec = fnip->fi_rpc_to;
365 	wait.tv_usec = 0;
366 	do {
367 		tryagain = FALSE;
368 		error = 0;
369 
370 		/*
371 		 * Mask out all signals except SIGHUP, SIGINT, SIGQUIT
372 		 * and SIGTERM. (Preserving the existing masks)
373 		 */
374 		sigintr(&smask, 1);
375 
376 		status = CLNT_CALL(client, which, xdrargs, argsp,
377 		    xdrres, resp, wait);
378 
379 		/*
380 		 * Restore original signal mask
381 		 */
382 		sigunintr(&smask);
383 
384 		switch (status) {
385 		case RPC_SUCCESS:
386 			break;
387 
388 		case RPC_INTR:
389 			error = EINTR;
390 			break;
391 
392 		case RPC_TIMEDOUT:
393 			tryagain = TRUE;
394 			error = ETIMEDOUT;
395 			break;
396 
397 		case RPC_CANTCONNECT:
398 		case RPC_CANTCREATESTREAM:
399 			/*
400 			 * The connection could not be established
401 			 */
402 			/* fall thru */
403 		case RPC_XPRTFAILED:
404 			/*
405 			 * The connection could not be established or
406 			 * was dropped, we differentiate between the two
407 			 * conditions by calling CLNT_GETERR and look at
408 			 * rpcerror.re_errno.
409 			 * If rpcerr.re_errno == ECONNREFUSED, then the
410 			 * connection could not be established at all.
411 			 */
412 			error = ECONNREFUSED;
413 			if (status == RPC_XPRTFAILED) {
414 				CLNT_GETERR(client, &rpcerr);
415 				if (rpcerr.re_errno != ECONNREFUSED) {
416 					/*
417 					 * The connection was dropped, return
418 					 * to the caller if hard is not set.
419 					 * It is the responsability of the
420 					 * caller to retry the call if
421 					 * appropriate.
422 					 */
423 					error = ECONNRESET;
424 				}
425 			}
426 			/*
427 			 * We know that the current thread is doing work on
428 			 * behalf of its own zone, so it's ok to use
429 			 * curproc->p_zone.
430 			 */
431 			ASSERT(fngp->fng_zoneid == getzoneid());
432 			if (zone_status_get(curproc->p_zone) >=
433 			    ZONE_IS_SHUTTING_DOWN) {
434 				/*
435 				 * There's no point in trying to talk to
436 				 * automountd.  Plus, zone_shutdown() is
437 				 * waiting for us.
438 				 */
439 				tryagain = FALSE;
440 				break;
441 			}
442 			tryagain = hard;
443 			if (!fngp->fng_printed_not_running_msg) {
444 				if (tryagain) {
445 					fngp->fng_printed_not_running_msg = 1;
446 					zprintf(fngp->fng_zoneid,
447 					"automountd not running, retrying\n");
448 				}
449 			}
450 			break;
451 
452 		default:
453 			auto_log(fngp, CE_WARN, "autofs: %s",
454 			    clnt_sperrno(status));
455 			error = ENOENT;
456 			break;
457 		}
458 	} while (tryagain);
459 
460 	if (status == RPC_SUCCESS) {
461 		if (fngp->fng_printed_not_running_msg == 1) {
462 			fngp->fng_printed_not_running_msg = 0;
463 			zprintf(fngp->fng_zoneid, "automountd OK\n");
464 		}
465 	}
466 	auth_destroy(client->cl_auth);
467 	clnt_destroy(client);
468 
469 done:
470 	ASSERT(status == RPC_SUCCESS || error != 0);
471 
472 	AUTOFS_DPRINT((5, "auto_calldaemon error=%d\n", error));
473 	return (error);
474 }
475 
476 static int
477 auto_null_request(fninfo_t *fnip, cred_t *cred, bool_t hard)
478 {
479 	int error;
480 
481 	AUTOFS_DPRINT((4, "\tauto_null_request\n"));
482 
483 	error = auto_calldaemon(fnip, NULLPROC, xdr_void, NULL, xdr_void, NULL,
484 	    cred, hard);
485 
486 	AUTOFS_DPRINT((5, "\tauto_null_request: error=%d\n", error));
487 	return (error);
488 }
489 
490 static int
491 auto_lookup_request(
492 	fninfo_t *fnip,
493 	char *key,
494 	struct linka *lnp,
495 	cred_t *cred,
496 	bool_t hard,
497 	bool_t *mountreq)
498 {
499 	int error;
500 	struct autofs_globals *fngp;
501 	struct autofs_lookupargs request;
502 	struct autofs_lookupres result;
503 	struct linka *p;
504 
505 	AUTOFS_DPRINT((4, "auto_lookup_request: path=%s name=%s\n",
506 	    fnip->fi_path, key));
507 
508 	fngp = vntofn(fnip->fi_rootvp)->fn_globals;
509 	request.map = fnip->fi_map;
510 	request.path = fnip->fi_path;
511 
512 	if (fnip->fi_flags & MF_DIRECT)
513 		request.name = fnip->fi_key;
514 	else
515 		request.name = key;
516 	AUTOFS_DPRINT((4, "auto_lookup_request: using key=%s\n", request.name));
517 
518 	request.subdir = fnip->fi_subdir;
519 	request.opts = fnip->fi_opts;
520 	request.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE;
521 
522 	bzero(&result, sizeof (result));
523 	error = auto_calldaemon(fnip, AUTOFS_LOOKUP,
524 	    xdr_autofs_lookupargs, &request,
525 	    xdr_autofs_lookupres, &result,
526 	    cred, hard);
527 	if (!error) {
528 		fngp->fng_verbose = result.lu_verbose;
529 		switch (result.lu_res) {
530 		case AUTOFS_OK:
531 			switch (result.lu_type.action) {
532 			case AUTOFS_MOUNT_RQ:
533 				lnp->link = NULL;
534 				lnp->dir = NULL;
535 				*mountreq = TRUE;
536 				break;
537 			case AUTOFS_LINK_RQ:
538 				p =
539 				&result.lu_type.lookup_result_type_u.lt_linka;
540 				lnp->dir = kmem_alloc(strlen(p->dir) + 1,
541 				    KM_SLEEP);
542 				(void) strcpy(lnp->dir, p->dir);
543 				lnp->link = kmem_alloc(strlen(p->link) + 1,
544 				    KM_SLEEP);
545 				(void) strcpy(lnp->link, p->link);
546 				break;
547 			case AUTOFS_NONE:
548 				lnp->link = NULL;
549 				lnp->dir = NULL;
550 				break;
551 			default:
552 				auto_log(fngp, CE_WARN,
553 				    "auto_lookup_request: bad action type %d",
554 				    result.lu_res);
555 				error = ENOENT;
556 			}
557 			break;
558 		case AUTOFS_NOENT:
559 			error = ENOENT;
560 			break;
561 		default:
562 			error = ENOENT;
563 			auto_log(fngp, CE_WARN,
564 			    "auto_lookup_request: unknown result: %d",
565 			    result.lu_res);
566 			break;
567 		}
568 	}
569 
570 done:
571 	xdr_free(xdr_autofs_lookupres, (char *)&result);
572 
573 	AUTOFS_DPRINT((5, "auto_lookup_request: path=%s name=%s error=%d\n",
574 	    fnip->fi_path, key, error));
575 	return (error);
576 }
577 
578 static int
579 auto_mount_request(
580 	fninfo_t *fnip,
581 	char *key,
582 	action_list **alpp,
583 	cred_t *cred,
584 	bool_t hard)
585 {
586 	int error;
587 	struct autofs_globals *fngp;
588 	struct autofs_lookupargs request;
589 	struct autofs_mountres *result;
590 
591 	AUTOFS_DPRINT((4, "auto_mount_request: path=%s name=%s\n",
592 	    fnip->fi_path, key));
593 
594 	fngp = vntofn(fnip->fi_rootvp)->fn_globals;
595 	request.map = fnip->fi_map;
596 	request.path = fnip->fi_path;
597 
598 	if (fnip->fi_flags & MF_DIRECT)
599 		request.name = fnip->fi_key;
600 	else
601 		request.name = key;
602 	AUTOFS_DPRINT((4, "auto_mount_request: using key=%s\n", request.name));
603 
604 	request.subdir = fnip->fi_subdir;
605 	request.opts = fnip->fi_opts;
606 	request.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE;
607 
608 	*alpp = NULL;
609 	result = kmem_zalloc(sizeof (*result), KM_SLEEP);
610 	error = auto_calldaemon(fnip, AUTOFS_MOUNT,
611 	    xdr_autofs_lookupargs, &request,
612 	    xdr_autofs_mountres, result,
613 	    cred, hard);
614 	if (!error) {
615 		fngp->fng_verbose = result->mr_verbose;
616 		switch (result->mr_type.status) {
617 		case AUTOFS_ACTION:
618 			error = 0;
619 			/*
620 			 * Save the action list since it is used by
621 			 * the caller. We NULL the action list pointer
622 			 * in 'result' so that xdr_free() will not free
623 			 * the list.
624 			 */
625 			*alpp = result->mr_type.mount_result_type_u.list;
626 			result->mr_type.mount_result_type_u.list = NULL;
627 			break;
628 		case AUTOFS_DONE:
629 			error = result->mr_type.mount_result_type_u.error;
630 			break;
631 		default:
632 			error = ENOENT;
633 			auto_log(fngp, CE_WARN,
634 			    "auto_mount_request: unknown status %d",
635 			    result->mr_type.status);
636 			break;
637 		}
638 	}
639 
640 	xdr_free(xdr_autofs_mountres, (char *)result);
641 	kmem_free(result, sizeof (*result));
642 
643 	AUTOFS_DPRINT((5, "auto_mount_request: path=%s name=%s error=%d\n",
644 	    fnip->fi_path, key, error));
645 	return (error);
646 }
647 
648 
649 static int
650 auto_send_unmount_request(
651 	fninfo_t *fnip,
652 	umntrequest *ul,
653 	cred_t *cred,
654 	bool_t hard)
655 {
656 	int error;
657 	umntres result;
658 
659 	AUTOFS_DPRINT((4, "\tauto_send_unmount_request: fstype=%s "
660 			" mntpnt=%s\n", ul->fstype, ul->mntpnt));
661 
662 	error = auto_calldaemon(fnip, AUTOFS_UNMOUNT,
663 	    xdr_umntrequest, ul,
664 	    xdr_umntres, &result,
665 	    cred, hard);
666 	if (!error)
667 		error = result.status;
668 
669 	AUTOFS_DPRINT((5, "\tauto_send_unmount_request: error=%d\n", error));
670 
671 	return (error);
672 }
673 
674 static int
675 auto_perform_link(fnnode_t *fnp, struct linka *linkp, cred_t *cred)
676 {
677 	vnode_t *vp;
678 	size_t len;
679 	char *tmp;
680 
681 	AUTOFS_DPRINT((3, "auto_perform_link: fnp=%p dir=%s link=%s\n",
682 	    (void *)fnp, linkp->dir, linkp->link));
683 
684 	len = strlen(linkp->link) + 1;		/* include '\0' */
685 	tmp = kmem_zalloc(len, KM_SLEEP);
686 	(void) kcopy(linkp->link, tmp, len);
687 	mutex_enter(&fnp->fn_lock);
688 	fnp->fn_symlink = tmp;
689 	fnp->fn_symlinklen = (uint_t)len;
690 	fnp->fn_flags |= MF_THISUID_MATCH_RQD;
691 	crhold(cred);
692 	fnp->fn_cred = cred;
693 	mutex_exit(&fnp->fn_lock);
694 
695 	vp = fntovn(fnp);
696 	vp->v_type = VLNK;
697 
698 	return (0);
699 }
700 
701 static boolean_t
702 auto_invalid_action(fninfo_t *dfnip, fnnode_t *dfnp, action_list *p)
703 {
704 	struct mounta *m;
705 	struct autofs_args *argsp;
706 	vnode_t *dvp;
707 	char buff[AUTOFS_MAXPATHLEN];
708 	size_t len;
709 	struct autofs_globals *fngp;
710 
711 	fngp = dfnp->fn_globals;
712 	dvp = fntovn(dfnp);
713 	/*
714 	 * Before we go any further, this better be a mount request.
715 	 */
716 	if (p->action.action != AUTOFS_MOUNT_RQ)
717 		return (B_TRUE);
718 	m = &p->action.action_list_entry_u.mounta;
719 	/*
720 	 * Make sure we aren't geting passed NULL values or a "dir" that
721 	 * isn't "." and doesn't begin with "./".
722 	 *
723 	 * We also only want to perform autofs mounts, so make sure
724 	 * no-one is trying to trick us into doing anything else.
725 	 */
726 	if (m->spec == NULL || m->dir == NULL || m->dir[0] != '.' ||
727 	    (m->dir[1] != '/' && m->dir[1] != '\0') ||
728 	    m->fstype == NULL || strcmp(m->fstype, "autofs") != 0 ||
729 	    m->dataptr == NULL || m->datalen != sizeof (struct autofs_args) ||
730 	    m->optptr == NULL)
731 		return (B_TRUE);
732 	/*
733 	 * We also don't like ".."s in the pathname.  Symlinks are
734 	 * handled by the fact that we'll use NOFOLLOW when we do
735 	 * lookup()s.
736 	 */
737 	if (strstr(m->dir, "/../") != NULL ||
738 	    (len = strlen(m->dir)) > sizeof ("/..") - 1 &&
739 	    m->dir[len] == '.' && m->dir[len - 1] == '.' &&
740 	    m->dir[len - 2] == '/')
741 		return (B_TRUE);
742 	argsp = (struct autofs_args *)m->dataptr;
743 	/*
744 	 * We don't want NULL values here either.
745 	 */
746 	if (argsp->addr.buf == NULL || argsp->path == NULL ||
747 	    argsp->opts == NULL || argsp->map == NULL || argsp->subdir == NULL)
748 		return (B_TRUE);
749 	/*
750 	 * We know what the claimed pathname *should* look like:
751 	 *
752 	 * If the parent (dfnp) is a mount point (VROOT), then
753 	 * the path should be (dfnip->fi_path + m->dir).
754 	 *
755 	 * Else, we know we're only two levels deep, so we use
756 	 * (dfnip->fi_path + dfnp->fn_name + m->dir).
757 	 *
758 	 * Furthermore, "." only makes sense if dfnp is a
759 	 * trigger node.
760 	 *
761 	 * At this point it seems like the passed-in path is
762 	 * redundant.
763 	 */
764 	if (dvp->v_flag & VROOT) {
765 		if (m->dir[1] == '\0' && !(dfnp->fn_flags & MF_TRIGGER))
766 			return (B_TRUE);
767 		(void) snprintf(buff, sizeof (buff), "%s%s",
768 		    dfnip->fi_path, m->dir + 1);
769 	} else {
770 		(void) snprintf(buff, sizeof (buff), "%s/%s%s",
771 		    dfnip->fi_path, dfnp->fn_name, m->dir + 1);
772 	}
773 	if (strcmp(argsp->path, buff) != 0) {
774 		auto_log(fngp, CE_WARN, "autofs: expected path of '%s', "
775 		    "got '%s' instead.", buff, argsp->path);
776 		return (B_TRUE);
777 	}
778 	return (B_FALSE); /* looks OK */
779 }
780 
781 static int
782 auto_perform_actions(
783 	fninfo_t *dfnip,
784 	fnnode_t *dfnp,
785 	action_list *alp,
786 	cred_t *cred)	/* Credentials of the caller */
787 {
788 	action_list *p;
789 	struct mounta *m, margs;
790 	struct autofs_args *argsp;
791 	int error, success = 0;
792 	vnode_t *mvp, *dvp, *newvp;
793 	fnnode_t *newfnp, *mfnp;
794 	int auto_mount = 0;
795 	int save_triggers = 0;		/* set when we need to save at least */
796 					/* one trigger node */
797 	int update_times = 0;
798 	char *mntpnt;
799 	char buff[AUTOFS_MAXPATHLEN];
800 	timestruc_t now;
801 	struct autofs_globals *fngp;
802 	cred_t *zcred;	/* kcred-like credentials limited by our zone */
803 
804 	AUTOFS_DPRINT((4, "auto_perform_actions: alp=%p\n", (void *)alp));
805 
806 	fngp = dfnp->fn_globals;
807 	dvp = fntovn(dfnp);
808 
809 	/*
810 	 * As automountd running in a zone may be compromised, and this may be
811 	 * an attack, we can't trust everything passed in by automountd, and we
812 	 * need to do argument verification.  We'll issue a warning and drop
813 	 * the request if it doesn't seem right.
814 	 */
815 	for (p = alp; p != NULL; p = p->next) {
816 		if (auto_invalid_action(dfnip, dfnp, p)) {
817 			/*
818 			 * This warning should be sent to the global zone,
819 			 * since presumably the zone administrator is the same
820 			 * as the attacker.
821 			 */
822 			cmn_err(CE_WARN, "autofs: invalid action list received "
823 			    "by automountd in zone %s.",
824 			    curproc->p_zone->zone_name);
825 			/*
826 			 * This conversation is over.
827 			 */
828 			xdr_free(xdr_action_list, (char *)alp);
829 			return (EINVAL);
830 		}
831 	}
832 
833 	zcred = zone_get_kcred(getzoneid());
834 	ASSERT(zcred != NULL);
835 
836 	if (vn_mountedvfs(dvp) != NULL) {
837 		/*
838 		 * The daemon successfully mounted a filesystem
839 		 * on the AUTOFS root node.
840 		 */
841 		mutex_enter(&dfnp->fn_lock);
842 		dfnp->fn_flags |= MF_MOUNTPOINT;
843 		ASSERT(dfnp->fn_dirents == NULL);
844 		mutex_exit(&dfnp->fn_lock);
845 		success++;
846 	} else {
847 		/*
848 		 * Clear MF_MOUNTPOINT.
849 		 */
850 		mutex_enter(&dfnp->fn_lock);
851 		if (dfnp->fn_flags & MF_MOUNTPOINT) {
852 			AUTOFS_DPRINT((10, "autofs: clearing mountpoint "
853 			    "flag on %s.", dfnp->fn_name));
854 			ASSERT(dfnp->fn_dirents == NULL);
855 			ASSERT(dfnp->fn_trigger == NULL);
856 		}
857 		dfnp->fn_flags &= ~MF_MOUNTPOINT;
858 		mutex_exit(&dfnp->fn_lock);
859 	}
860 
861 	for (p = alp; p != NULL; p = p->next) {
862 		vfs_t *vfsp;	/* dummy argument */
863 		vfs_t *mvfsp;
864 
865 		auto_mount = 0;
866 
867 		m = &p->action.action_list_entry_u.mounta;
868 		argsp = (struct autofs_args *)m->dataptr;
869 		/*
870 		 * use the parent directory's timeout since it's the
871 		 * one specified/inherited by automount.
872 		 */
873 		argsp->mount_to = dfnip->fi_mount_to;
874 		/*
875 		 * The mountpoint is relative, and it is guaranteed to
876 		 * begin with "."
877 		 *
878 		 */
879 		ASSERT(m->dir[0] == '.');
880 		if (m->dir[0] == '.' && m->dir[1] == '\0') {
881 			/*
882 			 * mounting on the trigger node
883 			 */
884 			mvp = dvp;
885 			VN_HOLD(mvp);
886 			goto mount;
887 		}
888 		/*
889 		 * ignore "./" in front of mountpoint
890 		 */
891 		ASSERT(m->dir[1] == '/');
892 		mntpnt = m->dir + 2;
893 
894 		AUTOFS_DPRINT((10, "\tdfnip->fi_path=%s\n", dfnip->fi_path));
895 		AUTOFS_DPRINT((10, "\tdfnip->fi_flags=%x\n", dfnip->fi_flags));
896 		AUTOFS_DPRINT((10, "\tmntpnt=%s\n", mntpnt));
897 
898 		if (dfnip->fi_flags & MF_DIRECT) {
899 			AUTOFS_DPRINT((10, "\tDIRECT\n"));
900 			(void) sprintf(buff, "%s/%s", dfnip->fi_path, mntpnt);
901 		} else {
902 			AUTOFS_DPRINT((10, "\tINDIRECT\n"));
903 			(void) sprintf(buff, "%s/%s/%s", dfnip->fi_path,
904 			    dfnp->fn_name, mntpnt);
905 		}
906 
907 		if (vn_mountedvfs(dvp) == NULL) {
908 			/*
909 			 * Daemon didn't mount anything on the root
910 			 * We have to create the mountpoint if it doesn't
911 			 * exist already
912 			 *
913 			 * We use the caller's credentials in case a UID-match
914 			 * is required (MF_THISUID_MATCH_RQD).
915 			 */
916 			rw_enter(&dfnp->fn_rwlock, RW_WRITER);
917 			error = auto_search(dfnp, mntpnt, &mfnp, cred);
918 			if (error == 0) {
919 				/*
920 				 * AUTOFS mountpoint exists
921 				 */
922 				if (vn_mountedvfs(fntovn(mfnp)) != NULL) {
923 					cmn_err(CE_PANIC,
924 					    "auto_perform_actions: "
925 					    "mfnp=%p covered", (void *)mfnp);
926 				}
927 			} else {
928 				/*
929 				 * Create AUTOFS mountpoint
930 				 */
931 				ASSERT((dfnp->fn_flags & MF_MOUNTPOINT) == 0);
932 				error = auto_enter(dfnp, mntpnt, &mfnp, cred);
933 				ASSERT(mfnp->fn_linkcnt == 1);
934 				mfnp->fn_linkcnt++;
935 			}
936 			if (!error)
937 				update_times = 1;
938 			rw_exit(&dfnp->fn_rwlock);
939 			ASSERT(error != EEXIST);
940 			if (!error) {
941 				/*
942 				 * mfnp is already held.
943 				 */
944 				mvp = fntovn(mfnp);
945 			} else {
946 				auto_log(fngp, CE_WARN, "autofs: mount of %s "
947 				    "failed - can't create mountpoint.", buff);
948 				continue;
949 			}
950 		} else {
951 			/*
952 			 * Find mountpoint in VFS mounted here. If not found,
953 			 * fail the submount, though the overall mount has
954 			 * succeeded since the root is mounted.
955 			 */
956 			if (error = auto_getmntpnt(dvp, mntpnt, &mvp, kcred)) {
957 				auto_log(fngp, CE_WARN, "autofs: mount of %s "
958 				    "failed - mountpoint doesn't exist.", buff);
959 				continue;
960 			}
961 			if (mvp->v_type == VLNK) {
962 				auto_log(fngp, CE_WARN, "autofs: %s symbolic "
963 				    "link: not a valid mountpoint "
964 				    "- mount failed", buff);
965 				VN_RELE(mvp);
966 				error = ENOENT;
967 				continue;
968 			}
969 		}
970 mount:
971 		m->flags |= MS_SYSSPACE | MS_OPTIONSTR;
972 		/*
973 		 * Copy mounta struct here so we can substitute a buffer
974 		 * that is large enough to hold the returned option string,
975 		 * if that string is longer that the input option string.
976 		 * This can happen if there are default options enabled
977 		 * that were not in the input option string.
978 		 */
979 		bcopy(m, &margs, sizeof (*m));
980 		margs.optptr = kmem_alloc(MAX_MNTOPT_STR, KM_SLEEP);
981 		margs.optlen = MAX_MNTOPT_STR;
982 		(void) strcpy(margs.optptr, m->optptr);
983 		margs.dir = argsp->path;
984 		/*
985 		 * We use the zone's kcred because we don't want the zone to be
986 		 * able to thus do something it wouldn't normally be able to.
987 		 */
988 		error = domount(NULL, &margs, mvp, zcred, &vfsp);
989 		kmem_free(margs.optptr, MAX_MNTOPT_STR);
990 		if (error != 0) {
991 			auto_log(fngp, CE_WARN,
992 			    "autofs: domount of %s failed error=%d",
993 			    buff, error);
994 			VN_RELE(mvp);
995 			continue;
996 		}
997 		VFS_RELE(vfsp);
998 
999 		/*
1000 		 * If mountpoint is an AUTOFS node, then I'm going to
1001 		 * flag it that the Filesystem mounted on top was mounted
1002 		 * in the kernel so that the unmount can be done inside the
1003 		 * kernel as well.
1004 		 * I don't care to flag non-AUTOFS mountpoints when an AUTOFS
1005 		 * in-kernel mount was done on top, because the unmount
1006 		 * routine already knows that such case was done in the kernel.
1007 		 */
1008 		if (vfs_matchops(dvp->v_vfsp, vfs_getops(mvp->v_vfsp))) {
1009 			mfnp = vntofn(mvp);
1010 			mutex_enter(&mfnp->fn_lock);
1011 			mfnp->fn_flags |= MF_IK_MOUNT;
1012 			mutex_exit(&mfnp->fn_lock);
1013 		}
1014 
1015 		(void) vn_vfsrlock_wait(mvp);
1016 		mvfsp = vn_mountedvfs(mvp);
1017 		if (mvfsp != NULL) {
1018 			error = VFS_ROOT(mvfsp, &newvp);
1019 			vn_vfsunlock(mvp);
1020 			if (error) {
1021 				/*
1022 				 * We've dropped the locks, so let's get
1023 				 * the mounted vfs again in case it changed.
1024 				 */
1025 				(void) vn_vfswlock_wait(mvp);
1026 				mvfsp = vn_mountedvfs(mvp);
1027 				if (mvfsp != NULL) {
1028 					error = dounmount(mvfsp, 0, CRED());
1029 					if (error) {
1030 						cmn_err(CE_WARN,
1031 						    "autofs: could not "
1032 						    "unmount vfs=%p",
1033 						(void *)mvfsp);
1034 					}
1035 				} else
1036 					vn_vfsunlock(mvp);
1037 				VN_RELE(mvp);
1038 				continue;
1039 			}
1040 		} else {
1041 			vn_vfsunlock(mvp);
1042 			VN_RELE(mvp);
1043 			continue;
1044 		}
1045 
1046 		auto_mount = vfs_matchops(dvp->v_vfsp,
1047 						vfs_getops(newvp->v_vfsp));
1048 		newfnp = vntofn(newvp);
1049 		newfnp->fn_parent = dfnp;
1050 
1051 		/*
1052 		 * At this time we want to save the AUTOFS filesystem as
1053 		 * a trigger node. (We only do this if the mount occured
1054 		 * on a node different from the root.
1055 		 * We look at the trigger nodes during
1056 		 * the automatic unmounting to make sure we remove them
1057 		 * as a unit and remount them as a unit if the filesystem
1058 		 * mounted at the root could not be unmounted.
1059 		 */
1060 		if (auto_mount && (error == 0) && (mvp != dvp)) {
1061 			save_triggers++;
1062 			/*
1063 			 * Add AUTOFS mount to hierarchy
1064 			 */
1065 			newfnp->fn_flags |= MF_TRIGGER;
1066 			rw_enter(&newfnp->fn_rwlock, RW_WRITER);
1067 			newfnp->fn_next = dfnp->fn_trigger;
1068 			rw_exit(&newfnp->fn_rwlock);
1069 			rw_enter(&dfnp->fn_rwlock, RW_WRITER);
1070 			dfnp->fn_trigger = newfnp;
1071 			rw_exit(&dfnp->fn_rwlock);
1072 			/*
1073 			 * Don't VN_RELE(newvp) here since dfnp now holds
1074 			 * reference to it as its trigger node.
1075 			 */
1076 			AUTOFS_DPRINT((10, "\tadding trigger %s to %s\n",
1077 			    newfnp->fn_name, dfnp->fn_name));
1078 			AUTOFS_DPRINT((10, "\tfirst trigger is %s\n",
1079 			    dfnp->fn_trigger->fn_name));
1080 			if (newfnp->fn_next != NULL)
1081 				AUTOFS_DPRINT((10, "\tnext trigger is %s\n",
1082 				    newfnp->fn_next->fn_name));
1083 			else
1084 				AUTOFS_DPRINT((10, "\tno next trigger\n"));
1085 		} else
1086 			VN_RELE(newvp);
1087 
1088 		if (!error)
1089 			success++;
1090 
1091 		if (update_times) {
1092 			gethrestime(&now);
1093 			dfnp->fn_atime = dfnp->fn_mtime = now;
1094 		}
1095 
1096 		VN_RELE(mvp);
1097 	}
1098 
1099 	if (save_triggers) {
1100 		/*
1101 		 * Make sure the parent can't be freed while it has triggers.
1102 		 */
1103 		VN_HOLD(dvp);
1104 	}
1105 
1106 	crfree(zcred);
1107 
1108 done:
1109 	/*
1110 	 * Return failure if daemon didn't mount anything, and all
1111 	 * kernel mounts attempted failed.
1112 	 */
1113 	error = success ? 0 : ENOENT;
1114 
1115 	if (alp != NULL) {
1116 		if ((error == 0) && save_triggers) {
1117 			/*
1118 			 * Save action_list information, so that we can use it
1119 			 * when it comes time to remount the trigger nodes
1120 			 * The action list is freed when the directory node
1121 			 * containing the reference to it is unmounted in
1122 			 * unmount_tree().
1123 			 */
1124 			mutex_enter(&dfnp->fn_lock);
1125 			ASSERT(dfnp->fn_alp == NULL);
1126 			dfnp->fn_alp = alp;
1127 			mutex_exit(&dfnp->fn_lock);
1128 		} else {
1129 			/*
1130 			 * free the action list now,
1131 			 */
1132 			xdr_free(xdr_action_list, (char *)alp);
1133 		}
1134 	}
1135 
1136 	AUTOFS_DPRINT((5, "auto_perform_actions: error=%d\n", error));
1137 	return (error);
1138 }
1139 
1140 fnnode_t *
1141 auto_makefnnode(
1142 	vtype_t type,
1143 	vfs_t *vfsp,
1144 	char *name,
1145 	cred_t *cred,
1146 	struct autofs_globals *fngp)
1147 {
1148 	fnnode_t *fnp;
1149 	vnode_t *vp;
1150 	char *tmpname;
1151 	timestruc_t now;
1152 	/*
1153 	 * autofs uses odd inode numbers
1154 	 * automountd uses even inode numbers
1155 	 *
1156 	 * To preserve the age-old semantics that inum+devid is unique across
1157 	 * the system, this variable must be global across zones.
1158 	 */
1159 	static ino_t nodeid = 3;
1160 
1161 	fnp = kmem_zalloc(sizeof (*fnp), KM_SLEEP);
1162 	fnp->fn_vnode = vn_alloc(KM_SLEEP);
1163 
1164 	vp = fntovn(fnp);
1165 	tmpname = kmem_alloc(strlen(name) + 1, KM_SLEEP);
1166 	(void) strcpy(tmpname, name);
1167 	fnp->fn_name = &tmpname[0];
1168 	fnp->fn_namelen = (int)strlen(tmpname) + 1;	/* include '\0' */
1169 	fnp->fn_uid = crgetuid(cred);
1170 	fnp->fn_gid = crgetgid(cred);
1171 	/*
1172 	 * ".." is added in auto_enter and auto_mount.
1173 	 * "." is added in auto_mkdir and auto_mount.
1174 	 */
1175 	/*
1176 	 * Note that fn_size and fn_linkcnt are already 0 since
1177 	 * we used kmem_zalloc to allocated fnp
1178 	 */
1179 	fnp->fn_mode = AUTOFS_MODE;
1180 	gethrestime(&now);
1181 	fnp->fn_atime = fnp->fn_mtime = fnp->fn_ctime = now;
1182 	fnp->fn_ref_time = now.tv_sec;
1183 	mutex_enter(&autofs_nodeid_lock);
1184 	fnp->fn_nodeid = nodeid;
1185 	nodeid += 2;
1186 	fnp->fn_globals = fngp;
1187 	fngp->fng_fnnode_count++;
1188 	mutex_exit(&autofs_nodeid_lock);
1189 	vn_setops(vp, auto_vnodeops);
1190 	vp->v_type = type;
1191 	vp->v_data = (void *)fnp;
1192 	vp->v_vfsp = vfsp;
1193 	mutex_init(&fnp->fn_lock, NULL, MUTEX_DEFAULT, NULL);
1194 	rw_init(&fnp->fn_rwlock, NULL, RW_DEFAULT, NULL);
1195 	cv_init(&fnp->fn_cv_mount, NULL, CV_DEFAULT, NULL);
1196 	vn_exists(vp);
1197 	return (fnp);
1198 }
1199 
1200 
1201 void
1202 auto_freefnnode(fnnode_t *fnp)
1203 {
1204 	vnode_t *vp = fntovn(fnp);
1205 
1206 	AUTOFS_DPRINT((4, "auto_freefnnode: fnp=%p\n", (void *)fnp));
1207 
1208 	ASSERT(fnp->fn_linkcnt == 0);
1209 	ASSERT(vp->v_count == 0);
1210 	ASSERT(fnp->fn_dirents == NULL);
1211 	ASSERT(fnp->fn_parent == NULL);
1212 
1213 	vn_invalid(vp);
1214 	kmem_free(fnp->fn_name, fnp->fn_namelen);
1215 	if (fnp->fn_symlink) {
1216 		ASSERT(fnp->fn_flags & MF_THISUID_MATCH_RQD);
1217 		kmem_free(fnp->fn_symlink, fnp->fn_symlinklen);
1218 	}
1219 	if (fnp->fn_cred)
1220 		crfree(fnp->fn_cred);
1221 	mutex_destroy(&fnp->fn_lock);
1222 	rw_destroy(&fnp->fn_rwlock);
1223 	cv_destroy(&fnp->fn_cv_mount);
1224 	vn_free(vp);
1225 
1226 	mutex_enter(&autofs_nodeid_lock);
1227 	fnp->fn_globals->fng_fnnode_count--;
1228 	mutex_exit(&autofs_nodeid_lock);
1229 	kmem_free(fnp, sizeof (*fnp));
1230 }
1231 
1232 void
1233 auto_disconnect(
1234 	fnnode_t *dfnp,
1235 	fnnode_t *fnp)
1236 {
1237 	fnnode_t *tmp, **fnpp;
1238 	vnode_t *vp = fntovn(fnp);
1239 	timestruc_t now;
1240 
1241 	AUTOFS_DPRINT((4,
1242 	    "auto_disconnect: dfnp=%p fnp=%p linkcnt=%d\n v_count=%d",
1243 	    (void *)dfnp, (void *)fnp, fnp->fn_linkcnt, vp->v_count));
1244 
1245 	ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock));
1246 	ASSERT(fnp->fn_linkcnt == 1);
1247 
1248 	if (vn_mountedvfs(vp) != NULL) {
1249 		cmn_err(CE_PANIC, "auto_disconnect: vp %p mounted on",
1250 		    (void *)vp);
1251 	}
1252 
1253 	/*
1254 	 * Decrement by 1 because we're removing the entry in dfnp.
1255 	 */
1256 	fnp->fn_linkcnt--;
1257 	fnp->fn_size--;
1258 
1259 	/*
1260 	 * only changed while holding parent's (dfnp) rw_lock
1261 	 */
1262 	fnp->fn_parent = NULL;
1263 
1264 	fnpp = &dfnp->fn_dirents;
1265 	for (;;) {
1266 		tmp = *fnpp;
1267 		if (tmp == NULL) {
1268 			cmn_err(CE_PANIC,
1269 			    "auto_disconnect: %p not in %p dirent list",
1270 			    (void *)fnp, (void *)dfnp);
1271 		}
1272 		if (tmp == fnp) {
1273 			*fnpp = tmp->fn_next; 	/* remove it from the list */
1274 			ASSERT(vp->v_count == 0);
1275 			/* child had a pointer to parent ".." */
1276 			dfnp->fn_linkcnt--;
1277 			dfnp->fn_size--;
1278 			break;
1279 		}
1280 		fnpp = &tmp->fn_next;
1281 	}
1282 
1283 	mutex_enter(&fnp->fn_lock);
1284 	gethrestime(&now);
1285 	fnp->fn_atime = fnp->fn_mtime = now;
1286 	mutex_exit(&fnp->fn_lock);
1287 
1288 	AUTOFS_DPRINT((5, "auto_disconnect: done\n"));
1289 }
1290 
1291 int
1292 auto_enter(fnnode_t *dfnp, char *name, fnnode_t **fnpp, cred_t *cred)
1293 {
1294 	struct fnnode *cfnp, **spp;
1295 	vnode_t *dvp = fntovn(dfnp);
1296 	ushort_t offset = 0;
1297 	ushort_t diff;
1298 
1299 	AUTOFS_DPRINT((4, "auto_enter: dfnp=%p, name=%s ", (void *)dfnp, name));
1300 
1301 	ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock));
1302 
1303 	cfnp = dfnp->fn_dirents;
1304 	if (cfnp == NULL) {
1305 		/*
1306 		 * offset = 0 for '.' and offset = 1 for '..'
1307 		 */
1308 		spp = &dfnp->fn_dirents;
1309 		offset = 2;
1310 	}
1311 
1312 	for (; cfnp; cfnp = cfnp->fn_next) {
1313 		if (strcmp(cfnp->fn_name, name) == 0) {
1314 			mutex_enter(&cfnp->fn_lock);
1315 			if (cfnp->fn_flags & MF_THISUID_MATCH_RQD) {
1316 				/*
1317 				 * "thisuser" kind of node, need to
1318 				 * match CREDs as well
1319 				 */
1320 				mutex_exit(&cfnp->fn_lock);
1321 				if (crcmp(cfnp->fn_cred, cred) == 0)
1322 					return (EEXIST);
1323 			} else {
1324 				mutex_exit(&cfnp->fn_lock);
1325 				return (EEXIST);
1326 			}
1327 		}
1328 
1329 		if (cfnp->fn_next != NULL) {
1330 			diff = (ushort_t)
1331 			    (cfnp->fn_next->fn_offset - cfnp->fn_offset);
1332 			ASSERT(diff != 0);
1333 			if (diff > 1 && offset == 0) {
1334 				offset = (ushort_t)cfnp->fn_offset + 1;
1335 				spp = &cfnp->fn_next;
1336 			}
1337 		} else if (offset == 0) {
1338 			offset = (ushort_t)cfnp->fn_offset + 1;
1339 			spp = &cfnp->fn_next;
1340 		}
1341 	}
1342 
1343 	*fnpp = auto_makefnnode(VDIR, dvp->v_vfsp, name, cred,
1344 	    dfnp->fn_globals);
1345 	if (*fnpp == NULL)
1346 		return (ENOMEM);
1347 
1348 	/*
1349 	 * I don't hold the mutex on fnpp because I created it, and
1350 	 * I'm already holding the writers lock for it's parent
1351 	 * directory, therefore nobody can reference it without me first
1352 	 * releasing the writers lock.
1353 	 */
1354 	(*fnpp)->fn_offset = offset;
1355 	(*fnpp)->fn_next = *spp;
1356 	*spp = *fnpp;
1357 	(*fnpp)->fn_parent = dfnp;
1358 	(*fnpp)->fn_linkcnt++;	/* parent now holds reference to entry */
1359 	(*fnpp)->fn_size++;
1360 
1361 	/*
1362 	 * dfnp->fn_linkcnt and dfnp->fn_size protected by dfnp->rw_lock
1363 	 */
1364 	dfnp->fn_linkcnt++;	/* child now holds reference to parent '..' */
1365 	dfnp->fn_size++;
1366 
1367 	dfnp->fn_ref_time = gethrestime_sec();
1368 
1369 	AUTOFS_DPRINT((5, "*fnpp=%p\n", (void *)*fnpp));
1370 	return (0);
1371 }
1372 
1373 int
1374 auto_search(fnnode_t *dfnp, char *name, fnnode_t **fnpp, cred_t *cred)
1375 {
1376 	vnode_t *dvp;
1377 	fnnode_t *p;
1378 	int error = ENOENT, match = 0;
1379 
1380 	AUTOFS_DPRINT((4, "auto_search: dfnp=%p, name=%s...\n",
1381 	    (void *)dfnp, name));
1382 
1383 	dvp = fntovn(dfnp);
1384 	if (dvp->v_type != VDIR) {
1385 		cmn_err(CE_PANIC, "auto_search: dvp=%p not a directory",
1386 		    (void *)dvp);
1387 	}
1388 
1389 	ASSERT(RW_LOCK_HELD(&dfnp->fn_rwlock));
1390 	for (p = dfnp->fn_dirents; p != NULL; p = p->fn_next) {
1391 		if (strcmp(p->fn_name, name) == 0) {
1392 			mutex_enter(&p->fn_lock);
1393 			if (p->fn_flags & MF_THISUID_MATCH_RQD) {
1394 				/*
1395 				 * "thisuser" kind of node
1396 				 * Need to match CREDs as well
1397 				 */
1398 				mutex_exit(&p->fn_lock);
1399 				match = crcmp(p->fn_cred, cred) == 0;
1400 			} else {
1401 				/*
1402 				 * No need to check CRED
1403 				 */
1404 				mutex_exit(&p->fn_lock);
1405 				match = 1;
1406 			}
1407 		}
1408 		if (match) {
1409 			error = 0;
1410 			if (fnpp) {
1411 				*fnpp = p;
1412 				VN_HOLD(fntovn(*fnpp));
1413 			}
1414 			break;
1415 		}
1416 	}
1417 
1418 	AUTOFS_DPRINT((5, "auto_search: error=%d\n", error));
1419 	return (error);
1420 }
1421 
1422 /*
1423  * If dvp is mounted on, get path's vnode in the mounted on
1424  * filesystem.  Path is relative to dvp, ie "./path".
1425  * If successful, *mvp points to a the held mountpoint vnode.
1426  */
1427 /* ARGSUSED */
1428 static int
1429 auto_getmntpnt(
1430 	vnode_t *dvp,
1431 	char *path,
1432 	vnode_t **mvpp,		/* vnode for mountpoint */
1433 	cred_t *cred)
1434 {
1435 	int error = 0;
1436 	vnode_t *newvp;
1437 	char namebuf[TYPICALMAXPATHLEN];
1438 	struct pathname lookpn;
1439 	vfs_t *vfsp;
1440 
1441 	AUTOFS_DPRINT((4, "auto_getmntpnt: path=%s\n", path));
1442 
1443 	if (error = vn_vfsrlock_wait(dvp))
1444 		return (error);
1445 
1446 	/*
1447 	 * Now that we have the vfswlock, check to see if dvp
1448 	 * is still mounted on.  If not, then just bail out as
1449 	 * there is no need to remount the triggers since the
1450 	 * higher level mount point has gotten unmounted.
1451 	 */
1452 	vfsp = vn_mountedvfs(dvp);
1453 	if (vfsp == NULL) {
1454 		vn_vfsunlock(dvp);
1455 		error = EBUSY;
1456 		goto done;
1457 	}
1458 	/*
1459 	 * Since mounted on, lookup "path" in the new filesystem,
1460 	 * it is important that we do the filesystem jump here to
1461 	 * avoid lookuppn() calling auto_lookup on dvp and deadlock.
1462 	 */
1463 	error = VFS_ROOT(vfsp, &newvp);
1464 	vn_vfsunlock(dvp);
1465 	if (error)
1466 		goto done;
1467 
1468 	/*
1469 	 * We do a VN_HOLD on newvp just in case the first call to
1470 	 * lookuppnvp() fails with ENAMETOOLONG.  We should still have a
1471 	 * reference to this vnode for the second call to lookuppnvp().
1472 	 */
1473 	VN_HOLD(newvp);
1474 
1475 	/*
1476 	 * Now create the pathname struct so we can make use of lookuppnvp,
1477 	 * and pn_getcomponent.
1478 	 * This code is similar to lookupname() in fs/lookup.c.
1479 	 */
1480 	error = pn_get_buf(path, UIO_SYSSPACE, &lookpn,
1481 		namebuf, sizeof (namebuf));
1482 	if (error == 0) {
1483 		error = lookuppnvp(&lookpn, NULL, NO_FOLLOW, NULLVPP,
1484 		    mvpp, rootdir, newvp, cred);
1485 	} else
1486 		VN_RELE(newvp);
1487 	if (error == ENAMETOOLONG) {
1488 		/*
1489 		 * This thread used a pathname > TYPICALMAXPATHLEN bytes long.
1490 		 * newvp is VN_RELE'd by this call to lookuppnvp.
1491 		 *
1492 		 * Using 'rootdir' in a zone's context is OK here: we already
1493 		 * ascertained that there are no '..'s in the path, and we're
1494 		 * not following symlinks.
1495 		 */
1496 		if ((error = pn_get(path, UIO_SYSSPACE, &lookpn)) == 0) {
1497 			error = lookuppnvp(&lookpn, NULL, NO_FOLLOW, NULLVPP,
1498 			    mvpp, rootdir, newvp, cred);
1499 			pn_free(&lookpn);
1500 		} else
1501 			VN_RELE(newvp);
1502 	} else {
1503 		/*
1504 		 * Need to release newvp here since we held it.
1505 		 */
1506 		VN_RELE(newvp);
1507 	}
1508 
1509 done:
1510 	AUTOFS_DPRINT((5, "auto_getmntpnt: path=%s *mvpp=%p error=%d\n",
1511 	    path, (void *)*mvpp, error));
1512 	return (error);
1513 }
1514 
1515 #define	DEEPER(x) (((x)->fn_dirents != NULL) || \
1516 			(vn_mountedvfs(fntovn((x)))) != NULL)
1517 
1518 /*
1519  * The caller, should have already VN_RELE'd its reference to the
1520  * root vnode of this filesystem.
1521  */
1522 static int
1523 auto_inkernel_unmount(vfs_t *vfsp)
1524 {
1525 	vnode_t *cvp = vfsp->vfs_vnodecovered;
1526 	int error;
1527 
1528 	AUTOFS_DPRINT((4,
1529 	    "auto_inkernel_unmount: devid=%lx mntpnt(%p) count %u\n",
1530 	    vfsp->vfs_dev, (void *)cvp, cvp->v_count));
1531 
1532 	ASSERT(vn_vfswlock_held(cvp));
1533 
1534 	/*
1535 	 * Perform the unmount
1536 	 * The mountpoint has already been locked by the caller.
1537 	 */
1538 	error = dounmount(vfsp, 0, kcred);
1539 
1540 	AUTOFS_DPRINT((5, "auto_inkernel_unmount: exit count %u\n",
1541 	    cvp->v_count));
1542 	return (error);
1543 }
1544 
1545 /*
1546  * unmounts trigger nodes in the kernel.
1547  */
1548 static void
1549 unmount_triggers(fnnode_t *fnp, action_list **alp)
1550 {
1551 	fnnode_t *tp, *next;
1552 	int error = 0;
1553 	vfs_t *vfsp;
1554 	vnode_t *tvp;
1555 
1556 	AUTOFS_DPRINT((4, "unmount_triggers: fnp=%p\n", (void *)fnp));
1557 	ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock));
1558 
1559 	*alp = fnp->fn_alp;
1560 	next = fnp->fn_trigger;
1561 	while ((tp = next) != NULL) {
1562 		tvp = fntovn(tp);
1563 		ASSERT(tvp->v_count >= 2);
1564 		next = tp->fn_next;
1565 		/*
1566 		 * drop writer's lock since the unmount will end up
1567 		 * disconnecting this node from fnp and needs to acquire
1568 		 * the writer's lock again.
1569 		 * next has at least a reference count >= 2 since it's
1570 		 * a trigger node, therefore can not be accidentally freed
1571 		 * by a VN_RELE
1572 		 */
1573 		rw_exit(&fnp->fn_rwlock);
1574 
1575 		vfsp = tvp->v_vfsp;
1576 
1577 		/*
1578 		 * Its parent was holding a reference to it, since this
1579 		 * is a trigger vnode.
1580 		 */
1581 		VN_RELE(tvp);
1582 		if (error = auto_inkernel_unmount(vfsp)) {
1583 			cmn_err(CE_PANIC, "unmount_triggers: "
1584 			    "unmount of vp=%p failed error=%d",
1585 			    (void *)tvp, error);
1586 		}
1587 		/*
1588 		 * reacquire writer's lock
1589 		 */
1590 		rw_enter(&fnp->fn_rwlock, RW_WRITER);
1591 	}
1592 
1593 	/*
1594 	 * We were holding a reference to our parent.  Drop that.
1595 	 */
1596 	VN_RELE(fntovn(fnp));
1597 	fnp->fn_trigger = NULL;
1598 	fnp->fn_alp = NULL;
1599 
1600 	AUTOFS_DPRINT((5, "unmount_triggers: finished\n"));
1601 }
1602 
1603 /*
1604  * This routine locks the mountpoint of every trigger node if they're
1605  * not busy, or returns EBUSY if any node is busy. If a trigger node should
1606  * be unmounted first, then it sets nfnp to point to it, otherwise nfnp
1607  * points to NULL.
1608  */
1609 static int
1610 triggers_busy(fnnode_t *fnp, fnnode_t **nfnp)
1611 {
1612 	int error = 0, done;
1613 	int lck_error = 0;
1614 	fnnode_t *tp, *t1p;
1615 	vfs_t *vfsp;
1616 
1617 	ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock));
1618 
1619 	*nfnp = NULL;
1620 	for (tp = fnp->fn_trigger; tp != NULL; tp = tp->fn_next) {
1621 		AUTOFS_DPRINT((10, "\ttrigger: %s\n", tp->fn_name));
1622 		vfsp = fntovn(tp)->v_vfsp;
1623 		error = 0;
1624 		/*
1625 		 * The vn_vfsunlock will be done in auto_inkernel_unmount.
1626 		 */
1627 		lck_error = vn_vfswlock(vfsp->vfs_vnodecovered);
1628 		if (lck_error == 0) {
1629 			mutex_enter(&tp->fn_lock);
1630 			ASSERT((tp->fn_flags & MF_LOOKUP) == 0);
1631 			if (tp->fn_flags & MF_INPROG) {
1632 				/*
1633 				 * a mount is in progress
1634 				 */
1635 				error = EBUSY;
1636 			}
1637 			mutex_exit(&tp->fn_lock);
1638 		}
1639 		if (lck_error || error || DEEPER(tp) ||
1640 		    ((fntovn(tp))->v_count) > 2) {
1641 			/*
1642 			 * couldn't lock it because it's busy,
1643 			 * It is mounted on or has dirents?
1644 			 * If reference count is greater than two, then
1645 			 * somebody else is holding a reference to this vnode.
1646 			 * One reference is for the mountpoint, and the second
1647 			 * is for the trigger node.
1648 			 */
1649 			AUTOFS_DPRINT((10, "\ttrigger busy\n"));
1650 			if ((lck_error == 0) && (error == 0)) {
1651 				*nfnp = tp;
1652 				/*
1653 				 * The matching VN_RELE is done in
1654 				 * unmount_tree().
1655 				 */
1656 				VN_HOLD(fntovn(*nfnp));
1657 			}
1658 			/*
1659 			 * Unlock previously locked mountpoints
1660 			 */
1661 			for (done = 0, t1p = fnp->fn_trigger; !done;
1662 			    t1p = t1p->fn_next) {
1663 				/*
1664 				 * Unlock all nodes previously
1665 				 * locked. All nodes up to 'tp'
1666 				 * were successfully locked. If 'lck_err' is
1667 				 * set, then 'tp' was not locked, and thus
1668 				 * should not be unlocked. If
1669 				 * 'lck_err' is not set, then 'tp' was
1670 				 * successfully locked, and it should
1671 				 * be unlocked.
1672 				 */
1673 				if (t1p != tp || !lck_error) {
1674 					vfsp = fntovn(t1p)->v_vfsp;
1675 					vn_vfsunlock(vfsp->vfs_vnodecovered);
1676 				}
1677 				done = (t1p == tp);
1678 			}
1679 			error = EBUSY;
1680 			break;
1681 		}
1682 	}
1683 
1684 	AUTOFS_DPRINT((4, "triggers_busy: error=%d\n", error));
1685 	return (error);
1686 }
1687 
1688 /*
1689  * Unlock previously locked trigger nodes.
1690  */
1691 static int
1692 triggers_unlock(fnnode_t *fnp)
1693 {
1694 	fnnode_t *tp;
1695 	vfs_t *vfsp;
1696 
1697 	ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock));
1698 
1699 	for (tp = fnp->fn_trigger; tp != NULL; tp = tp->fn_next) {
1700 		AUTOFS_DPRINT((10, "\tunlock trigger: %s\n", tp->fn_name));
1701 		vfsp = fntovn(tp)->v_vfsp;
1702 		vn_vfsunlock(vfsp->vfs_vnodecovered);
1703 	}
1704 
1705 	return (0);
1706 }
1707 
1708 /*
1709  * It is the caller's responsibility to grab the VVFSLOCK.
1710  * Releases the VVFSLOCK upon return.
1711  */
1712 static int
1713 unmount_node(vnode_t *cvp, int force)
1714 {
1715 	int error = 0;
1716 	fnnode_t *cfnp;
1717 	vfs_t *vfsp;
1718 	umntrequest ul;
1719 	fninfo_t *fnip;
1720 
1721 	AUTOFS_DPRINT((4, "\tunmount_node cvp=%p\n", (void *)cvp));
1722 
1723 	ASSERT(vn_vfswlock_held(cvp));
1724 	cfnp = vntofn(cvp);
1725 	vfsp = vn_mountedvfs(cvp);
1726 
1727 	if (force || cfnp->fn_flags & MF_IK_MOUNT) {
1728 		/*
1729 		 * Mount was performed in the kernel, so
1730 		 * do an in-kernel unmount. auto_inkernel_unmount()
1731 		 * will vn_vfsunlock(cvp).
1732 		 */
1733 		error = auto_inkernel_unmount(vfsp);
1734 	} else {
1735 		zone_t *zone = NULL;
1736 		refstr_t *mntpt, *resource;
1737 		size_t mntoptslen;
1738 
1739 		/*
1740 		 * Get the mnttab information of the node
1741 		 * and ask the daemon to unmount it.
1742 		 */
1743 		bzero(&ul, sizeof (ul));
1744 		mntfs_getmntopts(vfsp, &ul.mntopts, &mntoptslen);
1745 		if (ul.mntopts == NULL) {
1746 			auto_log(cfnp->fn_globals, CE_WARN, "unmount_node: "
1747 			    "no memory");
1748 			vn_vfsunlock(cvp);
1749 			error = ENOMEM;
1750 			goto done;
1751 		}
1752 		if (mntoptslen > AUTOFS_MAXOPTSLEN)
1753 			ul.mntopts[AUTOFS_MAXOPTSLEN - 1] = '\0';
1754 
1755 		mntpt = vfs_getmntpoint(vfsp);
1756 		ul.mntpnt = (char *)refstr_value(mntpt);
1757 		resource = vfs_getresource(vfsp);
1758 		ul.mntresource = (char *)refstr_value(resource);
1759 
1760 		fnip = vfstofni(cvp->v_vfsp);
1761 		ul.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE;
1762 
1763 		/*
1764 		 * Since a zone'd automountd's view of the autofs mount points
1765 		 * differs from those in the kernel, we need to make sure we
1766 		 * give it consistent mount points.
1767 		 */
1768 		ASSERT(fnip->fi_zoneid == getzoneid());
1769 		zone = curproc->p_zone;
1770 
1771 		if (fnip->fi_zoneid != GLOBAL_ZONEID) {
1772 			if (ZONE_PATH_VISIBLE(ul.mntpnt, zone)) {
1773 				ul.mntpnt =
1774 				    ZONE_PATH_TRANSLATE(ul.mntpnt, zone);
1775 			}
1776 			if (ZONE_PATH_VISIBLE(ul.mntresource, zone)) {
1777 				ul.mntresource =
1778 				    ZONE_PATH_TRANSLATE(ul.mntresource, zone);
1779 			}
1780 		}
1781 		ul.fstype = vfssw[vfsp->vfs_fstype].vsw_name;
1782 		vn_vfsunlock(cvp);
1783 
1784 		error = auto_send_unmount_request(fnip, &ul, CRED(), FALSE);
1785 		kmem_free(ul.mntopts, mntoptslen);
1786 		refstr_rele(mntpt);
1787 		refstr_rele(resource);
1788 	}
1789 
1790 done:
1791 	AUTOFS_DPRINT((5, "\tunmount_node cvp=%p error=%d\n", (void *)cvp,
1792 	    error));
1793 	return (error);
1794 }
1795 
1796 /*
1797  * vp is the "root" of the AUTOFS filesystem.
1798  * return EBUSY if any thread is holding a reference to this vnode
1799  * other than us.
1800  */
1801 static int
1802 check_auto_node(vnode_t *vp)
1803 {
1804 	fnnode_t *fnp;
1805 	int error = 0;
1806 	/*
1807 	 * number of references to expect for
1808 	 * a non-busy vnode.
1809 	 */
1810 	uint_t count;
1811 
1812 	AUTOFS_DPRINT((4, "\tcheck_auto_node vp=%p ", (void *)vp));
1813 	fnp = vntofn(vp);
1814 	ASSERT(fnp->fn_flags & MF_INPROG);
1815 	ASSERT((fnp->fn_flags & MF_LOOKUP) == 0);
1816 
1817 	count = 1;		/* we are holding a reference to vp */
1818 	if (fnp->fn_flags & MF_TRIGGER) {
1819 		/*
1820 		 * parent holds a pointer to us (trigger)
1821 		 */
1822 		count++;
1823 	}
1824 	if (fnp->fn_trigger != NULL) {
1825 		/*
1826 		 * The trigger nodes have a hold on us.
1827 		 */
1828 		count++;
1829 	}
1830 	mutex_enter(&vp->v_lock);
1831 	if (vp->v_flag & VROOT)
1832 		count++;
1833 	ASSERT(vp->v_count > 0);
1834 	AUTOFS_DPRINT((10, "\tcount=%u ", vp->v_count));
1835 	if (vp->v_count > count)
1836 		error = EBUSY;
1837 	mutex_exit(&vp->v_lock);
1838 
1839 	AUTOFS_DPRINT((5, "\tcheck_auto_node error=%d ", error));
1840 	return (error);
1841 }
1842 
1843 /*
1844  * rootvp is the root of the AUTOFS filesystem.
1845  * If rootvp is busy (v_count > 1) returns EBUSY.
1846  * else removes every vnode under this tree.
1847  * ASSUMPTION: Assumes that the only node which can be busy is
1848  * the root vnode. This filesystem better be two levels deep only,
1849  * the root and its immediate subdirs.
1850  * The daemon will "AUTOFS direct-mount" only one level below the root.
1851  */
1852 static int
1853 unmount_autofs(vnode_t *rootvp)
1854 {
1855 	fnnode_t *fnp, *rootfnp, *nfnp;
1856 	int error;
1857 
1858 	AUTOFS_DPRINT((4, "\tunmount_autofs rootvp=%p ", (void *)rootvp));
1859 
1860 	error = check_auto_node(rootvp);
1861 	if (error == 0) {
1862 		/*
1863 		 * Remove all its immediate subdirectories.
1864 		 */
1865 		rootfnp = vntofn(rootvp);
1866 		rw_enter(&rootfnp->fn_rwlock, RW_WRITER);
1867 		nfnp = NULL;	/* lint clean */
1868 		for (fnp = rootfnp->fn_dirents; fnp != NULL; fnp = nfnp) {
1869 			ASSERT(fntovn(fnp)->v_count == 0);
1870 			ASSERT(fnp->fn_dirents == NULL);
1871 			ASSERT(fnp->fn_linkcnt == 2);
1872 			fnp->fn_linkcnt--;
1873 			auto_disconnect(rootfnp, fnp);
1874 			nfnp = fnp->fn_next;
1875 			auto_freefnnode(fnp);
1876 		}
1877 		rw_exit(&rootfnp->fn_rwlock);
1878 	}
1879 	AUTOFS_DPRINT((5, "\tunmount_autofs error=%d ", error));
1880 	return (error);
1881 }
1882 
1883 /*
1884  * max number of unmount threads running
1885  */
1886 static int autofs_unmount_threads = 5;
1887 
1888 /*
1889  * XXX unmount_tree() is not suspend-safe within the scope of
1890  * the present model defined for cpr to suspend the system. Calls made
1891  * by the unmount_tree() that have been identified to be unsafe are
1892  * (1) RPC client handle setup and client calls to automountd which can
1893  * block deep down in the RPC library, (2) kmem_alloc() calls with the
1894  * KM_SLEEP flag which can block if memory is low, and (3) VFS_*() and
1895  * VOP_*() calls which can result in over the wire calls to servers.
1896  * The thread should be completely reevaluated to make it suspend-safe in
1897  * case of future updates to the cpr model.
1898  */
1899 void
1900 unmount_tree(struct autofs_globals *fngp, int force)
1901 {
1902 	vnode_t *vp, *newvp;
1903 	vfs_t *vfsp;
1904 	fnnode_t *fnp, *nfnp, *pfnp;
1905 	action_list *alp;
1906 	int error, ilocked_it = 0;
1907 	fninfo_t *fnip;
1908 	time_t ref_time;
1909 	int autofs_busy_root, unmount_as_unit, unmount_done = 0;
1910 	timestruc_t now;
1911 
1912 	callb_cpr_t cprinfo;
1913 	kmutex_t unmount_tree_cpr_lock;
1914 
1915 	mutex_init(&unmount_tree_cpr_lock, NULL, MUTEX_DEFAULT, NULL);
1916 	CALLB_CPR_INIT(&cprinfo, &unmount_tree_cpr_lock, callb_generic_cpr,
1917 		"unmount_tree");
1918 
1919 	/*
1920 	 * Got to release lock before attempting unmount in case
1921 	 * it hangs.
1922 	 */
1923 	rw_enter(&fngp->fng_rootfnnodep->fn_rwlock, RW_READER);
1924 	if ((fnp = fngp->fng_rootfnnodep->fn_dirents) == NULL) {
1925 		ASSERT(fngp->fng_fnnode_count == 1);
1926 		/*
1927 		 * no autofs mounted, done.
1928 		 */
1929 		rw_exit(&fngp->fng_rootfnnodep->fn_rwlock);
1930 		goto done;
1931 	}
1932 	VN_HOLD(fntovn(fnp));
1933 	rw_exit(&fngp->fng_rootfnnodep->fn_rwlock);
1934 
1935 	vp = fntovn(fnp);
1936 	fnip = vfstofni(vp->v_vfsp);
1937 	/*
1938 	 * autofssys() will be calling in from the global zone and doing
1939 	 * work on the behalf of the given zone, hence we can't always assert
1940 	 * that we have the right credentials, nor that the caller is always in
1941 	 * the correct zone.
1942 	 *
1943 	 * We do, however, know that if this is a "forced unmount" operation
1944 	 * (which autofssys() does), then we won't go down to the krpc layers,
1945 	 * so we don't need to fudge with the credentials.
1946 	 */
1947 	ASSERT(force || fnip->fi_zoneid == getzoneid());
1948 	if (!force && auto_null_request(fnip, kcred, FALSE) != 0) {
1949 		/*
1950 		 * automountd not running in this zone,
1951 		 * don't attempt unmounting this round.
1952 		 */
1953 		VN_RELE(vp);
1954 		goto done;
1955 	}
1956 	/* reference time for this unmount round */
1957 	ref_time = gethrestime_sec();
1958 	/*
1959 	 * If this an autofssys() call, we need to make sure we don't skip
1960 	 * nodes because we think we saw them recently.
1961 	 */
1962 	mutex_enter(&fnp->fn_lock);
1963 	if (force && fnp->fn_unmount_ref_time >= ref_time)
1964 		ref_time = fnp->fn_unmount_ref_time + 1;
1965 	mutex_exit(&fnp->fn_lock);
1966 
1967 	AUTOFS_DPRINT((4, "unmount_tree (ID=%ld)\n", ref_time));
1968 top:
1969 	AUTOFS_DPRINT((10, "unmount_tree: %s\n", fnp->fn_name));
1970 	ASSERT(fnp);
1971 	vp = fntovn(fnp);
1972 	if (vp->v_type == VLNK) {
1973 		/*
1974 		 * can't unmount symbolic links
1975 		 */
1976 		goto next;
1977 	}
1978 	fnip = vfstofni(vp->v_vfsp);
1979 	ASSERT(vp->v_count > 0);
1980 	error = 0;
1981 	autofs_busy_root = unmount_as_unit = 0;
1982 	alp = NULL;
1983 
1984 	ilocked_it = 0;
1985 	mutex_enter(&fnp->fn_lock);
1986 	if (fnp->fn_flags & (MF_INPROG | MF_LOOKUP)) {
1987 		/*
1988 		 * Either a mount, lookup or another unmount of this
1989 		 * subtree is in progress, don't attempt to unmount at
1990 		 * this time.
1991 		 */
1992 		mutex_exit(&fnp->fn_lock);
1993 		error = EBUSY;
1994 		goto next;
1995 	}
1996 	if (fnp->fn_unmount_ref_time >= ref_time) {
1997 		/*
1998 		 * Already been here, try next node.
1999 		 */
2000 		mutex_exit(&fnp->fn_lock);
2001 		error = EBUSY;
2002 		goto next;
2003 	}
2004 	fnp->fn_unmount_ref_time = ref_time;
2005 
2006 	/*
2007 	 * If forced operation ignore timeout values
2008 	 */
2009 	if (!force && fnp->fn_ref_time + fnip->fi_mount_to >
2010 	    gethrestime_sec()) {
2011 		/*
2012 		 * Node has been referenced recently, try the
2013 		 * unmount of its children if any.
2014 		 */
2015 		mutex_exit(&fnp->fn_lock);
2016 		AUTOFS_DPRINT((10, "fn_ref_time within range\n"));
2017 		rw_enter(&fnp->fn_rwlock, RW_READER);
2018 		if (fnp->fn_dirents) {
2019 			/*
2020 			 * Has subdirectory, attempt their
2021 			 * unmount first
2022 			 */
2023 			nfnp = fnp->fn_dirents;
2024 			VN_HOLD(fntovn(nfnp));
2025 			rw_exit(&fnp->fn_rwlock);
2026 
2027 			VN_RELE(vp);
2028 			fnp = nfnp;
2029 			goto top;
2030 		}
2031 		rw_exit(&fnp->fn_rwlock);
2032 		/*
2033 		 * No children, try next node.
2034 		 */
2035 		error = EBUSY;
2036 		goto next;
2037 	}
2038 
2039 	AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG);
2040 	fnp->fn_error = 0;
2041 	mutex_exit(&fnp->fn_lock);
2042 	ilocked_it = 1;
2043 
2044 	rw_enter(&fnp->fn_rwlock, RW_WRITER);
2045 	if (fnp->fn_trigger != NULL) {
2046 		unmount_as_unit = 1;
2047 		if ((vn_mountedvfs(vp) == NULL) && (check_auto_node(vp))) {
2048 			/*
2049 			 * AUTOFS mountpoint is busy, there's
2050 			 * no point trying to unmount. Fall through
2051 			 * to attempt to unmount subtrees rooted
2052 			 * at a possible trigger node, but remember
2053 			 * not to unmount this tree.
2054 			 */
2055 			autofs_busy_root = 1;
2056 		}
2057 
2058 		if (triggers_busy(fnp, &nfnp)) {
2059 			rw_exit(&fnp->fn_rwlock);
2060 			if (nfnp == NULL) {
2061 				error = EBUSY;
2062 				goto next;
2063 			}
2064 			/*
2065 			 * nfnp is busy, try to unmount it first
2066 			 */
2067 			mutex_enter(&fnp->fn_lock);
2068 			AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
2069 			mutex_exit(&fnp->fn_lock);
2070 			VN_RELE(vp);
2071 			ASSERT(fntovn(nfnp)->v_count > 1);
2072 			fnp = nfnp;
2073 			goto top;
2074 		}
2075 
2076 		/*
2077 		 * At this point, we know all trigger nodes are locked,
2078 		 * and they're not busy or mounted on.
2079 		 */
2080 
2081 		if (autofs_busy_root) {
2082 			/*
2083 			 * Got to unlock the the trigger nodes since
2084 			 * I'm not really going to unmount the filesystem.
2085 			 */
2086 			(void) triggers_unlock(fnp);
2087 		} else {
2088 			/*
2089 			 * Attempt to unmount all the trigger nodes,
2090 			 * save the action_list in case we need to
2091 			 * remount them later. The action_list will be XDR
2092 			 * freed later if there was no need to remount the
2093 			 * trigger nodes.
2094 			 */
2095 			unmount_triggers(fnp, &alp);
2096 		}
2097 	}
2098 	rw_exit(&fnp->fn_rwlock);
2099 
2100 	if (autofs_busy_root)
2101 		goto next;
2102 
2103 	(void) vn_vfswlock_wait(vp);
2104 
2105 	vfsp = vn_mountedvfs(vp);
2106 	if (vfsp != NULL) {
2107 		/*
2108 		 * Node is mounted on.
2109 		 */
2110 		AUTOFS_DPRINT((10, "\tNode is mounted on\n"));
2111 
2112 		/*
2113 		 * Deal with /xfn/host/jurassic alikes here...
2114 		 */
2115 		if (vfs_matchops(vfsp, vfs_getops(vp->v_vfsp))) {
2116 			/*
2117 			 * If the filesystem mounted here is AUTOFS, and it
2118 			 * is busy, try to unmount the tree rooted on it
2119 			 * first. We know this call to VFS_ROOT is safe to
2120 			 * call while holding VVFSLOCK, since it resolves
2121 			 * to a call to auto_root().
2122 			 */
2123 			AUTOFS_DPRINT((10, "\t\tAUTOFS mounted here\n"));
2124 			if (VFS_ROOT(vfsp, &newvp)) {
2125 				cmn_err(CE_PANIC,
2126 				    "unmount_tree: VFS_ROOT(vfs=%p) failed",
2127 				    (void *)vfsp);
2128 			}
2129 			nfnp = vntofn(newvp);
2130 			if (DEEPER(nfnp)) {
2131 				vn_vfsunlock(vp);
2132 				mutex_enter(&fnp->fn_lock);
2133 				AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
2134 				mutex_exit(&fnp->fn_lock);
2135 				VN_RELE(vp);
2136 				fnp = nfnp;
2137 				goto top;
2138 			}
2139 			/*
2140 			 * Fall through to unmount this filesystem
2141 			 */
2142 			VN_RELE(newvp);
2143 		}
2144 
2145 		/*
2146 		 * vn_vfsunlock(vp) is done inside unmount_node()
2147 		 */
2148 		error = unmount_node(vp, force);
2149 		if (error == ECONNRESET) {
2150 			AUTOFS_DPRINT((10, "\tConnection dropped\n"));
2151 			if (vn_mountedvfs(vp) == NULL) {
2152 				/*
2153 				 * The filesystem was unmounted before the
2154 				 * daemon died. Unfortunately we can not
2155 				 * determine whether all the cleanup work was
2156 				 * successfully finished (i.e. update mnttab,
2157 				 * or notify NFS server of the unmount).
2158 				 * We should not retry the operation since the
2159 				 * filesystem has already been unmounted, and
2160 				 * may have already been removed from mnttab,
2161 				 * in such case the devid/rdevid we send to
2162 				 * the daemon will not be matched. So we have
2163 				 * to be contempt with the partial unmount.
2164 				 * Since the mountpoint is no longer covered, we
2165 				 * clear the error condition.
2166 				 */
2167 				error = 0;
2168 				auto_log(fngp, CE_WARN,
2169 				    "unmount_tree: automountd connection "
2170 				    "dropped");
2171 				if (fnip->fi_flags & MF_DIRECT) {
2172 					auto_log(fngp, CE_WARN, "unmount_tree: "
2173 					    "%s successfully unmounted - "
2174 					    "do not remount triggers",
2175 					    fnip->fi_path);
2176 				} else {
2177 					auto_log(fngp, CE_WARN, "unmount_tree: "
2178 					    "%s/%s successfully unmounted - "
2179 					    "do not remount triggers",
2180 					    fnip->fi_path, fnp->fn_name);
2181 				}
2182 			}
2183 		}
2184 	} else {
2185 		vn_vfsunlock(vp);
2186 		AUTOFS_DPRINT((10, "\tNode is AUTOFS\n"));
2187 		if (unmount_as_unit) {
2188 			AUTOFS_DPRINT((10, "\tunmount as unit\n"));
2189 			error = unmount_autofs(vp);
2190 		} else {
2191 			AUTOFS_DPRINT((10, "\tunmount one at a time\n"));
2192 			rw_enter(&fnp->fn_rwlock, RW_READER);
2193 			if (fnp->fn_dirents != NULL) {
2194 				/*
2195 				 * Has subdirectory, attempt their
2196 				 * unmount first
2197 				 */
2198 				nfnp = fnp->fn_dirents;
2199 				VN_HOLD(fntovn(nfnp));
2200 				rw_exit(&fnp->fn_rwlock);
2201 
2202 				mutex_enter(&fnp->fn_lock);
2203 				AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
2204 				mutex_exit(&fnp->fn_lock);
2205 				VN_RELE(vp);
2206 				fnp = nfnp;
2207 				goto top;
2208 			}
2209 			rw_exit(&fnp->fn_rwlock);
2210 			goto next;
2211 		}
2212 	}
2213 
2214 	if (error) {
2215 		AUTOFS_DPRINT((10, "\tUnmount failed\n"));
2216 		if (alp != NULL) {
2217 			/*
2218 			 * Unmount failed, got to remount triggers.
2219 			 */
2220 			ASSERT((fnp->fn_flags & MF_THISUID_MATCH_RQD) == 0);
2221 			error = auto_perform_actions(fnip, fnp, alp, CRED());
2222 			if (error) {
2223 				auto_log(fngp, CE_WARN, "autofs: can't remount "
2224 				    "triggers fnp=%p error=%d", (void *)fnp,
2225 				    error);
2226 				error = 0;
2227 				/*
2228 				 * The action list should have been
2229 				 * xdr_free'd by auto_perform_actions
2230 				 * since an error occured
2231 				 */
2232 				alp = NULL;
2233 			}
2234 		}
2235 	} else {
2236 		/*
2237 		 * The unmount succeeded, which will cause this node to
2238 		 * be removed from its parent if its an indirect mount,
2239 		 * therefore update the parent's atime and mtime now.
2240 		 * I don't update them in auto_disconnect() because I
2241 		 * don't want atime and mtime changing every time a
2242 		 * lookup goes to the daemon and creates a new node.
2243 		 */
2244 		unmount_done = 1;
2245 		if ((fnip->fi_flags & MF_DIRECT) == 0) {
2246 			gethrestime(&now);
2247 			if (fnp->fn_parent == fngp->fng_rootfnnodep)
2248 				fnp->fn_atime = fnp->fn_mtime = now;
2249 			else
2250 				fnp->fn_parent->fn_atime =
2251 					fnp->fn_parent->fn_mtime = now;
2252 		}
2253 
2254 		/*
2255 		 * Free the action list here
2256 		 */
2257 		if (alp != NULL) {
2258 			xdr_free(xdr_action_list, (char *)alp);
2259 			alp = NULL;
2260 		}
2261 	}
2262 
2263 	fnp->fn_ref_time = gethrestime_sec();
2264 
2265 next:
2266 	/*
2267 	 * Obtain parent's readers lock before grabbing
2268 	 * reference to next sibling.
2269 	 * XXX Note that nodes in the top level list (mounted
2270 	 * in user space not by the daemon in the kernel) parent is itself,
2271 	 * therefore grabbing the lock makes no sense, but doesn't
2272 	 * hurt either.
2273 	 */
2274 	pfnp = fnp->fn_parent;
2275 	ASSERT(pfnp != NULL);
2276 	rw_enter(&pfnp->fn_rwlock, RW_READER);
2277 	if ((nfnp = fnp->fn_next) != NULL)
2278 		VN_HOLD(fntovn(nfnp));
2279 	rw_exit(&pfnp->fn_rwlock);
2280 
2281 	if (ilocked_it) {
2282 		mutex_enter(&fnp->fn_lock);
2283 		if (unmount_done) {
2284 			/*
2285 			 * Other threads may be waiting for this unmount to
2286 			 * finish. We must let it know that in order to
2287 			 * proceed, it must trigger the mount itself.
2288 			 */
2289 			fnp->fn_flags &= ~MF_IK_MOUNT;
2290 			if (fnp->fn_flags & MF_WAITING)
2291 				fnp->fn_error = EAGAIN;
2292 			unmount_done = 0;
2293 		}
2294 		AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
2295 		mutex_exit(&fnp->fn_lock);
2296 		ilocked_it = 0;
2297 	}
2298 
2299 	if (nfnp != NULL) {
2300 		VN_RELE(vp);
2301 		fnp = nfnp;
2302 		/*
2303 		 * Unmount next element
2304 		 */
2305 		goto top;
2306 	}
2307 
2308 	/*
2309 	 * We don't want to unmount rootfnnodep, so the check is made here
2310 	 */
2311 	ASSERT(pfnp != fnp);
2312 	if (pfnp != fngp->fng_rootfnnodep) {
2313 		/*
2314 		 * Now attempt to unmount my parent
2315 		 */
2316 		VN_HOLD(fntovn(pfnp));
2317 		VN_RELE(vp);
2318 		fnp = pfnp;
2319 
2320 		goto top;
2321 	}
2322 
2323 	VN_RELE(vp);
2324 
2325 	/*
2326 	 * At this point we've walked the entire tree and attempted to unmount
2327 	 * as much as we can one level at a time.
2328 	 */
2329 done:
2330 	mutex_enter(&unmount_tree_cpr_lock);
2331 	CALLB_CPR_EXIT(&cprinfo);
2332 	mutex_destroy(&unmount_tree_cpr_lock);
2333 }
2334 
2335 static void
2336 unmount_zone_tree(struct autofs_globals *fngp)
2337 {
2338 	unmount_tree(fngp, 0);
2339 	mutex_enter(&fngp->fng_unmount_threads_lock);
2340 	fngp->fng_unmount_threads--;
2341 	mutex_exit(&fngp->fng_unmount_threads_lock);
2342 
2343 	AUTOFS_DPRINT((5, "unmount_tree done. Thread exiting.\n"));
2344 
2345 	zthread_exit();
2346 	/* NOTREACHED */
2347 }
2348 
2349 static int autofs_unmount_thread_timer = 120;	/* in seconds */
2350 
2351 void
2352 auto_do_unmount(struct autofs_globals *fngp)
2353 {
2354 	callb_cpr_t cprinfo;
2355 	clock_t timeleft;
2356 	zone_t *zone = curproc->p_zone;
2357 
2358 	CALLB_CPR_INIT(&cprinfo, &fngp->fng_unmount_threads_lock,
2359 		callb_generic_cpr, "auto_do_unmount");
2360 
2361 	for (;;) {	/* forever */
2362 		mutex_enter(&fngp->fng_unmount_threads_lock);
2363 		CALLB_CPR_SAFE_BEGIN(&cprinfo);
2364 newthread:
2365 		mutex_exit(&fngp->fng_unmount_threads_lock);
2366 		timeleft = zone_status_timedwait(zone, lbolt +
2367 		    autofs_unmount_thread_timer * hz, ZONE_IS_SHUTTING_DOWN);
2368 		mutex_enter(&fngp->fng_unmount_threads_lock);
2369 
2370 		if (timeleft != -1) {	/* didn't time out */
2371 			ASSERT(zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN);
2372 			/*
2373 			 * zone is exiting... don't create any new threads.
2374 			 * fng_unmount_threads_lock is released implicitly by
2375 			 * the below.
2376 			 */
2377 			CALLB_CPR_SAFE_END(&cprinfo,
2378 				&fngp->fng_unmount_threads_lock);
2379 			CALLB_CPR_EXIT(&cprinfo);
2380 			zthread_exit();
2381 			/* NOTREACHED */
2382 		}
2383 		if (fngp->fng_unmount_threads < autofs_unmount_threads) {
2384 			fngp->fng_unmount_threads++;
2385 			CALLB_CPR_SAFE_END(&cprinfo,
2386 				&fngp->fng_unmount_threads_lock);
2387 			mutex_exit(&fngp->fng_unmount_threads_lock);
2388 
2389 			(void) zthread_create(NULL, 0, unmount_zone_tree, fngp,
2390 			    0, minclsyspri);
2391 		} else
2392 			goto newthread;
2393 	}
2394 	/* NOTREACHED */
2395 }
2396 
2397 /*
2398  * Is nobrowse specified in option string?
2399  * opts should be a null ('\0') terminated string.
2400  * Returns non-zero if nobrowse has been specified.
2401  */
2402 int
2403 auto_nobrowse_option(char *opts)
2404 {
2405 	char *buf;
2406 	char *p;
2407 	char *t;
2408 	int nobrowse = 0;
2409 	int last_opt = 0;
2410 	size_t len;
2411 
2412 	len = strlen(opts) + 1;
2413 	p = buf = kmem_alloc(len, KM_SLEEP);
2414 	(void) strcpy(buf, opts);
2415 	do {
2416 		if (t = strchr(p, ','))
2417 			*t++ = '\0';
2418 		else
2419 			last_opt++;
2420 		if (strcmp(p, MNTOPT_NOBROWSE) == 0)
2421 			nobrowse = 1;
2422 		else if (strcmp(p, MNTOPT_BROWSE) == 0)
2423 			nobrowse = 0;
2424 		p = t;
2425 	} while (!last_opt);
2426 	kmem_free(buf, len);
2427 
2428 	return (nobrowse);
2429 }
2430 
2431 /*
2432  * used to log warnings only if automountd is running
2433  * with verbose mode set
2434  */
2435 void
2436 auto_log(struct autofs_globals *fngp, int level, const char *fmt, ...)
2437 {
2438 	va_list args;
2439 
2440 	if (fngp->fng_verbose > 0) {
2441 		va_start(args, fmt);
2442 		vzcmn_err(fngp->fng_zoneid, level, fmt, args);
2443 		va_end(args);
2444 	}
2445 }
2446 
2447 #ifdef DEBUG
2448 static int autofs_debug = 0;
2449 
2450 /*
2451  * Utilities used by both client and server
2452  * Standard levels:
2453  * 0) no debugging
2454  * 1) hard failures
2455  * 2) soft failures
2456  * 3) current test software
2457  * 4) main procedure entry points
2458  * 5) main procedure exit points
2459  * 6) utility procedure entry points
2460  * 7) utility procedure exit points
2461  * 8) obscure procedure entry points
2462  * 9) obscure procedure exit points
2463  * 10) random stuff
2464  * 11) all <= 1
2465  * 12) all <= 2
2466  * 13) all <= 3
2467  * ...
2468  */
2469 /* PRINTFLIKE2 */
2470 void
2471 auto_dprint(int level, const char *fmt, ...)
2472 {
2473 	va_list args;
2474 
2475 	if (autofs_debug == level ||
2476 	    (autofs_debug > 10 && (autofs_debug - 10) >= level)) {
2477 		va_start(args, fmt);
2478 		(void) vprintf(fmt, args);
2479 		va_end(args);
2480 	}
2481 }
2482 #endif /* DEBUG */
2483