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.
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.
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]
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2018 by Delphix. All rights reserved.
27 #include <sys/t_lock.h>
28 #include <sys/cmn_err.h>
29 #include <sys/instance.h>
33 #include <sys/hwconf.h>
34 #include <sys/sunddi.h>
35 #include <sys/sunndi.h>
36 #include <sys/sunmdi.h>
37 #include <sys/ddi_impldefs.h>
38 #include <sys/ndi_impldefs.h>
40 #include <sys/devcache.h>
41 #include <sys/devid_cache.h>
42 #include <sys/sysmacros.h>
45 * Discovery refers to the heroic effort made to discover a device which
46 * cannot be accessed at the physical path where it once resided. Discovery
47 * involves walking the entire device tree attaching all possible disk
48 * instances, to search for the device referenced by a devid. Obviously,
49 * full device discovery is something to be avoided where possible.
50 * Note that simply invoking devfsadm(8) is equivalent to running full
51 * discovery at the devid cache level.
53 * Reasons why a disk may not be accessible:
55 * disk removed or cable disconnected
56 * disk or adapter broken
58 * Note that discovery is not needed and cannot succeed in any of these
61 * When discovery may succeed:
62 * Discovery will result in success when a device has been moved
63 * to a different address. Note that it's recommended that
64 * devfsadm(8) be invoked (no arguments required) whenever a system's
65 * h/w configuration has been updated. Alternatively, a
66 * reconfiguration boot can be used to accomplish the same result.
68 * Note that discovery is not necessary to be able to correct an access
69 * failure for a device which was powered off. Assuming the cache has an
70 * entry for such a device, simply powering it on should permit the system
71 * to access it. If problems persist after powering it on, invoke
74 * Discovery prior to mounting root is only of interest when booting
75 * from a filesystem which accesses devices by device id, which of
80 * devid_discovery_boot (default 1)
81 * Number of times discovery will be attempted prior to mounting root.
82 * Must be done at least once to recover from corrupted or missing
83 * devid cache backing store. Probably there's no reason to ever
84 * set this to greater than one as a missing device will remain
85 * unavailable no matter how often the system searches for it.
87 * devid_discovery_postboot (default 1)
88 * Number of times discovery will be attempted after mounting root.
89 * This must be performed at least once to discover any devices
90 * needed after root is mounted which may have been powered
91 * off and moved before booting.
92 * Setting this to a larger positive number will introduce
93 * some inconsistency in system operation. Searching for a device
94 * will take an indeterminate amount of time, sometimes slower,
95 * sometimes faster. In addition, the system will sometimes
96 * discover a newly powered on device, sometimes it won't.
97 * Use of this option is not therefore recommended.
99 * devid_discovery_postboot_always (default 0)
100 * Set to 1, the system will always attempt full discovery.
102 * devid_discovery_secs (default 0)
103 * Set to a positive value, the system will attempt full discovery
104 * but with a minimum delay between attempts. A device search
105 * within the period of time specified will result in failure.
107 * devid_cache_read_disable (default 0)
108 * Set to 1 to disable reading /etc/devices/devid_cache.
109 * Devid cache will continue to operate normally but
110 * at least one discovery attempt will be required.
112 * devid_cache_write_disable (default 0)
113 * Set to 1 to disable updates to /etc/devices/devid_cache.
114 * Any updates to the devid cache will not be preserved across a reboot.
116 * devid_report_error (default 0)
117 * Set to 1 to enable some error messages related to devid
120 * The devid is packed in the cache file as a byte array. For
121 * portability, this could be done in the encoded string format.
125 int devid_discovery_boot
= 1;
126 int devid_discovery_postboot
= 1;
127 int devid_discovery_postboot_always
= 0;
128 int devid_discovery_secs
= 0;
130 int devid_cache_read_disable
= 0;
131 int devid_cache_write_disable
= 0;
133 int devid_report_error
= 0;
137 * State to manage discovery of devices providing a devid
139 static int devid_discovery_busy
= 0;
140 static kmutex_t devid_discovery_mutex
;
141 static kcondvar_t devid_discovery_cv
;
142 static clock_t devid_last_discovery
= 0;
146 int nvp_devid_debug
= 0;
148 int devid_log_registers
= 0;
149 int devid_log_finds
= 0;
150 int devid_log_lookups
= 0;
151 int devid_log_discovery
= 0;
152 int devid_log_matches
= 0;
153 int devid_log_paths
= 0;
154 int devid_log_failures
= 0;
155 int devid_log_hold
= 0;
156 int devid_log_unregisters
= 0;
157 int devid_log_removes
= 0;
158 int devid_register_debug
= 0;
159 int devid_log_stale
= 0;
160 int devid_log_detaches
= 0;
164 * devid cache file registration for cache reads and updates
166 static nvf_ops_t devid_cache_ops
= {
167 "/etc/devices/devid_cache", /* path to cache */
168 devid_cache_unpack_nvlist
, /* read: nvlist to nvp */
169 devid_cache_pack_list
, /* write: nvp to nvlist */
170 devid_list_free
, /* free data list */
171 NULL
/* write complete callback */
175 * handle to registered devid cache handlers
177 nvf_handle_t dcfd_handle
;
181 * Initialize devid cache file management
184 devid_cache_init(void)
186 dcfd_handle
= nvf_register_file(&devid_cache_ops
);
189 list_create(nvf_list(dcfd_handle
), sizeof (nvp_devid_t
),
190 offsetof(nvp_devid_t
, nvp_link
));
192 mutex_init(&devid_discovery_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
193 cv_init(&devid_discovery_cv
, NULL
, CV_DRIVER
, NULL
);
197 * Read and initialize the devid cache from the persistent store
200 devid_cache_read(void)
202 if (!devid_cache_read_disable
) {
203 rw_enter(nvf_lock(dcfd_handle
), RW_WRITER
);
204 ASSERT(list_head(nvf_list(dcfd_handle
)) == NULL
);
205 (void) nvf_read_file(dcfd_handle
);
206 rw_exit(nvf_lock(dcfd_handle
));
211 devid_nvp_free(nvp_devid_t
*dp
)
214 kmem_free(dp
->nvp_devpath
, strlen(dp
->nvp_devpath
)+1);
216 kmem_free(dp
->nvp_devid
, ddi_devid_sizeof(dp
->nvp_devid
));
218 kmem_free(dp
, sizeof (nvp_devid_t
));
222 devid_list_free(nvf_handle_t fd
)
227 ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle
)));
229 listp
= nvf_list(fd
);
230 while (np
= list_head(listp
)) {
231 list_remove(listp
, np
);
237 * Free an nvp element in a list
240 devid_nvp_unlink_and_free(nvf_handle_t fd
, nvp_devid_t
*np
)
242 list_remove(nvf_list(fd
), np
);
247 * Unpack a device path/nvlist pair to the list of devid cache elements.
248 * Used to parse the nvlist format when reading
249 * /etc/devices/devid_cache
252 devid_cache_unpack_nvlist(nvf_handle_t fd
, nvlist_t
*nvl
, char *name
)
259 NVP_DEVID_DEBUG_PATH((name
));
260 ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle
)));
263 * check path for a devid
265 rval
= nvlist_lookup_byte_array(nvl
,
266 DP_DEVID_ID
, (uchar_t
**)&devidp
, &n
);
268 if (ddi_devid_valid(devidp
) == DDI_SUCCESS
) {
269 ASSERT(n
== ddi_devid_sizeof(devidp
));
270 np
= kmem_zalloc(sizeof (nvp_devid_t
), KM_SLEEP
);
271 np
->nvp_devpath
= i_ddi_strdup(name
, KM_SLEEP
);
272 np
->nvp_devid
= kmem_alloc(n
, KM_SLEEP
);
273 (void) bcopy(devidp
, np
->nvp_devid
, n
);
274 list_insert_tail(nvf_list(fd
), np
);
275 NVP_DEVID_DEBUG_DEVID((np
->nvp_devid
));
278 "%s: invalid devid\n", name
));
282 "%s: devid not available\n", name
));
289 * Pack the list of devid cache elements into a single nvlist
290 * Used when writing the nvlist file.
293 devid_cache_pack_list(nvf_handle_t fd
, nvlist_t
**ret_nvl
)
295 nvlist_t
*nvl
, *sub_nvl
;
300 ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle
)));
302 rval
= nvlist_alloc(&nvl
, NV_UNIQUE_NAME
, KM_SLEEP
);
304 nvf_error("%s: nvlist alloc error %d\n",
305 nvf_cache_name(fd
), rval
);
306 return (DDI_FAILURE
);
309 listp
= nvf_list(fd
);
310 for (np
= list_head(listp
); np
; np
= list_next(listp
, np
)) {
311 if (np
->nvp_devid
== NULL
)
313 NVP_DEVID_DEBUG_PATH(np
->nvp_devpath
);
314 rval
= nvlist_alloc(&sub_nvl
, NV_UNIQUE_NAME
, KM_SLEEP
);
316 nvf_error("%s: nvlist alloc error %d\n",
317 nvf_cache_name(fd
), rval
);
322 rval
= nvlist_add_byte_array(sub_nvl
, DP_DEVID_ID
,
323 (uchar_t
*)np
->nvp_devid
,
324 ddi_devid_sizeof(np
->nvp_devid
));
326 NVP_DEVID_DEBUG_DEVID(np
->nvp_devid
);
329 "%s: nvlist add error %d (devid)\n",
330 nvf_cache_name(fd
), rval
);
334 rval
= nvlist_add_nvlist(nvl
, np
->nvp_devpath
, sub_nvl
);
336 nvf_error("%s: nvlist add error %d (sublist)\n",
337 nvf_cache_name(fd
), rval
);
340 nvlist_free(sub_nvl
);
344 return (DDI_SUCCESS
);
347 nvlist_free(sub_nvl
);
350 return (DDI_FAILURE
);
354 e_devid_do_discovery(void)
356 ASSERT(mutex_owned(&devid_discovery_mutex
));
358 if (i_ddi_io_initialized() == 0) {
359 if (devid_discovery_boot
> 0) {
360 devid_discovery_boot
--;
364 if (devid_discovery_postboot_always
> 0)
366 if (devid_discovery_postboot
> 0) {
367 devid_discovery_postboot
--;
370 if (devid_discovery_secs
> 0) {
371 if ((ddi_get_lbolt() - devid_last_discovery
) >
372 drv_usectohz(devid_discovery_secs
* MICROSEC
)) {
378 DEVID_LOG_DISC((CE_CONT
, "devid_discovery: no discovery\n"));
383 e_ddi_devid_hold_by_major(major_t major
)
385 DEVID_LOG_DISC((CE_CONT
,
386 "devid_discovery: ddi_hold_installed_driver %d\n", major
));
388 if (ddi_hold_installed_driver(major
) == NULL
)
391 ddi_rele_driver(major
);
394 /* legacy support - see below */
395 static char *e_ddi_devid_hold_driver_list
[] = { "sd", "ssd" };
397 #define N_DRIVERS_TO_HOLD \
398 (sizeof (e_ddi_devid_hold_driver_list) / sizeof (char *))
401 e_ddi_devid_hold_installed_driver(ddi_devid_t devid
)
403 impl_devid_t
*id
= (impl_devid_t
*)devid
;
404 major_t major
, hint_major
;
405 char hint
[DEVID_HINT_SIZE
+ 1];
406 struct devnames
*dnp
;
410 /* Count non-null bytes */
411 for (i
= 0; i
< DEVID_HINT_SIZE
; i
++)
412 if (id
->did_driver
[i
] == '\0')
415 /* Make a copy of the driver hint */
416 bcopy(id
->did_driver
, hint
, i
);
419 /* search for the devid using the hint driver */
420 hint_major
= ddi_name_to_major(hint
);
421 if (hint_major
!= DDI_MAJOR_T_NONE
) {
422 e_ddi_devid_hold_by_major(hint_major
);
426 * search for the devid with each driver declaring
427 * itself as a devid registrant.
429 for (major
= 0; major
< devcnt
; major
++) {
430 if (major
== hint_major
)
432 dnp
= &devnamesp
[major
];
433 if (dnp
->dn_flags
& DN_DEVID_REGISTRANT
) {
434 e_ddi_devid_hold_by_major(major
);
439 * Legacy support: may be removed once an upgrade mechanism
440 * for driver conf files is available.
442 drvp
= e_ddi_devid_hold_driver_list
;
443 for (i
= 0; i
< N_DRIVERS_TO_HOLD
; i
++, drvp
++) {
444 major
= ddi_name_to_major(*drvp
);
445 if (major
!= DDI_MAJOR_T_NONE
&& major
!= hint_major
) {
446 e_ddi_devid_hold_by_major(major
);
452 * Return success if discovery was attempted, to indicate
453 * that the desired device may now be available.
456 e_ddi_devid_discovery(ddi_devid_t devid
)
459 int rval
= DDI_SUCCESS
;
461 mutex_enter(&devid_discovery_mutex
);
463 if (devid_discovery_busy
) {
464 DEVID_LOG_DISC((CE_CONT
, "devid_discovery: busy\n"));
465 while (devid_discovery_busy
) {
466 cv_wait(&devid_discovery_cv
, &devid_discovery_mutex
);
468 } else if (e_devid_do_discovery()) {
469 devid_discovery_busy
= 1;
470 mutex_exit(&devid_discovery_mutex
);
472 if (i_ddi_io_initialized() == 0) {
473 e_ddi_devid_hold_installed_driver(devid
);
475 DEVID_LOG_DISC((CE_CONT
,
476 "devid_discovery: ndi_devi_config\n"));
477 flags
= NDI_DEVI_PERSIST
| NDI_CONFIG
| NDI_NO_EVENT
;
478 if (i_ddi_io_initialized())
479 flags
|= NDI_DRV_CONF_REPROBE
;
480 (void) ndi_devi_config(ddi_root_node(), flags
);
483 mutex_enter(&devid_discovery_mutex
);
484 devid_discovery_busy
= 0;
485 cv_broadcast(&devid_discovery_cv
);
486 if (devid_discovery_secs
> 0)
487 devid_last_discovery
= ddi_get_lbolt();
488 DEVID_LOG_DISC((CE_CONT
, "devid_discovery: done\n"));
491 DEVID_LOG_DISC((CE_CONT
, "no devid discovery\n"));
494 mutex_exit(&devid_discovery_mutex
);
500 * As part of registering a devid for a device,
501 * update the devid cache with this device/devid pair
502 * or note that this combination has registered.
504 * If a devpath is provided it will be used as the path to register the
505 * devid against, otherwise we use ddi_pathname(dip). In both cases
506 * we duplicate the path string so that it can be cached/freed indepdently
507 * of the original owner.
510 e_devid_cache_register_cmn(dev_info_t
*dip
, ddi_devid_t devid
, char *devpath
)
513 nvp_devid_t
*new_nvp
;
514 ddi_devid_t new_devid
;
516 char *path
, *fullpath
;
517 ddi_devid_t free_devid
= NULL
;
523 ASSERT(ddi_devid_valid(devid
) == DDI_SUCCESS
);
526 pathlen
= strlen(devpath
) + 1;
527 path
= kmem_alloc(pathlen
, KM_SLEEP
);
528 bcopy(devpath
, path
, pathlen
);
531 * We are willing to accept DS_BOUND nodes if we can form a full
532 * ddi_pathname (i.e. the node is part way to becomming
533 * DS_INITIALIZED and devi_addr/ddi_get_name_addr are non-NULL).
535 if (ddi_get_name_addr(dip
) == NULL
)
536 return (DDI_FAILURE
);
538 fullpath
= kmem_alloc(MAXPATHLEN
, KM_SLEEP
);
539 (void) ddi_pathname(dip
, fullpath
);
540 pathlen
= strlen(fullpath
) + 1;
541 path
= kmem_alloc(pathlen
, KM_SLEEP
);
542 bcopy(fullpath
, path
, pathlen
);
543 kmem_free(fullpath
, MAXPATHLEN
);
546 DEVID_LOG_REG(("register", devid
, path
));
548 new_nvp
= kmem_zalloc(sizeof (nvp_devid_t
), KM_SLEEP
);
549 new_devid_size
= ddi_devid_sizeof(devid
);
550 new_devid
= kmem_alloc(new_devid_size
, KM_SLEEP
);
551 (void) bcopy(devid
, new_devid
, new_devid_size
);
553 rw_enter(nvf_lock(dcfd_handle
), RW_WRITER
);
555 listp
= nvf_list(dcfd_handle
);
556 for (np
= list_head(listp
); np
; np
= list_next(listp
, np
)) {
557 if (strcmp(path
, np
->nvp_devpath
) == 0) {
558 DEVID_DEBUG2((CE_CONT
,
559 "register: %s path match\n", path
));
560 if (np
->nvp_devid
== NULL
) {
561 replace
: np
->nvp_devid
= new_devid
;
563 NVP_DEVID_DIP
| NVP_DEVID_REGISTERED
;
565 if (!devid_cache_write_disable
) {
566 nvf_mark_dirty(dcfd_handle
);
569 rw_exit(nvf_lock(dcfd_handle
));
570 kmem_free(new_nvp
, sizeof (nvp_devid_t
));
571 kmem_free(path
, pathlen
);
574 if (ddi_devid_valid(np
->nvp_devid
) != DDI_SUCCESS
) {
575 /* replace invalid devid */
576 free_devid
= np
->nvp_devid
;
580 * We're registering an already-cached path
581 * Does the device's devid match the cache?
583 if (ddi_devid_compare(devid
, np
->nvp_devid
) != 0) {
584 DEVID_DEBUG((CE_CONT
, "devid register: "
585 "devid %s does not match\n", path
));
587 * We do not expect devids to change, log it.
590 ddi_devid_str_encode(np
->nvp_devid
, NULL
);
592 ddi_devid_str_encode(devid
, NULL
);
594 cmn_err(CE_CONT
, "devid register: devid for "
595 "%s does not match. stored: %s, new: %s.",
596 path
, devid_stored
, devid_new
);
598 ddi_devid_str_free(devid_stored
);
599 ddi_devid_str_free(devid_new
);
602 * Replace cached devid for this path
603 * with newly registered devid. A devid
604 * may map to multiple paths but one path
605 * should only map to one devid.
607 devid_nvp_unlink_and_free(dcfd_handle
, np
);
611 DEVID_DEBUG2((CE_CONT
,
612 "devid register: %s devid match\n", path
));
614 NVP_DEVID_DIP
| NVP_DEVID_REGISTERED
;
616 rw_exit(nvf_lock(dcfd_handle
));
617 kmem_free(new_nvp
, sizeof (nvp_devid_t
));
618 kmem_free(path
, pathlen
);
619 kmem_free(new_devid
, new_devid_size
);
620 return (DDI_SUCCESS
);
626 * Add newly registered devid to the cache
630 new_nvp
->nvp_devpath
= path
;
631 new_nvp
->nvp_flags
= NVP_DEVID_DIP
| NVP_DEVID_REGISTERED
;
632 new_nvp
->nvp_dip
= dip
;
633 new_nvp
->nvp_devid
= new_devid
;
635 if (!devid_cache_write_disable
) {
637 nvf_mark_dirty(dcfd_handle
);
639 list_insert_tail(nvf_list(dcfd_handle
), new_nvp
);
641 rw_exit(nvf_lock(dcfd_handle
));
645 kmem_free(free_devid
, ddi_devid_sizeof(free_devid
));
650 return (DDI_SUCCESS
);
654 e_devid_cache_register(dev_info_t
*dip
, ddi_devid_t devid
)
656 return (e_devid_cache_register_cmn(dip
, devid
, NULL
));
660 * Unregister a device's devid; the devinfo may hit on multiple entries
661 * arising from both pHCI and vHCI paths.
662 * Called as an instance detachs.
663 * Invalidate the devid's devinfo reference.
664 * Devid-path remains in the cache.
668 e_devid_cache_unregister(dev_info_t
*dip
)
673 rw_enter(nvf_lock(dcfd_handle
), RW_WRITER
);
675 listp
= nvf_list(dcfd_handle
);
676 for (np
= list_head(listp
); np
; np
= list_next(listp
, np
)) {
677 if (np
->nvp_devid
== NULL
)
679 if ((np
->nvp_flags
& NVP_DEVID_DIP
) && np
->nvp_dip
== dip
) {
680 DEVID_LOG_UNREG((CE_CONT
,
681 "unregister: %s\n", np
->nvp_devpath
));
682 np
->nvp_flags
&= ~NVP_DEVID_DIP
;
687 rw_exit(nvf_lock(dcfd_handle
));
691 e_devid_cache_pathinfo(mdi_pathinfo_t
*pip
, ddi_devid_t devid
)
693 char *path
= mdi_pi_pathname(pip
);
695 return (e_devid_cache_register_cmn(mdi_pi_get_client(pip
), devid
,
700 * Purge devid cache of stale devids
703 devid_cache_cleanup(void)
705 nvp_devid_t
*np
, *next
;
709 rw_enter(nvf_lock(dcfd_handle
), RW_WRITER
);
711 listp
= nvf_list(dcfd_handle
);
712 for (np
= list_head(listp
); np
; np
= next
) {
713 next
= list_next(listp
, np
);
714 if (np
->nvp_devid
== NULL
)
716 if ((np
->nvp_flags
& NVP_DEVID_REGISTERED
) == 0) {
717 DEVID_LOG_REMOVE((CE_CONT
,
718 "cleanup: %s\n", np
->nvp_devpath
));
719 if (!devid_cache_write_disable
) {
720 nvf_mark_dirty(dcfd_handle
);
723 devid_nvp_unlink_and_free(dcfd_handle
, np
);
727 rw_exit(nvf_lock(dcfd_handle
));
735 * Build a list of dev_t's for a device/devid
737 * The effect of this function is cumulative, adding dev_t's
738 * for the device to the list of all dev_t's for a given
742 e_devid_minor_to_devlist(
750 struct ddi_minor_data
*dmdp
;
752 int ndevts
= *devtcntp
;
754 ASSERT(i_ddi_devi_attached(dip
));
756 /* are we looking for a set of minor nodes? */
757 if ((minor_name
== DEVID_MINOR_NAME_ALL
) ||
758 (minor_name
== DEVID_MINOR_NAME_ALL_CHR
) ||
759 (minor_name
== DEVID_MINOR_NAME_ALL_BLK
))
762 /* Find matching minor names */
763 ndi_devi_enter(dip
, &circ
);
764 for (dmdp
= DEVI(dip
)->devi_minor
; dmdp
; dmdp
= dmdp
->next
) {
766 /* Skip non-minors, and non matching minor names */
767 if ((dmdp
->type
!= DDM_MINOR
) || ((minor_all
== 0) &&
768 strcmp(dmdp
->ddm_name
, minor_name
)))
771 /* filter out minor_all mismatches */
773 (((minor_name
== DEVID_MINOR_NAME_ALL_CHR
) &&
774 (dmdp
->ddm_spec_type
!= S_IFCHR
)) ||
775 ((minor_name
== DEVID_MINOR_NAME_ALL_BLK
) &&
776 (dmdp
->ddm_spec_type
!= S_IFBLK
))))
779 if (ndevts
< ndevts_alloced
)
780 devtsp
[ndevts
] = dmdp
->ddm_dev
;
783 ndi_devi_exit(dip
, circ
);
789 * Search for cached entries matching a devid
791 * a list of dev_info nodes, for those devices in the attached state
792 * a list of pathnames whose instances registered the given devid
793 * If the lists passed in are not sufficient to return the matching
794 * references, return the size of lists required.
795 * The dev_info nodes are returned with a hold that the caller must release.
798 e_devid_cache_devi_path_lists(ddi_devid_t devid
, int retmax
,
799 int *retndevis
, dev_info_t
**retdevis
, int *retnpaths
, char **retpaths
)
803 dev_info_t
*dip
, *pdip
;
811 listp
= nvf_list(dcfd_handle
);
812 for (np
= list_head(listp
); np
; np
= list_next(listp
, np
)) {
813 if (np
->nvp_devid
== NULL
)
815 if (ddi_devid_valid(np
->nvp_devid
) != DDI_SUCCESS
) {
817 "find: invalid devid %s\n",
821 if (ddi_devid_compare(devid
, np
->nvp_devid
) == 0) {
822 DEVID_DEBUG2((CE_CONT
,
823 "find: devid match: %s 0x%x\n",
824 np
->nvp_devpath
, np
->nvp_flags
));
825 DEVID_LOG_MATCH(("find", devid
, np
->nvp_devpath
));
826 DEVID_LOG_PATHS((CE_CONT
, "%s\n", np
->nvp_devpath
));
829 * Check if we have a cached devinfo reference for this
830 * devid. Place a hold on it to prevent detach
831 * Otherwise, use the path instead.
832 * Note: returns with a hold on each dev_info
836 if (np
->nvp_flags
& NVP_DEVID_DIP
) {
837 pdip
= ddi_get_parent(np
->nvp_dip
);
838 if (ndi_devi_tryenter(pdip
, &circ
)) {
841 ndi_devi_exit(pdip
, circ
);
842 ASSERT(!DEVI_IS_ATTACHING(dip
));
843 ASSERT(!DEVI_IS_DETACHING(dip
));
845 DEVID_LOG_DETACH((CE_CONT
,
846 "may be detaching: %s\n",
852 if (ndevis
< retmax
) {
853 retdevis
[ndevis
++] = dip
;
860 retpaths
[npaths
++] = np
->nvp_devpath
;
868 return (maxdevis
> maxpaths
? maxdevis
: maxpaths
);
873 * Search the devid cache, returning dev_t list for all
874 * device paths mapping to the device identified by the
877 * Primary interface used by ddi_lyr_devid_to_devlist()
880 e_devid_cache_to_devt_list(ddi_devid_t devid
, char *minor_name
,
881 int *retndevts
, dev_t
**retdevts
)
885 dev_t
*devts
, *udevts
;
887 int ndevts
, undevts
, ndevts_alloced
;
888 dev_info_t
*devi
, **devis
;
889 int ndevis
, npaths
, nalloced
;
890 ddi_devid_t match_devid
;
892 DEVID_LOG_FIND(("find", devid
, NULL
));
894 ASSERT(ddi_devid_valid(devid
) == DDI_SUCCESS
);
895 if (ddi_devid_valid(devid
) != DDI_SUCCESS
) {
896 DEVID_LOG_ERR(("invalid devid", devid
, NULL
));
897 return (DDI_FAILURE
);
903 paths
= kmem_zalloc(nalloced
* sizeof (char *), KM_SLEEP
);
904 devis
= kmem_zalloc(nalloced
* sizeof (dev_info_t
*), KM_SLEEP
);
906 rw_enter(nvf_lock(dcfd_handle
), RW_READER
);
907 n
= e_devid_cache_devi_path_lists(devid
, nalloced
,
908 &ndevis
, devis
, &npaths
, paths
);
911 rw_exit(nvf_lock(dcfd_handle
));
912 for (i
= 0; i
< ndevis
; i
++)
913 ndi_rele_devi(devis
[i
]);
914 kmem_free(paths
, nalloced
* sizeof (char *));
915 kmem_free(devis
, nalloced
* sizeof (dev_info_t
*));
919 for (i
= 0; i
< npaths
; i
++) {
920 path
= i_ddi_strdup(paths
[i
], KM_SLEEP
);
923 rw_exit(nvf_lock(dcfd_handle
));
925 if (ndevis
== 0 && npaths
== 0) {
926 DEVID_LOG_ERR(("no devid found", devid
, NULL
));
927 kmem_free(paths
, nalloced
* sizeof (char *));
928 kmem_free(devis
, nalloced
* sizeof (dev_info_t
*));
929 return (DDI_FAILURE
);
932 ndevts_alloced
= 128;
935 devts
= kmem_alloc(ndevts_alloced
* sizeof (dev_t
), KM_SLEEP
);
936 for (i
= 0; i
< ndevis
; i
++) {
937 ASSERT(!DEVI_IS_ATTACHING(devis
[i
]));
938 ASSERT(!DEVI_IS_DETACHING(devis
[i
]));
939 e_devid_minor_to_devlist(devis
[i
], minor_name
,
940 ndevts_alloced
, &ndevts
, devts
);
941 if (ndevts
> ndevts_alloced
) {
942 kmem_free(devts
, ndevts_alloced
* sizeof (dev_t
));
943 ndevts_alloced
+= 128;
947 for (i
= 0; i
< npaths
; i
++) {
948 DEVID_LOG_LOOKUP((CE_CONT
, "lookup %s\n", paths
[i
]));
949 devi
= e_ddi_hold_devi_by_path(paths
[i
], 0);
951 DEVID_LOG_STALE(("stale device reference",
956 * Verify the newly attached device registered a matching devid
958 if (i_ddi_devi_get_devid(DDI_DEV_T_ANY
, devi
,
959 &match_devid
) != DDI_SUCCESS
) {
961 "%s: no devid registered on attach\n",
963 ddi_release_devi(devi
);
967 if (ddi_devid_compare(devid
, match_devid
) != 0) {
968 DEVID_LOG_STALE(("new devid registered",
970 ddi_release_devi(devi
);
971 ddi_devid_free(match_devid
);
974 ddi_devid_free(match_devid
);
976 e_devid_minor_to_devlist(devi
, minor_name
,
977 ndevts_alloced
, &ndevts
, devts
);
978 ddi_release_devi(devi
);
979 if (ndevts
> ndevts_alloced
) {
981 ndevts_alloced
* sizeof (dev_t
));
982 ndevts_alloced
+= 128;
987 /* drop hold from e_devid_cache_devi_path_lists */
988 for (i
= 0; i
< ndevis
; i
++) {
989 ndi_rele_devi(devis
[i
]);
991 for (i
= 0; i
< npaths
; i
++) {
992 kmem_free(paths
[i
], strlen(paths
[i
]) + 1);
994 kmem_free(paths
, nalloced
* sizeof (char *));
995 kmem_free(devis
, nalloced
* sizeof (dev_info_t
*));
998 DEVID_LOG_ERR(("no devid found", devid
, NULL
));
999 kmem_free(devts
, ndevts_alloced
* sizeof (dev_t
));
1000 return (DDI_FAILURE
);
1004 * Build the final list of sorted dev_t's with duplicates collapsed so
1005 * returned results are consistent. This prevents implementation
1006 * artifacts from causing unnecessary changes in SVM namespace.
1009 for (i
= 0; i
< (ndevts
- 1); i
++) {
1010 for (j
= 0; j
< ((ndevts
- 1) - i
); j
++) {
1011 if (devts
[j
+ 1] < devts
[j
]) {
1013 devts
[j
] = devts
[j
+ 1];
1014 devts
[j
+ 1] = tdevt
;
1019 /* determine number of unique values */
1020 for (undevts
= ndevts
, i
= 1; i
< ndevts
; i
++) {
1021 if (devts
[i
- 1] == devts
[i
])
1025 /* allocate unique */
1026 udevts
= kmem_alloc(undevts
* sizeof (dev_t
), KM_SLEEP
);
1029 udevts
[0] = devts
[0];
1030 for (i
= 1, j
= 1; i
< ndevts
; i
++) {
1031 if (devts
[i
- 1] != devts
[i
])
1032 udevts
[j
++] = devts
[i
];
1034 ASSERT(j
== undevts
);
1036 kmem_free(devts
, ndevts_alloced
* sizeof (dev_t
));
1038 *retndevts
= undevts
;
1041 return (DDI_SUCCESS
);
1045 e_devid_cache_free_devt_list(int ndevts
, dev_t
*devt_list
)
1047 kmem_free(devt_list
, ndevts
* sizeof (dev_t
*));
1051 * If given a full path and NULL ua, search for a cache entry
1052 * whose path matches the full path. On a cache hit duplicate the
1053 * devid of the matched entry into the given devid (caller
1054 * must free); nodenamebuf is not touched for this usage.
1056 * Given a path and a non-NULL unit address, search the cache for any entry
1057 * matching "<path>/%@<unit-address>" where '%' is a wildcard meaning
1058 * any node name. The path should not end a '/'. On a cache hit
1059 * duplicate the devid as before (caller must free) and copy into
1060 * the caller-provided nodenamebuf (if not NULL) the nodename of the
1063 * We must not make use of nvp_dip since that may be NULL for cached
1064 * entries that are not present in the current tree.
1067 e_devid_cache_path_to_devid(char *path
, char *ua
,
1068 char *nodenamebuf
, ddi_devid_t
*devidp
)
1070 size_t pathlen
, ualen
;
1071 int rv
= DDI_FAILURE
;
1076 if (path
== NULL
|| *path
== '\0' || (ua
&& *ua
== '\0') ||
1078 return (DDI_FAILURE
);
1083 pathlen
= strlen(path
);
1087 rw_enter(nvf_lock(dcfd_handle
), RW_READER
);
1089 listp
= nvf_list(dcfd_handle
);
1090 for (np
= list_head(listp
); np
; np
= list_next(listp
, np
)) {
1091 size_t nodelen
, candlen
, n
;
1092 ddi_devid_t devid_dup
;
1095 if (np
->nvp_devid
== NULL
)
1098 if (ddi_devid_valid(np
->nvp_devid
) != DDI_SUCCESS
) {
1100 "pathsearch: invalid devid %s\n",
1105 cand
= np
->nvp_devpath
; /* candidate path */
1107 /* If a full pathname was provided the compare is easy */
1109 if (strcmp(cand
, path
) == 0)
1116 * The compare for initial path plus ua and unknown nodename
1119 * Does the initial path component match 'path'?
1121 if (strncmp(path
, cand
, pathlen
) != 0)
1124 candlen
= strlen(cand
);
1127 * The next character must be a '/' and there must be no
1128 * further '/' thereafter. Begin by checking that the
1129 * candidate is long enough to include at mininum a
1130 * "/<nodename>@<ua>" after the initial portion already
1131 * matched assuming a nodename length of 1.
1133 if (candlen
< pathlen
+ 1 + 1 + 1 + ualen
||
1134 cand
[pathlen
] != '/' ||
1135 strchr(cand
+ pathlen
+ 1, '/') != NULL
)
1138 node
= cand
+ pathlen
+ 1; /* <node>@<ua> string */
1141 * Find the '@' before the unit address. Check for
1142 * unit address match.
1144 if ((uasep
= strchr(node
, '@')) == NULL
)
1148 * Check we still have enough length and that ua matches
1150 nodelen
= (uintptr_t)uasep
- (uintptr_t)node
;
1151 if (candlen
< pathlen
+ 1 + nodelen
+ 1 + ualen
||
1152 strncmp(ua
, uasep
+ 1, ualen
) != 0)
1155 n
= ddi_devid_sizeof(np
->nvp_devid
);
1156 devid_dup
= kmem_alloc(n
, KM_SLEEP
); /* caller must free */
1157 (void) bcopy(np
->nvp_devid
, devid_dup
, n
);
1158 *devidp
= devid_dup
;
1160 if (ua
&& nodenamebuf
) {
1161 (void) strncpy(nodenamebuf
, node
, nodelen
);
1162 nodenamebuf
[nodelen
] = '\0';
1169 rw_exit(nvf_lock(dcfd_handle
));
1176 devid_log(char *fmt
, ddi_devid_t devid
, char *path
)
1178 char *devidstr
= ddi_devid_str_encode(devid
, NULL
);
1180 cmn_err(CE_CONT
, "%s: %s %s\n", fmt
, path
, devidstr
);
1182 cmn_err(CE_CONT
, "%s: %s\n", fmt
, devidstr
);
1184 ddi_devid_str_free(devidstr
);