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