Home | History | Annotate | Download | only in dev
      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 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * utility routines for the /dev fs
     28  */
     29 
     30 #include <sys/types.h>
     31 #include <sys/param.h>
     32 #include <sys/t_lock.h>
     33 #include <sys/systm.h>
     34 #include <sys/sysmacros.h>
     35 #include <sys/user.h>
     36 #include <sys/time.h>
     37 #include <sys/vfs.h>
     38 #include <sys/vnode.h>
     39 #include <sys/file.h>
     40 #include <sys/fcntl.h>
     41 #include <sys/flock.h>
     42 #include <sys/kmem.h>
     43 #include <sys/uio.h>
     44 #include <sys/errno.h>
     45 #include <sys/stat.h>
     46 #include <sys/cred.h>
     47 #include <sys/dirent.h>
     48 #include <sys/pathname.h>
     49 #include <sys/cmn_err.h>
     50 #include <sys/debug.h>
     51 #include <sys/mode.h>
     52 #include <sys/policy.h>
     53 #include <fs/fs_subr.h>
     54 #include <sys/mount.h>
     55 #include <sys/fs/snode.h>
     56 #include <sys/fs/dv_node.h>
     57 #include <sys/fs/sdev_impl.h>
     58 #include <sys/fs/sdev_node.h>
     59 #include <sys/sunndi.h>
     60 #include <sys/sunmdi.h>
     61 #include <sys/conf.h>
     62 #include <sys/proc.h>
     63 #include <sys/user.h>
     64 #include <sys/modctl.h>
     65 
     66 #ifdef DEBUG
     67 int sdev_debug = 0x00000001;
     68 int sdev_debug_cache_flags = 0;
     69 #endif
     70 
     71 /*
     72  * globals
     73  */
     74 /* prototype memory vattrs */
     75 vattr_t sdev_vattr_dir = {
     76 	AT_TYPE|AT_MODE|AT_UID|AT_GID,		/* va_mask */
     77 	VDIR,					/* va_type */
     78 	SDEV_DIRMODE_DEFAULT,			/* va_mode */
     79 	SDEV_UID_DEFAULT,			/* va_uid */
     80 	SDEV_GID_DEFAULT,			/* va_gid */
     81 	0,					/* va_fsid */
     82 	0,					/* va_nodeid */
     83 	0,					/* va_nlink */
     84 	0,					/* va_size */
     85 	0,					/* va_atime */
     86 	0,					/* va_mtime */
     87 	0,					/* va_ctime */
     88 	0,					/* va_rdev */
     89 	0,					/* va_blksize */
     90 	0,					/* va_nblocks */
     91 	0					/* va_vcode */
     92 };
     93 
     94 vattr_t sdev_vattr_lnk = {
     95 	AT_TYPE|AT_MODE,			/* va_mask */
     96 	VLNK,					/* va_type */
     97 	SDEV_LNKMODE_DEFAULT,			/* va_mode */
     98 	SDEV_UID_DEFAULT,			/* va_uid */
     99 	SDEV_GID_DEFAULT,			/* va_gid */
    100 	0,					/* va_fsid */
    101 	0,					/* va_nodeid */
    102 	0,					/* va_nlink */
    103 	0,					/* va_size */
    104 	0,					/* va_atime */
    105 	0,					/* va_mtime */
    106 	0,					/* va_ctime */
    107 	0,					/* va_rdev */
    108 	0,					/* va_blksize */
    109 	0,					/* va_nblocks */
    110 	0					/* va_vcode */
    111 };
    112 
    113 vattr_t sdev_vattr_blk = {
    114 	AT_TYPE|AT_MODE|AT_UID|AT_GID,		/* va_mask */
    115 	VBLK,					/* va_type */
    116 	S_IFBLK | SDEV_DEVMODE_DEFAULT,		/* va_mode */
    117 	SDEV_UID_DEFAULT,			/* va_uid */
    118 	SDEV_GID_DEFAULT,			/* va_gid */
    119 	0,					/* va_fsid */
    120 	0,					/* va_nodeid */
    121 	0,					/* va_nlink */
    122 	0,					/* va_size */
    123 	0,					/* va_atime */
    124 	0,					/* va_mtime */
    125 	0,					/* va_ctime */
    126 	0,					/* va_rdev */
    127 	0,					/* va_blksize */
    128 	0,					/* va_nblocks */
    129 	0					/* va_vcode */
    130 };
    131 
    132 vattr_t sdev_vattr_chr = {
    133 	AT_TYPE|AT_MODE|AT_UID|AT_GID,		/* va_mask */
    134 	VCHR,					/* va_type */
    135 	S_IFCHR | SDEV_DEVMODE_DEFAULT,		/* va_mode */
    136 	SDEV_UID_DEFAULT,			/* va_uid */
    137 	SDEV_GID_DEFAULT,			/* va_gid */
    138 	0,					/* va_fsid */
    139 	0,					/* va_nodeid */
    140 	0,					/* va_nlink */
    141 	0,					/* va_size */
    142 	0,					/* va_atime */
    143 	0,					/* va_mtime */
    144 	0,					/* va_ctime */
    145 	0,					/* va_rdev */
    146 	0,					/* va_blksize */
    147 	0,					/* va_nblocks */
    148 	0					/* va_vcode */
    149 };
    150 
    151 kmem_cache_t	*sdev_node_cache;	/* sdev_node cache */
    152 int		devtype;		/* fstype */
    153 
    154 struct devname_ops *devname_ns_ops;	/* default name service directory ops */
    155 kmutex_t devname_nsmaps_lock;	/* protect devname_nsmaps */
    156 
    157 /* static */
    158 static struct devname_nsmap *devname_nsmaps = NULL;
    159 				/* contents from /etc/dev/devname_master */
    160 static int devname_nsmaps_invalidated = 0; /* "devfsadm -m" has run */
    161 
    162 static struct vnodeops *sdev_get_vop(struct sdev_node *);
    163 static void sdev_set_no_nocache(struct sdev_node *);
    164 static int sdev_get_moduleops(struct sdev_node *);
    165 static fs_operation_def_t *sdev_merge_vtab(const fs_operation_def_t []);
    166 static void sdev_free_vtab(fs_operation_def_t *);
    167 
    168 static void
    169 sdev_prof_free(struct sdev_node *dv)
    170 {
    171 	ASSERT(!SDEV_IS_GLOBAL(dv));
    172 	if (dv->sdev_prof.dev_name)
    173 		nvlist_free(dv->sdev_prof.dev_name);
    174 	if (dv->sdev_prof.dev_map)
    175 		nvlist_free(dv->sdev_prof.dev_map);
    176 	if (dv->sdev_prof.dev_symlink)
    177 		nvlist_free(dv->sdev_prof.dev_symlink);
    178 	if (dv->sdev_prof.dev_glob_incdir)
    179 		nvlist_free(dv->sdev_prof.dev_glob_incdir);
    180 	if (dv->sdev_prof.dev_glob_excdir)
    181 		nvlist_free(dv->sdev_prof.dev_glob_excdir);
    182 	bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
    183 }
    184 
    185 /* sdev_node cache constructor */
    186 /*ARGSUSED1*/
    187 static int
    188 i_sdev_node_ctor(void *buf, void *cfarg, int flag)
    189 {
    190 	struct sdev_node *dv = (struct sdev_node *)buf;
    191 	struct vnode *vp;
    192 
    193 	bzero(buf, sizeof (struct sdev_node));
    194 	vp = dv->sdev_vnode = vn_alloc(flag);
    195 	if (vp == NULL) {
    196 		return (-1);
    197 	}
    198 	vp->v_data = dv;
    199 	rw_init(&dv->sdev_contents, NULL, RW_DEFAULT, NULL);
    200 	return (0);
    201 }
    202 
    203 /* sdev_node cache destructor */
    204 /*ARGSUSED1*/
    205 static void
    206 i_sdev_node_dtor(void *buf, void *arg)
    207 {
    208 	struct sdev_node *dv = (struct sdev_node *)buf;
    209 	struct vnode *vp = SDEVTOV(dv);
    210 
    211 	rw_destroy(&dv->sdev_contents);
    212 	vn_free(vp);
    213 }
    214 
    215 /* initialize sdev_node cache */
    216 void
    217 sdev_node_cache_init()
    218 {
    219 	int flags = 0;
    220 
    221 #ifdef	DEBUG
    222 	flags = sdev_debug_cache_flags;
    223 	if (flags)
    224 		sdcmn_err(("cache debug flags 0x%x\n", flags));
    225 #endif	/* DEBUG */
    226 
    227 	ASSERT(sdev_node_cache == NULL);
    228 	sdev_node_cache = kmem_cache_create("sdev_node_cache",
    229 	    sizeof (struct sdev_node), 0, i_sdev_node_ctor, i_sdev_node_dtor,
    230 	    NULL, NULL, NULL, flags);
    231 }
    232 
    233 /* destroy sdev_node cache */
    234 void
    235 sdev_node_cache_fini()
    236 {
    237 	ASSERT(sdev_node_cache != NULL);
    238 	kmem_cache_destroy(sdev_node_cache);
    239 	sdev_node_cache = NULL;
    240 }
    241 
    242 /*
    243  * Compare two nodes lexographically to balance avl tree
    244  */
    245 static int
    246 sdev_compare_nodes(const struct sdev_node *dv1, const struct sdev_node *dv2)
    247 {
    248 	int rv;
    249 	if ((rv = strcmp(dv1->sdev_name, dv2->sdev_name)) == 0)
    250 		return (0);
    251 	return ((rv < 0) ? -1 : 1);
    252 }
    253 
    254 void
    255 sdev_set_nodestate(struct sdev_node *dv, sdev_node_state_t state)
    256 {
    257 	ASSERT(dv);
    258 	ASSERT(RW_WRITE_HELD(&dv->sdev_contents));
    259 	dv->sdev_state = state;
    260 }
    261 
    262 static void
    263 sdev_attrinit(struct sdev_node *dv, vattr_t *vap)
    264 {
    265 	timestruc_t now;
    266 
    267 	ASSERT(vap);
    268 
    269 	dv->sdev_attr = kmem_zalloc(sizeof (struct vattr), KM_SLEEP);
    270 	*dv->sdev_attr = *vap;
    271 
    272 	dv->sdev_attr->va_mode = MAKEIMODE(vap->va_type, vap->va_mode);
    273 
    274 	gethrestime(&now);
    275 	dv->sdev_attr->va_atime = now;
    276 	dv->sdev_attr->va_mtime = now;
    277 	dv->sdev_attr->va_ctime = now;
    278 }
    279 
    280 /* alloc and initialize a sdev_node */
    281 int
    282 sdev_nodeinit(struct sdev_node *ddv, char *nm, struct sdev_node **newdv,
    283     vattr_t *vap)
    284 {
    285 	struct sdev_node *dv = NULL;
    286 	struct vnode *vp;
    287 	size_t nmlen, len;
    288 	devname_handle_t  *dhl;
    289 
    290 	nmlen = strlen(nm) + 1;
    291 	if (nmlen > MAXNAMELEN) {
    292 		sdcmn_err9(("sdev_nodeinit: node name %s"
    293 		    " too long\n", nm));
    294 		*newdv = NULL;
    295 		return (ENAMETOOLONG);
    296 	}
    297 
    298 	dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP);
    299 
    300 	dv->sdev_name = kmem_alloc(nmlen, KM_SLEEP);
    301 	bcopy(nm, dv->sdev_name, nmlen);
    302 	dv->sdev_namelen = nmlen - 1;	/* '\0' not included */
    303 	len = strlen(ddv->sdev_path) + strlen(nm) + 2;
    304 	dv->sdev_path = kmem_alloc(len, KM_SLEEP);
    305 	(void) snprintf(dv->sdev_path, len, "%s/%s", ddv->sdev_path, nm);
    306 	/* overwritten for VLNK nodes */
    307 	dv->sdev_symlink = NULL;
    308 
    309 	vp = SDEVTOV(dv);
    310 	vn_reinit(vp);
    311 	vp->v_vfsp = SDEVTOV(ddv)->v_vfsp;
    312 	if (vap)
    313 		vp->v_type = vap->va_type;
    314 
    315 	/*
    316 	 * initialized to the parent's vnodeops.
    317 	 * maybe overwriten for a VDIR
    318 	 */
    319 	vn_setops(vp, vn_getops(SDEVTOV(ddv)));
    320 	vn_exists(vp);
    321 
    322 	dv->sdev_dotdot = NULL;
    323 	dv->sdev_attrvp = NULL;
    324 	if (vap) {
    325 		sdev_attrinit(dv, vap);
    326 	} else {
    327 		dv->sdev_attr = NULL;
    328 	}
    329 
    330 	dv->sdev_ino = sdev_mkino(dv);
    331 	dv->sdev_nlink = 0;		/* updated on insert */
    332 	dv->sdev_flags = ddv->sdev_flags; /* inherit from the parent first */
    333 	dv->sdev_flags |= SDEV_BUILD;
    334 	mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL);
    335 	cv_init(&dv->sdev_lookup_cv, NULL, CV_DEFAULT, NULL);
    336 	if (SDEV_IS_GLOBAL(ddv)) {
    337 		dv->sdev_flags |= SDEV_GLOBAL;
    338 		dv->sdev_mapinfo = NULL;
    339 		dhl = &(dv->sdev_handle);
    340 		dhl->dh_data = dv;
    341 		dhl->dh_spec = DEVNAME_NS_NONE;
    342 		dhl->dh_args = NULL;
    343 		sdev_set_no_nocache(dv);
    344 		dv->sdev_gdir_gen = 0;
    345 	} else {
    346 		dv->sdev_flags &= ~SDEV_GLOBAL;
    347 		dv->sdev_origin = NULL; /* set later */
    348 		bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
    349 		dv->sdev_ldir_gen = 0;
    350 		dv->sdev_devtree_gen = 0;
    351 	}
    352 
    353 	rw_enter(&dv->sdev_contents, RW_WRITER);
    354 	sdev_set_nodestate(dv, SDEV_INIT);
    355 	rw_exit(&dv->sdev_contents);
    356 	*newdv = dv;
    357 
    358 	return (0);
    359 }
    360 
    361 /*
    362  * transition a sdev_node into SDEV_READY state
    363  */
    364 int
    365 sdev_nodeready(struct sdev_node *dv, struct vattr *vap, struct vnode *avp,
    366     void *args, struct cred *cred)
    367 {
    368 	int error = 0;
    369 	struct vnode *vp = SDEVTOV(dv);
    370 	vtype_t type;
    371 
    372 	ASSERT(dv && (dv->sdev_state != SDEV_READY) && vap);
    373 
    374 	type = vap->va_type;
    375 	vp->v_type = type;
    376 	vp->v_rdev = vap->va_rdev;
    377 	rw_enter(&dv->sdev_contents, RW_WRITER);
    378 	if (type == VDIR) {
    379 		dv->sdev_nlink = 2;
    380 		dv->sdev_flags &= ~SDEV_PERSIST;
    381 		dv->sdev_flags &= ~SDEV_DYNAMIC;
    382 		vn_setops(vp, sdev_get_vop(dv)); /* from internal vtab */
    383 		error = sdev_get_moduleops(dv); /* from plug-in module */
    384 		ASSERT(dv->sdev_dotdot);
    385 		ASSERT(SDEVTOV(dv->sdev_dotdot)->v_type == VDIR);
    386 		vp->v_rdev = SDEVTOV(dv->sdev_dotdot)->v_rdev;
    387 		avl_create(&dv->sdev_entries,
    388 		    (int (*)(const void *, const void *))sdev_compare_nodes,
    389 		    sizeof (struct sdev_node),
    390 		    offsetof(struct sdev_node, sdev_avllink));
    391 	} else if (type == VLNK) {
    392 		ASSERT(args);
    393 		dv->sdev_nlink = 1;
    394 		dv->sdev_symlink = i_ddi_strdup((char *)args, KM_SLEEP);
    395 	} else {
    396 		dv->sdev_nlink = 1;
    397 	}
    398 
    399 	if (!(SDEV_IS_GLOBAL(dv))) {
    400 		dv->sdev_origin = (struct sdev_node *)args;
    401 		dv->sdev_flags &= ~SDEV_PERSIST;
    402 	}
    403 
    404 	/*
    405 	 * shadow node is created here OR
    406 	 * if failed (indicated by dv->sdev_attrvp == NULL),
    407 	 * created later in sdev_setattr
    408 	 */
    409 	if (avp) {
    410 		dv->sdev_attrvp = avp;
    411 	} else {
    412 		if (dv->sdev_attr == NULL)
    413 			sdev_attrinit(dv, vap);
    414 		else
    415 			*dv->sdev_attr = *vap;
    416 
    417 		if ((SDEV_IS_PERSIST(dv) && (dv->sdev_attrvp == NULL)) ||
    418 		    ((SDEVTOV(dv)->v_type == VDIR) &&
    419 		    (dv->sdev_attrvp == NULL))) {
    420 			error = sdev_shadow_node(dv, cred);
    421 		}
    422 	}
    423 
    424 	if (error == 0) {
    425 		/* transition to READY state */
    426 		sdev_set_nodestate(dv, SDEV_READY);
    427 		sdev_nc_node_exists(dv);
    428 	} else {
    429 		sdev_set_nodestate(dv, SDEV_ZOMBIE);
    430 	}
    431 	rw_exit(&dv->sdev_contents);
    432 	return (error);
    433 }
    434 
    435 /*
    436  * setting ZOMBIE state
    437  */
    438 static int
    439 sdev_nodezombied(struct sdev_node *dv)
    440 {
    441 	rw_enter(&dv->sdev_contents, RW_WRITER);
    442 	sdev_set_nodestate(dv, SDEV_ZOMBIE);
    443 	rw_exit(&dv->sdev_contents);
    444 	return (0);
    445 }
    446 
    447 /*
    448  * Build the VROOT sdev_node.
    449  */
    450 /*ARGSUSED*/
    451 struct sdev_node *
    452 sdev_mkroot(struct vfs *vfsp, dev_t devdev, struct vnode *mvp,
    453     struct vnode *avp, struct cred *cred)
    454 {
    455 	struct sdev_node *dv;
    456 	struct vnode *vp;
    457 	char devdir[] = "/dev";
    458 
    459 	ASSERT(sdev_node_cache != NULL);
    460 	ASSERT(avp);
    461 	dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP);
    462 	vp = SDEVTOV(dv);
    463 	vn_reinit(vp);
    464 	vp->v_flag |= VROOT;
    465 	vp->v_vfsp = vfsp;
    466 	vp->v_type = VDIR;
    467 	vp->v_rdev = devdev;
    468 	vn_setops(vp, sdev_vnodeops); /* apply the default vnodeops at /dev */
    469 	vn_exists(vp);
    470 
    471 	if (vfsp->vfs_mntpt)
    472 		dv->sdev_name = i_ddi_strdup(
    473 		    (char *)refstr_value(vfsp->vfs_mntpt), KM_SLEEP);
    474 	else
    475 		/* vfs_mountdev1 set mount point later */
    476 		dv->sdev_name = i_ddi_strdup("/dev", KM_SLEEP);
    477 	dv->sdev_namelen = strlen(dv->sdev_name); /* '\0' not included */
    478 	dv->sdev_path = i_ddi_strdup(devdir, KM_SLEEP);
    479 	dv->sdev_ino = SDEV_ROOTINO;
    480 	dv->sdev_nlink = 2;		/* name + . (no sdev_insert) */
    481 	dv->sdev_dotdot = dv;		/* .. == self */
    482 	dv->sdev_attrvp = avp;
    483 	dv->sdev_attr = NULL;
    484 	mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL);
    485 	cv_init(&dv->sdev_lookup_cv, NULL, CV_DEFAULT, NULL);
    486 	if (strcmp(dv->sdev_name, "/dev") == 0) {
    487 		mutex_init(&devname_nsmaps_lock, NULL, MUTEX_DEFAULT, NULL);
    488 		dv->sdev_mapinfo = NULL;
    489 		dv->sdev_flags = SDEV_BUILD|SDEV_GLOBAL|SDEV_PERSIST;
    490 		bzero(&dv->sdev_handle, sizeof (dv->sdev_handle));
    491 		dv->sdev_gdir_gen = 0;
    492 	} else {
    493 		dv->sdev_flags = SDEV_BUILD;
    494 		dv->sdev_flags &= ~SDEV_PERSIST;
    495 		bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
    496 		dv->sdev_ldir_gen = 0;
    497 		dv->sdev_devtree_gen = 0;
    498 	}
    499 
    500 	avl_create(&dv->sdev_entries,
    501 	    (int (*)(const void *, const void *))sdev_compare_nodes,
    502 	    sizeof (struct sdev_node),
    503 	    offsetof(struct sdev_node, sdev_avllink));
    504 
    505 	rw_enter(&dv->sdev_contents, RW_WRITER);
    506 	sdev_set_nodestate(dv, SDEV_READY);
    507 	rw_exit(&dv->sdev_contents);
    508 	sdev_nc_node_exists(dv);
    509 	return (dv);
    510 }
    511 
    512 /*
    513  *  1. load the module
    514  *  2. modload invokes sdev_module_register, which in turn sets
    515  *     the dv->sdev_mapinfo->dir_ops
    516  *
    517  * note: locking order:
    518  *	dv->sdev_contents -> map->dir_lock
    519  */
    520 static int
    521 sdev_get_moduleops(struct sdev_node *dv)
    522 {
    523 	int error = 0;
    524 	struct devname_nsmap *map = NULL;
    525 	char *module;
    526 	char *path;
    527 	int load = 1;
    528 
    529 	ASSERT(SDEVTOV(dv)->v_type == VDIR);
    530 
    531 	if (devname_nsmaps == NULL)
    532 		return (0);
    533 
    534 	if (!sdev_nsmaps_loaded() && !sdev_nsmaps_reloaded())
    535 		return (0);
    536 
    537 
    538 	path = dv->sdev_path;
    539 	if ((map = sdev_get_nsmap_by_dir(path, 0))) {
    540 		rw_enter(&map->dir_lock, RW_READER);
    541 		if (map->dir_invalid) {
    542 			if (map->dir_module && map->dir_newmodule &&
    543 			    (strcmp(map->dir_module,
    544 			    map->dir_newmodule) == 0)) {
    545 				load = 0;
    546 			}
    547 			sdev_replace_nsmap(map, map->dir_newmodule,
    548 			    map->dir_newmap);
    549 		}
    550 
    551 		module = map->dir_module;
    552 		if (module && load) {
    553 			sdcmn_err6(("sdev_get_moduleops: "
    554 			    "load module %s", module));
    555 			rw_exit(&map->dir_lock);
    556 			error = modload("devname", module);
    557 			sdcmn_err6(("sdev_get_moduleops: error %d\n", error));
    558 			if (error < 0) {
    559 				return (-1);
    560 			}
    561 		} else if (module == NULL) {
    562 			/*
    563 			 * loading the module ops for name services
    564 			 */
    565 			if (devname_ns_ops == NULL) {
    566 				sdcmn_err6((
    567 				    "sdev_get_moduleops: modload default\n"));
    568 				error = modload("devname", DEVNAME_NSCONFIG);
    569 				sdcmn_err6((
    570 				    "sdev_get_moduleops: error %d\n", error));
    571 				if (error < 0) {
    572 					return (-1);
    573 				}
    574 			}
    575 
    576 			if (!rw_tryupgrade(&map->dir_lock)) {
    577 				rw_exit(&map->dir_lock);
    578 				rw_enter(&map->dir_lock, RW_WRITER);
    579 			}
    580 			ASSERT(devname_ns_ops);
    581 			map->dir_ops = devname_ns_ops;
    582 			rw_exit(&map->dir_lock);
    583 		}
    584 	}
    585 
    586 	dv->sdev_mapinfo = map;
    587 	return (0);
    588 }
    589 
    590 /* directory dependent vop table */
    591 struct sdev_vop_table {
    592 	char *vt_name;				/* subdirectory name */
    593 	const fs_operation_def_t *vt_service;	/* vnodeops table */
    594 	struct vnodeops *vt_vops;		/* constructed vop */
    595 	struct vnodeops **vt_global_vops;	/* global container for vop */
    596 	int (*vt_vtor)(struct sdev_node *);	/* validate sdev_node */
    597 	int vt_flags;
    598 };
    599 
    600 /*
    601  * A nice improvement would be to provide a plug-in mechanism
    602  * for this table instead of a const table.
    603  */
    604 static struct sdev_vop_table vtab[] =
    605 {
    606 	{ "pts", devpts_vnodeops_tbl, NULL, &devpts_vnodeops, devpts_validate,
    607 	SDEV_DYNAMIC | SDEV_VTOR },
    608 
    609 	{ "vt", devvt_vnodeops_tbl, NULL, &devvt_vnodeops, devvt_validate,
    610 	SDEV_DYNAMIC | SDEV_VTOR },
    611 
    612 	{ "zcons", NULL, NULL, NULL, NULL, SDEV_NO_NCACHE },
    613 
    614 	{ "net", devnet_vnodeops_tbl, NULL, &devnet_vnodeops, devnet_validate,
    615 	SDEV_DYNAMIC | SDEV_VTOR },
    616 
    617 	{ "ipnet", devipnet_vnodeops_tbl, NULL, &devipnet_vnodeops,
    618 	devipnet_validate, SDEV_DYNAMIC | SDEV_VTOR | SDEV_NO_NCACHE },
    619 
    620 	{ NULL, NULL, NULL, NULL, NULL, 0}
    621 };
    622 
    623 
    624 /*
    625  *  sets a directory's vnodeops if the directory is in the vtab;
    626  */
    627 static struct vnodeops *
    628 sdev_get_vop(struct sdev_node *dv)
    629 {
    630 	int i;
    631 	char *path;
    632 
    633 	path = dv->sdev_path;
    634 	ASSERT(path);
    635 
    636 	/* gets the relative path to /dev/ */
    637 	path += 5;
    638 
    639 	/* gets the vtab entry if matches */
    640 	for (i = 0; vtab[i].vt_name; i++) {
    641 		if (strcmp(vtab[i].vt_name, path) != 0)
    642 			continue;
    643 		dv->sdev_flags |= vtab[i].vt_flags;
    644 
    645 		if (vtab[i].vt_vops) {
    646 			if (vtab[i].vt_global_vops)
    647 				*(vtab[i].vt_global_vops) = vtab[i].vt_vops;
    648 			return (vtab[i].vt_vops);
    649 		}
    650 
    651 		if (vtab[i].vt_service) {
    652 			fs_operation_def_t *templ;
    653 			templ = sdev_merge_vtab(vtab[i].vt_service);
    654 			if (vn_make_ops(vtab[i].vt_name,
    655 			    (const fs_operation_def_t *)templ,
    656 			    &vtab[i].vt_vops) != 0) {
    657 				cmn_err(CE_PANIC, "%s: malformed vnode ops\n",
    658 				    vtab[i].vt_name);
    659 				/*NOTREACHED*/
    660 			}
    661 			if (vtab[i].vt_global_vops) {
    662 				*(vtab[i].vt_global_vops) = vtab[i].vt_vops;
    663 			}
    664 			sdev_free_vtab(templ);
    665 			return (vtab[i].vt_vops);
    666 		}
    667 		return (sdev_vnodeops);
    668 	}
    669 
    670 	/* child inherits the persistence of the parent */
    671 	if (SDEV_IS_PERSIST(dv->sdev_dotdot))
    672 		dv->sdev_flags |= SDEV_PERSIST;
    673 
    674 	return (sdev_vnodeops);
    675 }
    676 
    677 static void
    678 sdev_set_no_nocache(struct sdev_node *dv)
    679 {
    680 	int i;
    681 	char *path;
    682 
    683 	ASSERT(dv->sdev_path);
    684 	path = dv->sdev_path + strlen("/dev/");
    685 
    686 	for (i = 0; vtab[i].vt_name; i++) {
    687 		if (strcmp(vtab[i].vt_name, path) == 0) {
    688 			if (vtab[i].vt_flags & SDEV_NO_NCACHE)
    689 				dv->sdev_flags |= SDEV_NO_NCACHE;
    690 			break;
    691 		}
    692 	}
    693 }
    694 
    695 void *
    696 sdev_get_vtor(struct sdev_node *dv)
    697 {
    698 	int i;
    699 
    700 	for (i = 0; vtab[i].vt_name; i++) {
    701 		if (strcmp(vtab[i].vt_name, dv->sdev_name) != 0)
    702 			continue;
    703 		return ((void *)vtab[i].vt_vtor);
    704 	}
    705 	return (NULL);
    706 }
    707 
    708 /*
    709  * Build the base root inode
    710  */
    711 ino_t
    712 sdev_mkino(struct sdev_node *dv)
    713 {
    714 	ino_t	ino;
    715 
    716 	/*
    717 	 * for now, follow the lead of tmpfs here
    718 	 * need to someday understand the requirements here
    719 	 */
    720 	ino = (ino_t)(uint32_t)((uintptr_t)dv >> 3);
    721 	ino += SDEV_ROOTINO + 1;
    722 
    723 	return (ino);
    724 }
    725 
    726 static int
    727 sdev_getlink(struct vnode *linkvp, char **link)
    728 {
    729 	int err;
    730 	char *buf;
    731 	struct uio uio = {0};
    732 	struct iovec iov = {0};
    733 
    734 	if (linkvp == NULL)
    735 		return (ENOENT);
    736 	ASSERT(linkvp->v_type == VLNK);
    737 
    738 	buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
    739 	iov.iov_base = buf;
    740 	iov.iov_len = MAXPATHLEN;
    741 	uio.uio_iov = &iov;
    742 	uio.uio_iovcnt = 1;
    743 	uio.uio_resid = MAXPATHLEN;
    744 	uio.uio_segflg = UIO_SYSSPACE;
    745 	uio.uio_llimit = MAXOFFSET_T;
    746 
    747 	err = VOP_READLINK(linkvp, &uio, kcred, NULL);
    748 	if (err) {
    749 		cmn_err(CE_WARN, "readlink %s failed in dev\n", buf);
    750 		kmem_free(buf, MAXPATHLEN);
    751 		return (ENOENT);
    752 	}
    753 
    754 	/* mission complete */
    755 	*link = i_ddi_strdup(buf, KM_SLEEP);
    756 	kmem_free(buf, MAXPATHLEN);
    757 	return (0);
    758 }
    759 
    760 /*
    761  * A convenient wrapper to get the devfs node vnode for a device
    762  * minor functionality: readlink() of a /dev symlink
    763  * Place the link into dv->sdev_symlink
    764  */
    765 static int
    766 sdev_follow_link(struct sdev_node *dv)
    767 {
    768 	int err;
    769 	struct vnode *linkvp;
    770 	char *link = NULL;
    771 
    772 	linkvp = SDEVTOV(dv);
    773 	if (linkvp == NULL)
    774 		return (ENOENT);
    775 	ASSERT(linkvp->v_type == VLNK);
    776 	err = sdev_getlink(linkvp, &link);
    777 	if (err) {
    778 		(void) sdev_nodezombied(dv);
    779 		dv->sdev_symlink = NULL;
    780 		return (ENOENT);
    781 	}
    782 
    783 	ASSERT(link != NULL);
    784 	dv->sdev_symlink = link;
    785 	return (0);
    786 }
    787 
    788 static int
    789 sdev_node_check(struct sdev_node *dv, struct vattr *nvap, void *nargs)
    790 {
    791 	vtype_t otype = SDEVTOV(dv)->v_type;
    792 
    793 	/*
    794 	 * existing sdev_node has a different type.
    795 	 */
    796 	if (otype != nvap->va_type) {
    797 		sdcmn_err9(("sdev_node_check: existing node "
    798 		    "  %s type %d does not match new node type %d\n",
    799 		    dv->sdev_name, otype, nvap->va_type));
    800 		return (EEXIST);
    801 	}
    802 
    803 	/*
    804 	 * For a symlink, the target should be the same.
    805 	 */
    806 	if (otype == VLNK) {
    807 		ASSERT(nargs != NULL);
    808 		ASSERT(dv->sdev_symlink != NULL);
    809 		if (strcmp(dv->sdev_symlink, (char *)nargs) != 0) {
    810 			sdcmn_err9(("sdev_node_check: existing node "
    811 			    " %s has different symlink %s as new node "
    812 			    " %s\n", dv->sdev_name, dv->sdev_symlink,
    813 			    (char *)nargs));
    814 			return (EEXIST);
    815 		}
    816 	}
    817 
    818 	return (0);
    819 }
    820 
    821 /*
    822  * sdev_mknode - a wrapper for sdev_nodeinit(), sdev_nodeready()
    823  *
    824  * arguments:
    825  *	- ddv (parent)
    826  *	- nm (child name)
    827  *	- newdv (sdev_node for nm is returned here)
    828  *	- vap (vattr for the node to be created, va_type should be set.
    829  *	- avp (attribute vnode)
    830  *	  the defaults should be used if unknown)
    831  *	- cred
    832  *	- args
    833  *	    . tnm (for VLNK)
    834  *	    . global sdev_node (for !SDEV_GLOBAL)
    835  * 	- state: SDEV_INIT, SDEV_READY
    836  *
    837  * only ddv, nm, newddv, vap, cred are required for sdev_mknode(SDEV_INIT)
    838  *
    839  * NOTE:  directory contents writers lock needs to be held before
    840  *	  calling this routine.
    841  */
    842 int
    843 sdev_mknode(struct sdev_node *ddv, char *nm, struct sdev_node **newdv,
    844     struct vattr *vap, struct vnode *avp, void *args, struct cred *cred,
    845     sdev_node_state_t state)
    846 {
    847 	int error = 0;
    848 	sdev_node_state_t node_state;
    849 	struct sdev_node *dv = NULL;
    850 
    851 	ASSERT(state != SDEV_ZOMBIE);
    852 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
    853 
    854 	if (*newdv) {
    855 		dv = *newdv;
    856 	} else {
    857 		/* allocate and initialize a sdev_node */
    858 		if (ddv->sdev_state == SDEV_ZOMBIE) {
    859 			sdcmn_err9(("sdev_mknode: parent %s ZOMBIEd\n",
    860 			    ddv->sdev_path));
    861 			return (ENOENT);
    862 		}
    863 
    864 		error = sdev_nodeinit(ddv, nm, &dv, vap);
    865 		if (error != 0) {
    866 			sdcmn_err9(("sdev_mknode: error %d,"
    867 			    " name %s can not be initialized\n",
    868 			    error, nm));
    869 			return (error);
    870 		}
    871 		ASSERT(dv);
    872 
    873 		/* insert into the directory cache */
    874 		error = sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_ADD);
    875 		if (error) {
    876 			sdcmn_err9(("sdev_mknode: node %s can not"
    877 			    " be added into directory cache\n", nm));
    878 			return (ENOENT);
    879 		}
    880 	}
    881 
    882 	ASSERT(dv);
    883 	node_state = dv->sdev_state;
    884 	ASSERT(node_state != SDEV_ZOMBIE);
    885 
    886 	if (state == SDEV_READY) {
    887 		switch (node_state) {
    888 		case SDEV_INIT:
    889 			error = sdev_nodeready(dv, vap, avp, args, cred);
    890 			if (error) {
    891 				sdcmn_err9(("sdev_mknode: node %s can NOT"
    892 				    " be transitioned into READY state, "
    893 				    "error %d\n", nm, error));
    894 			}
    895 			break;
    896 		case SDEV_READY:
    897 			/*
    898 			 * Do some sanity checking to make sure
    899 			 * the existing sdev_node is what has been
    900 			 * asked for.
    901 			 */
    902 			error = sdev_node_check(dv, vap, args);
    903 			break;
    904 		default:
    905 			break;
    906 		}
    907 	}
    908 
    909 	if (!error) {
    910 		*newdv = dv;
    911 		ASSERT((*newdv)->sdev_state != SDEV_ZOMBIE);
    912 	} else {
    913 		SDEV_SIMPLE_RELE(dv);
    914 		*newdv = NULL;
    915 	}
    916 
    917 	return (error);
    918 }
    919 
    920 /*
    921  * convenient wrapper to change vp's ATIME, CTIME and MTIME
    922  */
    923 void
    924 sdev_update_timestamps(struct vnode *vp, cred_t *cred, uint_t mask)
    925 {
    926 	struct vattr attr;
    927 	timestruc_t now;
    928 	int err;
    929 
    930 	ASSERT(vp);
    931 	gethrestime(&now);
    932 	if (mask & AT_CTIME)
    933 		attr.va_ctime = now;
    934 	if (mask & AT_MTIME)
    935 		attr.va_mtime = now;
    936 	if (mask & AT_ATIME)
    937 		attr.va_atime = now;
    938 
    939 	attr.va_mask = (mask & AT_TIMES);
    940 	err = VOP_SETATTR(vp, &attr, 0, cred, NULL);
    941 	if (err && (err != EROFS)) {
    942 		sdcmn_err(("update timestamps error %d\n", err));
    943 	}
    944 }
    945 
    946 /*
    947  * the backing store vnode is released here
    948  */
    949 /*ARGSUSED1*/
    950 void
    951 sdev_nodedestroy(struct sdev_node *dv, uint_t flags)
    952 {
    953 	/* no references */
    954 	ASSERT(dv->sdev_nlink == 0);
    955 
    956 	if (dv->sdev_attrvp != NULLVP) {
    957 		VN_RELE(dv->sdev_attrvp);
    958 		/*
    959 		 * reset the attrvp so that no more
    960 		 * references can be made on this already
    961 		 * vn_rele() vnode
    962 		 */
    963 		dv->sdev_attrvp = NULLVP;
    964 	}
    965 
    966 	if (dv->sdev_attr != NULL) {
    967 		kmem_free(dv->sdev_attr, sizeof (struct vattr));
    968 		dv->sdev_attr = NULL;
    969 	}
    970 
    971 	if (dv->sdev_name != NULL) {
    972 		kmem_free(dv->sdev_name, dv->sdev_namelen + 1);
    973 		dv->sdev_name = NULL;
    974 	}
    975 
    976 	if (dv->sdev_symlink != NULL) {
    977 		kmem_free(dv->sdev_symlink, strlen(dv->sdev_symlink) + 1);
    978 		dv->sdev_symlink = NULL;
    979 	}
    980 
    981 	if (dv->sdev_path) {
    982 		kmem_free(dv->sdev_path, strlen(dv->sdev_path) + 1);
    983 		dv->sdev_path = NULL;
    984 	}
    985 
    986 	if (!SDEV_IS_GLOBAL(dv))
    987 		sdev_prof_free(dv);
    988 
    989 	if (SDEVTOV(dv)->v_type == VDIR) {
    990 		ASSERT(SDEV_FIRST_ENTRY(dv) == NULL);
    991 		avl_destroy(&dv->sdev_entries);
    992 	}
    993 
    994 	mutex_destroy(&dv->sdev_lookup_lock);
    995 	cv_destroy(&dv->sdev_lookup_cv);
    996 
    997 	/* return node to initial state as per constructor */
    998 	(void) memset((void *)&dv->sdev_instance_data, 0,
    999 	    sizeof (dv->sdev_instance_data));
   1000 	vn_invalid(SDEVTOV(dv));
   1001 	kmem_cache_free(sdev_node_cache, dv);
   1002 }
   1003 
   1004 /*
   1005  * DIRECTORY CACHE lookup
   1006  */
   1007 struct sdev_node *
   1008 sdev_findbyname(struct sdev_node *ddv, char *nm)
   1009 {
   1010 	struct sdev_node *dv;
   1011 	struct sdev_node dvtmp;
   1012 	avl_index_t	where;
   1013 
   1014 	ASSERT(RW_LOCK_HELD(&ddv->sdev_contents));
   1015 
   1016 	dvtmp.sdev_name = nm;
   1017 	dv = avl_find(&ddv->sdev_entries, &dvtmp, &where);
   1018 	if (dv) {
   1019 		ASSERT(dv->sdev_dotdot == ddv);
   1020 		ASSERT(strcmp(dv->sdev_name, nm) == 0);
   1021 		SDEV_HOLD(dv);
   1022 		return (dv);
   1023 	}
   1024 	return (NULL);
   1025 }
   1026 
   1027 /*
   1028  * Inserts a new sdev_node in a parent directory
   1029  */
   1030 void
   1031 sdev_direnter(struct sdev_node *ddv, struct sdev_node *dv)
   1032 {
   1033 	avl_index_t where;
   1034 
   1035 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
   1036 	ASSERT(SDEVTOV(ddv)->v_type == VDIR);
   1037 	ASSERT(ddv->sdev_nlink >= 2);
   1038 	ASSERT(dv->sdev_nlink == 0);
   1039 
   1040 	dv->sdev_dotdot = ddv;
   1041 	VERIFY(avl_find(&ddv->sdev_entries, dv, &where) == NULL);
   1042 	avl_insert(&ddv->sdev_entries, dv, where);
   1043 	ddv->sdev_nlink++;
   1044 }
   1045 
   1046 /*
   1047  * The following check is needed because while sdev_nodes are linked
   1048  * in SDEV_INIT state, they have their link counts incremented only
   1049  * in SDEV_READY state.
   1050  */
   1051 static void
   1052 decr_link(struct sdev_node *dv)
   1053 {
   1054 	if (dv->sdev_state != SDEV_INIT)
   1055 		dv->sdev_nlink--;
   1056 	else
   1057 		ASSERT(dv->sdev_nlink == 0);
   1058 }
   1059 
   1060 /*
   1061  * Delete an existing dv from directory cache
   1062  *
   1063  * In the case of a node is still held by non-zero reference count,
   1064  *     the node is put into ZOMBIE state. Once the reference count
   1065  *     reaches "0", the node is unlinked and destroyed,
   1066  *     in sdev_inactive().
   1067  */
   1068 static int
   1069 sdev_dirdelete(struct sdev_node *ddv, struct sdev_node *dv)
   1070 {
   1071 	struct vnode *vp;
   1072 
   1073 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
   1074 
   1075 	vp = SDEVTOV(dv);
   1076 	mutex_enter(&vp->v_lock);
   1077 
   1078 	/* dv is held still */
   1079 	if (vp->v_count > 1) {
   1080 		rw_enter(&dv->sdev_contents, RW_WRITER);
   1081 		if (dv->sdev_state == SDEV_READY) {
   1082 			sdcmn_err9((
   1083 			    "sdev_delete: node %s busy with count %d\n",
   1084 			    dv->sdev_name, vp->v_count));
   1085 			dv->sdev_state = SDEV_ZOMBIE;
   1086 		}
   1087 		rw_exit(&dv->sdev_contents);
   1088 		--vp->v_count;
   1089 		mutex_exit(&vp->v_lock);
   1090 		return (EBUSY);
   1091 	}
   1092 	ASSERT(vp->v_count == 1);
   1093 
   1094 	/* unlink from the memory cache */
   1095 	ddv->sdev_nlink--;	/* .. to above */
   1096 	if (vp->v_type == VDIR) {
   1097 		decr_link(dv);		/* . to self */
   1098 	}
   1099 
   1100 	avl_remove(&ddv->sdev_entries, dv);
   1101 	decr_link(dv);	/* name, back to zero */
   1102 	vp->v_count--;
   1103 	mutex_exit(&vp->v_lock);
   1104 
   1105 	/* destroy the node */
   1106 	sdev_nodedestroy(dv, 0);
   1107 	return (0);
   1108 }
   1109 
   1110 /*
   1111  * check if the source is in the path of the target
   1112  *
   1113  * source and target are different
   1114  */
   1115 /*ARGSUSED2*/
   1116 static int
   1117 sdev_checkpath(struct sdev_node *sdv, struct sdev_node *tdv, struct cred *cred)
   1118 {
   1119 	int error = 0;
   1120 	struct sdev_node *dotdot, *dir;
   1121 
   1122 	dotdot = tdv->sdev_dotdot;
   1123 	ASSERT(dotdot);
   1124 
   1125 	/* fs root */
   1126 	if (dotdot == tdv) {
   1127 		return (0);
   1128 	}
   1129 
   1130 	for (;;) {
   1131 		/*
   1132 		 * avoid error cases like
   1133 		 *	mv a a/b
   1134 		 *	mv a a/b/c
   1135 		 *	etc.
   1136 		 */
   1137 		if (dotdot == sdv) {
   1138 			error = EINVAL;
   1139 			break;
   1140 		}
   1141 
   1142 		dir = dotdot;
   1143 		dotdot = dir->sdev_dotdot;
   1144 
   1145 		/* done checking because root is reached */
   1146 		if (dir == dotdot) {
   1147 			break;
   1148 		}
   1149 	}
   1150 	return (error);
   1151 }
   1152 
   1153 int
   1154 sdev_rnmnode(struct sdev_node *oddv, struct sdev_node *odv,
   1155     struct sdev_node *nddv, struct sdev_node **ndvp, char *nnm,
   1156     struct cred *cred)
   1157 {
   1158 	int error = 0;
   1159 	struct vnode *ovp = SDEVTOV(odv);
   1160 	struct vnode *nvp;
   1161 	struct vattr vattr;
   1162 	int doingdir = (ovp->v_type == VDIR);
   1163 	char *link = NULL;
   1164 	int samedir = (oddv == nddv) ? 1 : 0;
   1165 	int bkstore = 0;
   1166 	struct sdev_node *idv = NULL;
   1167 	struct sdev_node *ndv = NULL;
   1168 	timestruc_t now;
   1169 
   1170 	vattr.va_mask = AT_MODE|AT_UID|AT_GID;
   1171 	error = VOP_GETATTR(ovp, &vattr, 0, cred, NULL);
   1172 	if (error)
   1173 		return (error);
   1174 
   1175 	if (!samedir)
   1176 		rw_enter(&oddv->sdev_contents, RW_WRITER);
   1177 	rw_enter(&nddv->sdev_contents, RW_WRITER);
   1178 
   1179 	/*
   1180 	 * the source may have been deleted by another thread before
   1181 	 * we gets here.
   1182 	 */
   1183 	if (odv->sdev_state != SDEV_READY) {
   1184 		error = ENOENT;
   1185 		goto err_out;
   1186 	}
   1187 
   1188 	if (doingdir && (odv == nddv)) {
   1189 		error = EINVAL;
   1190 		goto err_out;
   1191 	}
   1192 
   1193 	/*
   1194 	 * If renaming a directory, and the parents are different (".." must be
   1195 	 * changed) then the source dir must not be in the dir hierarchy above
   1196 	 * the target since it would orphan everything below the source dir.
   1197 	 */
   1198 	if (doingdir && (oddv != nddv)) {
   1199 		error = sdev_checkpath(odv, nddv, cred);
   1200 		if (error)
   1201 			goto err_out;
   1202 	}
   1203 
   1204 	/* destination existing */
   1205 	if (*ndvp) {
   1206 		nvp = SDEVTOV(*ndvp);
   1207 		ASSERT(nvp);
   1208 
   1209 		/* handling renaming to itself */
   1210 		if (odv == *ndvp) {
   1211 			error = 0;
   1212 			goto err_out;
   1213 		}
   1214 
   1215 		if (nvp->v_type == VDIR) {
   1216 			if (!doingdir) {
   1217 				error = EISDIR;
   1218 				goto err_out;
   1219 			}
   1220 
   1221 			if (vn_vfswlock(nvp)) {
   1222 				error = EBUSY;
   1223 				goto err_out;
   1224 			}
   1225 
   1226 			if (vn_mountedvfs(nvp) != NULL) {
   1227 				vn_vfsunlock(nvp);
   1228 				error = EBUSY;
   1229 				goto err_out;
   1230 			}
   1231 
   1232 			/* in case dir1 exists in dir2 and "mv dir1 dir2" */
   1233 			if ((*ndvp)->sdev_nlink > 2) {
   1234 				vn_vfsunlock(nvp);
   1235 				error = EEXIST;
   1236 				goto err_out;
   1237 			}
   1238 			vn_vfsunlock(nvp);
   1239 
   1240 			(void) sdev_dirdelete(nddv, *ndvp);
   1241 			*ndvp = NULL;
   1242 			ASSERT(nddv->sdev_attrvp);
   1243 			error = VOP_RMDIR(nddv->sdev_attrvp, nnm,
   1244 			    nddv->sdev_attrvp, cred, NULL, 0);
   1245 			if (error)
   1246 				goto err_out;
   1247 		} else {
   1248 			if (doingdir) {
   1249 				error = ENOTDIR;
   1250 				goto err_out;
   1251 			}
   1252 
   1253 			if (SDEV_IS_PERSIST((*ndvp))) {
   1254 				bkstore = 1;
   1255 			}
   1256 
   1257 			/*
   1258 			 * get rid of the node from the directory cache
   1259 			 * note, in case EBUSY is returned, the ZOMBIE
   1260 			 * node is taken care in sdev_mknode.
   1261 			 */
   1262 			(void) sdev_dirdelete(nddv, *ndvp);
   1263 			*ndvp = NULL;
   1264 			if (bkstore) {
   1265 				ASSERT(nddv->sdev_attrvp);
   1266 				error = VOP_REMOVE(nddv->sdev_attrvp,
   1267 				    nnm, cred, NULL, 0);
   1268 				if (error)
   1269 					goto err_out;
   1270 			}
   1271 		}
   1272 	}
   1273 
   1274 	/* fix the source for a symlink */
   1275 	if (vattr.va_type == VLNK) {
   1276 		if (odv->sdev_symlink == NULL) {
   1277 			error = sdev_follow_link(odv);
   1278 			if (error) {
   1279 				error = ENOENT;
   1280 				goto err_out;
   1281 			}
   1282 		}
   1283 		ASSERT(odv->sdev_symlink);
   1284 		link = i_ddi_strdup(odv->sdev_symlink, KM_SLEEP);
   1285 	}
   1286 
   1287 	/*
   1288 	 * make a fresh node from the source attrs
   1289 	 */
   1290 	ASSERT(RW_WRITE_HELD(&nddv->sdev_contents));
   1291 	error = sdev_mknode(nddv, nnm, ndvp, &vattr,
   1292 	    NULL, (void *)link, cred, SDEV_READY);
   1293 
   1294 	if (link)
   1295 		kmem_free(link, strlen(link) + 1);
   1296 
   1297 	if (error)
   1298 		goto err_out;
   1299 	ASSERT(*ndvp);
   1300 	ASSERT((*ndvp)->sdev_state == SDEV_READY);
   1301 
   1302 	/* move dir contents */
   1303 	if (doingdir) {
   1304 		for (idv = SDEV_FIRST_ENTRY(odv); idv;
   1305 		    idv = SDEV_NEXT_ENTRY(odv, idv)) {
   1306 			error = sdev_rnmnode(odv, idv,
   1307 			    (struct sdev_node *)(*ndvp), &ndv,
   1308 			    idv->sdev_name, cred);
   1309 			if (error)
   1310 				goto err_out;
   1311 			ndv = NULL;
   1312 		}
   1313 	}
   1314 
   1315 	if ((*ndvp)->sdev_attrvp) {
   1316 		sdev_update_timestamps((*ndvp)->sdev_attrvp, kcred,
   1317 		    AT_CTIME|AT_ATIME);
   1318 	} else {
   1319 		ASSERT((*ndvp)->sdev_attr);
   1320 		gethrestime(&now);
   1321 		(*ndvp)->sdev_attr->va_ctime = now;
   1322 		(*ndvp)->sdev_attr->va_atime = now;
   1323 	}
   1324 
   1325 	if (nddv->sdev_attrvp) {
   1326 		sdev_update_timestamps(nddv->sdev_attrvp, kcred,
   1327 		    AT_MTIME|AT_ATIME);
   1328 	} else {
   1329 		ASSERT(nddv->sdev_attr);
   1330 		gethrestime(&now);
   1331 		nddv->sdev_attr->va_mtime = now;
   1332 		nddv->sdev_attr->va_atime = now;
   1333 	}
   1334 	rw_exit(&nddv->sdev_contents);
   1335 	if (!samedir)
   1336 		rw_exit(&oddv->sdev_contents);
   1337 
   1338 	SDEV_RELE(*ndvp);
   1339 	return (error);
   1340 
   1341 err_out:
   1342 	rw_exit(&nddv->sdev_contents);
   1343 	if (!samedir)
   1344 		rw_exit(&oddv->sdev_contents);
   1345 	return (error);
   1346 }
   1347 
   1348 /*
   1349  * Merge sdev_node specific information into an attribute structure.
   1350  *
   1351  * note: sdev_node is not locked here
   1352  */
   1353 void
   1354 sdev_vattr_merge(struct sdev_node *dv, struct vattr *vap)
   1355 {
   1356 	struct vnode *vp = SDEVTOV(dv);
   1357 
   1358 	vap->va_nlink = dv->sdev_nlink;
   1359 	vap->va_nodeid = dv->sdev_ino;
   1360 	vap->va_fsid = SDEVTOV(dv->sdev_dotdot)->v_rdev;
   1361 	vap->va_type = vp->v_type;
   1362 
   1363 	if (vp->v_type == VDIR) {
   1364 		vap->va_rdev = 0;
   1365 		vap->va_fsid = vp->v_rdev;
   1366 	} else if (vp->v_type == VLNK) {
   1367 		vap->va_rdev = 0;
   1368 		vap->va_mode  &= ~S_IFMT;
   1369 		vap->va_mode |= S_IFLNK;
   1370 	} else if ((vp->v_type == VCHR) || (vp->v_type == VBLK)) {
   1371 		vap->va_rdev = vp->v_rdev;
   1372 		vap->va_mode &= ~S_IFMT;
   1373 		if (vap->va_type == VCHR)
   1374 			vap->va_mode |= S_IFCHR;
   1375 		else
   1376 			vap->va_mode |= S_IFBLK;
   1377 	} else {
   1378 		vap->va_rdev = 0;
   1379 	}
   1380 }
   1381 
   1382 static struct vattr *
   1383 sdev_getdefault_attr(enum vtype type)
   1384 {
   1385 	if (type == VDIR)
   1386 		return (&sdev_vattr_dir);
   1387 	else if (type == VCHR)
   1388 		return (&sdev_vattr_chr);
   1389 	else if (type == VBLK)
   1390 		return (&sdev_vattr_blk);
   1391 	else if (type == VLNK)
   1392 		return (&sdev_vattr_lnk);
   1393 	else
   1394 		return (NULL);
   1395 }
   1396 int
   1397 sdev_to_vp(struct sdev_node *dv, struct vnode **vpp)
   1398 {
   1399 	int rv = 0;
   1400 	struct vnode *vp = SDEVTOV(dv);
   1401 
   1402 	switch (vp->v_type) {
   1403 	case VCHR:
   1404 	case VBLK:
   1405 		/*
   1406 		 * If vnode is a device, return special vnode instead
   1407 		 * (though it knows all about -us- via sp->s_realvp)
   1408 		 */
   1409 		*vpp = specvp(vp, vp->v_rdev, vp->v_type, kcred);
   1410 		VN_RELE(vp);
   1411 		if (*vpp == NULLVP)
   1412 			rv = ENOSYS;
   1413 		break;
   1414 	default:	/* most types are returned as is */
   1415 		*vpp = vp;
   1416 		break;
   1417 	}
   1418 	return (rv);
   1419 }
   1420 
   1421 /*
   1422  * loopback into sdev_lookup()
   1423  */
   1424 static struct vnode *
   1425 devname_find_by_devpath(char *devpath, struct vattr *vattr)
   1426 {
   1427 	int error = 0;
   1428 	struct vnode *vp;
   1429 
   1430 	error = lookupname(devpath, UIO_SYSSPACE, NO_FOLLOW, NULLVPP, &vp);
   1431 	if (error) {
   1432 		return (NULL);
   1433 	}
   1434 
   1435 	if (vattr)
   1436 		(void) VOP_GETATTR(vp, vattr, 0, kcred, NULL);
   1437 	return (vp);
   1438 }
   1439 
   1440 /*
   1441  * the junction between devname and devfs
   1442  */
   1443 static struct vnode *
   1444 devname_configure_by_path(char *physpath, struct vattr *vattr)
   1445 {
   1446 	int error = 0;
   1447 	struct vnode *vp;
   1448 
   1449 	ASSERT(strncmp(physpath, "/devices/", sizeof ("/devices/") - 1)
   1450 	    == 0);
   1451 
   1452 	error = devfs_lookupname(physpath + sizeof ("/devices/") - 1,
   1453 	    NULLVPP, &vp);
   1454 	if (error != 0) {
   1455 		if (error == ENODEV) {
   1456 			cmn_err(CE_CONT, "%s: not found (line %d)\n",
   1457 			    physpath, __LINE__);
   1458 		}
   1459 
   1460 		return (NULL);
   1461 	}
   1462 
   1463 	if (vattr)
   1464 		(void) VOP_GETATTR(vp, vattr, 0, kcred, NULL);
   1465 	return (vp);
   1466 }
   1467 
   1468 /*
   1469  * junction between devname and root file system, e.g. ufs
   1470  */
   1471 int
   1472 devname_backstore_lookup(struct sdev_node *ddv, char *nm, struct vnode **rvp)
   1473 {
   1474 	struct vnode *rdvp = ddv->sdev_attrvp;
   1475 	int rval = 0;
   1476 
   1477 	ASSERT(rdvp);
   1478 
   1479 	rval = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, kcred, NULL, NULL,
   1480 	    NULL);
   1481 	return (rval);
   1482 }
   1483 
   1484 static int
   1485 sdev_filldir_from_store(struct sdev_node *ddv, int dlen, struct cred *cred)
   1486 {
   1487 	struct sdev_node *dv = NULL;
   1488 	char	*nm;
   1489 	struct vnode *dirvp;
   1490 	int	error;
   1491 	vnode_t	*vp;
   1492 	int eof;
   1493 	struct iovec iov;
   1494 	struct uio uio;
   1495 	struct dirent64 *dp;
   1496 	dirent64_t *dbuf;
   1497 	size_t dbuflen;
   1498 	struct vattr vattr;
   1499 	char *link = NULL;
   1500 
   1501 	if (ddv->sdev_attrvp == NULL)
   1502 		return (0);
   1503 	if (!(ddv->sdev_flags & SDEV_BUILD))
   1504 		return (0);
   1505 
   1506 	dirvp = ddv->sdev_attrvp;
   1507 	VN_HOLD(dirvp);
   1508 	dbuf = kmem_zalloc(dlen, KM_SLEEP);
   1509 
   1510 	uio.uio_iov = &iov;
   1511 	uio.uio_iovcnt = 1;
   1512 	uio.uio_segflg = UIO_SYSSPACE;
   1513 	uio.uio_fmode = 0;
   1514 	uio.uio_extflg = UIO_COPY_CACHED;
   1515 	uio.uio_loffset = 0;
   1516 	uio.uio_llimit = MAXOFFSET_T;
   1517 
   1518 	eof = 0;
   1519 	error = 0;
   1520 	while (!error && !eof) {
   1521 		uio.uio_resid = dlen;
   1522 		iov.iov_base = (char *)dbuf;
   1523 		iov.iov_len = dlen;
   1524 		(void) VOP_RWLOCK(dirvp, V_WRITELOCK_FALSE, NULL);
   1525 		error = VOP_READDIR(dirvp, &uio, kcred, &eof, NULL, 0);
   1526 		VOP_RWUNLOCK(dirvp, V_WRITELOCK_FALSE, NULL);
   1527 
   1528 		dbuflen = dlen - uio.uio_resid;
   1529 		if (error || dbuflen == 0)
   1530 			break;
   1531 
   1532 		if (!(ddv->sdev_flags & SDEV_BUILD)) {
   1533 			error = 0;
   1534 			break;
   1535 		}
   1536 
   1537 		for (dp = dbuf; ((intptr_t)dp <
   1538 		    (intptr_t)dbuf + dbuflen);
   1539 		    dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) {
   1540 			nm = dp->d_name;
   1541 
   1542 			if (strcmp(nm, ".") == 0 ||
   1543 			    strcmp(nm, "..") == 0)
   1544 				continue;
   1545 
   1546 			vp = NULLVP;
   1547 			dv = sdev_cache_lookup(ddv, nm);
   1548 			if (dv) {
   1549 				if (dv->sdev_state != SDEV_ZOMBIE) {
   1550 					SDEV_SIMPLE_RELE(dv);
   1551 				} else {
   1552 					/*
   1553 					 * A ZOMBIE node may not have been
   1554 					 * cleaned up from the backing store,
   1555 					 * bypass this entry in this case,
   1556 					 * and clean it up from the directory
   1557 					 * cache if this is the last call.
   1558 					 */
   1559 					(void) sdev_dirdelete(ddv, dv);
   1560 				}
   1561 				continue;
   1562 			}
   1563 
   1564 			/* refill the cache if not already */
   1565 			error = devname_backstore_lookup(ddv, nm, &vp);
   1566 			if (error)
   1567 				continue;
   1568 
   1569 			vattr.va_mask = AT_MODE|AT_UID|AT_GID;
   1570 			error = VOP_GETATTR(vp, &vattr, 0, cred, NULL);
   1571 			if (error)
   1572 				continue;
   1573 
   1574 			if (vattr.va_type == VLNK) {
   1575 				error = sdev_getlink(vp, &link);
   1576 				if (error) {
   1577 					continue;
   1578 				}
   1579 				ASSERT(link != NULL);
   1580 			}
   1581 
   1582 			if (!rw_tryupgrade(&ddv->sdev_contents)) {
   1583 				rw_exit(&ddv->sdev_contents);
   1584 				rw_enter(&ddv->sdev_contents, RW_WRITER);
   1585 			}
   1586 			error = sdev_mknode(ddv, nm, &dv, &vattr, vp, link,
   1587 			    cred, SDEV_READY);
   1588 			rw_downgrade(&ddv->sdev_contents);
   1589 
   1590 			if (link != NULL) {
   1591 				kmem_free(link, strlen(link) + 1);
   1592 				link = NULL;
   1593 			}
   1594 
   1595 			if (!error) {
   1596 				ASSERT(dv);
   1597 				ASSERT(dv->sdev_state != SDEV_ZOMBIE);
   1598 				SDEV_SIMPLE_RELE(dv);
   1599 			}
   1600 			vp = NULL;
   1601 			dv = NULL;
   1602 		}
   1603 	}
   1604 
   1605 done:
   1606 	VN_RELE(dirvp);
   1607 	kmem_free(dbuf, dlen);
   1608 
   1609 	return (error);
   1610 }
   1611 
   1612 void
   1613 sdev_filldir_dynamic(struct sdev_node *ddv)
   1614 {
   1615 	int error;
   1616 	int i;
   1617 	struct vattr *vap;
   1618 	char *nm = NULL;
   1619 	struct sdev_node *dv = NULL;
   1620 
   1621 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
   1622 	ASSERT((ddv->sdev_flags & SDEV_BUILD));
   1623 
   1624 	vap = sdev_getdefault_attr(VDIR);
   1625 	for (i = 0; vtab[i].vt_name != NULL; i++) {
   1626 		nm = vtab[i].vt_name;
   1627 		ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
   1628 		dv = NULL;
   1629 		error = sdev_mknode(ddv, nm, &dv, vap, NULL,
   1630 		    NULL, kcred, SDEV_READY);
   1631 		if (error) {
   1632 			cmn_err(CE_WARN, "%s/%s: error %d\n",
   1633 			    ddv->sdev_name, nm, error);
   1634 		} else {
   1635 			ASSERT(dv);
   1636 			ASSERT(dv->sdev_state != SDEV_ZOMBIE);
   1637 			SDEV_SIMPLE_RELE(dv);
   1638 		}
   1639 	}
   1640 }
   1641 
   1642 /*
   1643  * Creating a backing store entry based on sdev_attr.
   1644  * This is called either as part of node creation in a persistent directory
   1645  * or from setattr/setsecattr to persist access attributes across reboot.
   1646  */
   1647 int
   1648 sdev_shadow_node(struct sdev_node *dv, struct cred *cred)
   1649 {
   1650 	int error = 0;
   1651 	struct vnode *dvp = SDEVTOV(dv->sdev_dotdot);
   1652 	struct vnode *rdvp = VTOSDEV(dvp)->sdev_attrvp;
   1653 	struct vattr *vap = dv->sdev_attr;
   1654 	char *nm = dv->sdev_name;
   1655 	struct vnode *tmpvp, **rvp = &tmpvp, *rrvp = NULL;
   1656 
   1657 	ASSERT(dv && dv->sdev_name && rdvp);
   1658 	ASSERT(RW_WRITE_HELD(&dv->sdev_contents) && dv->sdev_attrvp == NULL);
   1659 
   1660 lookup:
   1661 	/* try to find it in the backing store */
   1662 	error = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, cred, NULL, NULL,
   1663 	    NULL);
   1664 	if (error == 0) {
   1665 		if (VOP_REALVP(*rvp, &rrvp, NULL) == 0) {
   1666 			VN_HOLD(rrvp);
   1667 			VN_RELE(*rvp);
   1668 			*rvp = rrvp;
   1669 		}
   1670 
   1671 		kmem_free(dv->sdev_attr, sizeof (vattr_t));
   1672 		dv->sdev_attr = NULL;
   1673 		dv->sdev_attrvp = *rvp;
   1674 		return (0);
   1675 	}
   1676 
   1677 	/* let's try to persist the node */
   1678 	gethrestime(&vap->va_atime);
   1679 	vap->va_mtime = vap->va_atime;
   1680 	vap->va_ctime = vap->va_atime;
   1681 	vap->va_mask |= AT_TYPE|AT_MODE;
   1682 	switch (vap->va_type) {
   1683 	case VDIR:
   1684 		error = VOP_MKDIR(rdvp, nm, vap, rvp, cred, NULL, 0, NULL);
   1685 		sdcmn_err9(("sdev_shadow_node: mkdir vp %p error %d\n",
   1686 		    (void *)(*rvp), error));
   1687 		break;
   1688 	case VCHR:
   1689 	case VBLK:
   1690 	case VREG:
   1691 	case VDOOR:
   1692 		error = VOP_CREATE(rdvp, nm, vap, NONEXCL, VREAD|VWRITE,
   1693 		    rvp, cred, 0, NULL, NULL);
   1694 		sdcmn_err9(("sdev_shadow_node: create vp %p, error %d\n",
   1695 		    (void *)(*rvp), error));
   1696 		if (!error)
   1697 			VN_RELE(*rvp);
   1698 		break;
   1699 	case VLNK:
   1700 		ASSERT(dv->sdev_symlink);
   1701 		error = VOP_SYMLINK(rdvp, nm, vap, dv->sdev_symlink, cred,
   1702 		    NULL, 0);
   1703 		sdcmn_err9(("sdev_shadow_node: create symlink error %d\n",
   1704 		    error));
   1705 		break;
   1706 	default:
   1707 		cmn_err(CE_PANIC, "dev: %s: sdev_shadow_node "
   1708 		    "create\n", nm);
   1709 		/*NOTREACHED*/
   1710 	}
   1711 
   1712 	/* go back to lookup to factor out spec node and set attrvp */
   1713 	if (error == 0)
   1714 		goto lookup;
   1715 
   1716 	sdcmn_err(("cannot persist %s - error %d\n", dv->sdev_path, error));
   1717 	return (error);
   1718 }
   1719 
   1720 static int
   1721 sdev_cache_add(struct sdev_node *ddv, struct sdev_node **dv, char *nm)
   1722 {
   1723 	int error = 0;
   1724 	struct sdev_node *dup = NULL;
   1725 
   1726 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
   1727 	if ((dup = sdev_findbyname(ddv, nm)) == NULL) {
   1728 		sdev_direnter(ddv, *dv);
   1729 	} else {
   1730 		if (dup->sdev_state == SDEV_ZOMBIE) {
   1731 			error = sdev_dirdelete(ddv, dup);
   1732 			/*
   1733 			 * The ZOMBIE node is still hanging
   1734 			 * around with more than one reference counts.
   1735 			 * Fail the new node creation so that
   1736 			 * the directory cache won't have
   1737 			 * duplicate entries for the same named node
   1738 			 */
   1739 			if (error == EBUSY) {
   1740 				SDEV_SIMPLE_RELE(*dv);
   1741 				sdev_nodedestroy(*dv, 0);
   1742 				*dv = NULL;
   1743 				return (error);
   1744 			}
   1745 			sdev_direnter(ddv, *dv);
   1746 		} else {
   1747 			ASSERT((*dv)->sdev_state != SDEV_ZOMBIE);
   1748 			SDEV_SIMPLE_RELE(*dv);
   1749 			sdev_nodedestroy(*dv, 0);
   1750 			*dv = dup;
   1751 		}
   1752 	}
   1753 
   1754 	return (0);
   1755 }
   1756 
   1757 static int
   1758 sdev_cache_delete(struct sdev_node *ddv, struct sdev_node **dv)
   1759 {
   1760 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
   1761 	return (sdev_dirdelete(ddv, *dv));
   1762 }
   1763 
   1764 /*
   1765  * update the in-core directory cache
   1766  */
   1767 int
   1768 sdev_cache_update(struct sdev_node *ddv, struct sdev_node **dv, char *nm,
   1769     sdev_cache_ops_t ops)
   1770 {
   1771 	int error = 0;
   1772 
   1773 	ASSERT((SDEV_HELD(*dv)));
   1774 
   1775 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
   1776 	switch (ops) {
   1777 	case SDEV_CACHE_ADD:
   1778 		error = sdev_cache_add(ddv, dv, nm);
   1779 		break;
   1780 	case SDEV_CACHE_DELETE:
   1781 		error = sdev_cache_delete(ddv, dv);
   1782 		break;
   1783 	default:
   1784 		break;
   1785 	}
   1786 
   1787 	return (error);
   1788 }
   1789 
   1790 /*
   1791  * retrieve the named entry from the directory cache
   1792  */
   1793 struct sdev_node *
   1794 sdev_cache_lookup(struct sdev_node *ddv, char *nm)
   1795 {
   1796 	struct sdev_node *dv = NULL;
   1797 
   1798 	ASSERT(RW_LOCK_HELD(&ddv->sdev_contents));
   1799 	dv = sdev_findbyname(ddv, nm);
   1800 
   1801 	return (dv);
   1802 }
   1803 
   1804 /*
   1805  * Implicit reconfig for nodes constructed by a link generator
   1806  * Start devfsadm if needed, or if devfsadm is in progress,
   1807  * prepare to block on devfsadm either completing or
   1808  * constructing the desired node.  As devfsadmd is global
   1809  * in scope, constructing all necessary nodes, we only
   1810  * need to initiate it once.
   1811  */
   1812 static int
   1813 sdev_call_devfsadmd(struct sdev_node *ddv, struct sdev_node *dv, char *nm)
   1814 {
   1815 	int error = 0;
   1816 
   1817 	if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) {
   1818 		sdcmn_err6(("lookup: waiting for %s/%s, 0x%x\n",
   1819 		    ddv->sdev_name, nm, devfsadm_state));
   1820 		mutex_enter(&dv->sdev_lookup_lock);
   1821 		SDEV_BLOCK_OTHERS(dv, (SDEV_LOOKUP | SDEV_LGWAITING));
   1822 		mutex_exit(&dv->sdev_lookup_lock);
   1823 		error = 0;
   1824 	} else if (!DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state)) {
   1825 		sdcmn_err6(("lookup %s/%s starting devfsadm, 0x%x\n",
   1826 		    ddv->sdev_name, nm, devfsadm_state));
   1827 
   1828 		sdev_devfsadmd_thread(ddv, dv, kcred);
   1829 		mutex_enter(&dv->sdev_lookup_lock);
   1830 		SDEV_BLOCK_OTHERS(dv,
   1831 		    (SDEV_LOOKUP | SDEV_LGWAITING));
   1832 		mutex_exit(&dv->sdev_lookup_lock);
   1833 		error = 0;
   1834 	} else {
   1835 		error = -1;
   1836 	}
   1837 
   1838 	return (error);
   1839 }
   1840 
   1841 static int
   1842 sdev_call_modulelookup(struct sdev_node *ddv, struct sdev_node **dvp, char *nm,
   1843     int (*fn)(char *, devname_handle_t *, struct cred *), struct cred *cred)
   1844 {
   1845 	struct vnode *rvp = NULL;
   1846 	int error = 0;
   1847 	struct vattr *vap;
   1848 	devname_spec_t spec;
   1849 	devname_handle_t *hdl;
   1850 	void *args = NULL;
   1851 	struct sdev_node *dv = *dvp;
   1852 
   1853 	ASSERT(dv && ddv);
   1854 	hdl = &(dv->sdev_handle);
   1855 	ASSERT(hdl->dh_data == dv);
   1856 	mutex_enter(&dv->sdev_lookup_lock);
   1857 	SDEV_BLOCK_OTHERS(dv, SDEV_LOOKUP);
   1858 	mutex_exit(&dv->sdev_lookup_lock);
   1859 	error = (*fn)(nm, hdl, cred);
   1860 	if (error) {
   1861 		return (error);
   1862 	}
   1863 
   1864 	spec = hdl->dh_spec;
   1865 	args = hdl->dh_args;
   1866 	ASSERT(args);
   1867 
   1868 	switch (spec) {
   1869 	case DEVNAME_NS_PATH:
   1870 		/*
   1871 		 * symlink of:
   1872 		 *	/dev/dir/nm -> /device/...
   1873 		 */
   1874 		rvp = devname_configure_by_path((char *)args, NULL);
   1875 		break;
   1876 	case DEVNAME_NS_DEV:
   1877 		/*
   1878 		 * symlink of:
   1879 		 *	/dev/dir/nm -> /dev/...
   1880 		 */
   1881 		rvp = devname_find_by_devpath((char *)args, NULL);
   1882 		break;
   1883 	default:
   1884 		if (args)
   1885 			kmem_free((char *)args, strlen(args) + 1);
   1886 		return (ENOENT);
   1887 
   1888 	}
   1889 
   1890 	if (rvp == NULL) {
   1891 		if (args)
   1892 			kmem_free((char *)args, strlen(args) + 1);
   1893 		return (ENOENT);
   1894 	} else {
   1895 		vap = sdev_getdefault_attr(VLNK);
   1896 		ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   1897 		/*
   1898 		 * Could sdev_mknode return a different dv_node
   1899 		 * once the lock is dropped?
   1900 		 */
   1901 		if (!rw_tryupgrade(&ddv->sdev_contents)) {
   1902 			rw_exit(&ddv->sdev_contents);
   1903 			rw_enter(&ddv->sdev_contents, RW_WRITER);
   1904 		}
   1905 		error = sdev_mknode(ddv, nm, &dv, vap, NULL, args, cred,
   1906 		    SDEV_READY);
   1907 		rw_downgrade(&ddv->sdev_contents);
   1908 		if (error) {
   1909 			if (args)
   1910 				kmem_free((char *)args, strlen(args) + 1);
   1911 			return (error);
   1912 		} else {
   1913 			mutex_enter(&dv->sdev_lookup_lock);
   1914 			SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP);
   1915 			mutex_exit(&dv->sdev_lookup_lock);
   1916 			error = 0;
   1917 		}
   1918 	}
   1919 
   1920 	if (args)
   1921 		kmem_free((char *)args, strlen(args) + 1);
   1922 
   1923 	*dvp = dv;
   1924 	return (0);
   1925 }
   1926 
   1927 /*
   1928  *  Support for specialized device naming construction mechanisms
   1929  */
   1930 static int
   1931 sdev_call_dircallback(struct sdev_node *ddv, struct sdev_node **dvp, char *nm,
   1932     int (*callback)(struct sdev_node *, char *, void **, struct cred *,
   1933     void *, char *), int flags, struct cred *cred)
   1934 {
   1935 	int rv = 0;
   1936 	char *physpath = NULL;
   1937 	struct vnode *rvp = NULL;
   1938 	struct vattr vattr;
   1939 	struct vattr *vap;
   1940 	struct sdev_node *dv = *dvp;
   1941 
   1942 	mutex_enter(&dv->sdev_lookup_lock);
   1943 	SDEV_BLOCK_OTHERS(dv, SDEV_LOOKUP);
   1944 	mutex_exit(&dv->sdev_lookup_lock);
   1945 
   1946 	/* for non-devfsadm devices */
   1947 	if (flags & SDEV_PATH) {
   1948 		physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
   1949 		rv = callback(ddv, nm, (void *)&physpath, kcred, NULL,
   1950 		    NULL);
   1951 		if (rv) {
   1952 			kmem_free(physpath, MAXPATHLEN);
   1953 			return (-1);
   1954 		}
   1955 
   1956 		rvp = devname_configure_by_path(physpath, NULL);
   1957 		if (rvp == NULL) {
   1958 			sdcmn_err3(("devname_configure_by_path: "
   1959 			    "failed for /dev/%s/%s\n",
   1960 			    ddv->sdev_name, nm));
   1961 			kmem_free(physpath, MAXPATHLEN);
   1962 			rv = -1;
   1963 		} else {
   1964 			vap = sdev_getdefault_attr(VLNK);
   1965 			ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   1966 
   1967 			/*
   1968 			 * Sdev_mknode may return back a different sdev_node
   1969 			 * that was created by another thread that
   1970 			 * raced to the directroy cache before this thread.
   1971 			 *
   1972 			 * With current directory cache mechanism
   1973 			 * (linked list with the sdev_node name as
   1974 			 * the entity key), this is a way to make sure
   1975 			 * only one entry exists for the same name
   1976 			 * in the same directory. The outcome is
   1977 			 * the winner wins.
   1978 			 */
   1979 			if (!rw_tryupgrade(&ddv->sdev_contents)) {
   1980 				rw_exit(&ddv->sdev_contents);
   1981 				rw_enter(&ddv->sdev_contents, RW_WRITER);
   1982 			}
   1983 			rv = sdev_mknode(ddv, nm, &dv, vap, NULL,
   1984 			    (void *)physpath, cred, SDEV_READY);
   1985 			rw_downgrade(&ddv->sdev_contents);
   1986 			kmem_free(physpath, MAXPATHLEN);
   1987 			if (rv) {
   1988 				return (rv);
   1989 			} else {
   1990 				mutex_enter(&dv->sdev_lookup_lock);
   1991 				SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP);
   1992 				mutex_exit(&dv->sdev_lookup_lock);
   1993 				return (0);
   1994 			}
   1995 		}
   1996 	} else if (flags & SDEV_VLINK) {
   1997 		physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
   1998 		rv = callback(ddv, nm, (void *)&physpath, kcred, NULL,
   1999 		    NULL);
   2000 		if (rv) {
   2001 			kmem_free(physpath, MAXPATHLEN);
   2002 			return (-1);
   2003 		}
   2004 
   2005 		vap = sdev_getdefault_attr(VLNK);
   2006 		vap->va_size = strlen(physpath);
   2007 		ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   2008 
   2009 		if (!rw_tryupgrade(&ddv->sdev_contents)) {
   2010 			rw_exit(&ddv->sdev_contents);
   2011 			rw_enter(&ddv->sdev_contents, RW_WRITER);
   2012 		}
   2013 		rv = sdev_mknode(ddv, nm, &dv, vap, NULL,
   2014 		    (void *)physpath, cred, SDEV_READY);
   2015 		rw_downgrade(&ddv->sdev_contents);
   2016 		kmem_free(physpath, MAXPATHLEN);
   2017 		if (rv)
   2018 			return (rv);
   2019 
   2020 		mutex_enter(&dv->sdev_lookup_lock);
   2021 		SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP);
   2022 		mutex_exit(&dv->sdev_lookup_lock);
   2023 		return (0);
   2024 	} else if (flags & SDEV_VNODE) {
   2025 		/*
   2026 		 * DBNR has its own way to create the device
   2027 		 * and return a backing store vnode in rvp
   2028 		 */
   2029 		ASSERT(callback);
   2030 		rv = callback(ddv, nm, (void *)&rvp, kcred, NULL, NULL);
   2031 		if (rv || (rvp == NULL)) {
   2032 			sdcmn_err3(("devname_lookup_func: SDEV_VNODE "
   2033 			    "callback failed \n"));
   2034 			return (-1);
   2035 		}
   2036 		vap = sdev_getdefault_attr(rvp->v_type);
   2037 		if (vap == NULL)
   2038 			return (-1);
   2039 
   2040 		ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   2041 		if (!rw_tryupgrade(&ddv->sdev_contents)) {
   2042 			rw_exit(&ddv->sdev_contents);
   2043 			rw_enter(&ddv->sdev_contents, RW_WRITER);
   2044 		}
   2045 		rv = sdev_mknode(ddv, nm, &dv, vap, rvp, NULL,
   2046 		    cred, SDEV_READY);
   2047 		rw_downgrade(&ddv->sdev_contents);
   2048 		if (rv)
   2049 			return (rv);
   2050 
   2051 		mutex_enter(&dv->sdev_lookup_lock);
   2052 		SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP);
   2053 		mutex_exit(&dv->sdev_lookup_lock);
   2054 		return (0);
   2055 	} else if (flags & SDEV_VATTR) {
   2056 		/*
   2057 		 * /dev/pts
   2058 		 *
   2059 		 * DBNR has its own way to create the device
   2060 		 * "0" is returned upon success.
   2061 		 *
   2062 		 * callback is responsible to set the basic attributes,
   2063 		 * e.g. va_type/va_uid/va_gid/
   2064 		 *    dev_t if VCHR or VBLK/
   2065 		 */
   2066 		ASSERT(callback);
   2067 		rv = callback(ddv, nm, (void *)&vattr, kcred, NULL, NULL);
   2068 		if (rv) {
   2069 			sdcmn_err3(("devname_lookup_func: SDEV_NONE "
   2070 			    "callback failed \n"));
   2071 			return (-1);
   2072 		}
   2073 
   2074 		ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   2075 		if (!rw_tryupgrade(&ddv->sdev_contents)) {
   2076 			rw_exit(&ddv->sdev_contents);
   2077 			rw_enter(&ddv->sdev_contents, RW_WRITER);
   2078 		}
   2079 		rv = sdev_mknode(ddv, nm, &dv, &vattr, NULL, NULL,
   2080 		    cred, SDEV_READY);
   2081 		rw_downgrade(&ddv->sdev_contents);
   2082 
   2083 		if (rv)
   2084 			return (rv);
   2085 
   2086 		mutex_enter(&dv->sdev_lookup_lock);
   2087 		SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP);
   2088 		mutex_exit(&dv->sdev_lookup_lock);
   2089 		return (0);
   2090 	} else {
   2091 		impossible(("lookup: %s/%s by %s not supported (%d)\n",
   2092 		    SDEVTOV(ddv)->v_path, nm, curproc->p_user.u_comm,
   2093 		    __LINE__));
   2094 		rv = -1;
   2095 	}
   2096 
   2097 	*dvp = dv;
   2098 	return (rv);
   2099 }
   2100 
   2101 static int
   2102 is_devfsadm_thread(char *exec_name)
   2103 {
   2104 	/*
   2105 	 * note: because devfsadmd -> /usr/sbin/devfsadm
   2106 	 * it is safe to use "devfsadm" to capture the lookups
   2107 	 * from devfsadm and its daemon version.
   2108 	 */
   2109 	if (strcmp(exec_name, "devfsadm") == 0)
   2110 		return (1);
   2111 	return (0);
   2112 }
   2113 
   2114 
   2115 /*
   2116  * Lookup Order:
   2117  *	sdev_node cache;
   2118  *	backing store (SDEV_PERSIST);
   2119  *	DBNR: a. dir_ops implemented in the loadable modules;
   2120  *	      b. vnode ops in vtab.
   2121  */
   2122 int
   2123 devname_lookup_func(struct sdev_node *ddv, char *nm, struct vnode **vpp,
   2124     struct cred *cred, int (*callback)(struct sdev_node *, char *, void **,
   2125     struct cred *, void *, char *), int flags)
   2126 {
   2127 	int rv = 0, nmlen;
   2128 	struct vnode *rvp = NULL;
   2129 	struct sdev_node *dv = NULL;
   2130 	int	retried = 0;
   2131 	int	error = 0;
   2132 	struct devname_nsmap *map = NULL;
   2133 	struct devname_ops *dirops = NULL;
   2134 	int (*fn)(char *, devname_handle_t *, struct cred *) = NULL;
   2135 	struct vattr vattr;
   2136 	char *lookup_thread = curproc->p_user.u_comm;
   2137 	int failed_flags = 0;
   2138 	int (*vtor)(struct sdev_node *) = NULL;
   2139 	int state;
   2140 	int parent_state;
   2141 	char *link = NULL;
   2142 
   2143 	if (SDEVTOV(ddv)->v_type != VDIR)
   2144 		return (ENOTDIR);
   2145 
   2146 	/*
   2147 	 * Empty name or ., return node itself.
   2148 	 */
   2149 	nmlen = strlen(nm);
   2150 	if ((nmlen == 0) || ((nmlen == 1) && (nm[0] == '.'))) {
   2151 		*vpp = SDEVTOV(ddv);
   2152 		VN_HOLD(*vpp);
   2153 		return (0);
   2154 	}
   2155 
   2156 	/*
   2157 	 * .., return the parent directory
   2158 	 */
   2159 	if ((nmlen == 2) && (strcmp(nm, "..") == 0)) {
   2160 		*vpp = SDEVTOV(ddv->sdev_dotdot);
   2161 		VN_HOLD(*vpp);
   2162 		return (0);
   2163 	}
   2164 
   2165 	rw_enter(&ddv->sdev_contents, RW_READER);
   2166 	if (ddv->sdev_flags & SDEV_VTOR) {
   2167 		vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
   2168 		ASSERT(vtor);
   2169 	}
   2170 
   2171 tryagain:
   2172 	/*
   2173 	 * (a) directory cache lookup:
   2174 	 */
   2175 	ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   2176 	parent_state = ddv->sdev_state;
   2177 	dv = sdev_cache_lookup(ddv, nm);
   2178 	if (dv) {
   2179 		state = dv->sdev_state;
   2180 		switch (state) {
   2181 		case SDEV_INIT:
   2182 			if (is_devfsadm_thread(lookup_thread))
   2183 				break;
   2184 
   2185 			/* ZOMBIED parent won't allow node creation */
   2186 			if (parent_state == SDEV_ZOMBIE) {
   2187 				SD_TRACE_FAILED_LOOKUP(ddv, nm,
   2188 				    retried);
   2189 				goto nolock_notfound;
   2190 			}
   2191 
   2192 			mutex_enter(&dv->sdev_lookup_lock);
   2193 			/* compensate the threads started after devfsadm */
   2194 			if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) &&
   2195 			    !(SDEV_IS_LOOKUP(dv)))
   2196 				SDEV_BLOCK_OTHERS(dv,
   2197 				    (SDEV_LOOKUP | SDEV_LGWAITING));
   2198 
   2199 			if (SDEV_IS_LOOKUP(dv)) {
   2200 				failed_flags |= SLF_REBUILT;
   2201 				rw_exit(&ddv->sdev_contents);
   2202 				error = sdev_wait4lookup(dv, SDEV_LOOKUP);
   2203 				mutex_exit(&dv->sdev_lookup_lock);
   2204 				rw_enter(&ddv->sdev_contents, RW_READER);
   2205 
   2206 				if (error != 0) {
   2207 					SD_TRACE_FAILED_LOOKUP(ddv, nm,
   2208 					    retried);
   2209 					goto nolock_notfound;
   2210 				}
   2211 
   2212 				state = dv->sdev_state;
   2213 				if (state == SDEV_INIT) {
   2214 					SD_TRACE_FAILED_LOOKUP(ddv, nm,
   2215 					    retried);
   2216 					goto nolock_notfound;
   2217 				} else if (state == SDEV_READY) {
   2218 					goto found;
   2219 				} else if (state == SDEV_ZOMBIE) {
   2220 					rw_exit(&ddv->sdev_contents);
   2221 					SD_TRACE_FAILED_LOOKUP(ddv, nm,
   2222 					    retried);
   2223 					SDEV_RELE(dv);
   2224 					goto lookup_failed;
   2225 				}
   2226 			} else {
   2227 				mutex_exit(&dv->sdev_lookup_lock);
   2228 			}
   2229 			break;
   2230 		case SDEV_READY:
   2231 			goto found;
   2232 		case SDEV_ZOMBIE:
   2233 			rw_exit(&ddv->sdev_contents);
   2234 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2235 			SDEV_RELE(dv);
   2236 			goto lookup_failed;
   2237 		default:
   2238 			rw_exit(&ddv->sdev_contents);
   2239 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2240 			sdev_lookup_failed(ddv, nm, failed_flags);
   2241 			*vpp = NULLVP;
   2242 			return (ENOENT);
   2243 		}
   2244 	}
   2245 	ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   2246 
   2247 	/*
   2248 	 * ZOMBIED parent does not allow new node creation.
   2249 	 * bail out early
   2250 	 */
   2251 	if (parent_state == SDEV_ZOMBIE) {
   2252 		rw_exit(&ddv->sdev_contents);
   2253 		*vpp = NULL;
   2254 		SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2255 		return (ENOENT);
   2256 	}
   2257 
   2258 	/*
   2259 	 * (b0): backing store lookup
   2260 	 *	SDEV_PERSIST is default except:
   2261 	 *		1) pts nodes
   2262 	 *		2) non-chmod'ed local nodes
   2263 	 */
   2264 	if (SDEV_IS_PERSIST(ddv)) {
   2265 		error = devname_backstore_lookup(ddv, nm, &rvp);
   2266 
   2267 		if (!error) {
   2268 			sdcmn_err3(("devname_backstore_lookup: "
   2269 			    "found attrvp %p for %s\n", (void *)rvp, nm));
   2270 
   2271 			vattr.va_mask = AT_MODE|AT_UID|AT_GID;
   2272 			error = VOP_GETATTR(rvp, &vattr, 0, cred, NULL);
   2273 			if (error) {
   2274 				rw_exit(&ddv->sdev_contents);
   2275 				if (dv)
   2276 					SDEV_RELE(dv);
   2277 				SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2278 				sdev_lookup_failed(ddv, nm, failed_flags);
   2279 				*vpp = NULLVP;
   2280 				return (ENOENT);
   2281 			}
   2282 
   2283 			if (vattr.va_type == VLNK) {
   2284 				error = sdev_getlink(rvp, &link);
   2285 				if (error) {
   2286 					rw_exit(&ddv->sdev_contents);
   2287 					if (dv)
   2288 						SDEV_RELE(dv);
   2289 					SD_TRACE_FAILED_LOOKUP(ddv, nm,
   2290 					    retried);
   2291 					sdev_lookup_failed(ddv, nm,
   2292 					    failed_flags);
   2293 					*vpp = NULLVP;
   2294 					return (ENOENT);
   2295 				}
   2296 				ASSERT(link != NULL);
   2297 			}
   2298 
   2299 			if (!rw_tryupgrade(&ddv->sdev_contents)) {
   2300 				rw_exit(&ddv->sdev_contents);
   2301 				rw_enter(&ddv->sdev_contents, RW_WRITER);
   2302 			}
   2303 			error = sdev_mknode(ddv, nm, &dv, &vattr,
   2304 			    rvp, link, cred, SDEV_READY);
   2305 			rw_downgrade(&ddv->sdev_contents);
   2306 
   2307 			if (link != NULL) {
   2308 				kmem_free(link, strlen(link) + 1);
   2309 				link = NULL;
   2310 			}
   2311 
   2312 			if (error) {
   2313 				SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2314 				rw_exit(&ddv->sdev_contents);
   2315 				if (dv)
   2316 					SDEV_RELE(dv);
   2317 				goto lookup_failed;
   2318 			} else {
   2319 				goto found;
   2320 			}
   2321 		} else if (retried) {
   2322 			rw_exit(&ddv->sdev_contents);
   2323 			sdcmn_err3(("retry of lookup of %s/%s: failed\n",
   2324 			    ddv->sdev_name, nm));
   2325 			if (dv)
   2326 				SDEV_RELE(dv);
   2327 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2328 			sdev_lookup_failed(ddv, nm, failed_flags);
   2329 			*vpp = NULLVP;
   2330 			return (ENOENT);
   2331 		}
   2332 	}
   2333 
   2334 lookup_create_node:
   2335 	/* first thread that is doing the lookup on this node */
   2336 	if (!dv) {
   2337 		if (!rw_tryupgrade(&ddv->sdev_contents)) {
   2338 			rw_exit(&ddv->sdev_contents);
   2339 			rw_enter(&ddv->sdev_contents, RW_WRITER);
   2340 		}
   2341 		error = sdev_mknode(ddv, nm, &dv, NULL, NULL, NULL,
   2342 		    cred, SDEV_INIT);
   2343 		if (!dv) {
   2344 			rw_exit(&ddv->sdev_contents);
   2345 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2346 			sdev_lookup_failed(ddv, nm, failed_flags);
   2347 			*vpp = NULLVP;
   2348 			return (ENOENT);
   2349 		}
   2350 		rw_downgrade(&ddv->sdev_contents);
   2351 	}
   2352 	ASSERT(dv);
   2353 	ASSERT(SDEV_HELD(dv));
   2354 
   2355 	if (SDEV_IS_NO_NCACHE(dv)) {
   2356 		failed_flags |= SLF_NO_NCACHE;
   2357 	}
   2358 
   2359 	if (SDEV_IS_GLOBAL(ddv)) {
   2360 		map = sdev_get_map(ddv, 1);
   2361 		dirops = map ? map->dir_ops : NULL;
   2362 		fn = dirops ? dirops->devnops_lookup : NULL;
   2363 	}
   2364 
   2365 	/*
   2366 	 * (b1) invoking devfsadm once per life time for devfsadm nodes
   2367 	 */
   2368 	if ((fn == NULL) && !callback) {
   2369 
   2370 		if (sdev_reconfig_boot || !i_ddi_io_initialized() ||
   2371 		    SDEV_IS_DYNAMIC(ddv) || SDEV_IS_NO_NCACHE(dv) ||
   2372 		    ((moddebug & MODDEBUG_FINI_EBUSY) != 0)) {
   2373 			ASSERT(SDEV_HELD(dv));
   2374 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2375 			goto nolock_notfound;
   2376 		}
   2377 
   2378 		/*
   2379 		 * filter out known non-existent devices recorded
   2380 		 * during initial reconfiguration boot for which
   2381 		 * reconfig should not be done and lookup may
   2382 		 * be short-circuited now.
   2383 		 */
   2384 		if (sdev_lookup_filter(ddv, nm)) {
   2385 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2386 			goto nolock_notfound;
   2387 		}
   2388 
   2389 		/* bypassing devfsadm internal nodes */
   2390 		if (is_devfsadm_thread(lookup_thread)) {
   2391 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2392 			goto nolock_notfound;
   2393 		}
   2394 
   2395 		if (sdev_reconfig_disable) {
   2396 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2397 			goto nolock_notfound;
   2398 		}
   2399 
   2400 		error = sdev_call_devfsadmd(ddv, dv, nm);
   2401 		if (error == 0) {
   2402 			sdcmn_err8(("lookup of %s/%s by %s: reconfig\n",
   2403 			    ddv->sdev_name, nm, curproc->p_user.u_comm));
   2404 			if (sdev_reconfig_verbose) {
   2405 				cmn_err(CE_CONT,
   2406 				    "?lookup of %s/%s by %s: reconfig\n",
   2407 				    ddv->sdev_name, nm, curproc->p_user.u_comm);
   2408 			}
   2409 			retried = 1;
   2410 			failed_flags |= SLF_REBUILT;
   2411 			ASSERT(dv->sdev_state != SDEV_ZOMBIE);
   2412 			SDEV_SIMPLE_RELE(dv);
   2413 			goto tryagain;
   2414 		} else {
   2415 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2416 			goto nolock_notfound;
   2417 		}
   2418 	}
   2419 
   2420 	/*
   2421 	 * (b2) Directory Based Name Resolution (DBNR):
   2422 	 *	ddv	- parent
   2423 	 *	nm	- /dev/(ddv->sdev_name)/nm
   2424 	 *
   2425 	 *	note: module vnode ops take precedence than the build-in ones
   2426 	 */
   2427 	if (fn) {
   2428 		error = sdev_call_modulelookup(ddv, &dv, nm, fn, cred);
   2429 		if (error) {
   2430 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2431 			goto notfound;
   2432 		} else {
   2433 			goto found;
   2434 		}
   2435 	} else if (callback) {
   2436 		error = sdev_call_dircallback(ddv, &dv, nm, callback,
   2437 		    flags, cred);
   2438 		if (error == 0) {
   2439 			goto found;
   2440 		} else {
   2441 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2442 			goto notfound;
   2443 		}
   2444 	}
   2445 	ASSERT(rvp);
   2446 
   2447 found:
   2448 	ASSERT(!(dv->sdev_flags & SDEV_STALE));
   2449 	ASSERT(dv->sdev_state == SDEV_READY);
   2450 	if (vtor) {
   2451 		/*
   2452 		 * Check validity of returned node
   2453 		 */
   2454 		switch (vtor(dv)) {
   2455 		case SDEV_VTOR_VALID:
   2456 			break;
   2457 		case SDEV_VTOR_STALE:
   2458 			/*
   2459 			 * The name exists, but the cache entry is
   2460 			 * stale and needs to be re-created.
   2461 			 */
   2462 			ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   2463 			if (rw_tryupgrade(&ddv->sdev_contents) == 0) {
   2464 				rw_exit(&ddv->sdev_contents);
   2465 				rw_enter(&ddv->sdev_contents, RW_WRITER);
   2466 			}
   2467 			error = sdev_cache_update(ddv, &dv, nm,
   2468 			    SDEV_CACHE_DELETE);
   2469 			rw_downgrade(&ddv->sdev_contents);
   2470 			if (error == 0) {
   2471 				dv = NULL;
   2472 				goto lookup_create_node;
   2473 			}
   2474 			/* FALLTHRU */
   2475 		case SDEV_VTOR_INVALID:
   2476 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2477 			sdcmn_err7(("lookup: destroy invalid "
   2478 			    "node: %s(%p)\n", dv->sdev_name, (void *)dv));
   2479 			goto nolock_notfound;
   2480 		case SDEV_VTOR_SKIP:
   2481 			sdcmn_err7(("lookup: node not applicable - "
   2482 			    "skipping: %s(%p)\n", dv->sdev_name, (void *)dv));
   2483 			rw_exit(&ddv->sdev_contents);
   2484 			SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
   2485 			SDEV_RELE(dv);
   2486 			goto lookup_failed;
   2487 		default:
   2488 			cmn_err(CE_PANIC,
   2489 			    "dev fs: validator failed: %s(%p)\n",
   2490 			    dv->sdev_name, (void *)dv);
   2491 			break;
   2492 			/*NOTREACHED*/
   2493 		}
   2494 	}
   2495 
   2496 	if ((SDEVTOV(dv)->v_type == VDIR) && SDEV_IS_GLOBAL(dv)) {
   2497 		rw_enter(&dv->sdev_contents, RW_READER);
   2498 		(void) sdev_get_map(dv, 1);
   2499 		rw_exit(&dv->sdev_contents);
   2500 	}
   2501 	rw_exit(&ddv->sdev_contents);
   2502 	rv = sdev_to_vp(dv, vpp);
   2503 	sdcmn_err3(("devname_lookup_func: returning vp %p v_count %d state %d "
   2504 	    "for nm %s, error %d\n", (void *)*vpp, (*vpp)->v_count,
   2505 	    dv->sdev_state, nm, rv));
   2506 	return (rv);
   2507 
   2508 notfound:
   2509 	mutex_enter(&dv->sdev_lookup_lock);
   2510 	SDEV_UNBLOCK_OTHERS(dv, SDEV_LOOKUP);
   2511 	mutex_exit(&dv->sdev_lookup_lock);
   2512 nolock_notfound:
   2513 	/*
   2514 	 * Destroy the node that is created for synchronization purposes.
   2515 	 */
   2516 	sdcmn_err3(("devname_lookup_func: %s with state %d\n",
   2517 	    nm, dv->sdev_state));
   2518 	ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   2519 	if (dv->sdev_state == SDEV_INIT) {
   2520 		if (!rw_tryupgrade(&ddv->sdev_contents)) {
   2521 			rw_exit(&ddv->sdev_contents);
   2522 			rw_enter(&ddv->sdev_contents, RW_WRITER);
   2523 		}
   2524 
   2525 		/*
   2526 		 * Node state may have changed during the lock
   2527 		 * changes. Re-check.
   2528 		 */
   2529 		if (dv->sdev_state == SDEV_INIT) {
   2530 			(void) sdev_dirdelete(ddv, dv);
   2531 			rw_exit(&ddv->sdev_contents);
   2532 			sdev_lookup_failed(ddv, nm, failed_flags);
   2533 			*vpp = NULL;
   2534 			return (ENOENT);
   2535 		}
   2536 	}
   2537 
   2538 	rw_exit(&ddv->sdev_contents);
   2539 	SDEV_RELE(dv);
   2540 
   2541 lookup_failed:
   2542 	sdev_lookup_failed(ddv, nm, failed_flags);
   2543 	*vpp = NULL;
   2544 	return (ENOENT);
   2545 }
   2546 
   2547 /*
   2548  * Given a directory node, mark all nodes beneath as
   2549  * STALE, i.e. nodes that don't exist as far as new
   2550  * consumers are concerned.  Remove them from the
   2551  * list of directory entries so that no lookup or
   2552  * directory traversal will find them.  The node
   2553  * not deallocated so existing holds are not affected.
   2554  */
   2555 void
   2556 sdev_stale(struct sdev_node *ddv)
   2557 {
   2558 	struct sdev_node *dv;
   2559 	struct vnode *vp;
   2560 
   2561 	ASSERT(SDEVTOV(ddv)->v_type == VDIR);
   2562 
   2563 	rw_enter(&ddv->sdev_contents, RW_WRITER);
   2564 	for (dv = SDEV_FIRST_ENTRY(ddv); dv; dv = SDEV_NEXT_ENTRY(ddv, dv)) {
   2565 		vp = SDEVTOV(dv);
   2566 		if (vp->v_type == VDIR)
   2567 			sdev_stale(dv);
   2568 
   2569 		sdcmn_err9(("sdev_stale: setting stale %s\n",
   2570 		    dv->sdev_path));
   2571 		dv->sdev_flags |= SDEV_STALE;
   2572 		avl_remove(&ddv->sdev_entries, dv);
   2573 	}
   2574 	ddv->sdev_flags |= SDEV_BUILD;
   2575 	rw_exit(&ddv->sdev_contents);
   2576 }
   2577 
   2578 /*
   2579  * Given a directory node, clean out all the nodes beneath.
   2580  * If expr is specified, clean node with names matching expr.
   2581  * If SDEV_ENFORCE is specified in flags, busy nodes are made stale,
   2582  *	so they are excluded from future lookups.
   2583  */
   2584 int
   2585 sdev_cleandir(struct sdev_node *ddv, char *expr, uint_t flags)
   2586 {
   2587 	int error = 0;
   2588 	int busy = 0;
   2589 	struct vnode *vp;
   2590 	struct sdev_node *dv, *next = NULL;
   2591 	int bkstore = 0;
   2592 	int len = 0;
   2593 	char *bks_name = NULL;
   2594 
   2595 	ASSERT(SDEVTOV(ddv)->v_type == VDIR);
   2596 
   2597 	/*
   2598 	 * We try our best to destroy all unused sdev_node's
   2599 	 */
   2600 	rw_enter(&ddv->sdev_contents, RW_WRITER);
   2601 	for (dv = SDEV_FIRST_ENTRY(ddv); dv; dv = next) {
   2602 		next = SDEV_NEXT_ENTRY(ddv, dv);
   2603 		vp = SDEVTOV(dv);
   2604 
   2605 		if (expr && gmatch(dv->sdev_name, expr) == 0)
   2606 			continue;
   2607 
   2608 		if (vp->v_type == VDIR &&
   2609 		    sdev_cleandir(dv, NULL, flags) != 0) {
   2610 			sdcmn_err9(("sdev_cleandir: dir %s busy\n",
   2611 			    dv->sdev_name));
   2612 			busy++;
   2613 			continue;
   2614 		}
   2615 
   2616 		if (vp->v_count > 0 && (flags & SDEV_ENFORCE) == 0) {
   2617 			sdcmn_err9(("sdev_cleandir: dir %s busy\n",
   2618 			    dv->sdev_name));
   2619 			busy++;
   2620 			continue;
   2621 		}
   2622 
   2623 		/*
   2624 		 * at this point, either dv is not held or SDEV_ENFORCE
   2625 		 * is specified. In either case, dv needs to be deleted
   2626 		 */
   2627 		SDEV_HOLD(dv);
   2628 
   2629 		bkstore = SDEV_IS_PERSIST(dv) ? 1 : 0;
   2630 		if (bkstore && (vp->v_type == VDIR))
   2631 			bkstore += 1;
   2632 
   2633 		if (bkstore) {
   2634 			len = strlen(dv->sdev_name) + 1;
   2635 			bks_name = kmem_alloc(len, KM_SLEEP);
   2636 			bcopy(dv->sdev_name, bks_name, len);
   2637 		}
   2638 
   2639 		error = sdev_dirdelete(ddv, dv);
   2640 
   2641 		if (error == EBUSY) {
   2642 			sdcmn_err9(("sdev_cleandir: dir busy\n"));
   2643 			busy++;
   2644 		}
   2645 
   2646 		/* take care the backing store clean up */
   2647 		if (bkstore && (error == 0)) {
   2648 			ASSERT(bks_name);
   2649 			ASSERT(ddv->sdev_attrvp);
   2650 
   2651 			if (bkstore == 1) {
   2652 				error = VOP_REMOVE(ddv->sdev_attrvp,
   2653 				    bks_name, kcred, NULL, 0);
   2654 			} else if (bkstore == 2) {
   2655 				error = VOP_RMDIR(ddv->sdev_attrvp,
   2656 				    bks_name, ddv->sdev_attrvp, kcred, NULL, 0);
   2657 			}
   2658 
   2659 			/* do not propagate the backing store errors */
   2660 			if (error) {
   2661 				sdcmn_err9(("sdev_cleandir: backing store"
   2662 				    "not cleaned\n"));
   2663 				error = 0;
   2664 			}
   2665 
   2666 			bkstore = 0;
   2667 			kmem_free(bks_name, len);
   2668 			bks_name = NULL;
   2669 			len = 0;
   2670 		}
   2671 	}
   2672 
   2673 	ddv->sdev_flags |= SDEV_BUILD;
   2674 	rw_exit(&ddv->sdev_contents);
   2675 
   2676 	if (busy) {
   2677 		error = EBUSY;
   2678 	}
   2679 
   2680 	return (error);
   2681 }
   2682 
   2683 /*
   2684  * a convenient wrapper for readdir() funcs
   2685  */
   2686 size_t
   2687 add_dir_entry(dirent64_t *de, char *nm, size_t size, ino_t ino, offset_t off)
   2688 {
   2689 	size_t reclen = DIRENT64_RECLEN(strlen(nm));
   2690 	if (reclen > size)
   2691 		return (0);
   2692 
   2693 	de->d_ino = (ino64_t)ino;
   2694 	de->d_off = (off64_t)off + 1;
   2695 	de->d_reclen = (ushort_t)reclen;
   2696 	(void) strncpy(de->d_name, nm, DIRENT64_NAMELEN(reclen));
   2697 	return (reclen);
   2698 }
   2699 
   2700 /*
   2701  * sdev_mount service routines
   2702  */
   2703 int
   2704 sdev_copyin_mountargs(struct mounta *uap, struct sdev_mountargs *args)
   2705 {
   2706 	int	error;
   2707 
   2708 	if (uap->datalen != sizeof (*args))
   2709 		return (EINVAL);
   2710 
   2711 	if (error = copyin(uap->dataptr, args, sizeof (*args))) {
   2712 		cmn_err(CE_WARN, "sdev_copyin_mountargs: can not"
   2713 		    "get user data. error %d\n", error);
   2714 		return (EFAULT);
   2715 	}
   2716 
   2717 	return (0);
   2718 }
   2719 
   2720 #ifdef nextdp
   2721 #undef nextdp
   2722 #endif
   2723 #define	nextdp(dp)	((struct dirent64 *) \
   2724 			    (intptr_t)((char *)(dp) + (dp)->d_reclen))
   2725 
   2726 /*
   2727  * readdir helper func
   2728  */
   2729 int
   2730 devname_readdir_func(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp,
   2731     int flags)
   2732 {
   2733 	struct sdev_node *ddv = VTOSDEV(vp);
   2734 	struct sdev_node *dv;
   2735 	dirent64_t	*dp;
   2736 	ulong_t		outcount = 0;
   2737 	size_t		namelen;
   2738 	ulong_t		alloc_count;
   2739 	void		*outbuf;
   2740 	struct iovec	*iovp;
   2741 	int		error = 0;
   2742 	size_t		reclen;
   2743 	offset_t	diroff;
   2744 	offset_t	soff;
   2745 	int		this_reclen;
   2746 	struct devname_nsmap	*map = NULL;
   2747 	struct devname_ops	*dirops = NULL;
   2748 	int (*fn)(devname_handle_t *, struct cred *) = NULL;
   2749 	int (*vtor)(struct sdev_node *) = NULL;
   2750 	struct vattr attr;
   2751 	timestruc_t now;
   2752 
   2753 	ASSERT(ddv->sdev_attr || ddv->sdev_attrvp);
   2754 	ASSERT(RW_READ_HELD(&ddv->sdev_contents));
   2755 
   2756 	if (uiop->uio_loffset >= MAXOFF_T) {
   2757 		if (eofp)
   2758 			*eofp = 1;
   2759 		return (0);
   2760 	}
   2761 
   2762 	if (uiop->uio_iovcnt != 1)
   2763 		return (EINVAL);
   2764 
   2765 	if (vp->v_type != VDIR)
   2766 		return (ENOTDIR);
   2767 
   2768 	if (ddv->sdev_flags & SDEV_VTOR) {
   2769 		vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
   2770 		ASSERT(vtor);
   2771 	}
   2772 
   2773 	if (eofp != NULL)
   2774 		*eofp = 0;
   2775 
   2776 	soff = uiop->uio_loffset;
   2777 	iovp = uiop->uio_iov;
   2778 	alloc_count = iovp->iov_len;
   2779 	dp = outbuf = kmem_alloc(alloc_count, KM_SLEEP);
   2780 	outcount = 0;
   2781 
   2782 	if (ddv->sdev_state == SDEV_ZOMBIE)
   2783 		goto get_cache;
   2784 
   2785 	if (SDEV_IS_GLOBAL(ddv)) {
   2786 		map = sdev_get_map(ddv, 0);
   2787 		dirops = map ? map->dir_ops : NULL;
   2788 		fn = dirops ? dirops->devnops_readdir : NULL;
   2789 
   2790 		if (map && map->dir_map) {
   2791 			/*
   2792 			 * load the name mapping rule database
   2793 			 * through invoking devfsadm and symlink
   2794 			 * all the entries in the map
   2795 			 */
   2796 			devname_rdr_result_t rdr_result;
   2797 			int do_thread = 0;
   2798 
   2799 			rw_enter(&map->dir_lock, RW_READER);
   2800 			do_thread = map->dir_maploaded ? 0 : 1;
   2801 			rw_exit(&map->dir_lock);
   2802 
   2803 			if (do_thread) {
   2804 				mutex_enter(&ddv->sdev_lookup_lock);
   2805 				SDEV_BLOCK_OTHERS(ddv, SDEV_READDIR);
   2806 				mutex_exit(&ddv->sdev_lookup_lock);
   2807 
   2808 				sdev_dispatch_to_nsrdr_thread(ddv,
   2809 				    map->dir_map, &rdr_result);
   2810 			}
   2811 		} else if ((sdev_boot_state == SDEV_BOOT_STATE_COMPLETE) &&
   2812 		    !sdev_reconfig_boot && (flags & SDEV_BROWSE) &&
   2813 		    !SDEV_IS_DYNAMIC(ddv) && !SDEV_IS_NO_NCACHE(ddv) &&
   2814 		    ((moddebug & MODDEBUG_FINI_EBUSY) == 0) &&
   2815 		    !DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state) &&
   2816 		    !DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) &&
   2817 		    !sdev_reconfig_disable) {
   2818 			/*
   2819 			 * invoking "devfsadm" to do system device reconfig
   2820 			 */
   2821 			mutex_enter(&ddv->sdev_lookup_lock);
   2822 			SDEV_BLOCK_OTHERS(ddv,
   2823 			    (SDEV_READDIR|SDEV_LGWAITING));
   2824 			mutex_exit(&ddv->sdev_lookup_lock);
   2825 
   2826 			sdcmn_err8(("readdir of %s by %s: reconfig\n",
   2827 			    ddv->sdev_path, curproc->p_user.u_comm));
   2828 			if (sdev_reconfig_verbose) {
   2829 				cmn_err(CE_CONT,
   2830 				    "?readdir of %s by %s: reconfig\n",
   2831 				    ddv->sdev_path, curproc->p_user.u_comm);
   2832 			}
   2833 
   2834 			sdev_devfsadmd_thread(ddv, NULL, kcred);
   2835 		} else if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) {
   2836 			/*
   2837 			 * compensate the "ls" started later than "devfsadm"
   2838 			 */
   2839 			mutex_enter(&ddv->sdev_lookup_lock);
   2840 			SDEV_BLOCK_OTHERS(ddv, (SDEV_READDIR|SDEV_LGWAITING));
   2841 			mutex_exit(&ddv->sdev_lookup_lock);
   2842 		}
   2843 
   2844 		/*
   2845 		 * release the contents lock so that
   2846 		 * the cache may be updated by devfsadmd
   2847 		 */
   2848 		rw_exit(&ddv->sdev_contents);
   2849 		mutex_enter(&ddv->sdev_lookup_lock);
   2850 		if (SDEV_IS_READDIR(ddv))
   2851 			(void) sdev_wait4lookup(ddv, SDEV_READDIR);
   2852 		mutex_exit(&ddv->sdev_lookup_lock);
   2853 		rw_enter(&ddv->sdev_contents, RW_READER);
   2854 
   2855 		sdcmn_err4(("readdir of directory %s by %s\n",
   2856 		    ddv->sdev_name, curproc->p_user.u_comm));
   2857 		if (ddv->sdev_flags & SDEV_BUILD) {
   2858 			if (SDEV_IS_PERSIST(ddv)) {
   2859 				error = sdev_filldir_from_store(ddv,
   2860 				    alloc_count, cred);
   2861 			}
   2862 			ddv->sdev_flags &= ~SDEV_BUILD;
   2863 		}
   2864 	}
   2865 
   2866 get_cache:
   2867 	/* handle "." and ".." */
   2868 	diroff = 0;
   2869 	if (soff == 0) {
   2870 		/* first time */
   2871 		this_reclen = DIRENT64_RECLEN(1);
   2872 		if (alloc_count < this_reclen) {
   2873 			error = EINVAL;
   2874 			goto done;
   2875 		}
   2876 
   2877 		dp->d_ino = (ino64_t)ddv->sdev_ino;
   2878 		dp->d_off = (off64_t)1;
   2879 		dp->d_reclen = (ushort_t)this_reclen;
   2880 
   2881 		(void) strncpy(dp->d_name, ".",
   2882 		    DIRENT64_NAMELEN(this_reclen));
   2883 		outcount += dp->d_reclen;
   2884 		dp = nextdp(dp);
   2885 	}
   2886 
   2887 	diroff++;
   2888 	if (soff <= 1) {
   2889 		this_reclen = DIRENT64_RECLEN(2);
   2890 		if (alloc_count < outcount + this_reclen) {
   2891 			error = EINVAL;
   2892 			goto done;
   2893 		}
   2894 
   2895 		dp->d_reclen = (ushort_t)this_reclen;
   2896 		dp->d_ino = (ino64_t)ddv->sdev_dotdot->sdev_ino;
   2897 		dp->d_off = (off64_t)2;
   2898 
   2899 		(void) strncpy(dp->d_name, "..",
   2900 		    DIRENT64_NAMELEN(this_reclen));
   2901 		outcount += dp->d_reclen;
   2902 
   2903 		dp = nextdp(dp);
   2904 	}
   2905 
   2906 
   2907 	/* gets the cache */
   2908 	diroff++;
   2909 	for (dv = SDEV_FIRST_ENTRY(ddv); dv;
   2910 	    dv = SDEV_NEXT_ENTRY(ddv, dv), diroff++) {
   2911 		sdcmn_err3(("sdev_readdir: diroff %lld soff %lld for '%s' \n",
   2912 		    diroff, soff, dv->sdev_name));
   2913 
   2914 		/* bypassing pre-matured nodes */
   2915 		if (diroff < soff || (dv->sdev_state != SDEV_READY)) {
   2916 			sdcmn_err3(("sdev_readdir: pre-mature node  "
   2917 			    "%s\n", dv->sdev_name));
   2918 			continue;
   2919 		}
   2920 
   2921 		/*
   2922 		 * Check validity of node
   2923 		 */
   2924 		if (vtor) {
   2925 			switch (vtor(dv)) {
   2926 			case SDEV_VTOR_VALID:
   2927 				break;
   2928 			case SDEV_VTOR_INVALID:
   2929 			case SDEV_VTOR_SKIP:
   2930 				continue;
   2931 			default:
   2932 				cmn_err(CE_PANIC,
   2933 				    "dev fs: validator failed: %s(%p)\n",
   2934 				    dv->sdev_name, (void *)dv);
   2935 				break;
   2936 			/*NOTREACHED*/
   2937 			}
   2938 		}
   2939 
   2940 		/*
   2941 		 * call back into the module for the validity/bookkeeping
   2942 		 * of this entry
   2943 		 */
   2944 		if (fn) {
   2945 			error = (*fn)(&(dv->sdev_handle), cred);
   2946 			if (error) {
   2947 				sdcmn_err4(("sdev_readdir: module did not "
   2948 				    "validate %s\n", dv->sdev_name));
   2949 				continue;
   2950 			}
   2951 		}
   2952 
   2953 		namelen = strlen(dv->sdev_name);
   2954 		reclen = DIRENT64_RECLEN(namelen);
   2955 		if (outcount + reclen > alloc_count) {
   2956 			goto full;
   2957 		}
   2958 		dp->d_reclen = (ushort_t)reclen;
   2959 		dp->d_ino = (ino64_t)dv->sdev_ino;
   2960 		dp->d_off = (off64_t)diroff + 1;
   2961 		(void) strncpy(dp->d_name, dv->sdev_name,
   2962 		    DIRENT64_NAMELEN(reclen));
   2963 		outcount += reclen;
   2964 		dp = nextdp(dp);
   2965 	}
   2966 
   2967 full:
   2968 	sdcmn_err4(("sdev_readdir: moving %lu bytes: "
   2969 	    "diroff %lld, soff %lld, dv %p\n", outcount, diroff, soff,
   2970 	    (void *)dv));
   2971 
   2972 	if (outcount)
   2973 		error = uiomove(outbuf, outcount, UIO_READ, uiop);
   2974 
   2975 	if (!error) {
   2976 		uiop->uio_loffset = diroff;
   2977 		if (eofp)
   2978 			*eofp = dv ? 0 : 1;
   2979 	}
   2980 
   2981 
   2982 	if (ddv->sdev_attrvp) {
   2983 		gethrestime(&now);
   2984 		attr.va_ctime = now;
   2985 		attr.va_atime = now;
   2986 		attr.va_mask = AT_CTIME|AT_ATIME;
   2987 
   2988 		(void) VOP_SETATTR(ddv->sdev_attrvp, &attr, 0, kcred, NULL);
   2989 	}
   2990 done:
   2991 	kmem_free(outbuf, alloc_count);
   2992 	return (error);
   2993 }
   2994 
   2995 static int
   2996 sdev_modctl_lookup(const char *path, vnode_t **r_vp)
   2997 {
   2998 	vnode_t *vp;
   2999 	vnode_t *cvp;
   3000 	struct sdev_node *svp;
   3001 	char *nm;
   3002 	struct pathname pn;
   3003 	int error;
   3004 	int persisted = 0;
   3005 
   3006 	ASSERT(INGLOBALZONE(curproc));
   3007 
   3008 	if (error = pn_get((char *)path, UIO_SYSSPACE, &pn))
   3009 		return (error);
   3010 	nm = kmem_alloc(MAXNAMELEN, KM_SLEEP);
   3011 
   3012 	vp = rootdir;
   3013 	VN_HOLD(vp);
   3014 
   3015 	while (pn_pathleft(&pn)) {
   3016 		ASSERT(vp->v_type == VDIR || vp->v_type == VLNK);
   3017 		(void) pn_getcomponent(&pn, nm);
   3018 
   3019 		/*
   3020 		 * Deal with the .. special case where we may be
   3021 		 * traversing up across a mount point, to the
   3022 		 * root of this filesystem or global root.
   3023 		 */
   3024 		if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) {
   3025 checkforroot:
   3026 			if (VN_CMP(vp, rootdir)) {
   3027 				nm[1] = 0;
   3028 			} else if (vp->v_flag & VROOT) {
   3029 				vfs_t *vfsp;
   3030 				cvp = vp;
   3031 				vfsp = cvp->v_vfsp;
   3032 				vfs_rlock_wait(vfsp);
   3033 				vp = cvp->v_vfsp->vfs_vnodecovered;
   3034 				if (vp == NULL ||
   3035 				    (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) {
   3036 					vfs_unlock(vfsp);
   3037 					VN_RELE(cvp);
   3038 					error = EIO;
   3039 					break;
   3040 				}
   3041 				VN_HOLD(vp);
   3042 				vfs_unlock(vfsp);
   3043 				VN_RELE(cvp);
   3044 				cvp = NULL;
   3045 				goto checkforroot;
   3046 			}
   3047 		}
   3048 
   3049 		error = VOP_LOOKUP(vp, nm, &cvp, NULL, 0, NULL, kcred, NULL,
   3050 		    NULL, NULL);
   3051 		if (error) {
   3052 			VN_RELE(vp);
   3053 			break;
   3054 		}
   3055 
   3056 		/* traverse mount points encountered on our journey */
   3057 		if (vn_ismntpt(cvp) && (error = traverse(&cvp)) != 0) {
   3058 			VN_RELE(vp);
   3059 			VN_RELE(cvp);
   3060 			break;
   3061 		}
   3062 
   3063 		/*
   3064 		 * symbolic link, can be either relative and absolute
   3065 		 */
   3066 		if ((cvp->v_type == VLNK) && pn_pathleft(&pn)) {
   3067 			struct pathname linkpath;
   3068 			pn_alloc(&linkpath);
   3069 			if (error = pn_getsymlink(cvp, &linkpath, kcred)) {
   3070 				pn_free(&linkpath);
   3071 				break;
   3072 			}
   3073 			if (pn_pathleft(&linkpath) == 0)
   3074 				(void) pn_set(&linkpath, ".");
   3075 			error = pn_insert(&pn, &linkpath, strlen(nm));
   3076 			pn_free(&linkpath);
   3077 			if (pn.pn_pathlen == 0) {
   3078 				VN_RELE(vp);
   3079 				return (ENOENT);
   3080 			}
   3081 			if (pn.pn_path[0] == '/') {
   3082 				pn_skipslash(&pn);
   3083 				VN_RELE(vp);
   3084 				VN_RELE(cvp);
   3085 				vp = rootdir;
   3086 				VN_HOLD(vp);
   3087 			} else {
   3088 				VN_RELE(cvp);
   3089 			}
   3090 			continue;
   3091 		}
   3092 
   3093 		VN_RELE(vp);
   3094 
   3095 		/*
   3096 		 * Direct the operation to the persisting filesystem
   3097 		 * underlying /dev.  Bail if we encounter a
   3098 		 * non-persistent dev entity here.
   3099 		 */
   3100 		if (cvp->v_vfsp->vfs_fstype == devtype) {
   3101 
   3102 			if ((VTOSDEV(cvp)->sdev_flags & SDEV_PERSIST) == 0) {
   3103 				error = ENOENT;
   3104 				VN_RELE(cvp);
   3105 				break;
   3106 			}
   3107 
   3108 			if (VTOSDEV(cvp) == NULL) {
   3109 				error = ENOENT;
   3110 				VN_RELE(cvp);
   3111 				break;
   3112 			}
   3113 			svp = VTOSDEV(cvp);
   3114 			if ((vp = svp->sdev_attrvp) == NULL) {
   3115 				error = ENOENT;
   3116 				VN_RELE(cvp);
   3117 				break;
   3118 			}
   3119 			persisted = 1;
   3120 			VN_HOLD(vp);
   3121 			VN_RELE(cvp);
   3122 			cvp = vp;
   3123 		}
   3124 
   3125 		vp = cvp;
   3126 		pn_skipslash(&pn);
   3127 	}
   3128 
   3129 	kmem_free(nm, MAXNAMELEN);
   3130 	pn_free(&pn);
   3131 
   3132 	if (error)
   3133 		return (error);
   3134 
   3135 	/*
   3136 	 * Only return persisted nodes in the filesystem underlying /dev.
   3137 	 */
   3138 	if (!persisted) {
   3139 		VN_RELE(vp);
   3140 		return (ENOENT);
   3141 	}
   3142 
   3143 	*r_vp = vp;
   3144 	return (0);
   3145 }
   3146 
   3147 int
   3148 sdev_modctl_readdir(const char *dir, char ***dirlistp,
   3149 	int *npathsp, int *npathsp_alloc, int checking_empty)
   3150 {
   3151 	char	**pathlist = NULL;
   3152 	char	**newlist = NULL;
   3153 	int	npaths = 0;
   3154 	int	npaths_alloc = 0;
   3155 	dirent64_t *dbuf = NULL;
   3156 	int	n;
   3157 	char	*s;
   3158 	int error;
   3159 	vnode_t *vp;
   3160 	int eof;
   3161 	struct iovec iov;
   3162 	struct uio uio;
   3163 	struct dirent64 *dp;
   3164 	size_t dlen;
   3165 	size_t dbuflen;
   3166 	int ndirents = 64;
   3167 	char *nm;
   3168 
   3169 	error = sdev_modctl_lookup(dir, &vp);
   3170 	sdcmn_err11(("modctl readdir: %s by %s: %s\n",
   3171 	    dir, curproc->p_user.u_comm,
   3172 	    (error == 0) ? "ok" : "failed"));
   3173 	if (error)
   3174 		return (error);
   3175 
   3176 	dlen = ndirents * (sizeof (*dbuf));
   3177 	dbuf = kmem_alloc(dlen, KM_SLEEP);
   3178 
   3179 	uio.uio_iov = &iov;
   3180 	uio.uio_iovcnt = 1;
   3181 	uio.uio_segflg = UIO_SYSSPACE;
   3182 	uio.uio_fmode = 0;
   3183 	uio.uio_extflg = UIO_COPY_CACHED;
   3184 	uio.uio_loffset = 0;
   3185 	uio.uio_llimit = MAXOFFSET_T;
   3186 
   3187 	eof = 0;
   3188 	error = 0;
   3189 	while (!error && !eof) {
   3190 		uio.uio_resid = dlen;
   3191 		iov.iov_base = (char *)dbuf;
   3192 		iov.iov_len = dlen;
   3193 
   3194 		(void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
   3195 		error = VOP_READDIR(vp, &uio, kcred, &eof, NULL, 0);
   3196 		VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
   3197 
   3198 		dbuflen = dlen - uio.uio_resid;
   3199 
   3200 		if (error || dbuflen == 0)
   3201 			break;
   3202 
   3203 		for (dp = dbuf; ((intptr_t)dp < (intptr_t)dbuf + dbuflen);
   3204 		    dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) {
   3205 
   3206 			nm = dp->d_name;
   3207 
   3208 			if (strcmp(nm, ".") == 0 || strcmp(nm, "..") == 0)
   3209 				continue;
   3210 			if (npaths == npaths_alloc) {
   3211 				npaths_alloc += 64;
   3212 				newlist = (char **)
   3213 				    kmem_zalloc((npaths_alloc + 1) *
   3214 				    sizeof (char *), KM_SLEEP);
   3215 				if (pathlist) {
   3216 					bcopy(pathlist, newlist,
   3217 					    npaths * sizeof (char *));
   3218 					kmem_free(pathlist,
   3219 					    (npaths + 1) * sizeof (char *));
   3220 				}
   3221 				pathlist = newlist;
   3222 			}
   3223 			n = strlen(nm) + 1;
   3224 			s = kmem_alloc(n, KM_SLEEP);
   3225 			bcopy(nm, s, n);
   3226 			pathlist[npaths++] = s;
   3227 			sdcmn_err11(("  %s/%s\n", dir, s));
   3228 
   3229 			/* if checking empty, one entry is as good as many */
   3230 			if (checking_empty) {
   3231 				eof = 1;
   3232 				break;
   3233 			}
   3234 		}
   3235 	}
   3236 
   3237 exit:
   3238 	VN_RELE(vp);
   3239 
   3240 	if (dbuf)
   3241 		kmem_free(dbuf, dlen);
   3242 
   3243 	if (error)
   3244 		return (error);
   3245 
   3246 	*dirlistp = pathlist;
   3247 	*npathsp = npaths;
   3248 	*npathsp_alloc = npaths_alloc;
   3249 
   3250 	return (0);
   3251 }
   3252 
   3253 void
   3254 sdev_modctl_readdir_free(char **pathlist, int npaths, int npaths_alloc)
   3255 {
   3256 	int	i, n;
   3257 
   3258 	for (i = 0; i < npaths; i++) {
   3259 		n = strlen(pathlist[i]) + 1;
   3260 		kmem_free(pathlist[i], n);
   3261 	}
   3262 
   3263 	kmem_free(pathlist, (npaths_alloc + 1) * sizeof (char *));
   3264 }
   3265 
   3266 int
   3267 sdev_modctl_devexists(const char *path)
   3268 {
   3269 	vnode_t *vp;
   3270 	int error;
   3271 
   3272 	error = sdev_modctl_lookup(path, &vp);
   3273 	sdcmn_err11(("modctl dev exists: %s by %s: %s\n",
   3274 	    path, curproc->p_user.u_comm,
   3275 	    (error == 0) ? "ok" : "failed"));
   3276 	if (error == 0)
   3277 		VN_RELE(vp);
   3278 
   3279 	return (error);
   3280 }
   3281 
   3282 void
   3283 sdev_update_newnsmap(struct devname_nsmap *map, char *module, char *mapname)
   3284 {
   3285 	rw_enter(&map->dir_lock, RW_WRITER);
   3286 	if (module) {
   3287 		ASSERT(map->dir_newmodule == NULL);
   3288 		map->dir_newmodule = i_ddi_strdup(module, KM_SLEEP);
   3289 	}
   3290 	if (mapname) {
   3291 		ASSERT(map->dir_newmap == NULL);
   3292 		map->dir_newmap = i_ddi_strdup(mapname, KM_SLEEP);
   3293 	}
   3294 
   3295 	map->dir_invalid = 1;
   3296 	rw_exit(&map->dir_lock);
   3297 }
   3298 
   3299 void
   3300 sdev_replace_nsmap(struct devname_nsmap *map, char *module, char *mapname)
   3301 {
   3302 	char *old_module = NULL;
   3303 	char *old_map = NULL;
   3304 
   3305 	ASSERT(RW_LOCK_HELD(&map->dir_lock));
   3306 	if (!rw_tryupgrade(&map->dir_lock)) {
   3307 		rw_exit(&map->dir_lock);
   3308 		rw_enter(&map->dir_lock, RW_WRITER);
   3309 	}
   3310 
   3311 	old_module = map->dir_module;
   3312 	if (module) {
   3313 		if (old_module && strcmp(old_module, module) != 0) {
   3314 			kmem_free(old_module, strlen(old_module) + 1);
   3315 		}
   3316 		map->dir_module = module;
   3317 		map->dir_newmodule = NULL;
   3318 	}
   3319 
   3320 	old_map = map->dir_map;
   3321 	if (mapname) {
   3322 		if (old_map && strcmp(old_map, mapname) != 0) {
   3323 			kmem_free(old_map, strlen(old_map) + 1);
   3324 		}
   3325 
   3326 		map->dir_map = mapname;
   3327 		map->dir_newmap = NULL;
   3328 	}
   3329 	map->dir_maploaded = 0;
   3330 	map->dir_invalid = 0;
   3331 	rw_downgrade(&map->dir_lock);
   3332 }
   3333 
   3334 /*
   3335  * dir_name should have at least one attribute,
   3336  *	dir_module
   3337  *	or dir_map
   3338  *	or both
   3339  * caller holds the devname_nsmaps_lock
   3340  */
   3341 void
   3342 sdev_insert_nsmap(char *dir_name, char *dir_module, char *dir_map)
   3343 {
   3344 	struct devname_nsmap *map;
   3345 	int len = 0;
   3346 
   3347 	ASSERT(dir_name);
   3348 	ASSERT(dir_module || dir_map);
   3349 	ASSERT(MUTEX_HELD(&devname_nsmaps_lock));
   3350 
   3351 	if (map = sdev_get_nsmap_by_dir(dir_name, 1)) {
   3352 		sdev_update_newnsmap(map, dir_module, dir_map);
   3353 		return;
   3354 	}
   3355 
   3356 	map = (struct devname_nsmap *)kmem_zalloc(sizeof (*map), KM_SLEEP);
   3357 	map->dir_name = i_ddi_strdup(dir_name, KM_SLEEP);
   3358 	if (dir_module) {
   3359 		map->dir_module = i_ddi_strdup(dir_module, KM_SLEEP);
   3360 	}
   3361 
   3362 	if (dir_map) {
   3363 		if (dir_map[0] != '/') {
   3364 			len = strlen(ETC_DEV_DIR) + strlen(dir_map) + 2;
   3365 			map->dir_map = kmem_zalloc(len, KM_SLEEP);
   3366 			(void) snprintf(map->dir_map, len, "%s/%s", ETC_DEV_DIR,
   3367 			    dir_map);
   3368 		} else {
   3369 			map->dir_map = i_ddi_strdup(dir_map, KM_SLEEP);
   3370 		}
   3371 	}
   3372 
   3373 	map->dir_ops = NULL;
   3374 	map->dir_maploaded = 0;
   3375 	map->dir_invalid = 0;
   3376 	rw_init(&map->dir_lock, NULL, RW_DEFAULT, NULL);
   3377 
   3378 	map->next = devname_nsmaps;
   3379 	map->prev = NULL;
   3380 	if (devname_nsmaps) {
   3381 		devname_nsmaps->prev = map;
   3382 	}
   3383 	devname_nsmaps = map;
   3384 }
   3385 
   3386 struct devname_nsmap *
   3387 sdev_get_nsmap_by_dir(char *dir_path, int locked)
   3388 {
   3389 	struct devname_nsmap *map = NULL;
   3390 
   3391 	if (!locked)
   3392 		mutex_enter(&devname_nsmaps_lock);
   3393 	for (map = devname_nsmaps; map; map = map->next) {
   3394 		sdcmn_err6(("sdev_get_nsmap_by_dir: dir %s\n", map->dir_name));
   3395 		if (strcmp(map->dir_name, dir_path) == 0) {
   3396 			if (!locked)
   3397 				mutex_exit(&devname_nsmaps_lock);
   3398 			return (map);
   3399 		}
   3400 	}
   3401 	if (!locked)
   3402 		mutex_exit(&devname_nsmaps_lock);
   3403 	return (NULL);
   3404 }
   3405 
   3406 struct devname_nsmap *
   3407 sdev_get_nsmap_by_module(char *mod_name)
   3408 {
   3409 	struct devname_nsmap *map = NULL;
   3410 
   3411 	mutex_enter(&devname_nsmaps_lock);
   3412 	for (map = devname_nsmaps; map; map = map->next) {
   3413 		sdcmn_err7(("sdev_get_nsmap_by_module: module %s\n",
   3414 		    map->dir_module));
   3415 		if (map->dir_module && strcmp(map->dir_module, mod_name) == 0) {
   3416 			mutex_exit(&devname_nsmaps_lock);
   3417 			return (map);
   3418 		}
   3419 	}
   3420 	mutex_exit(&devname_nsmaps_lock);
   3421 	return (NULL);
   3422 }
   3423 
   3424 void
   3425 sdev_invalidate_nsmaps()
   3426 {
   3427 	struct devname_nsmap *map = NULL;
   3428 
   3429 	ASSERT(MUTEX_HELD(&devname_nsmaps_lock));
   3430 
   3431 	if (devname_nsmaps == NULL)
   3432 		return;
   3433 
   3434 	for (map = devname_nsmaps; map; map = map->next) {
   3435 		rw_enter(&map->dir_lock, RW_WRITER);
   3436 		map->dir_invalid = 1;
   3437 		rw_exit(&map->dir_lock);
   3438 	}
   3439 	devname_nsmaps_invalidated = 1;
   3440 }
   3441 
   3442 
   3443 int
   3444 sdev_nsmaps_loaded()
   3445 {
   3446 	int ret = 0;
   3447 
   3448 	mutex_enter(&devname_nsmaps_lock);
   3449 	if (devname_nsmaps_loaded)
   3450 		ret = 1;
   3451 
   3452 	mutex_exit(&devname_nsmaps_lock);
   3453 	return (ret);
   3454 }
   3455 
   3456 int
   3457 sdev_nsmaps_reloaded()
   3458 {
   3459 	int ret = 0;
   3460 
   3461 	mutex_enter(&devname_nsmaps_lock);
   3462 	if (devname_nsmaps_invalidated)
   3463 		ret = 1;
   3464 
   3465 	mutex_exit(&devname_nsmaps_lock);
   3466 	return (ret);
   3467 }
   3468 
   3469 static void
   3470 sdev_free_nsmap(struct devname_nsmap *map)
   3471 {
   3472 	ASSERT(map);
   3473 	if (map->dir_name)
   3474 		kmem_free(map->dir_name, strlen(map->dir_name) + 1);
   3475 	if (map->dir_module)
   3476 		kmem_free(map->dir_module, strlen(map->dir_module) + 1);
   3477 	if (map->dir_map)
   3478 		kmem_free(map->dir_map, strlen(map->dir_map) + 1);
   3479 	rw_destroy(&map->dir_lock);
   3480 	kmem_free(map, sizeof (*map));
   3481 }
   3482 
   3483 void
   3484 sdev_validate_nsmaps()
   3485 {
   3486 	struct devname_nsmap *map = NULL;
   3487 	struct devname_nsmap *oldmap = NULL;
   3488 
   3489 	ASSERT(MUTEX_HELD(&devname_nsmaps_lock));
   3490 	map = devname_nsmaps;
   3491 	while (map) {
   3492 		rw_enter(&map->dir_lock, RW_READER);
   3493 		if ((map->dir_invalid == 1) && (map->dir_newmodule == NULL) &&
   3494 		    (map->dir_newmap == NULL)) {
   3495 			oldmap = map;
   3496 			rw_exit(&map->dir_lock);
   3497 			if (map->prev)
   3498 				map->prev->next = oldmap->next;
   3499 			if (map == devname_nsmaps)
   3500 				devname_nsmaps = oldmap->next;
   3501 
   3502 			map = oldmap->next;
   3503 			if (map)
   3504 				map->prev = oldmap->prev;
   3505 			sdev_free_nsmap(oldmap);
   3506 			oldmap = NULL;
   3507 		} else {
   3508 			rw_exit(&map->dir_lock);
   3509 			map = map->next;
   3510 		}
   3511 	}
   3512 	devname_nsmaps_invalidated = 0;
   3513 }
   3514 
   3515 static int
   3516 sdev_map_is_invalid(struct devname_nsmap *map)
   3517 {
   3518 	int ret = 0;
   3519 
   3520 	ASSERT(map);
   3521 	rw_enter(&map->dir_lock, RW_READER);
   3522 	if (map->dir_invalid)
   3523 		ret = 1;
   3524 	rw_exit(&map->dir_lock);
   3525 	return (ret);
   3526 }
   3527 
   3528 static int
   3529 sdev_check_map(struct devname_nsmap *map)
   3530 {
   3531 	struct devname_nsmap *mapp;
   3532 
   3533 	mutex_enter(&devname_nsmaps_lock);
   3534 	if (devname_nsmaps == NULL) {
   3535 		mutex_exit(&devname_nsmaps_lock);
   3536 		return (1);
   3537 	}
   3538 
   3539 	for (mapp = devname_nsmaps; mapp; mapp = mapp->next) {
   3540 		if (mapp == map) {
   3541 			mutex_exit(&devname_nsmaps_lock);
   3542 			return (0);
   3543 		}
   3544 	}
   3545 
   3546 	mutex_exit(&devname_nsmaps_lock);
   3547 	return (1);
   3548 
   3549 }
   3550 
   3551 struct devname_nsmap *
   3552 sdev_get_map(struct sdev_node *dv, int validate)
   3553 {
   3554 	struct devname_nsmap *map;
   3555 	int error;
   3556 
   3557 	ASSERT(RW_READ_HELD(&dv->sdev_contents));
   3558 	map = dv->sdev_mapinfo;
   3559 	if (map && sdev_check_map(map)) {
   3560 		if (!rw_tryupgrade(&dv->sdev_contents)) {
   3561 			rw_exit(&dv->sdev_contents);
   3562 			rw_enter(&dv->sdev_contents, RW_WRITER);
   3563 		}
   3564 		dv->sdev_mapinfo = NULL;
   3565 		rw_downgrade(&dv->sdev_contents);
   3566 		return (NULL);
   3567 	}
   3568 
   3569 	if (validate && (!map || (map && sdev_map_is_invalid(map)))) {
   3570 		if (!rw_tryupgrade(&dv->sdev_contents)) {
   3571 			rw_exit(&dv->sdev_contents);
   3572 			rw_enter(&dv->sdev_contents, RW_WRITER);
   3573 		}
   3574 		error = sdev_get_moduleops(dv);
   3575 		if (!error)
   3576 			map = dv->sdev_mapinfo;
   3577 		rw_downgrade(&dv->sdev_contents);
   3578 	}
   3579 	return (map);
   3580 }
   3581 
   3582 extern int sdev_vnodeops_tbl_size;
   3583 
   3584 /*
   3585  * construct a new template with overrides from vtab
   3586  */
   3587 static fs_operation_def_t *
   3588 sdev_merge_vtab(const fs_operation_def_t tab[])
   3589 {
   3590 	fs_operation_def_t *new;
   3591 	const fs_operation_def_t *tab_entry;
   3592 
   3593 	/* make a copy of standard vnode ops table */
   3594 	new = kmem_alloc(sdev_vnodeops_tbl_size, KM_SLEEP);
   3595 	bcopy((void *)sdev_vnodeops_tbl, new, sdev_vnodeops_tbl_size);
   3596 
   3597 	/* replace the overrides from tab */
   3598 	for (tab_entry = tab; tab_entry->name != NULL; tab_entry++) {
   3599 		fs_operation_def_t *std_entry = new;
   3600 		while (std_entry->name) {
   3601 			if (strcmp(tab_entry->name, std_entry->name) == 0) {
   3602 				std_entry->func = tab_entry->func;
   3603 				break;
   3604 			}
   3605 			std_entry++;
   3606 		}
   3607 		if (std_entry->name == NULL)
   3608 			cmn_err(CE_NOTE, "sdev_merge_vtab: entry %s unused.",
   3609 			    tab_entry->name);
   3610 	}
   3611 
   3612 	return (new);
   3613 }
   3614 
   3615 /* free memory allocated by sdev_merge_vtab */
   3616 static void
   3617 sdev_free_vtab(fs_operation_def_t *new)
   3618 {
   3619 	kmem_free(new, sdev_vnodeops_tbl_size);
   3620 }
   3621 
   3622 void
   3623 devname_get_vnode(devname_handle_t *hdl, vnode_t **vpp)
   3624 {
   3625 	struct sdev_node *dv = hdl->dh_data;
   3626 
   3627 	ASSERT(dv);
   3628 
   3629 	rw_enter(&dv->sdev_contents, RW_READER);
   3630 	*vpp = SDEVTOV(dv);
   3631 	rw_exit(&dv->sdev_contents);
   3632 }
   3633 
   3634 int
   3635 devname_get_path(devname_handle_t *hdl, char **path)
   3636 {
   3637 	struct sdev_node *dv = hdl->dh_data;
   3638 
   3639 	ASSERT(dv);
   3640 
   3641 	rw_enter(&dv->sdev_contents, RW_READER);
   3642 	*path = dv->sdev_path;
   3643 	rw_exit(&dv->sdev_contents);
   3644 	return (0);
   3645 }
   3646 
   3647 int
   3648 devname_get_name(devname_handle_t *hdl, char **entry)
   3649 {
   3650 	struct sdev_node *dv = hdl->dh_data;
   3651 
   3652 	ASSERT(dv);
   3653 	rw_enter(&dv->sdev_contents, RW_READER);
   3654 	*entry = dv->sdev_name;
   3655 	rw_exit(&dv->sdev_contents);
   3656 	return (0);
   3657 }
   3658 
   3659 void
   3660 devname_get_dir_vnode(devname_handle_t *hdl, vnode_t **vpp)
   3661 {
   3662 	struct sdev_node *dv = hdl->dh_data->sdev_dotdot;
   3663 
   3664 	ASSERT(dv);
   3665 
   3666 	rw_enter(&dv->sdev_contents, RW_READER);
   3667 	*vpp = SDEVTOV(dv);
   3668 	rw_exit(&dv->sdev_contents);
   3669 }
   3670 
   3671 int
   3672 devname_get_dir_path(devname_handle_t *hdl, char **path)
   3673 {
   3674 	struct sdev_node *dv = hdl->dh_data->sdev_dotdot;
   3675 
   3676 	ASSERT(dv);
   3677 	rw_enter(&dv->sdev_contents, RW_READER);
   3678 	*path = dv->sdev_path;
   3679 	rw_exit(&dv->sdev_contents);
   3680 	return (0);
   3681 }
   3682 
   3683 int
   3684 devname_get_dir_name(devname_handle_t *hdl, char **entry)
   3685 {
   3686 	struct sdev_node *dv = hdl->dh_data->sdev_dotdot;
   3687 
   3688 	ASSERT(dv);
   3689 	rw_enter(&dv->sdev_contents, RW_READER);
   3690 	*entry = dv->sdev_name;
   3691 	rw_exit(&dv->sdev_contents);
   3692 	return (0);
   3693 }
   3694 
   3695 int
   3696 devname_get_dir_nsmap(devname_handle_t *hdl, struct devname_nsmap **map)
   3697 {
   3698 	struct sdev_node *dv = hdl->dh_data->sdev_dotdot;
   3699 
   3700 	ASSERT(dv);
   3701 	rw_enter(&dv->sdev_contents, RW_READER);
   3702 	*map = dv->sdev_mapinfo;
   3703 	rw_exit(&dv->sdev_contents);
   3704 	return (0);
   3705 }
   3706 
   3707 int
   3708 devname_get_dir_handle(devname_handle_t *hdl, devname_handle_t **dir_hdl)
   3709 {
   3710 	struct sdev_node *dv = hdl->dh_data->sdev_dotdot;
   3711 
   3712 	ASSERT(dv);
   3713 	rw_enter(&dv->sdev_contents, RW_READER);
   3714 	*dir_hdl = &(dv->sdev_handle);
   3715 	rw_exit(&dv->sdev_contents);
   3716 	return (0);
   3717 }
   3718 
   3719 void
   3720 devname_set_nodetype(devname_handle_t *hdl, void *args, int spec)
   3721 {
   3722 	struct sdev_node *dv = hdl->dh_data;
   3723 
   3724 	ASSERT(dv);
   3725 	rw_enter(&dv->sdev_contents, RW_WRITER);
   3726 	hdl->dh_spec = (devname_spec_t)spec;
   3727 	hdl->dh_args = (void *)i_ddi_strdup((char *)args, KM_SLEEP);
   3728 	rw_exit(&dv->sdev_contents);
   3729 }
   3730 
   3731 /*
   3732  * a generic setattr() function
   3733  *
   3734  * note: flags only supports AT_UID and AT_GID.
   3735  *	 Future enhancements can be done for other types, e.g. AT_MODE
   3736  */
   3737 int
   3738 devname_setattr_func(struct vnode *vp, struct vattr *vap, int flags,
   3739     struct cred *cred, int (*callback)(struct sdev_node *, struct vattr *,
   3740     int), int protocol)
   3741 {
   3742 	struct sdev_node	*dv = VTOSDEV(vp);
   3743 	struct sdev_node	*parent = dv->sdev_dotdot;
   3744 	struct vattr		*get;
   3745 	uint_t			mask = vap->va_mask;
   3746 	int 			error;
   3747 
   3748 	/* some sanity checks */
   3749 	if (vap->va_mask & AT_NOSET)
   3750 		return (EINVAL);
   3751 
   3752 	if (vap->va_mask & AT_SIZE) {
   3753 		if (vp->v_type == VDIR) {
   3754 			return (EISDIR);
   3755 		}
   3756 	}
   3757 
   3758 	/* no need to set attribute, but do not fail either */
   3759 	ASSERT(parent);
   3760 	rw_enter(&parent->sdev_contents, RW_READER);
   3761 	if (dv->sdev_state == SDEV_ZOMBIE) {
   3762 		rw_exit(&parent->sdev_contents);
   3763 		return (0);
   3764 	}
   3765 
   3766 	/* If backing store exists, just set it. */
   3767 	if (dv->sdev_attrvp) {
   3768 		rw_exit(&parent->sdev_contents);
   3769 		return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL));
   3770 	}
   3771 
   3772 	/*
   3773 	 * Otherwise, for nodes with the persistence attribute, create it.
   3774 	 */
   3775 	ASSERT(dv->sdev_attr);
   3776 	if (SDEV_IS_PERSIST(dv) ||
   3777 	    ((vap->va_mask & ~AT_TIMES) != 0 && !SDEV_IS_DYNAMIC(dv))) {
   3778 		sdev_vattr_merge(dv, vap);
   3779 		rw_enter(&dv->sdev_contents, RW_WRITER);
   3780 		error = sdev_shadow_node(dv, cred);
   3781 		rw_exit(&dv->sdev_contents);
   3782 		rw_exit(&parent->sdev_contents);
   3783 
   3784 		if (error)
   3785 			return (error);
   3786 		return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL));
   3787 	}
   3788 
   3789 
   3790 	/*
   3791 	 * sdev_attr was allocated in sdev_mknode
   3792 	 */
   3793 	rw_enter(&dv->sdev_contents, RW_WRITER);
   3794 	error = secpolicy_vnode_setattr(cred, vp, vap,
   3795 	    dv->sdev_attr, flags, sdev_unlocked_access, dv);
   3796 	if (error) {
   3797 		rw_exit(&dv->sdev_contents);
   3798 		rw_exit(&parent->sdev_contents);
   3799 		return (error);
   3800 	}
   3801 
   3802 	get = dv->sdev_attr;
   3803 	if (mask & AT_MODE) {
   3804 		get->va_mode &= S_IFMT;
   3805 		get->va_mode |= vap->va_mode & ~S_IFMT;
   3806 	}
   3807 
   3808 	if ((mask & AT_UID) || (mask & AT_GID)) {
   3809 		if (mask & AT_UID)
   3810 			get->va_uid = vap->va_uid;
   3811 		if (mask & AT_GID)
   3812 			get->va_gid = vap->va_gid;
   3813 		/*
   3814 		 * a callback must be provided if the protocol is set
   3815 		 */
   3816 		if ((protocol & AT_UID) || (protocol & AT_GID)) {
   3817 			ASSERT(callback);
   3818 			error = callback(dv, get, protocol);
   3819 			if (error) {
   3820 				rw_exit(&dv->sdev_contents);
   3821 				rw_exit(&parent->sdev_contents);
   3822 				return (error);
   3823 			}
   3824 		}
   3825 	}
   3826 
   3827 	if (mask & AT_ATIME)
   3828 		get->va_atime = vap->va_atime;
   3829 	if (mask & AT_MTIME)
   3830 		get->va_mtime = vap->va_mtime;
   3831 	if (mask & (AT_MODE | AT_UID | AT_GID | AT_CTIME)) {
   3832 		gethrestime(&get->va_ctime);
   3833 	}
   3834 
   3835 	sdev_vattr_merge(dv, get);
   3836 	rw_exit(&dv->sdev_contents);
   3837 	rw_exit(&parent->sdev_contents);
   3838 	return (0);
   3839 }
   3840 
   3841 /*
   3842  * a generic inactive() function
   3843  */
   3844 void
   3845 devname_inactive_func(struct vnode *vp, struct cred *cred,
   3846     void (*callback)(struct vnode *))
   3847 {
   3848 	int clean;
   3849 	struct