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