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