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 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Gathers properties exported by libtopo and uses them to construct diskmon
29 * data structures, which hold the configuration information for the
30 * DE.
31 */
32
33 #include <limits.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <strings.h>
38 #include <ctype.h>
39 #include <pthread.h>
40 #include <libnvpair.h>
41 #include <config_admin.h>
42 #include <sys/fm/protocol.h>
43 #include <fm/libtopo.h>
44 #include <fm/topo_hc.h>
45
46 #include "disk.h"
47 #include "disk_monitor.h"
48 #include "hotplug_mgr.h"
49 #include "topo_gather.h"
50
51 #define TOPO_PGROUP_IO "io" /* duplicated from did_props.h */
52 #define MAX_CONF_MSG_LEN 256
53
54 static nvlist_t *g_topo2diskmon = NULL;
55
56 /*
57 * The following function template is required for nvlists that were
58 * create with no flags (so there can be multiple identical name or name-value
59 * pairs). The function defined below returns the first match for the name
60 * provided.
61 */
62 #define NONUNIQUE_NVLIST_FN(suffix, type, atype) \
63 static int \
64 nonunique_nvlist_lookup_##suffix(nvlist_t *nvlp, const char *n, atype *rpp) \
65 { \
66 nvpair_t *nvp = NULL; \
67 while ((nvp = nvlist_next_nvpair(nvlp, nvp)) != NULL) { \
68 if (nvpair_type(nvp) != type) \
69 continue; \
70 if (strcmp(nvpair_name(nvp), n) == 0) \
71 return (nvpair_value_##suffix(nvp, rpp)); \
72 } \
73 return (ENOENT); \
74 }
75
NONUNIQUE_NVLIST_FN(string,DATA_TYPE_STRING,char *)76 NONUNIQUE_NVLIST_FN(string, DATA_TYPE_STRING, char *)
77
78 static diskmon_t *
79 dm_fmristring_to_diskmon(char *str)
80 {
81 diskmon_t *p = NULL;
82 uint64_t u64val;
83 char ch;
84 char *lastsl = strrchr(str, '/');
85
86 ch = *lastsl;
87 *lastsl = 0;
88
89 if (nvlist_lookup_uint64(g_topo2diskmon, str, &u64val) == 0) {
90
91 p = (diskmon_t *)(uintptr_t)u64val;
92 }
93
94 *lastsl = ch;
95
96 return (p);
97 }
98
99 diskmon_t *
dm_fmri_to_diskmon(fmd_hdl_t * hdl,nvlist_t * fmri)100 dm_fmri_to_diskmon(fmd_hdl_t *hdl, nvlist_t *fmri)
101 {
102 topo_hdl_t *thdl;
103 nvlist_t *dupfmri;
104 diskmon_t *diskp;
105 char *buf;
106 int err;
107
108 if (nvlist_dup(fmri, &dupfmri, 0) != 0)
109 return (NULL);
110
111 (void) nvlist_remove(dupfmri, FM_FMRI_HC_REVISION, DATA_TYPE_STRING);
112 (void) nvlist_remove(dupfmri, FM_FMRI_HC_SERIAL_ID, DATA_TYPE_STRING);
113 (void) nvlist_remove(dupfmri, FM_FMRI_HC_PART, DATA_TYPE_STRING);
114
115 thdl = fmd_hdl_topo_hold(hdl, TOPO_VERSION);
116 if (topo_fmri_nvl2str(thdl, dupfmri, &buf, &err) != 0) {
117 fmd_hdl_topo_rele(hdl, thdl);
118 nvlist_free(dupfmri);
119 return (NULL);
120 }
121 fmd_hdl_topo_rele(hdl, thdl);
122
123 diskp = dm_fmristring_to_diskmon(buf);
124
125 nvlist_free(dupfmri);
126 topo_hdl_strfree(thdl, buf);
127
128 return (diskp);
129 }
130
131 static nvlist_t *
find_disk_monitor_private_pgroup(tnode_t * node)132 find_disk_monitor_private_pgroup(tnode_t *node)
133 {
134 int err;
135 nvlist_t *list_of_lists, *nvlp, *dupnvlp;
136 nvlist_t *disk_monitor_pgrp = NULL;
137 nvpair_t *nvp = NULL;
138 char *pgroup_name;
139
140 /*
141 * topo_prop_get_all() returns an nvlist that contains other
142 * nvlists (some of which are property groups). Since the private
143 * property group we need will be among the list of property
144 * groups returned (hopefully), we need to walk the list of nvlists
145 * in the topo node's properties to find the property groups, then
146 * check inside each embedded nvlist to see if it's the pgroup we're
147 * looking for.
148 */
149 if ((list_of_lists = topo_prop_getprops(node, &err)) != NULL) {
150 /*
151 * Go through the list of nvlists, looking for the
152 * property group we need.
153 */
154 while ((nvp = nvlist_next_nvpair(list_of_lists, nvp)) != NULL) {
155
156 if (nvpair_type(nvp) != DATA_TYPE_NVLIST ||
157 strcmp(nvpair_name(nvp), TOPO_PROP_GROUP) != 0 ||
158 nvpair_value_nvlist(nvp, &nvlp) != 0)
159 continue;
160
161 dm_assert(nvlp != NULL);
162 pgroup_name = NULL;
163
164 if (nonunique_nvlist_lookup_string(nvlp,
165 TOPO_PROP_GROUP_NAME, &pgroup_name) != 0 ||
166 strcmp(pgroup_name, DISK_MONITOR_PROPERTIES) != 0)
167 continue;
168 else {
169 /*
170 * Duplicate the nvlist so that when the
171 * master nvlist is freed (below), we will
172 * still refer to allocated memory.
173 */
174 if (nvlist_dup(nvlp, &dupnvlp, 0) == 0)
175 disk_monitor_pgrp = dupnvlp;
176 else
177 disk_monitor_pgrp = NULL;
178 break;
179 }
180 }
181
182 nvlist_free(list_of_lists);
183 }
184
185 return (disk_monitor_pgrp);
186 }
187
188 /*
189 * Look up the FMRI corresponding to the node in the global
190 * hash table and return the pointer stored (if any). Save the
191 * FMRI string in *str if str is non-NULL.
192 */
193 static void *
fmri2ptr(topo_hdl_t * thp,tnode_t * node,char ** str,int * err)194 fmri2ptr(topo_hdl_t *thp, tnode_t *node, char **str, int *err)
195 {
196 nvlist_t *fmri = NULL;
197 char *cstr = NULL;
198 uint64_t u64val;
199 void *p = NULL;
200
201 if (topo_node_resource(node, &fmri, err) != 0)
202 return (NULL);
203
204 if (topo_fmri_nvl2str(thp, fmri, &cstr, err) != 0) {
205 nvlist_free(fmri);
206 return (NULL);
207 }
208
209 if (nvlist_lookup_uint64(g_topo2diskmon, cstr, &u64val) == 0) {
210
211 p = (void *)(uintptr_t)u64val;
212 }
213
214 nvlist_free(fmri);
215 if (str != NULL)
216 *str = dstrdup(cstr);
217 topo_hdl_strfree(thp, cstr);
218 return (p);
219 }
220
221 typedef struct walk_diskmon {
222 diskmon_t *target;
223 char *pfmri;
224 } walk_diskmon_t;
225
226 static int
topo_add_disk(topo_hdl_t * thp,tnode_t * node,walk_diskmon_t * wdp)227 topo_add_disk(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp)
228 {
229 diskmon_t *target_diskp = wdp->target;
230 char *devpath = NULL;
231 char *capacity = NULL;
232 char *firmrev = NULL;
233 char *serial = NULL;
234 char *manuf = NULL;
235 char *model = NULL;
236 char *label;
237 uint64_t ptr = 0;
238 int err;
239 dm_fru_t *frup;
240 diskmon_t *diskp;
241
242 if (wdp->pfmri == NULL) {
243 log_msg(MM_TOPO, "No diskmon for parent of node %p.\n", node);
244 return (0);
245 }
246
247 if (nvlist_lookup_uint64(g_topo2diskmon, wdp->pfmri, &ptr) != 0) {
248 log_msg(MM_TOPO, "No diskmon for %s: parent of node %p.\n",
249 wdp->pfmri, node);
250 dstrfree(wdp->pfmri);
251 /* Skip this disk: */
252 return (0);
253 }
254
255 dstrfree(wdp->pfmri);
256 wdp->pfmri = NULL;
257
258 diskp = (diskmon_t *)(uintptr_t)ptr;
259
260 /* If we were called upon to update a particular disk, do it */
261 if (target_diskp != NULL && diskp != target_diskp) {
262 return (0);
263 }
264
265 /*
266 * Update the diskmon's location field with the disk's label
267 */
268 if (diskp->location)
269 dstrfree(diskp->location);
270 if (topo_node_label(node, &label, &err) == 0) {
271 diskp->location = dstrdup(label);
272 topo_hdl_strfree(thp, label);
273 } else
274 diskp->location = dstrdup("unknown location");
275
276 /*
277 * Check for a device path property (if the disk is configured,
278 * it will be present) and add it to the diskmon's properties)
279 */
280 if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH,
281 &devpath, &err) == 0) {
282 char devp[PATH_MAX];
283 /*
284 * Consumers of the DISK_PROP_DEVPATH property expect a raw
285 * minor device node
286 */
287 (void) snprintf(devp, PATH_MAX, "%s:q,raw", devpath);
288 (void) nvlist_add_string(diskp->props, DISK_PROP_DEVPATH,
289 devp);
290 topo_hdl_strfree(thp, devpath);
291 }
292
293 /*
294 * Add the logical disk node, if it exists
295 */
296 if (topo_prop_get_string(node, TOPO_PGROUP_STORAGE,
297 TOPO_STORAGE_LOGICAL_DISK_NAME, &devpath, &err) == 0) {
298 (void) nvlist_add_string(diskp->props, DISK_PROP_LOGNAME,
299 devpath);
300 topo_hdl_strfree(thp, devpath);
301 }
302
303 /*
304 * Add the FRU information (if present in the node) to the diskmon's
305 * fru data structure:
306 */
307 (void) topo_prop_get_string(node, TOPO_PGROUP_STORAGE,
308 TOPO_STORAGE_MODEL, &model, &err);
309
310 (void) topo_prop_get_string(node, TOPO_PGROUP_STORAGE,
311 TOPO_STORAGE_MANUFACTURER, &manuf, &err);
312
313 (void) topo_prop_get_string(node, TOPO_PGROUP_STORAGE,
314 TOPO_STORAGE_SERIAL_NUM, &serial, &err);
315
316 (void) topo_prop_get_string(node, TOPO_PGROUP_STORAGE,
317 TOPO_STORAGE_FIRMWARE_REV, &firmrev, &err);
318
319 (void) topo_prop_get_string(node, TOPO_PGROUP_STORAGE,
320 TOPO_STORAGE_CAPACITY, &capacity, &err);
321
322 frup = new_dmfru(manuf != NULL ? manuf : "", model != NULL ? model : "",
323 firmrev != NULL ? firmrev : "", serial != NULL ? serial : "",
324 capacity == NULL ? 0 : strtoull(capacity, 0, 0));
325
326 if (model)
327 topo_hdl_strfree(thp, model);
328 if (manuf)
329 topo_hdl_strfree(thp, manuf);
330 if (serial)
331 topo_hdl_strfree(thp, serial);
332 if (firmrev)
333 topo_hdl_strfree(thp, firmrev);
334 if (capacity)
335 topo_hdl_strfree(thp, capacity);
336
337 /* Add the fru information to the diskmon: */
338 dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0);
339 dm_assert(diskp->frup == NULL);
340 diskp->frup = frup;
341 dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0);
342
343 return (0);
344 }
345
346 static int
indicator_breakup(char * identifier,ind_state_t * state,char ** name)347 indicator_breakup(char *identifier, ind_state_t *state, char **name)
348 {
349 if (identifier[0] != '+' && identifier[0] != '-') {
350 log_msg(MM_CONF, "Invalid indicator name `%s'\n", identifier);
351 return (-1);
352 }
353
354 *state = (identifier[0] == '+') ? INDICATOR_ON : INDICATOR_OFF;
355 *name = &identifier[1];
356 return (0);
357 }
358
359 static int
topoprop_indicator_add(indicator_t ** indp,char * ind_name,char * ind_action)360 topoprop_indicator_add(indicator_t **indp, char *ind_name, char *ind_action)
361 {
362 /* The Indicator name is of the form: "[+-][A-Za-z][A-Za-z0-9]+" */
363 indicator_t *newindp;
364 ind_state_t state;
365 char *name;
366
367 if (indicator_breakup(ind_name, &state, &name) != 0)
368 return (-1);
369 newindp = new_indicator(state, name, ind_action);
370
371 link_indicator(indp, newindp);
372
373 return (0);
374 }
375
376 static hotplug_state_t
str2dmstate(char * str)377 str2dmstate(char *str)
378 {
379 if (strcasecmp("configured", str) == 0) {
380 return (HPS_CONFIGURED);
381 } else if (strcasecmp("unconfigured", str) == 0) {
382 return (HPS_UNCONFIGURED);
383 } else if (strcasecmp("absent", str) == 0) {
384 return (HPS_ABSENT);
385 } else if (strcasecmp("present", str) == 0) {
386 return (HPS_PRESENT);
387 } else
388 return (HPS_UNKNOWN);
389 }
390
391 static int
topoprop_indrule_add(indrule_t ** indrp,char * sts,char * acts)392 topoprop_indrule_add(indrule_t **indrp, char *sts, char *acts)
393 {
394 ind_action_t *indactp = NULL;
395 ind_state_t state;
396 char *name, *lasts, *p;
397 int stateslen = strlen(sts) + 1;
398 int actionslen = strlen(acts) + 1;
399 char *states = dstrdup(sts);
400 char *actions = dstrdup(acts);
401 state_transition_t strans;
402 boolean_t failed = B_FALSE;
403 conf_err_t err;
404 char msgbuf[MAX_CONF_MSG_LEN];
405
406 /* The state string is of the form "{STATE}>{STATE}" */
407 p = strchr(states, '>');
408 dm_assert(p != NULL);
409 *p = 0;
410 strans.begin = str2dmstate(states);
411 *p = '>';
412 strans.end = str2dmstate(p + 1);
413
414 if (strans.begin == HPS_UNKNOWN || strans.end == HPS_UNKNOWN) {
415 log_msg(MM_CONF, "Invalid states property `%s'\n", sts);
416 failed = B_TRUE;
417 } else if ((err = check_state_transition(strans.begin, strans.end))
418 != E_NO_ERROR) {
419 conf_error_msg(err, msgbuf, MAX_CONF_MSG_LEN, &strans);
420 log_msg(MM_CONF, "%s: Not adding disk to list!\n", msgbuf);
421 failed = B_TRUE;
422 }
423
424 /* Actions are of the form "{ACTION}[&{ACTION}]" */
425 if (!failed && (p = strtok_r(actions, "&", &lasts)) != NULL) {
426 /* At least 2 tokens */
427 do {
428 if (indicator_breakup(p, &state, &name) != 0) {
429 failed = B_TRUE;
430 break;
431 }
432
433 link_indaction(&indactp, new_indaction(state, name));
434
435 } while ((p = strtok_r(NULL, "&", &lasts)) != NULL);
436 } else if (!failed) {
437 /* One token */
438 if (indicator_breakup(actions, &state, &name) != 0)
439 return (-1);
440 indactp = new_indaction(state, name);
441 }
442
443 dfree(states, stateslen);
444 dfree(actions, actionslen);
445
446 if (!failed && (err = check_indactions(indactp)) != E_NO_ERROR) {
447 conf_error_msg(err, msgbuf, MAX_CONF_MSG_LEN, NULL);
448 log_msg(MM_CONF, "%s: Not adding disk to list!\n", msgbuf);
449 failed = B_TRUE;
450 }
451
452 if (failed) {
453 indaction_free(indactp);
454 return (-1);
455 } else
456 link_indrule(indrp, new_indrule(&strans, indactp));
457 return (0);
458 }
459
460
461 static int
topo_add_bay(topo_hdl_t * thp,tnode_t * node,walk_diskmon_t * wdp)462 topo_add_bay(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp)
463 {
464 diskmon_t *target_diskp = wdp->target;
465 nvlist_t *nvlp = find_disk_monitor_private_pgroup(node);
466 nvlist_t *prop_nvlp;
467 nvpair_t *nvp = NULL;
468 char *prop_name, *prop_value;
469 #define PNAME_MAX 128
470 char pname[PNAME_MAX];
471 char msgbuf[MAX_CONF_MSG_LEN];
472 char *indicator_name, *indicator_action;
473 char *indrule_states, *indrule_actions;
474 int err = 0, i;
475 conf_err_t conferr;
476 boolean_t conf_failure = B_FALSE;
477 char *unadj_physid = NULL;
478 char physid[MAXPATHLEN];
479 char *label;
480 nvlist_t *diskprops = NULL;
481 char *cstr = NULL;
482 indicator_t *indp = NULL;
483 indrule_t *indrp = NULL;
484 void *p;
485 diskmon_t *diskp;
486 void *ptr;
487
488 /* No private properties -- just ignore the port */
489 if (nvlp == NULL)
490 return (0);
491
492 /*
493 * Look for a diskmon based on this node's FMRI string.
494 * Once a diskmon has been created, it's not re-created. This is
495 * essential for the times when the tree-walk is called after a
496 * disk is inserted (or removed) -- in that case, the disk node
497 * handler simply updates the FRU information in the diskmon.
498 */
499 if ((p = fmri2ptr(thp, node, &cstr, &err)) != NULL) {
500
501 diskp = (diskmon_t *)p;
502
503 /*
504 * Delete the FRU information from the diskmon. If a disk
505 * is connected, its FRU information will be refreshed by
506 * the disk node code.
507 */
508 if (diskp->frup && (target_diskp == NULL ||
509 diskp == target_diskp)) {
510 dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0);
511 dmfru_free(diskp->frup);
512 diskp->frup = NULL;
513 dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0);
514 }
515
516 wdp->pfmri = cstr;
517 nvlist_free(nvlp);
518 return (0);
519 }
520
521 /*
522 * Determine the physical path to the attachment point
523 */
524 if (topo_prop_get_string(node, TOPO_PGROUP_IO,
525 TOPO_IO_AP_PATH, &unadj_physid, &err) == 0) {
526
527 adjust_dynamic_ap(unadj_physid, physid);
528 topo_hdl_strfree(thp, unadj_physid);
529 } else {
530
531 /* unadj_physid cannot have been allocated */
532 if (cstr)
533 dstrfree(cstr);
534 nvlist_free(nvlp);
535 return (-1);
536 }
537
538 /*
539 */
540
541 /*
542 * Process the properties. If we encounter a property that
543 * is not an indicator name, action, or rule, add it to the
544 * disk's props list.
545 */
546
547 /* Process indicators */
548 i = 0;
549 indicator_name = NULL;
550 indicator_action = NULL;
551 do {
552 if (indicator_name != NULL && indicator_action != NULL) {
553
554 if (topoprop_indicator_add(&indp, indicator_name,
555 indicator_action) != 0) {
556
557 conf_failure = B_TRUE;
558 }
559
560 topo_hdl_strfree(thp, indicator_name);
561 topo_hdl_strfree(thp, indicator_action);
562 }
563
564 (void) snprintf(pname, PNAME_MAX, BAY_IND_NAME "-%d", i);
565 if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES,
566 pname, &indicator_name, &err) != 0)
567 break;
568
569 (void) snprintf(pname, PNAME_MAX, BAY_IND_ACTION "-%d", i);
570 if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES,
571 pname, &indicator_action, &err) != 0)
572 break;
573
574 i++;
575 } while (!conf_failure && indicator_name != NULL &&
576 indicator_action != NULL);
577
578 if (!conf_failure && indp != NULL &&
579 (conferr = check_inds(indp)) != E_NO_ERROR) {
580 conf_error_msg(conferr, msgbuf, MAX_CONF_MSG_LEN, NULL);
581 log_msg(MM_CONF, "%s: Not adding disk to list\n", msgbuf);
582 conf_failure = B_TRUE;
583 }
584
585 /* Process state rules and indicator actions */
586 i = 0;
587 indrule_states = NULL;
588 indrule_actions = NULL;
589 do {
590 if (indrule_states != NULL && indrule_actions != NULL) {
591
592 if (topoprop_indrule_add(&indrp, indrule_states,
593 indrule_actions) != 0) {
594
595 conf_failure = B_TRUE;
596 }
597
598 topo_hdl_strfree(thp, indrule_states);
599 topo_hdl_strfree(thp, indrule_actions);
600 }
601
602 (void) snprintf(pname, PNAME_MAX, BAY_INDRULE_STATES "-%d", i);
603 if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES,
604 pname, &indrule_states, &err) != 0)
605 break;
606
607 (void) snprintf(pname, PNAME_MAX, BAY_INDRULE_ACTIONS "-%d",
608 i);
609 if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES,
610 pname, &indrule_actions, &err) != 0)
611 break;
612
613 i++;
614 } while (!conf_failure && indrule_states != NULL &&
615 indrule_actions != NULL);
616
617 if (!conf_failure && indrp != NULL && indp != NULL &&
618 ((conferr = check_indrules(indrp, (state_transition_t **)&ptr))
619 != E_NO_ERROR ||
620 (conferr = check_consistent_ind_indrules(indp, indrp,
621 (ind_action_t **)&ptr)) != E_NO_ERROR)) {
622
623 conf_error_msg(conferr, msgbuf, MAX_CONF_MSG_LEN, ptr);
624 log_msg(MM_CONF, "%s: Not adding disk to list\n", msgbuf);
625 conf_failure = B_TRUE;
626
627 }
628
629 /*
630 * Now collect miscellaneous properties.
631 * Each property is stored as an embedded nvlist named
632 * TOPO_PROP_VAL. The property name is stored in the value for
633 * key=TOPO_PROP_VAL_NAME and the property's value is
634 * stored in the value for key=TOPO_PROP_VAL_VAL. This is all
635 * necessary so we can subtractively decode the properties that
636 * we do not directly handle (so that these properties are added to
637 * the per-disk properties nvlist), increasing flexibility.
638 */
639 (void) nvlist_alloc(&diskprops, NV_UNIQUE_NAME, 0);
640 while ((nvp = nvlist_next_nvpair(nvlp, nvp)) != NULL) {
641 /* Only care about embedded nvlists named TOPO_PROP_VAL */
642 if (nvpair_type(nvp) != DATA_TYPE_NVLIST ||
643 strcmp(nvpair_name(nvp), TOPO_PROP_VAL) != 0 ||
644 nvpair_value_nvlist(nvp, &prop_nvlp) != 0)
645 continue;
646
647 if (nonunique_nvlist_lookup_string(prop_nvlp,
648 TOPO_PROP_VAL_NAME, &prop_name) != 0)
649 continue;
650
651 /* Filter out indicator properties */
652 if (strstr(prop_name, BAY_IND_NAME) != NULL ||
653 strstr(prop_name, BAY_IND_ACTION) != NULL ||
654 strstr(prop_name, BAY_INDRULE_STATES) != NULL ||
655 strstr(prop_name, BAY_INDRULE_ACTIONS) != NULL)
656 continue;
657
658 if (nonunique_nvlist_lookup_string(prop_nvlp, TOPO_PROP_VAL_VAL,
659 &prop_value) != 0)
660 continue;
661
662 /* Add the property to the disk's prop list: */
663 if (nvlist_add_string(diskprops, prop_name, prop_value) != 0)
664 log_msg(MM_TOPO,
665 "Could not add disk property `%s' with "
666 "value `%s'\n", prop_name, prop_value);
667 }
668
669 nvlist_free(nvlp);
670
671 if (cstr != NULL) {
672 namevalpr_t nvpr;
673 nvlist_t *dmap_nvl;
674
675 nvpr.name = DISK_AP_PROP_APID;
676 nvpr.value = strncmp(physid, "/devices", 8) == 0 ?
677 (physid + 8) : physid;
678
679 /*
680 * Set the diskmon's location to the value in this port's label.
681 * If there's a disk plugged in, the location will be updated
682 * to be the disk label (e.g. HD_ID_00). Until a disk is
683 * inserted, though, there won't be a disk libtopo node
684 * created.
685 */
686
687 /* Pass physid without the leading "/devices": */
688 dmap_nvl = namevalpr_to_nvlist(&nvpr);
689
690 diskp = new_diskmon(dmap_nvl, indp, indrp, diskprops);
691
692 if (topo_node_label(node, &label, &err) == 0) {
693 diskp->location = dstrdup(label);
694 topo_hdl_strfree(thp, label);
695 } else
696 diskp->location = dstrdup("unknown location");
697
698 if (!conf_failure && diskp != NULL) {
699 /* Add this diskmon to the disk list */
700 cfgdata_add_diskmon(config_data, diskp);
701 if (nvlist_add_uint64(g_topo2diskmon, cstr,
702 (uint64_t)(uintptr_t)diskp) != 0) {
703 log_msg(MM_TOPO,
704 "Could not add pointer to nvlist "
705 "for `%s'!\n", cstr);
706 }
707 } else if (diskp != NULL) {
708 diskmon_free(diskp);
709 } else {
710 nvlist_free(dmap_nvl);
711 if (indp)
712 ind_free(indp);
713 if (indrp)
714 indrule_free(indrp);
715 nvlist_free(diskprops);
716 }
717
718 wdp->pfmri = cstr;
719 }
720
721
722 return (0);
723 }
724
725 /*ARGSUSED*/
726 static int
gather_topo_cfg(topo_hdl_t * thp,tnode_t * node,void * arg)727 gather_topo_cfg(topo_hdl_t *thp, tnode_t *node, void *arg)
728 {
729 char *nodename = topo_node_name(node);
730 if (strcmp(DISK, nodename) == 0)
731 return (topo_add_disk(thp, node, (walk_diskmon_t *)arg)
732 ? TOPO_WALK_ERR : TOPO_WALK_NEXT);
733 else if (strcmp(BAY, nodename) == 0)
734 return (topo_add_bay(thp, node, (walk_diskmon_t *)arg)
735 ? TOPO_WALK_ERR : TOPO_WALK_NEXT);
736
737 return (TOPO_WALK_NEXT);
738 }
739
740
741 /*ARGSUSED*/
742 int
update_configuration_from_topo(fmd_hdl_t * hdl,diskmon_t * diskp)743 update_configuration_from_topo(fmd_hdl_t *hdl, diskmon_t *diskp)
744 {
745 int err;
746 topo_hdl_t *thp;
747 topo_walk_t *twp;
748 walk_diskmon_t wd;
749
750 if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL) {
751 return (TOPO_OPEN_ERROR);
752 }
753
754 wd.target = diskp;
755 wd.pfmri = NULL;
756 if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, gather_topo_cfg,
757 &wd, &err)) == NULL) {
758 fmd_hdl_topo_rele(hdl, thp);
759 return (err ? TOPO_WALK_INIT_ERROR : TOPO_SUCCESS);
760 }
761
762 if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) {
763
764 topo_walk_fini(twp);
765 if (wd.pfmri != NULL)
766 dstrfree(wd.pfmri);
767
768 fmd_hdl_topo_rele(hdl, thp);
769 return (TOPO_WALK_ERROR);
770 }
771
772 topo_walk_fini(twp);
773 fmd_hdl_topo_rele(hdl, thp);
774 if (wd.pfmri != NULL)
775 dstrfree(wd.pfmri);
776
777 return (TOPO_SUCCESS);
778 }
779
780 int
init_configuration_from_topo(void)781 init_configuration_from_topo(void)
782 {
783 return (nvlist_alloc(&g_topo2diskmon, NV_UNIQUE_NAME, 0));
784 }
785
786 void
fini_configuration_from_topo(void)787 fini_configuration_from_topo(void)
788 {
789 if (g_topo2diskmon) {
790 nvlist_free(g_topo2diskmon);
791 }
792 }
793