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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24 */
25
26 #include <sys/note.h>
27 #include <sys/t_lock.h>
28 #include <sys/cmn_err.h>
29 #include <sys/instance.h>
30 #include <sys/conf.h>
31 #include <sys/stat.h>
32 #include <sys/ddi.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>
39 #include <sys/kobj.h>
40 #include <sys/devcache.h>
41 #include <sys/devid_cache.h>
42 #include <sys/sysmacros.h>
43
44 /*
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(1M) is equivalent to running full
51 * discovery at the devid cache level.
52 *
53 * Reasons why a disk may not be accessible:
54 * disk powered off
55 * disk removed or cable disconnected
56 * disk or adapter broken
57 *
58 * Note that discovery is not needed and cannot succeed in any of these
59 * cases.
60 *
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(1M) 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.
67 *
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
72 * devfsadm(1M).
73 *
74 * Discovery prior to mounting root is only of interest when booting
75 * from a filesystem which accesses devices by device id, which of
76 * not all do.
77 *
78 * Tunables
79 *
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.
86 *
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.
98 *
99 * devid_discovery_postboot_always (default 0)
100 * Set to 1, the system will always attempt full discovery.
101 *
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.
106 *
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.
111 *
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.
115 *
116 * devid_report_error (default 0)
117 * Set to 1 to enable some error messages related to devid
118 * cache failures.
119 *
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.
122 */
123
124
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;
129
130 int devid_cache_read_disable = 0;
131 int devid_cache_write_disable = 0;
132
133 int devid_report_error = 0;
134
135
136 /*
137 * State to manage discovery of devices providing a devid
138 */
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;
143
144
145 #ifdef DEBUG
146 int nvp_devid_debug = 0;
147 int 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;
161 #endif /* DEBUG */
162
163 /*
164 * devid cache file registration for cache reads and updates
165 */
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 */
172 };
173
174 /*
175 * handle to registered devid cache handlers
176 */
177 nvf_handle_t dcfd_handle;
178
179
180 /*
181 * Initialize devid cache file management
182 */
183 void
184 devid_cache_init(void)
185 {
186 dcfd_handle = nvf_register_file(&devid_cache_ops);
187 ASSERT(dcfd_handle);
188
189 list_create(nvf_list(dcfd_handle), sizeof (nvp_devid_t),
190 offsetof(nvp_devid_t, nvp_link));
191
192 mutex_init(&devid_discovery_mutex, NULL, MUTEX_DEFAULT, NULL);
193 cv_init(&devid_discovery_cv, NULL, CV_DRIVER, NULL);
194 }
195
196 /*
197 * Read and initialize the devid cache from the persistent store
198 */
199 void
200 devid_cache_read(void)
201 {
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));
207 }
208 }
209
210 static void
211 devid_nvp_free(nvp_devid_t *dp)
212 {
213 if (dp->nvp_devpath)
214 kmem_free(dp->nvp_devpath, strlen(dp->nvp_devpath)+1);
215 if (dp->nvp_devid)
216 kmem_free(dp->nvp_devid, ddi_devid_sizeof(dp->nvp_devid));
217
218 kmem_free(dp, sizeof (nvp_devid_t));
219 }
220
221 static void
222 devid_list_free(nvf_handle_t fd)
223 {
224 list_t *listp;
225 nvp_devid_t *np;
226
227 ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle)));
228
229 listp = nvf_list(fd);
230 while (np = list_head(listp)) {
231 list_remove(listp, np);
232 devid_nvp_free(np);
233 }
234 }
235
236 /*
237 * Free an nvp element in a list
238 */
239 static void
240 devid_nvp_unlink_and_free(nvf_handle_t fd, nvp_devid_t *np)
241 {
242 list_remove(nvf_list(fd), np);
243 devid_nvp_free(np);
244 }
245
246 /*
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
250 */
251 static int
252 devid_cache_unpack_nvlist(nvf_handle_t fd, nvlist_t *nvl, char *name)
253 {
254 nvp_devid_t *np;
255 ddi_devid_t devidp;
256 int rval;
257 uint_t n;
258
259 NVP_DEVID_DEBUG_PATH((name));
260 ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle)));
261
262 /*
263 * check path for a devid
264 */
265 rval = nvlist_lookup_byte_array(nvl,
266 DP_DEVID_ID, (uchar_t **)&devidp, &n);
267 if (rval == 0) {
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));
276 } else {
277 DEVIDERR((CE_CONT,
278 "%s: invalid devid\n", name));
279 }
280 } else {
281 DEVIDERR((CE_CONT,
282 "%s: devid not available\n", name));
283 }
284
285 return (0);
286 }
287
288 /*
289 * Pack the list of devid cache elements into a single nvlist
290 * Used when writing the nvlist file.
291 */
292 static int
293 devid_cache_pack_list(nvf_handle_t fd, nvlist_t **ret_nvl)
294 {
295 nvlist_t *nvl, *sub_nvl;
296 nvp_devid_t *np;
297 int rval;
298 list_t *listp;
299
300 ASSERT(RW_WRITE_HELD(nvf_lock(dcfd_handle)));
301
302 rval = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
303 if (rval != 0) {
304 nvf_error("%s: nvlist alloc error %d\n",
305 nvf_cache_name(fd), rval);
306 return (DDI_FAILURE);
307 }
308
309 listp = nvf_list(fd);
310 for (np = list_head(listp); np; np = list_next(listp, np)) {
311 if (np->nvp_devid == NULL)
312 continue;
313 NVP_DEVID_DEBUG_PATH(np->nvp_devpath);
314 rval = nvlist_alloc(&sub_nvl, NV_UNIQUE_NAME, KM_SLEEP);
315 if (rval != 0) {
316 nvf_error("%s: nvlist alloc error %d\n",
317 nvf_cache_name(fd), rval);
318 sub_nvl = NULL;
319 goto err;
320 }
321
322 rval = nvlist_add_byte_array(sub_nvl, DP_DEVID_ID,
323 (uchar_t *)np->nvp_devid,
324 ddi_devid_sizeof(np->nvp_devid));
325 if (rval == 0) {
326 NVP_DEVID_DEBUG_DEVID(np->nvp_devid);
327 } else {
328 nvf_error(
329 "%s: nvlist add error %d (devid)\n",
330 nvf_cache_name(fd), rval);
331 goto err;
332 }
333
334 rval = nvlist_add_nvlist(nvl, np->nvp_devpath, sub_nvl);
335 if (rval != 0) {
336 nvf_error("%s: nvlist add error %d (sublist)\n",
337 nvf_cache_name(fd), rval);
338 goto err;
339 }
340 nvlist_free(sub_nvl);
341 }
342
343 *ret_nvl = nvl;
344 return (DDI_SUCCESS);
345
346 err:
347 nvlist_free(sub_nvl);
348 nvlist_free(nvl);
349 *ret_nvl = NULL;
350 return (DDI_FAILURE);
351 }
352
353 static int
354 e_devid_do_discovery(void)
355 {
356 ASSERT(mutex_owned(&devid_discovery_mutex));
357
358 if (i_ddi_io_initialized() == 0) {
359 if (devid_discovery_boot > 0) {
360 devid_discovery_boot--;
361 return (1);
362 }
363 } else {
364 if (devid_discovery_postboot_always > 0)
365 return (1);
366 if (devid_discovery_postboot > 0) {
367 devid_discovery_postboot--;
368 return (1);
369 }
370 if (devid_discovery_secs > 0) {
371 if ((ddi_get_lbolt() - devid_last_discovery) >
372 drv_usectohz(devid_discovery_secs * MICROSEC)) {
373 return (1);
374 }
375 }
376 }
377
378 DEVID_LOG_DISC((CE_CONT, "devid_discovery: no discovery\n"));
379 return (0);
380 }
381
382 static void
383 e_ddi_devid_hold_by_major(major_t major)
384 {
385 DEVID_LOG_DISC((CE_CONT,
386 "devid_discovery: ddi_hold_installed_driver %d\n", major));
387
388 if (ddi_hold_installed_driver(major) == NULL)
389 return;
390
391 ddi_rele_driver(major);
392 }
393
394 /* legacy support - see below */
395 static char *e_ddi_devid_hold_driver_list[] = { "sd", "ssd" };
396
397 #define N_DRIVERS_TO_HOLD \
398 (sizeof (e_ddi_devid_hold_driver_list) / sizeof (char *))
399
400 static void
401 e_ddi_devid_hold_installed_driver(ddi_devid_t devid)
402 {
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;
407 char **drvp;
408 int i;
409
410 /* Count non-null bytes */
411 for (i = 0; i < DEVID_HINT_SIZE; i++)
412 if (id->did_driver[i] == '\0')
413 break;
414
415 /* Make a copy of the driver hint */
416 bcopy(id->did_driver, hint, i);
417 hint[i] = '\0';
418
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);
423 }
424
425 /*
426 * search for the devid with each driver declaring
427 * itself as a devid registrant.
428 */
429 for (major = 0; major < devcnt; major++) {
430 if (major == hint_major)
431 continue;
432 dnp = &devnamesp[major];
433 if (dnp->dn_flags & DN_DEVID_REGISTRANT) {
434 e_ddi_devid_hold_by_major(major);
435 }
436 }
437
438 /*
439 * Legacy support: may be removed once an upgrade mechanism
440 * for driver conf files is available.
441 */
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);
447 }
448 }
449 }
450
451 /*
452 * Return success if discovery was attempted, to indicate
453 * that the desired device may now be available.
454 */
455 int
456 e_ddi_devid_discovery(ddi_devid_t devid)
457 {
458 int flags;
459 int rval = DDI_SUCCESS;
460
461 mutex_enter(&devid_discovery_mutex);
462
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);
467 }
468 } else if (e_devid_do_discovery()) {
469 devid_discovery_busy = 1;
470 mutex_exit(&devid_discovery_mutex);
471
472 if (i_ddi_io_initialized() == 0) {
473 e_ddi_devid_hold_installed_driver(devid);
474 } else {
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);
481 }
482
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"));
489 } else {
490 rval = DDI_FAILURE;
491 DEVID_LOG_DISC((CE_CONT, "no devid discovery\n"));
492 }
493
494 mutex_exit(&devid_discovery_mutex);
495
496 return (rval);
497 }
498
499 /*
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.
503 *
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.
508 */
509 static int
510 e_devid_cache_register_cmn(dev_info_t *dip, ddi_devid_t devid, char *devpath)
511 {
512 nvp_devid_t *np;
513 nvp_devid_t *new_nvp;
514 ddi_devid_t new_devid;
515 int new_devid_size;
516 char *path, *fullpath;
517 ddi_devid_t free_devid = NULL;
518 int pathlen;
519 list_t *listp;
520 int is_dirty = 0;
521
522
523 ASSERT(ddi_devid_valid(devid) == DDI_SUCCESS);
524
525 if (devpath) {
526 pathlen = strlen(devpath) + 1;
527 path = kmem_alloc(pathlen, KM_SLEEP);
528 bcopy(devpath, path, pathlen);
529 } else {
530 /*
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).
534 */
535 if (ddi_get_name_addr(dip) == NULL)
536 return (DDI_FAILURE);
537
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);
544 }
545
546 DEVID_LOG_REG(("register", devid, path));
547
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);
552
553 rw_enter(nvf_lock(dcfd_handle), RW_WRITER);
554
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;
562 np->nvp_flags |=
563 NVP_DEVID_DIP | NVP_DEVID_REGISTERED;
564 np->nvp_dip = dip;
565 if (!devid_cache_write_disable) {
566 nvf_mark_dirty(dcfd_handle);
567 is_dirty = 1;
568 }
569 rw_exit(nvf_lock(dcfd_handle));
570 kmem_free(new_nvp, sizeof (nvp_devid_t));
571 kmem_free(path, pathlen);
572 goto exit;
573 }
574 if (ddi_devid_valid(np->nvp_devid) != DDI_SUCCESS) {
575 /* replace invalid devid */
576 free_devid = np->nvp_devid;
577 goto replace;
578 }
579 /*
580 * We're registering an already-cached path
581 * Does the device's devid match the cache?
582 */
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));
586 /*
587 * Replace cached devid for this path
588 * with newly registered devid. A devid
589 * may map to multiple paths but one path
590 * should only map to one devid.
591 */
592 devid_nvp_unlink_and_free(dcfd_handle, np);
593 np = NULL;
594 break;
595 } else {
596 DEVID_DEBUG2((CE_CONT,
597 "devid register: %s devid match\n", path));
598 np->nvp_flags |=
599 NVP_DEVID_DIP | NVP_DEVID_REGISTERED;
600 np->nvp_dip = dip;
601 rw_exit(nvf_lock(dcfd_handle));
602 kmem_free(new_nvp, sizeof (nvp_devid_t));
603 kmem_free(path, pathlen);
604 kmem_free(new_devid, new_devid_size);
605 return (DDI_SUCCESS);
606 }
607 }
608 }
609
610 /*
611 * Add newly registered devid to the cache
612 */
613 ASSERT(np == NULL);
614
615 new_nvp->nvp_devpath = path;
616 new_nvp->nvp_flags = NVP_DEVID_DIP | NVP_DEVID_REGISTERED;
617 new_nvp->nvp_dip = dip;
618 new_nvp->nvp_devid = new_devid;
619
620 if (!devid_cache_write_disable) {
621 is_dirty = 1;
622 nvf_mark_dirty(dcfd_handle);
623 }
624 list_insert_tail(nvf_list(dcfd_handle), new_nvp);
625
626 rw_exit(nvf_lock(dcfd_handle));
627
628 exit:
629 if (free_devid)
630 kmem_free(free_devid, ddi_devid_sizeof(free_devid));
631
632 if (is_dirty)
633 nvf_wake_daemon();
634
635 return (DDI_SUCCESS);
636 }
637
638 int
639 e_devid_cache_register(dev_info_t *dip, ddi_devid_t devid)
640 {
641 return (e_devid_cache_register_cmn(dip, devid, NULL));
642 }
643
644 /*
645 * Unregister a device's devid; the devinfo may hit on multiple entries
646 * arising from both pHCI and vHCI paths.
647 * Called as an instance detachs.
648 * Invalidate the devid's devinfo reference.
649 * Devid-path remains in the cache.
650 */
651
652 void
653 e_devid_cache_unregister(dev_info_t *dip)
654 {
655 nvp_devid_t *np;
656 list_t *listp;
657
658 rw_enter(nvf_lock(dcfd_handle), RW_WRITER);
659
660 listp = nvf_list(dcfd_handle);
661 for (np = list_head(listp); np; np = list_next(listp, np)) {
662 if (np->nvp_devid == NULL)
663 continue;
664 if ((np->nvp_flags & NVP_DEVID_DIP) && np->nvp_dip == dip) {
665 DEVID_LOG_UNREG((CE_CONT,
666 "unregister: %s\n", np->nvp_devpath));
667 np->nvp_flags &= ~NVP_DEVID_DIP;
668 np->nvp_dip = NULL;
669 }
670 }
671
672 rw_exit(nvf_lock(dcfd_handle));
673 }
674
675 int
676 e_devid_cache_pathinfo(mdi_pathinfo_t *pip, ddi_devid_t devid)
677 {
678 char *path = mdi_pi_pathname(pip);
679
680 return (e_devid_cache_register_cmn(mdi_pi_get_client(pip), devid,
681 path));
682 }
683
684 /*
685 * Purge devid cache of stale devids
686 */
687 void
688 devid_cache_cleanup(void)
689 {
690 nvp_devid_t *np, *next;
691 list_t *listp;
692 int is_dirty = 0;
693
694 rw_enter(nvf_lock(dcfd_handle), RW_WRITER);
695
696 listp = nvf_list(dcfd_handle);
697 for (np = list_head(listp); np; np = next) {
698 next = list_next(listp, np);
699 if (np->nvp_devid == NULL)
700 continue;
701 if ((np->nvp_flags & NVP_DEVID_REGISTERED) == 0) {
702 DEVID_LOG_REMOVE((CE_CONT,
703 "cleanup: %s\n", np->nvp_devpath));
704 if (!devid_cache_write_disable) {
705 nvf_mark_dirty(dcfd_handle);
706 is_dirty = 0;
707 }
708 devid_nvp_unlink_and_free(dcfd_handle, np);
709 }
710 }
711
712 rw_exit(nvf_lock(dcfd_handle));
713
714 if (is_dirty)
715 nvf_wake_daemon();
716 }
717
718
719 /*
720 * Build a list of dev_t's for a device/devid
721 *
722 * The effect of this function is cumulative, adding dev_t's
723 * for the device to the list of all dev_t's for a given
724 * devid.
725 */
726 static void
727 e_devid_minor_to_devlist(
728 dev_info_t *dip,
729 char *minor_name,
730 int ndevts_alloced,
731 int *devtcntp,
732 dev_t *devtsp)
733 {
734 int circ;
735 struct ddi_minor_data *dmdp;
736 int minor_all = 0;
737 int ndevts = *devtcntp;
738
739 if (!i_ddi_devi_attached(dip)) {
740 return;
741 }
742
743 /* are we looking for a set of minor nodes? */
744 if ((minor_name == DEVID_MINOR_NAME_ALL) ||
745 (minor_name == DEVID_MINOR_NAME_ALL_CHR) ||
746 (minor_name == DEVID_MINOR_NAME_ALL_BLK))
747 minor_all = 1;
748
749 /* Find matching minor names */
750 ndi_devi_enter(dip, &circ);
751 for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
752
753 /* Skip non-minors, and non matching minor names */
754 if ((dmdp->type != DDM_MINOR) || ((minor_all == 0) &&
755 strcmp(dmdp->ddm_name, minor_name)))
756 continue;
757
758 /* filter out minor_all mismatches */
759 if (minor_all &&
760 (((minor_name == DEVID_MINOR_NAME_ALL_CHR) &&
761 (dmdp->ddm_spec_type != S_IFCHR)) ||
762 ((minor_name == DEVID_MINOR_NAME_ALL_BLK) &&
763 (dmdp->ddm_spec_type != S_IFBLK))))
764 continue;
765
766 if (ndevts < ndevts_alloced)
767 devtsp[ndevts] = dmdp->ddm_dev;
768 ndevts++;
769 }
770 ndi_devi_exit(dip, circ);
771
772 *devtcntp = ndevts;
773 }
774
775 /*
776 * Search for cached entries matching a devid
777 * Return two lists:
778 * a list of dev_info nodes, for those devices in the attached state
779 * a list of pathnames whose instances registered the given devid
780 * If the lists passed in are not sufficient to return the matching
781 * references, return the size of lists required.
782 * The dev_info nodes are returned with a hold that the caller must release.
783 */
784 static int
785 e_devid_cache_devi_path_lists(ddi_devid_t devid, int retmax,
786 int *retndevis, dev_info_t **retdevis, int *retnpaths, char **retpaths)
787 {
788 nvp_devid_t *np;
789 int ndevis, npaths;
790 dev_info_t *dip, *pdip;
791 int circ;
792 int maxdevis = 0;
793 int maxpaths = 0;
794 list_t *listp;
795
796 ndevis = 0;
797 npaths = 0;
798 listp = nvf_list(dcfd_handle);
799 for (np = list_head(listp); np; np = list_next(listp, np)) {
800 if (np->nvp_devid == NULL)
801 continue;
802 if (ddi_devid_valid(np->nvp_devid) != DDI_SUCCESS) {
803 DEVIDERR((CE_CONT,
804 "find: invalid devid %s\n",
805 np->nvp_devpath));
806 continue;
807 }
808 if (ddi_devid_compare(devid, np->nvp_devid) == 0) {
809 DEVID_DEBUG2((CE_CONT,
810 "find: devid match: %s 0x%x\n",
811 np->nvp_devpath, np->nvp_flags));
812 DEVID_LOG_MATCH(("find", devid, np->nvp_devpath));
813 DEVID_LOG_PATHS((CE_CONT, "%s\n", np->nvp_devpath));
814
815 /*
816 * Check if we have a cached devinfo reference for this
817 * devid. Place a hold on it to prevent detach
818 * Otherwise, use the path instead.
819 * Note: returns with a hold on each dev_info
820 * node in the list.
821 */
822 dip = NULL;
823 if (np->nvp_flags & NVP_DEVID_DIP) {
824 pdip = ddi_get_parent(np->nvp_dip);
825 if (ndi_devi_tryenter(pdip, &circ)) {
826 dip = np->nvp_dip;
827 ndi_hold_devi(dip);
828 ndi_devi_exit(pdip, circ);
829 ASSERT(!DEVI_IS_ATTACHING(dip));
830 ASSERT(!DEVI_IS_DETACHING(dip));
831 } else {
832 DEVID_LOG_DETACH((CE_CONT,
833 "may be detaching: %s\n",
834 np->nvp_devpath));
835 }
836 }
837
838 if (dip) {
839 if (ndevis < retmax) {
840 retdevis[ndevis++] = dip;
841 } else {
842 ndi_rele_devi(dip);
843 }
844 maxdevis++;
845 } else {
846 if (npaths < retmax)
847 retpaths[npaths++] = np->nvp_devpath;
848 maxpaths++;
849 }
850 }
851 }
852
853 *retndevis = ndevis;
854 *retnpaths = npaths;
855 return (maxdevis > maxpaths ? maxdevis : maxpaths);
856 }
857
858
859 /*
860 * Search the devid cache, returning dev_t list for all
861 * device paths mapping to the device identified by the
862 * given devid.
863 *
864 * Primary interface used by ddi_lyr_devid_to_devlist()
865 */
866 int
867 e_devid_cache_to_devt_list(ddi_devid_t devid, char *minor_name,
868 int *retndevts, dev_t **retdevts)
869 {
870 char *path, **paths;
871 int i, j, n;
872 dev_t *devts, *udevts;
873 dev_t tdevt;
874 int ndevts, undevts, ndevts_alloced;
875 dev_info_t *devi, **devis;
876 int ndevis, npaths, nalloced;
877 ddi_devid_t match_devid;
878
879 DEVID_LOG_FIND(("find", devid, NULL));
880
881 ASSERT(ddi_devid_valid(devid) == DDI_SUCCESS);
882 if (ddi_devid_valid(devid) != DDI_SUCCESS) {
883 DEVID_LOG_ERR(("invalid devid", devid, NULL));
884 return (DDI_FAILURE);
885 }
886
887 nalloced = 128;
888
889 for (;;) {
890 paths = kmem_zalloc(nalloced * sizeof (char *), KM_SLEEP);
891 devis = kmem_zalloc(nalloced * sizeof (dev_info_t *), KM_SLEEP);
892
893 rw_enter(nvf_lock(dcfd_handle), RW_READER);
894 n = e_devid_cache_devi_path_lists(devid, nalloced,
895 &ndevis, devis, &npaths, paths);
896 if (n <= nalloced)
897 break;
898 rw_exit(nvf_lock(dcfd_handle));
899 for (i = 0; i < ndevis; i++)
900 ndi_rele_devi(devis[i]);
901 kmem_free(paths, nalloced * sizeof (char *));
902 kmem_free(devis, nalloced * sizeof (dev_info_t *));
903 nalloced = n + 128;
904 }
905
906 for (i = 0; i < npaths; i++) {
907 path = i_ddi_strdup(paths[i], KM_SLEEP);
908 paths[i] = path;
909 }
910 rw_exit(nvf_lock(dcfd_handle));
911
912 if (ndevis == 0 && npaths == 0) {
913 DEVID_LOG_ERR(("no devid found", devid, NULL));
914 kmem_free(paths, nalloced * sizeof (char *));
915 kmem_free(devis, nalloced * sizeof (dev_info_t *));
916 return (DDI_FAILURE);
917 }
918
919 ndevts_alloced = 128;
920 restart:
921 ndevts = 0;
922 devts = kmem_alloc(ndevts_alloced * sizeof (dev_t), KM_SLEEP);
923 for (i = 0; i < ndevis; i++) {
924 ASSERT(!DEVI_IS_ATTACHING(devis[i]));
925 ASSERT(!DEVI_IS_DETACHING(devis[i]));
926 e_devid_minor_to_devlist(devis[i], minor_name,
927 ndevts_alloced, &ndevts, devts);
928 if (ndevts > ndevts_alloced) {
929 kmem_free(devts, ndevts_alloced * sizeof (dev_t));
930 ndevts_alloced += 128;
931 goto restart;
932 }
933 }
934 for (i = 0; i < npaths; i++) {
935 DEVID_LOG_LOOKUP((CE_CONT, "lookup %s\n", paths[i]));
936 devi = e_ddi_hold_devi_by_path(paths[i], 0);
937 if (devi == NULL) {
938 DEVID_LOG_STALE(("stale device reference",
939 devid, paths[i]));
940 continue;
941 }
942 /*
943 * Verify the newly attached device registered a matching devid
944 */
945 if (i_ddi_devi_get_devid(DDI_DEV_T_ANY, devi,
946 &match_devid) != DDI_SUCCESS) {
947 DEVIDERR((CE_CONT,
948 "%s: no devid registered on attach\n",
949 paths[i]));
950 ddi_release_devi(devi);
951 continue;
952 }
953
954 if (ddi_devid_compare(devid, match_devid) != 0) {
955 DEVID_LOG_STALE(("new devid registered",
956 devid, paths[i]));
957 ddi_release_devi(devi);
958 ddi_devid_free(match_devid);
959 continue;
960 }
961 ddi_devid_free(match_devid);
962
963 e_devid_minor_to_devlist(devi, minor_name,
964 ndevts_alloced, &ndevts, devts);
965 ddi_release_devi(devi);
966 if (ndevts > ndevts_alloced) {
967 kmem_free(devts,
968 ndevts_alloced * sizeof (dev_t));
969 ndevts_alloced += 128;
970 goto restart;
971 }
972 }
973
974 /* drop hold from e_devid_cache_devi_path_lists */
975 for (i = 0; i < ndevis; i++) {
976 ndi_rele_devi(devis[i]);
977 }
978 for (i = 0; i < npaths; i++) {
979 kmem_free(paths[i], strlen(paths[i]) + 1);
980 }
981 kmem_free(paths, nalloced * sizeof (char *));
982 kmem_free(devis, nalloced * sizeof (dev_info_t *));
983
984 if (ndevts == 0) {
985 DEVID_LOG_ERR(("no devid found", devid, NULL));
986 kmem_free(devts, ndevts_alloced * sizeof (dev_t));
987 return (DDI_FAILURE);
988 }
989
990 /*
991 * Build the final list of sorted dev_t's with duplicates collapsed so
992 * returned results are consistent. This prevents implementation
993 * artifacts from causing unnecessary changes in SVM namespace.
994 */
995 /* bubble sort */
996 for (i = 0; i < (ndevts - 1); i++) {
997 for (j = 0; j < ((ndevts - 1) - i); j++) {
998 if (devts[j + 1] < devts[j]) {
999 tdevt = devts[j];
1000 devts[j] = devts[j + 1];
1001 devts[j + 1] = tdevt;
1002 }
1003 }
1004 }
1005
1006 /* determine number of unique values */
1007 for (undevts = ndevts, i = 1; i < ndevts; i++) {
1008 if (devts[i - 1] == devts[i])
1009 undevts--;
1010 }
1011
1012 /* allocate unique */
1013 udevts = kmem_alloc(undevts * sizeof (dev_t), KM_SLEEP);
1014
1015 /* copy unique */
1016 udevts[0] = devts[0];
1017 for (i = 1, j = 1; i < ndevts; i++) {
1018 if (devts[i - 1] != devts[i])
1019 udevts[j++] = devts[i];
1020 }
1021 ASSERT(j == undevts);
1022
1023 kmem_free(devts, ndevts_alloced * sizeof (dev_t));
1024
1025 *retndevts = undevts;
1026 *retdevts = udevts;
1027
1028 return (DDI_SUCCESS);
1029 }
1030
1031 void
1032 e_devid_cache_free_devt_list(int ndevts, dev_t *devt_list)
1033 {
1034 kmem_free(devt_list, ndevts * sizeof (dev_t *));
1035 }
1036
1037 /*
1038 * If given a full path and NULL ua, search for a cache entry
1039 * whose path matches the full path. On a cache hit duplicate the
1040 * devid of the matched entry into the given devid (caller
1041 * must free); nodenamebuf is not touched for this usage.
1042 *
1043 * Given a path and a non-NULL unit address, search the cache for any entry
1044 * matching "<path>/%@<unit-address>" where '%' is a wildcard meaning
1045 * any node name. The path should not end a '/'. On a cache hit
1046 * duplicate the devid as before (caller must free) and copy into
1047 * the caller-provided nodenamebuf (if not NULL) the nodename of the
1048 * matched entry.
1049 *
1050 * We must not make use of nvp_dip since that may be NULL for cached
1051 * entries that are not present in the current tree.
1052 */
1053 int
1054 e_devid_cache_path_to_devid(char *path, char *ua,
1055 char *nodenamebuf, ddi_devid_t *devidp)
1056 {
1057 size_t pathlen, ualen;
1058 int rv = DDI_FAILURE;
1059 nvp_devid_t *np;
1060 list_t *listp;
1061 char *cand;
1062
1063 if (path == NULL || *path == '\0' || (ua && *ua == '\0') ||
1064 devidp == NULL)
1065 return (DDI_FAILURE);
1066
1067 *devidp = NULL;
1068
1069 if (ua) {
1070 pathlen = strlen(path);
1071 ualen = strlen(ua);
1072 }
1073
1074 rw_enter(nvf_lock(dcfd_handle), RW_READER);
1075
1076 listp = nvf_list(dcfd_handle);
1077 for (np = list_head(listp); np; np = list_next(listp, np)) {
1078 size_t nodelen, candlen, n;
1079 ddi_devid_t devid_dup;
1080 char *uasep, *node;
1081
1082 if (np->nvp_devid == NULL)
1083 continue;
1084
1085 if (ddi_devid_valid(np->nvp_devid) != DDI_SUCCESS) {
1086 DEVIDERR((CE_CONT,
1087 "pathsearch: invalid devid %s\n",
1088 np->nvp_devpath));
1089 continue;
1090 }
1091
1092 cand = np->nvp_devpath; /* candidate path */
1093
1094 /* If a full pathname was provided the compare is easy */
1095 if (ua == NULL) {
1096 if (strcmp(cand, path) == 0)
1097 goto match;
1098 else
1099 continue;
1100 }
1101
1102 /*
1103 * The compare for initial path plus ua and unknown nodename
1104 * is trickier.
1105 *
1106 * Does the initial path component match 'path'?
1107 */
1108 if (strncmp(path, cand, pathlen) != 0)
1109 continue;
1110
1111 candlen = strlen(cand);
1112
1113 /*
1114 * The next character must be a '/' and there must be no
1115 * further '/' thereafter. Begin by checking that the
1116 * candidate is long enough to include at mininum a
1117 * "/<nodename>@<ua>" after the initial portion already
1118 * matched assuming a nodename length of 1.
1119 */
1120 if (candlen < pathlen + 1 + 1 + 1 + ualen ||
1121 cand[pathlen] != '/' ||
1122 strchr(cand + pathlen + 1, '/') != NULL)
1123 continue;
1124
1125 node = cand + pathlen + 1; /* <node>@<ua> string */
1126
1127 /*
1128 * Find the '@' before the unit address. Check for
1129 * unit address match.
1130 */
1131 if ((uasep = strchr(node, '@')) == NULL)
1132 continue;
1133
1134 /*
1135 * Check we still have enough length and that ua matches
1136 */
1137 nodelen = (uintptr_t)uasep - (uintptr_t)node;
1138 if (candlen < pathlen + 1 + nodelen + 1 + ualen ||
1139 strncmp(ua, uasep + 1, ualen) != 0)
1140 continue;
1141 match:
1142 n = ddi_devid_sizeof(np->nvp_devid);
1143 devid_dup = kmem_alloc(n, KM_SLEEP); /* caller must free */
1144 (void) bcopy(np->nvp_devid, devid_dup, n);
1145 *devidp = devid_dup;
1146
1147 if (ua && nodenamebuf) {
1148 (void) strncpy(nodenamebuf, node, nodelen);
1149 nodenamebuf[nodelen] = '\0';
1150 }
1151
1152 rv = DDI_SUCCESS;
1153 break;
1154 }
1155
1156 rw_exit(nvf_lock(dcfd_handle));
1157
1158 return (rv);
1159 }
1160
1161 #ifdef DEBUG
1162 static void
1163 devid_log(char *fmt, ddi_devid_t devid, char *path)
1164 {
1165 char *devidstr = ddi_devid_str_encode(devid, NULL);
1166 if (path) {
1167 cmn_err(CE_CONT, "%s: %s %s\n", fmt, path, devidstr);
1168 } else {
1169 cmn_err(CE_CONT, "%s: %s\n", fmt, devidstr);
1170 }
1171 ddi_devid_str_free(devidstr);
1172 }
1173 #endif /* DEBUG */