Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/topo/libtopo/common/topo_prop.c
+++ new/usr/src/lib/fm/topo/libtopo/common/topo_prop.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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <strings.h>
27 27 #include <assert.h>
28 28 #include <fm/libtopo.h>
29 29 #include <topo_prop.h>
30 30 #include <topo_string.h>
31 31 #include <topo_alloc.h>
32 32 #include <topo_error.h>
33 33 #include <topo_method.h>
34 34
35 35 /*
36 36 * Topology nodes are permitted to contain property information.
37 37 * Property information is organized according to property grouping.
38 38 * Each property group defines a name, a stability level for that name,
39 39 * a stability level for all underlying property data (name, type, values),
40 40 * a version for the property group definition and and a list of uniquely
41 41 * defined properties. Property group versions are incremented when one of
42 42 * the following changes occurs:
43 43 * - a property name changes
44 44 * - a property type changes
45 45 * - a property definition is removed from the group
46 46 * Compatible changes such as new property definitions in the group do
47 47 * not require version changes.
48 48 *
49 49 * Each property defines a unique (within the group) name, a type and
50 50 * a value. Properties may be statically defined as int32, uint32, int64,
51 51 * uint64, fmri, string or arrays of each type. Properties may also be
52 52 * dynamically exported via module registered methods. For example, a module
53 53 * may register a method to export an ASRU property that is dynamically
54 54 * contructed when a call to topo_node_fmri() is invoked for a particular
55 55 * topology node.
56 56 *
57 57 * Static properties are persistently attached to topology nodes during
58 58 * enumeration by an enumeration module or as part of XML statements in a
59 59 * toplogy map file using the topo_prop_set* family of routines. Similarly,
60 60 * property methods are registered during enumeration or as part of
61 61 * statements in topololgy map files. Set-up of property methods is performed
62 62 * by calling topo_prop_method_register().
63 63 *
64 64 * All properties, whether statically persisted in a snapshot or dynamically
65 65 * obtained, may be read via the topo_prop_get* family of interfaces.
66 66 * Callers wishing to receive all property groups and properties for a given
67 67 * node may use topo_prop_getall(). This routine returns a nested nvlist
68 68 * of all groupings and property (name, type, value) sets. Groupings
69 69 * are defined by TOPO_PROP_GROUP (name, data stability, name stability and
70 70 * version) and a nested nvlist of properties (TOPO_PROP_VAL). Each property
71 71 * value is defined by its name, type and value.
72 72 */
73 73 static void topo_propval_destroy(topo_propval_t *);
74 74
75 75 static topo_pgroup_t *
76 76 pgroup_get(tnode_t *node, const char *pgname)
77 77 {
78 78 topo_pgroup_t *pg;
79 79 /*
80 80 * Check for an existing pgroup
81 81 */
82 82 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
83 83 pg = topo_list_next(pg)) {
84 84 if (strcmp(pg->tpg_info->tpi_name, pgname) == 0) {
85 85 return (pg);
86 86 }
87 87 }
88 88
89 89 return (NULL);
90 90 }
91 91
92 92 static topo_propval_t *
93 93 propval_get(topo_pgroup_t *pg, const char *pname)
94 94 {
95 95 topo_proplist_t *pvl;
96 96
97 97 if (pg == NULL)
98 98 return (NULL);
99 99
100 100 for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL;
101 101 pvl = topo_list_next(pvl)) {
↓ open down ↓ |
101 lines elided |
↑ open up ↑ |
102 102 if (strcmp(pvl->tp_pval->tp_name, pname) == 0)
103 103 return (pvl->tp_pval);
104 104 }
105 105
106 106 return (NULL);
107 107 }
108 108
109 109 static int
110 110 method_geterror(nvlist_t *nvl, int err, int *errp)
111 111 {
112 - if (nvl != NULL)
113 - nvlist_free(nvl);
112 + nvlist_free(nvl);
114 113
115 114 *errp = err;
116 115
117 116 return (-1);
118 117 }
119 118
120 119 static int
121 120 prop_method_get(tnode_t *node, topo_propval_t *pv, topo_propmethod_t *pm,
122 121 nvlist_t *pargs, int *err)
123 122 {
124 123 int ret;
125 124 nvlist_t *args, *nvl;
126 125 char *name;
127 126 topo_type_t type;
128 127
129 128 if (topo_hdl_nvalloc(pv->tp_hdl, &args, NV_UNIQUE_NAME) < 0 ||
130 129 nvlist_add_nvlist(args, TOPO_PROP_ARGS, pm->tpm_args) != 0)
131 130 return (method_geterror(NULL, ETOPO_PROP_NVL, err));
132 131
133 132 if (pargs != NULL)
134 133 if (nvlist_add_nvlist(args, TOPO_PROP_PARGS, pargs) != 0)
135 134 return (method_geterror(args, ETOPO_PROP_NVL, err));
136 135
137 136 /*
138 137 * Now, get the latest value
139 138 *
140 139 * Grab a reference to the property and then unlock the node. This will
141 140 * allow property methods to safely re-enter the prop_get codepath,
142 141 * making it possible for property methods to access other property
143 142 * values on the same node w\o causing a deadlock.
144 143 */
145 144 topo_prop_hold(pv);
146 145 topo_node_unlock(node);
147 146 if (topo_method_call(node, pm->tpm_name, pm->tpm_version,
148 147 args, &nvl, err) < 0) {
149 148 topo_node_lock(node);
150 149 topo_prop_rele(pv);
151 150 return (method_geterror(args, *err, err));
152 151 }
153 152 topo_node_lock(node);
154 153 topo_prop_rele(pv);
155 154
156 155 nvlist_free(args);
157 156
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
158 157 /* Verify the property contents */
159 158 ret = nvlist_lookup_string(nvl, TOPO_PROP_VAL_NAME, &name);
160 159 if (ret != 0 || strcmp(name, pv->tp_name) != 0)
161 160 return (method_geterror(nvl, ETOPO_PROP_NAME, err));
162 161
163 162 ret = nvlist_lookup_uint32(nvl, TOPO_PROP_VAL_TYPE, (uint32_t *)&type);
164 163 if (ret != 0 || type != pv->tp_type)
165 164 return (method_geterror(nvl, ETOPO_PROP_TYPE, err));
166 165
167 166 /* Release the last value and re-assign to the new value */
168 - if (pv->tp_val != NULL)
169 - nvlist_free(pv->tp_val);
167 + nvlist_free(pv->tp_val);
170 168 pv->tp_val = nvl;
171 169
172 170 return (0);
173 171 }
174 172
175 173 static topo_propval_t *
176 174 prop_get(tnode_t *node, const char *pgname, const char *pname, nvlist_t *pargs,
177 175 int *err)
178 176 {
179 177 topo_propval_t *pv = NULL;
180 178
181 179 if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL) {
182 180 *err = ETOPO_PROP_NOENT;
183 181 return (NULL);
184 182 }
185 183
186 184 if (pv->tp_flag & TOPO_PROP_NONVOLATILE && pv->tp_val != NULL)
187 185 return (pv);
188 186
189 187 if (pv->tp_method != NULL) {
190 188 if (prop_method_get(node, pv, pv->tp_method, pargs, err) < 0)
191 189 return (NULL);
192 190 }
193 191
194 192 return (pv);
195 193 }
196 194
197 195 static int
198 196 get_properror(tnode_t *node, int *errp, int err)
199 197 {
200 198 topo_node_unlock(node);
201 199 *errp = err;
202 200 return (-1);
203 201 }
204 202
205 203 static int
206 204 prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val,
207 205 topo_type_t type, uint_t *nelems, int *err)
208 206 {
209 207 int i, j, ret = 0;
210 208 topo_hdl_t *thp = node->tn_hdl;
211 209 topo_propval_t *pv;
212 210
213 211 topo_node_lock(node);
214 212 if ((pv = prop_get(node, pgname, pname, NULL, err))
215 213 == NULL)
216 214 return (get_properror(node, err, *err));
217 215
218 216 if (pv->tp_type != type)
219 217 return (get_properror(node, err, ETOPO_PROP_TYPE));
220 218
221 219 switch (type) {
222 220 case TOPO_TYPE_INT32:
223 221 ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL,
224 222 (int32_t *)val);
225 223 break;
226 224 case TOPO_TYPE_UINT32:
227 225 ret = nvlist_lookup_uint32(pv->tp_val,
228 226 TOPO_PROP_VAL_VAL, (uint32_t *)val);
229 227 break;
230 228 case TOPO_TYPE_INT64:
231 229 ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL,
232 230 (int64_t *)val);
233 231 break;
234 232 case TOPO_TYPE_UINT64:
235 233 ret = nvlist_lookup_uint64(pv->tp_val,
236 234 TOPO_PROP_VAL_VAL, (uint64_t *)val);
237 235 break;
238 236 case TOPO_TYPE_DOUBLE:
239 237 ret = nvlist_lookup_double(pv->tp_val,
240 238 TOPO_PROP_VAL_VAL, (double *)val);
241 239 break;
242 240 case TOPO_TYPE_STRING: {
243 241 char *str;
244 242
245 243 ret = nvlist_lookup_string(pv->tp_val,
246 244 TOPO_PROP_VAL_VAL, &str);
247 245 if (ret == 0) {
248 246 char *s2;
249 247 if ((s2 = topo_hdl_strdup(thp, str)) == NULL)
250 248 ret = -1;
251 249 else
252 250 *(char **)val = s2;
253 251 }
254 252 break;
255 253 }
256 254 case TOPO_TYPE_FMRI: {
257 255 nvlist_t *nvl;
258 256
259 257 ret = nvlist_lookup_nvlist(pv->tp_val,
260 258 TOPO_PROP_VAL_VAL, &nvl);
261 259 if (ret == 0)
262 260 ret = topo_hdl_nvdup(thp, nvl,
263 261 (nvlist_t **)val);
264 262 break;
265 263 }
266 264 case TOPO_TYPE_INT32_ARRAY: {
267 265 int32_t *a1, *a2;
268 266
269 267 if ((ret = nvlist_lookup_int32_array(pv->tp_val,
270 268 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
271 269 break;
272 270 if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) *
273 271 *nelems)) == NULL) {
274 272 ret = ETOPO_NOMEM;
275 273 break;
276 274 }
277 275 for (i = 0; i < *nelems; ++i)
278 276 a1[i] = a2[i];
279 277 *(int32_t **)val = a1;
280 278 break;
281 279 }
282 280 case TOPO_TYPE_UINT32_ARRAY: {
283 281 uint32_t *a1, *a2;
284 282
285 283 if ((ret = nvlist_lookup_uint32_array(pv->tp_val,
286 284 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
287 285 break;
288 286 if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) *
289 287 *nelems)) == NULL) {
290 288 ret = ETOPO_NOMEM;
291 289 break;
292 290 }
293 291 for (i = 0; i < *nelems; ++i)
294 292 a1[i] = a2[i];
295 293 *(uint32_t **)val = a1;
296 294 break;
297 295 }
298 296 case TOPO_TYPE_INT64_ARRAY: {
299 297 int64_t *a1, *a2;
300 298
301 299 if ((ret = nvlist_lookup_int64_array(pv->tp_val,
302 300 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
303 301 break;
304 302 if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) *
305 303 *nelems)) == NULL) {
306 304 ret = ETOPO_NOMEM;
307 305 break;
308 306 }
309 307 for (i = 0; i < *nelems; ++i)
310 308 a1[i] = a2[i];
311 309 *(int64_t **)val = a1;
312 310 break;
313 311 }
314 312 case TOPO_TYPE_UINT64_ARRAY: {
315 313 uint64_t *a1, *a2;
316 314
317 315 if ((ret = nvlist_lookup_uint64_array(pv->tp_val,
318 316 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
319 317 break;
320 318 if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) *
321 319 *nelems)) == NULL) {
322 320 ret = ETOPO_NOMEM;
323 321 break;
324 322 }
325 323 for (i = 0; i < *nelems; ++i)
326 324 a1[i] = a2[i];
327 325 *(uint64_t **)val = a1;
328 326 break;
329 327 }
330 328 case TOPO_TYPE_STRING_ARRAY: {
331 329 char **a1, **a2;
332 330
333 331 if ((ret = nvlist_lookup_string_array(pv->tp_val,
334 332 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
335 333 break;
336 334 if ((a1 = topo_hdl_alloc(thp, sizeof (char *) *
337 335 *nelems)) == NULL) {
338 336 ret = ETOPO_NOMEM;
339 337 break;
340 338 }
341 339 for (i = 0; i < *nelems; ++i) {
342 340 if ((a1[i] = topo_hdl_strdup(thp, a2[i]))
343 341 == NULL) {
344 342 for (j = 0; j < i; ++j)
345 343 topo_hdl_free(thp, a1[j],
346 344 sizeof (char *));
347 345 topo_hdl_free(thp, a1,
348 346 sizeof (char *) * *nelems);
349 347 break;
350 348 }
351 349 }
352 350 *(char ***)val = a1;
353 351 break;
354 352 }
355 353 case TOPO_TYPE_FMRI_ARRAY: {
356 354 nvlist_t **a1, **a2;
357 355
358 356 if ((ret = nvlist_lookup_nvlist_array(pv->tp_val,
359 357 TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
360 358 break;
361 359 if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) *
362 360 *nelems)) == NULL) {
363 361 ret = ETOPO_NOMEM;
364 362 break;
365 363 }
366 364 for (i = 0; i < *nelems; ++i) {
367 365 if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) {
368 366 for (j = 0; j < i; ++j)
369 367 nvlist_free(a1[j]);
370 368 topo_hdl_free(thp, a1,
371 369 sizeof (nvlist_t *) * *nelems);
372 370 break;
373 371 }
374 372 }
375 373 *(nvlist_t ***)val = a1;
376 374 break;
377 375 }
378 376 default:
379 377 ret = ETOPO_PROP_NOENT;
380 378 }
381 379
382 380 if (ret != 0)
383 381 if (ret == ENOENT)
384 382 return (get_properror(node, err, ETOPO_PROP_NOENT));
385 383 else if (ret < ETOPO_UNKNOWN)
386 384 return (get_properror(node, err, ETOPO_PROP_NVL));
387 385 else
388 386 return (get_properror(node, err, ret));
389 387
390 388 topo_node_unlock(node);
391 389 return (0);
392 390 }
393 391
394 392 int
395 393 topo_prop_get_int32(tnode_t *node, const char *pgname, const char *pname,
396 394 int32_t *val, int *err)
397 395 {
398 396 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_INT32,
399 397 NULL, err));
400 398 }
401 399
402 400 int
403 401 topo_prop_get_uint32(tnode_t *node, const char *pgname, const char *pname,
404 402 uint32_t *val, int *err)
405 403 {
406 404 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_UINT32,
407 405 NULL, err));
408 406 }
409 407
410 408 int
411 409 topo_prop_get_int64(tnode_t *node, const char *pgname, const char *pname,
412 410 int64_t *val, int *err)
413 411 {
414 412 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_INT64,
415 413 NULL, err));
416 414 }
417 415
418 416 int
419 417 topo_prop_get_uint64(tnode_t *node, const char *pgname, const char *pname,
420 418 uint64_t *val, int *err)
421 419 {
422 420 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_UINT64,
423 421 NULL, err));
424 422 }
425 423
426 424 int
427 425 topo_prop_get_double(tnode_t *node, const char *pgname, const char *pname,
428 426 double *val, int *err)
429 427 {
430 428 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_DOUBLE,
431 429 NULL, err));
432 430 }
433 431
434 432 int
435 433 topo_prop_get_string(tnode_t *node, const char *pgname, const char *pname,
436 434 char **val, int *err)
437 435 {
438 436 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_STRING,
439 437 NULL, err));
440 438 }
441 439
442 440 int
443 441 topo_prop_get_fmri(tnode_t *node, const char *pgname, const char *pname,
444 442 nvlist_t **val, int *err)
445 443 {
446 444 return (prop_getval(node, pgname, pname, (void *)val, TOPO_TYPE_FMRI,
447 445 NULL, err));
448 446 }
449 447
450 448 int
451 449 topo_prop_get_int32_array(tnode_t *node, const char *pgname, const char *pname,
452 450 int32_t **val, uint_t *nelem, int *err)
453 451 {
454 452 return (prop_getval(node, pgname, pname, (void *)val,
455 453 TOPO_TYPE_INT32_ARRAY, nelem, err));
456 454 }
457 455
458 456 int
459 457 topo_prop_get_uint32_array(tnode_t *node, const char *pgname, const char *pname,
460 458 uint32_t **val, uint_t *nelem, int *err)
461 459 {
462 460 return (prop_getval(node, pgname, pname, (void *)val,
463 461 TOPO_TYPE_UINT32_ARRAY, nelem, err));
464 462 }
465 463
466 464 int
467 465 topo_prop_get_int64_array(tnode_t *node, const char *pgname, const char *pname,
468 466 int64_t **val, uint_t *nelem, int *err)
469 467 {
470 468 return (prop_getval(node, pgname, pname, (void *)val,
471 469 TOPO_TYPE_INT64_ARRAY, nelem, err));
472 470 }
473 471
474 472 int
475 473 topo_prop_get_uint64_array(tnode_t *node, const char *pgname, const char *pname,
476 474 uint64_t **val, uint_t *nelem, int *err)
477 475 {
478 476 return (prop_getval(node, pgname, pname, (void *)val,
479 477 TOPO_TYPE_UINT64_ARRAY, nelem, err));
480 478 }
481 479
482 480 int
483 481 topo_prop_get_string_array(tnode_t *node, const char *pgname, const char *pname,
484 482 char ***val, uint_t *nelem, int *err)
485 483 {
486 484 return (prop_getval(node, pgname, pname, (void *)val,
487 485 TOPO_TYPE_STRING_ARRAY, nelem, err));
488 486 }
489 487
490 488 int
491 489 topo_prop_get_fmri_array(tnode_t *node, const char *pgname, const char *pname,
492 490 nvlist_t ***val, uint_t *nelem, int *err)
493 491 {
494 492 return (prop_getval(node, pgname, pname, (void *)val,
495 493 TOPO_TYPE_FMRI_ARRAY, nelem, err));
496 494 }
497 495
498 496 static topo_propval_t *
499 497 set_seterror(tnode_t *node, topo_proplist_t *pvl, int *errp, int err)
500 498 {
501 499 topo_hdl_t *thp = node->tn_hdl;
502 500 topo_propval_t *pv;
503 501
504 502 if (pvl != NULL) {
505 503 pv = pvl->tp_pval;
506 504 topo_propval_destroy(pv);
507 505 topo_hdl_free(thp, pvl, sizeof (topo_proplist_t));
508 506 }
509 507
510 508 topo_node_unlock(node);
511 509 *errp = err;
512 510
513 511 return (NULL);
514 512 }
515 513
516 514 static topo_propval_t *
517 515 prop_create(tnode_t *node, const char *pgname, const char *pname,
518 516 topo_type_t type, int flag, int *err)
519 517 {
520 518 topo_hdl_t *thp = node->tn_hdl;
521 519 topo_pgroup_t *pg;
522 520 topo_propval_t *pv;
523 521 topo_proplist_t *pvl;
524 522
525 523 /*
526 524 * Replace existing prop value with new one
527 525 */
528 526 if ((pg = pgroup_get(node, pgname)) == NULL) {
529 527 topo_node_unlock(node);
530 528 *err = ETOPO_PROP_NOENT;
531 529 return (NULL);
532 530 }
533 531
534 532 if ((pv = propval_get(pg, pname)) != NULL) {
535 533 if (pv->tp_type != type)
536 534 return (set_seterror(node, NULL, err, ETOPO_PROP_TYPE));
537 535 else if (! (pv->tp_flag & TOPO_PROP_MUTABLE))
538 536 return (set_seterror(node, NULL, err, ETOPO_PROP_DEFD));
539 537
540 538 nvlist_free(pv->tp_val);
541 539 pv->tp_val = NULL;
542 540 } else {
543 541 if ((pvl = topo_hdl_zalloc(thp, sizeof (topo_proplist_t)))
544 542 == NULL)
545 543 return (set_seterror(node, NULL, err, ETOPO_NOMEM));
546 544
547 545 if ((pv = topo_hdl_zalloc(thp, sizeof (topo_propval_t)))
548 546 == NULL)
549 547 return (set_seterror(node, pvl, err, ETOPO_NOMEM));
550 548
551 549 pv->tp_hdl = thp;
552 550 pvl->tp_pval = pv;
553 551
554 552 if ((pv->tp_name = topo_hdl_strdup(thp, pname))
555 553 == NULL)
556 554 return (set_seterror(node, pvl, err, ETOPO_NOMEM));
557 555 pv->tp_flag = flag;
558 556 pv->tp_type = type;
559 557 topo_prop_hold(pv);
560 558 topo_list_append(&pg->tpg_pvals, pvl);
561 559 }
562 560
563 561 return (pv);
564 562 }
565 563
566 564 static int
567 565 topo_prop_set(tnode_t *node, const char *pgname, const char *pname,
568 566 topo_type_t type, int flag, void *val, int nelems, int *err)
569 567 {
570 568 int ret;
571 569 topo_hdl_t *thp = node->tn_hdl;
572 570 nvlist_t *nvl;
573 571
574 572 if (topo_hdl_nvalloc(thp, &nvl, NV_UNIQUE_NAME) < 0) {
575 573 *err = ETOPO_PROP_NVL;
576 574 return (-1);
577 575 }
578 576
579 577 ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pname);
580 578 ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type);
581 579 switch (type) {
582 580 case TOPO_TYPE_INT32:
583 581 ret |= nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL,
584 582 *(int32_t *)val);
585 583 break;
586 584 case TOPO_TYPE_UINT32:
587 585 ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL,
588 586 *(uint32_t *)val);
589 587 break;
590 588 case TOPO_TYPE_INT64:
591 589 ret |= nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL,
592 590 *(int64_t *)val);
593 591 break;
594 592 case TOPO_TYPE_UINT64:
595 593 ret |= nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL,
596 594 *(uint64_t *)val);
597 595 break;
598 596 case TOPO_TYPE_DOUBLE:
599 597 ret |= nvlist_add_double(nvl, TOPO_PROP_VAL_VAL,
600 598 *(double *)val);
601 599 break;
602 600 case TOPO_TYPE_STRING:
603 601 ret |= nvlist_add_string(nvl, TOPO_PROP_VAL_VAL,
604 602 (char *)val);
605 603 break;
606 604 case TOPO_TYPE_FMRI:
607 605 ret |= nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL,
608 606 (nvlist_t *)val);
609 607 break;
610 608 case TOPO_TYPE_INT32_ARRAY:
611 609 ret |= nvlist_add_int32_array(nvl,
612 610 TOPO_PROP_VAL_VAL, (int32_t *)val, nelems);
613 611 break;
614 612 case TOPO_TYPE_UINT32_ARRAY:
615 613 ret |= nvlist_add_uint32_array(nvl,
616 614 TOPO_PROP_VAL_VAL, (uint32_t *)val, nelems);
617 615 break;
618 616 case TOPO_TYPE_INT64_ARRAY:
619 617 ret |= nvlist_add_int64_array(nvl,
620 618 TOPO_PROP_VAL_VAL, (int64_t *)val, nelems);
621 619 break;
622 620 case TOPO_TYPE_UINT64_ARRAY:
623 621 ret |= nvlist_add_uint64_array(nvl,
624 622 TOPO_PROP_VAL_VAL, (uint64_t *)val, nelems);
625 623 break;
626 624 case TOPO_TYPE_STRING_ARRAY:
627 625 ret |= nvlist_add_string_array(nvl,
628 626 TOPO_PROP_VAL_VAL, (char **)val, nelems);
629 627 break;
630 628 case TOPO_TYPE_FMRI_ARRAY:
631 629 ret |= nvlist_add_nvlist_array(nvl,
632 630 TOPO_PROP_VAL_VAL, (nvlist_t **)val, nelems);
633 631 break;
634 632 default:
635 633 *err = ETOPO_PROP_TYPE;
636 634 return (-1);
637 635 }
638 636
639 637 if (ret != 0) {
640 638 nvlist_free(nvl);
641 639 if (ret == ENOMEM) {
642 640 *err = ETOPO_PROP_NOMEM;
643 641 return (-1);
644 642 } else {
645 643 *err = ETOPO_PROP_NVL;
646 644 return (-1);
647 645 }
648 646 }
649 647
650 648 if (topo_prop_setprop(node, pgname, nvl, flag, nvl, err) != 0) {
651 649 nvlist_free(nvl);
652 650 return (-1); /* err set */
653 651 }
654 652 nvlist_free(nvl);
655 653 return (ret);
656 654 }
657 655
658 656 int
659 657 topo_prop_set_int32(tnode_t *node, const char *pgname, const char *pname,
660 658 int flag, int32_t val, int *err)
661 659 {
662 660 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT32, flag,
663 661 &val, 1, err));
664 662 }
665 663
666 664 int
667 665 topo_prop_set_uint32(tnode_t *node, const char *pgname, const char *pname,
668 666 int flag, uint32_t val, int *err)
669 667 {
670 668 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT32, flag,
671 669 &val, 1, err));
672 670 }
673 671
674 672 int
675 673 topo_prop_set_int64(tnode_t *node, const char *pgname, const char *pname,
676 674 int flag, int64_t val, int *err)
677 675 {
678 676 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT64, flag,
679 677 &val, 1, err));
680 678 }
681 679
682 680 int
683 681 topo_prop_set_uint64(tnode_t *node, const char *pgname, const char *pname,
684 682 int flag, uint64_t val, int *err)
685 683 {
686 684 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT64, flag,
687 685 &val, 1, err));
688 686 }
689 687
690 688 int
691 689 topo_prop_set_double(tnode_t *node, const char *pgname, const char *pname,
692 690 int flag, double val, int *err)
693 691 {
694 692 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_DOUBLE, flag,
695 693 &val, 1, err));
696 694 }
697 695
698 696 int
699 697 topo_prop_set_string(tnode_t *node, const char *pgname, const char *pname,
700 698 int flag, const char *val, int *err)
701 699 {
702 700 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_STRING, flag,
703 701 (void *)val, 1, err));
704 702 }
705 703
706 704 int
707 705 topo_prop_set_fmri(tnode_t *node, const char *pgname, const char *pname,
708 706 int flag, const nvlist_t *fmri, int *err)
709 707 {
710 708 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_FMRI, flag,
711 709 (void *)fmri, 1, err));
712 710 }
713 711
714 712 int
715 713 topo_prop_set_int32_array(tnode_t *node, const char *pgname, const char *pname,
716 714 int flag, int32_t *val, uint_t nelems, int *err)
717 715 {
718 716 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT32_ARRAY, flag,
719 717 val, nelems, err));
720 718 }
721 719
722 720 int
723 721 topo_prop_set_uint32_array(tnode_t *node, const char *pgname, const char *pname,
724 722 int flag, uint32_t *val, uint_t nelems, int *err)
725 723 {
726 724 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT32_ARRAY, flag,
727 725 val, nelems, err));
728 726 }
729 727
730 728 int
731 729 topo_prop_set_int64_array(tnode_t *node, const char *pgname, const char *pname,
732 730 int flag, int64_t *val, uint_t nelems, int *err)
733 731 {
734 732 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_INT64_ARRAY, flag,
735 733 val, nelems, err));
736 734 }
737 735
738 736 int
739 737 topo_prop_set_uint64_array(tnode_t *node, const char *pgname, const char *pname,
740 738 int flag, uint64_t *val, uint_t nelems, int *err)
741 739 {
742 740 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_UINT64_ARRAY, flag,
743 741 val, nelems, err));
744 742 }
745 743
746 744 int
747 745 topo_prop_set_string_array(tnode_t *node, const char *pgname, const char *pname,
748 746 int flag, const char **val, uint_t nelems, int *err)
749 747 {
750 748 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_STRING_ARRAY, flag,
751 749 (void *)val, nelems, err));
752 750 }
753 751
754 752 int
755 753 topo_prop_set_fmri_array(tnode_t *node, const char *pgname, const char *pname,
756 754 int flag, const nvlist_t **fmri, uint_t nelems, int *err)
757 755 {
758 756 return (topo_prop_set(node, pgname, pname, TOPO_TYPE_FMRI_ARRAY, flag,
759 757 (void *)fmri, nelems, err));
760 758 }
761 759
762 760 /*
763 761 * topo_prop_setprop() is a private project function for fmtopo
764 762 */
765 763 int
766 764 topo_prop_setprop(tnode_t *node, const char *pgname, nvlist_t *prop,
767 765 int flag, nvlist_t *pargs, int *err)
768 766 {
769 767 int ret;
770 768 topo_hdl_t *thp = node->tn_hdl;
771 769 topo_propval_t *pv;
772 770 nvlist_t *nvl, *args;
773 771 char *name;
774 772 topo_type_t type;
775 773
776 774 if (nvlist_lookup_string(prop, TOPO_PROP_VAL_NAME, &name) != 0) {
777 775 *err = ETOPO_PROP_NAME;
778 776 return (-1);
779 777 }
780 778 if (nvlist_lookup_uint32(prop, TOPO_PROP_VAL_TYPE, (uint32_t *)&type)
781 779 != 0) {
782 780 *err = ETOPO_PROP_TYPE;
783 781 return (-1);
784 782 }
785 783
786 784 topo_node_lock(node);
787 785 if ((pv = prop_create(node, pgname, name, type, flag, err)) == NULL)
788 786 return (-1); /* unlocked and err set */
789 787
790 788 /*
791 789 * Set by method or set to new prop value. If we fail, leave
792 790 * property in list with old value.
793 791 */
794 792 if (pv->tp_method != NULL) {
795 793 topo_propmethod_t *pm = pv->tp_method;
796 794
797 795 if (topo_hdl_nvalloc(pv->tp_hdl, &args, NV_UNIQUE_NAME) < 0) {
798 796 topo_node_unlock(node);
799 797 *err = ETOPO_PROP_NOMEM;
800 798 return (-1);
801 799 }
802 800 ret = nvlist_add_nvlist(args, TOPO_PROP_ARGS, pm->tpm_args);
803 801 if (pargs != NULL)
804 802 ret |= nvlist_add_nvlist(args, TOPO_PROP_PARGS, pargs);
805 803
806 804 if (ret != 0) {
807 805 topo_node_unlock(node);
808 806 nvlist_free(args);
809 807 *err = ETOPO_PROP_NVL;
810 808 return (-1);
811 809 }
812 810
813 811 /*
814 812 *
815 813 * Grab a reference to the property and then unlock the node.
816 814 * This will allow property methods to safely re-enter the
817 815 * prop_get codepath, making it possible for property methods
818 816 * to access other property values on the same node w\o causing
819 817 * a deadlock.
820 818 *
821 819 * We don't technically need this now, since this interface is
822 820 * currently only used by fmtopo (which is single-threaded), but
823 821 * we may make this interface available to other parts of
824 822 * libtopo in the future, so best to make it MT-safe now.
825 823 */
826 824 topo_prop_hold(pv);
827 825 topo_node_unlock(node);
828 826 ret = topo_method_call(node, pm->tpm_name, pm->tpm_version,
829 827 args, &nvl, err);
830 828 topo_node_lock(node);
831 829 topo_prop_rele(pv);
832 830
833 831 nvlist_free(args);
834 832 } else {
835 833 if ((ret = topo_hdl_nvdup(thp, prop, &nvl)) != 0)
836 834 *err = ETOPO_PROP_NOMEM;
837 835 }
838 836
839 837 if (ret != 0) {
840 838 topo_node_unlock(node);
841 839 return (-1);
842 840 }
843 841
844 842 pv->tp_val = nvl;
845 843 topo_node_unlock(node);
846 844 return (0);
847 845 }
↓ open down ↓ |
668 lines elided |
↑ open up ↑ |
848 846
849 847 static int
850 848 register_methoderror(tnode_t *node, topo_propmethod_t *pm, int *errp, int l,
851 849 int err)
852 850 {
853 851 topo_hdl_t *thp = node->tn_hdl;
854 852
855 853 if (pm != NULL) {
856 854 if (pm->tpm_name != NULL)
857 855 topo_hdl_strfree(thp, pm->tpm_name);
858 - if (pm->tpm_args != NULL)
859 - nvlist_free(pm->tpm_args);
856 + nvlist_free(pm->tpm_args);
860 857 topo_hdl_free(thp, pm, sizeof (topo_propmethod_t));
861 858 }
862 859
863 860 *errp = err;
864 861
865 862 if (l != 0)
866 863 topo_node_unlock(node);
867 864
868 865 return (-1);
869 866 }
870 867
871 868 int
872 869 prop_method_register(tnode_t *node, const char *pgname, const char *pname,
873 870 topo_type_t ptype, const char *mname, topo_version_t version,
874 871 const nvlist_t *args, int *err)
875 872 {
876 873 topo_hdl_t *thp = node->tn_hdl;
877 874 topo_propmethod_t *pm = NULL;
878 875 topo_propval_t *pv = NULL;
879 876
880 877 if ((pm = topo_hdl_zalloc(thp, sizeof (topo_propmethod_t))) == NULL)
881 878 return (register_methoderror(node, pm, err, 1,
882 879 ETOPO_PROP_NOMEM));
883 880
884 881 if ((pm->tpm_name = topo_hdl_strdup(thp, mname)) == NULL)
885 882 return (register_methoderror(node, pm, err, 1,
886 883 ETOPO_PROP_NOMEM));
887 884
888 885 pm->tpm_version = version;
889 886
890 887 if (topo_hdl_nvdup(thp, (nvlist_t *)args, &pm->tpm_args) != 0)
891 888 return (register_methoderror(node, pm, err, 1,
892 889 ETOPO_PROP_NOMEM));
893 890
894 891 /*
895 892 * It's possible the property may already exist. However we still want
896 893 * to allow the method to be registered. This is to handle the case
897 894 * where we specify a prop method in an xml map to override the value
898 895 * that was set by the enumerator.
899 896 *
900 897 * By default, propmethod-backed properties are not MUTABLE. This is
901 898 * done to simplify the programming model for modules that implement
902 899 * property methods as most propmethods tend to only support get
903 900 * operations. Enumerator modules can override this by calling
904 901 * topo_prop_setmutable(). Propmethods that are registered via XML can
905 902 * be set as mutable via the optional "mutable" attribute, which will
906 903 * result in the xml parser calling topo_prop_setflags() after
907 904 * registering the propmethod.
908 905 */
909 906 if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL)
910 907 if ((pv = prop_create(node, pgname, pname, ptype,
911 908 TOPO_PROP_IMMUTABLE, err)) == NULL) {
912 909 /* node unlocked */
913 910 return (register_methoderror(node, pm, err, 0, *err));
914 911 }
915 912
916 913 if (pv->tp_method != NULL)
917 914 return (register_methoderror(node, pm, err, 1,
918 915 ETOPO_METHOD_DEFD));
919 916
920 917 if (pv->tp_val != NULL) {
921 918 nvlist_free(pv->tp_val);
922 919 pv->tp_val = NULL;
923 920 }
924 921 pv->tp_method = pm;
925 922
926 923 topo_node_unlock(node);
927 924
928 925 return (0);
929 926 }
930 927
931 928 int
932 929 topo_prop_method_register(tnode_t *node, const char *pgname, const char *pname,
933 930 topo_type_t ptype, const char *mname, const nvlist_t *args, int *err)
934 931 {
935 932 topo_imethod_t *mp;
936 933
937 934 topo_node_lock(node);
938 935
939 936 if ((mp = topo_method_lookup(node, mname)) == NULL)
940 937 return (register_methoderror(node, NULL, err, 1,
941 938 ETOPO_METHOD_NOTSUP)); /* node unlocked */
942 939
943 940 topo_node_lock(node);
944 941
945 942 return (prop_method_register(node, pgname, pname, ptype, mname,
946 943 mp->tim_version, args, err)); /* err set and node unlocked */
947 944 }
948 945
949 946 int
950 947 topo_prop_method_version_register(tnode_t *node, const char *pgname,
951 948 const char *pname, topo_type_t ptype, const char *mname,
952 949 topo_version_t version, const nvlist_t *args, int *err)
953 950 {
954 951 topo_imethod_t *mp;
955 952
956 953 topo_node_lock(node);
957 954
958 955 if ((mp = topo_method_lookup(node, mname)) == NULL)
959 956 return (register_methoderror(node, NULL, err, 1,
960 957 ETOPO_METHOD_NOTSUP)); /* node unlocked */
961 958
962 959 topo_node_lock(node);
963 960
964 961 if (version < mp->tim_version)
965 962 return (register_methoderror(node, NULL, err, 1,
966 963 ETOPO_METHOD_VEROLD));
967 964 if (version > mp->tim_version)
968 965 return (register_methoderror(node, NULL, err, 1,
969 966 ETOPO_METHOD_VERNEW));
970 967
971 968 return (prop_method_register(node, pgname, pname, ptype, mname,
972 969 version, args, err)); /* err set and node unlocked */
973 970 }
974 971
975 972 void
976 973 topo_prop_method_unregister(tnode_t *node, const char *pgname,
977 974 const char *pname)
978 975 {
979 976 topo_propval_t *pv;
980 977 topo_pgroup_t *pg;
981 978 topo_proplist_t *pvl;
982 979 topo_hdl_t *thp = node->tn_hdl;
983 980
984 981 topo_node_lock(node);
985 982
986 983 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
987 984 pg = topo_list_next(pg)) {
988 985 if (strcmp(pg->tpg_info->tpi_name, pgname) == 0) {
989 986 break;
990 987 }
991 988 }
992 989
993 990 if (pg == NULL) {
994 991 topo_node_unlock(node);
995 992 return;
996 993 }
997 994
998 995 for (pvl = topo_list_next(&pg->tpg_list); pvl != NULL;
999 996 pvl = topo_list_next(pvl)) {
1000 997 pv = pvl->tp_pval;
1001 998 if (strcmp(pv->tp_name, pname) == 0) {
1002 999 topo_list_delete(&pg->tpg_pvals, pvl);
1003 1000 assert(pv->tp_refs == 1);
1004 1001 topo_prop_rele(pv);
1005 1002 topo_hdl_free(thp, pvl, sizeof (topo_proplist_t));
1006 1003 break;
1007 1004 }
1008 1005 }
1009 1006
1010 1007 topo_node_unlock(node);
1011 1008 }
1012 1009
1013 1010 int
1014 1011 topo_prop_setmutable(tnode_t *node, const char *pgname, const char *pname,
1015 1012 int *err)
1016 1013 {
1017 1014 topo_propval_t *pv = NULL;
1018 1015
1019 1016 topo_node_lock(node);
1020 1017 if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL) {
1021 1018 topo_node_unlock(node);
1022 1019 *err = ETOPO_PROP_NOENT;
1023 1020 return (-1);
1024 1021 }
1025 1022
1026 1023 /*
1027 1024 * If the property is being inherited then we don't want to allow a
1028 1025 * change from IMMUTABLE to MUTABLE.
1029 1026 */
1030 1027 if (pv->tp_refs > 1) {
1031 1028 topo_node_unlock(node);
1032 1029 *err = ETOPO_PROP_DEFD;
1033 1030 return (-1);
1034 1031 }
1035 1032 pv->tp_flag |= TOPO_PROP_MUTABLE;
1036 1033
1037 1034 topo_node_unlock(node);
1038 1035
1039 1036 return (0);
1040 1037 }
1041 1038 int
1042 1039 topo_prop_setnonvolatile(tnode_t *node, const char *pgname, const char *pname,
1043 1040 int *err)
1044 1041 {
1045 1042 topo_propval_t *pv = NULL;
1046 1043
1047 1044 topo_node_lock(node);
1048 1045 if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL) {
1049 1046 topo_node_unlock(node);
1050 1047 *err = ETOPO_PROP_NOENT;
1051 1048 return (-1);
1052 1049 }
1053 1050
1054 1051 pv->tp_flag |= TOPO_PROP_NONVOLATILE;
1055 1052
1056 1053 topo_node_unlock(node);
1057 1054
1058 1055 return (0);
1059 1056 }
1060 1057
1061 1058 static int
1062 1059 inherit_seterror(tnode_t *node, int *errp, int err)
1063 1060 {
1064 1061 topo_node_unlock(node);
1065 1062 topo_node_unlock(node->tn_parent);
1066 1063
1067 1064 *errp = err;
1068 1065
1069 1066 return (-1);
1070 1067 }
1071 1068
1072 1069 int
1073 1070 topo_prop_inherit(tnode_t *node, const char *pgname, const char *name, int *err)
1074 1071 {
1075 1072 topo_hdl_t *thp = node->tn_hdl;
1076 1073 tnode_t *pnode = node->tn_parent;
1077 1074 topo_pgroup_t *pg;
1078 1075 topo_propval_t *pv;
1079 1076 topo_proplist_t *pvl;
1080 1077
1081 1078 topo_node_lock(pnode);
1082 1079 topo_node_lock(node);
1083 1080
1084 1081 /*
1085 1082 * Check if the requested property group and prop val are already set
1086 1083 * on the node.
1087 1084 */
1088 1085 if (propval_get(pgroup_get(node, pgname), name) != NULL)
1089 1086 return (inherit_seterror(node, err, ETOPO_PROP_DEFD));
1090 1087
1091 1088 /*
1092 1089 * Check if the requested property group and prop val exists on the
1093 1090 * parent node
1094 1091 */
1095 1092 if ((pv = propval_get(pgroup_get(pnode, pgname), name)) == NULL)
1096 1093 return (inherit_seterror(node, err, ETOPO_PROP_NOENT));
1097 1094
1098 1095 /*
1099 1096 * Can this propval be inherited?
1100 1097 */
1101 1098 if (pv->tp_flag & TOPO_PROP_MUTABLE)
1102 1099 return (inherit_seterror(node, err, ETOPO_PROP_NOINHERIT));
1103 1100
1104 1101 /*
1105 1102 * Property group should already exist: bump the ref count for this
1106 1103 * propval and add it to the node's property group
1107 1104 */
1108 1105 if ((pg = pgroup_get(node, pgname)) == NULL)
1109 1106 return (inherit_seterror(node, err, ETOPO_PROP_NOENT));
1110 1107
1111 1108 if ((pvl = topo_hdl_zalloc(thp, sizeof (topo_proplist_t)))
1112 1109 == NULL)
1113 1110 return (inherit_seterror(node, err, ETOPO_NOMEM));
1114 1111
1115 1112 topo_prop_hold(pv);
1116 1113 pvl->tp_pval = pv;
1117 1114 topo_list_append(&pg->tpg_pvals, pvl);
1118 1115
1119 1116 topo_node_unlock(node);
1120 1117 topo_node_unlock(pnode);
1121 1118
1122 1119 return (0);
1123 1120 }
1124 1121
1125 1122 topo_pgroup_info_t *
1126 1123 topo_pgroup_info(tnode_t *node, const char *pgname, int *err)
1127 1124 {
1128 1125 topo_hdl_t *thp = node->tn_hdl;
1129 1126 topo_pgroup_t *pg;
1130 1127 topo_ipgroup_info_t *pip;
1131 1128 topo_pgroup_info_t *info;
1132 1129
1133 1130 topo_node_lock(node);
1134 1131 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
1135 1132 pg = topo_list_next(pg)) {
1136 1133 if (strcmp(pgname, pg->tpg_info->tpi_name) == 0) {
1137 1134 if ((info = topo_hdl_alloc(thp,
1138 1135 sizeof (topo_pgroup_info_t))) == NULL)
1139 1136 return (NULL);
1140 1137
1141 1138 pip = pg->tpg_info;
1142 1139 if ((info->tpi_name =
1143 1140 topo_hdl_strdup(thp, pip->tpi_name)) == NULL) {
1144 1141 *err = ETOPO_PROP_NOMEM;
1145 1142 topo_hdl_free(thp, info,
1146 1143 sizeof (topo_pgroup_info_t));
1147 1144 topo_node_unlock(node);
1148 1145 return (NULL);
1149 1146 }
1150 1147 info->tpi_namestab = pip->tpi_namestab;
1151 1148 info->tpi_datastab = pip->tpi_datastab;
1152 1149 info->tpi_version = pip->tpi_version;
1153 1150 topo_node_unlock(node);
1154 1151 return (info);
1155 1152 }
1156 1153 }
1157 1154
1158 1155 *err = ETOPO_PROP_NOENT;
1159 1156 topo_node_unlock(node);
1160 1157 return (NULL);
1161 1158 }
1162 1159
1163 1160 static int
1164 1161 pgroup_seterr(tnode_t *node, topo_pgroup_t *pg, topo_ipgroup_info_t *pip,
1165 1162 int *err)
1166 1163 {
1167 1164 topo_hdl_t *thp = node->tn_hdl;
1168 1165
1169 1166 if (pip != NULL) {
1170 1167 if (pip->tpi_name != NULL)
1171 1168 topo_hdl_strfree(thp, (char *)pip->tpi_name);
1172 1169 topo_hdl_free(thp, pip, sizeof (topo_ipgroup_info_t));
1173 1170 }
1174 1171
1175 1172 topo_hdl_free(thp, pg, sizeof (topo_pgroup_t));
1176 1173 *err = ETOPO_NOMEM;
1177 1174
1178 1175 topo_node_unlock(node);
1179 1176
1180 1177 return (-1);
1181 1178 }
1182 1179
1183 1180 int
1184 1181 topo_pgroup_create(tnode_t *node, const topo_pgroup_info_t *pinfo, int *err)
1185 1182 {
1186 1183 topo_pgroup_t *pg;
1187 1184 topo_ipgroup_info_t *pip;
1188 1185 topo_hdl_t *thp = node->tn_hdl;
1189 1186
1190 1187 *err = 0;
1191 1188
1192 1189 topo_node_lock(node);
1193 1190 /*
1194 1191 * Check for an existing pgroup
1195 1192 */
1196 1193 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
1197 1194 pg = topo_list_next(pg)) {
1198 1195 if (strcmp(pg->tpg_info->tpi_name, pinfo->tpi_name) == 0) {
1199 1196 *err = ETOPO_PROP_DEFD;
1200 1197 topo_node_unlock(node);
1201 1198 return (-1);
1202 1199 }
1203 1200 }
1204 1201
1205 1202 if ((pg = topo_hdl_zalloc(thp, sizeof (topo_pgroup_t))) == NULL) {
1206 1203 *err = ETOPO_NOMEM;
1207 1204 topo_node_unlock(node);
1208 1205 return (-1);
1209 1206 }
1210 1207
1211 1208 if ((pip = topo_hdl_zalloc(thp, sizeof (topo_ipgroup_info_t)))
1212 1209 == NULL)
1213 1210 return (pgroup_seterr(node, pg, pip, err));
1214 1211
1215 1212 if ((pip->tpi_name = topo_hdl_strdup(thp, pinfo->tpi_name))
1216 1213 == NULL)
1217 1214 return (pgroup_seterr(node, pg, pip, err));
1218 1215
1219 1216 pip->tpi_namestab = pinfo->tpi_namestab;
1220 1217 pip->tpi_datastab = pinfo->tpi_datastab;
1221 1218 pip->tpi_version = pinfo->tpi_version;
1222 1219
1223 1220 pg->tpg_info = pip;
1224 1221
1225 1222 topo_list_append(&node->tn_pgroups, pg);
1226 1223 topo_node_unlock(node);
1227 1224
1228 1225 return (0);
1229 1226 }
1230 1227
1231 1228 void
1232 1229 topo_pgroup_destroy(tnode_t *node, const char *pname)
1233 1230 {
1234 1231 topo_hdl_t *thp = node->tn_hdl;
1235 1232 topo_pgroup_t *pg;
1236 1233 topo_proplist_t *pvl;
1237 1234 topo_ipgroup_info_t *pip;
1238 1235
1239 1236 topo_node_lock(node);
1240 1237 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
1241 1238 pg = topo_list_next(pg)) {
1242 1239 if (strcmp(pg->tpg_info->tpi_name, pname) == 0) {
1243 1240 break;
1244 1241 }
1245 1242 }
1246 1243
1247 1244 if (pg == NULL) {
1248 1245 topo_node_unlock(node);
1249 1246 return;
1250 1247 }
1251 1248
1252 1249 while ((pvl = topo_list_next(&pg->tpg_list)) != NULL) {
1253 1250 topo_list_delete(&pg->tpg_pvals, pvl);
1254 1251 topo_prop_rele(pvl->tp_pval);
1255 1252 topo_hdl_free(thp, pvl, sizeof (topo_proplist_t));
1256 1253 }
1257 1254
1258 1255 topo_list_delete(&node->tn_pgroups, pg);
1259 1256 topo_node_unlock(node);
1260 1257
1261 1258 pip = pg->tpg_info;
1262 1259 if (pip != NULL) {
1263 1260 if (pip->tpi_name != NULL)
1264 1261 topo_hdl_strfree(thp, (char *)pip->tpi_name);
1265 1262 topo_hdl_free(thp, pip, sizeof (topo_ipgroup_info_t));
1266 1263 }
1267 1264
1268 1265 topo_hdl_free(thp, pg, sizeof (topo_pgroup_t));
1269 1266 }
1270 1267
1271 1268 void
1272 1269 topo_pgroup_destroy_all(tnode_t *node)
1273 1270 {
1274 1271 topo_hdl_t *thp = node->tn_hdl;
1275 1272 topo_pgroup_t *pg;
1276 1273 topo_proplist_t *pvl;
1277 1274 topo_ipgroup_info_t *pip;
1278 1275
1279 1276 topo_node_lock(node);
1280 1277 while ((pg = topo_list_next(&node->tn_pgroups)) != NULL) {
1281 1278 while ((pvl = topo_list_next(&pg->tpg_pvals)) != NULL) {
1282 1279 topo_list_delete(&pg->tpg_pvals, pvl);
1283 1280 topo_prop_rele(pvl->tp_pval);
1284 1281 topo_hdl_free(thp, pvl, sizeof (topo_proplist_t));
1285 1282 }
1286 1283
1287 1284 topo_list_delete(&node->tn_pgroups, pg);
1288 1285
1289 1286 pip = pg->tpg_info;
1290 1287 if (pip != NULL) {
1291 1288 if (pip->tpi_name != NULL)
1292 1289 topo_hdl_strfree(thp, (char *)pip->tpi_name);
1293 1290 topo_hdl_free(thp, pip, sizeof (topo_pgroup_info_t));
1294 1291 }
1295 1292
1296 1293 topo_hdl_free(thp, pg, sizeof (topo_pgroup_t));
1297 1294 }
1298 1295 topo_node_unlock(node);
1299 1296 }
↓ open down ↓ |
430 lines elided |
↑ open up ↑ |
1300 1297
1301 1298 static void
1302 1299 propmethod_destroy(topo_hdl_t *thp, topo_propval_t *pv)
1303 1300 {
1304 1301 topo_propmethod_t *pm;
1305 1302
1306 1303 pm = pv->tp_method;
1307 1304 if (pm != NULL) {
1308 1305 if (pm->tpm_name != NULL)
1309 1306 topo_hdl_strfree(thp, pm->tpm_name);
1310 - if (pm->tpm_args != NULL)
1311 - nvlist_free(pm->tpm_args);
1307 + nvlist_free(pm->tpm_args);
1312 1308 topo_hdl_free(thp, pm, sizeof (topo_propmethod_t));
1313 1309 pv->tp_method = NULL;
1314 1310 }
1315 1311 }
1316 1312
1317 1313 static void
1318 1314 topo_propval_destroy(topo_propval_t *pv)
1319 1315 {
1320 1316 topo_hdl_t *thp;
1321 1317
1322 1318 if (pv == NULL)
1323 1319 return;
1324 1320
1325 1321 thp = pv->tp_hdl;
1326 1322
1327 1323 if (pv->tp_name != NULL)
1328 1324 topo_hdl_strfree(thp, pv->tp_name);
1329 1325
1330 - if (pv->tp_val != NULL)
1331 - nvlist_free(pv->tp_val);
1326 + nvlist_free(pv->tp_val);
1332 1327
1333 1328 propmethod_destroy(thp, pv);
1334 1329
1335 1330 topo_hdl_free(thp, pv, sizeof (topo_propval_t));
1336 1331 }
1337 1332
1338 1333 void
1339 1334 topo_prop_hold(topo_propval_t *pv)
1340 1335 {
1341 1336 pv->tp_refs++;
1342 1337 }
1343 1338
1344 1339 void
1345 1340 topo_prop_rele(topo_propval_t *pv)
1346 1341 {
1347 1342 pv->tp_refs--;
1348 1343
1349 1344 assert(pv->tp_refs >= 0);
1350 1345
1351 1346 if (pv->tp_refs == 0)
1352 1347 topo_propval_destroy(pv);
1353 1348 }
1354 1349
1355 1350 /*
1356 1351 * topo_prop_getprop() and topo_prop_getprops() are private project functions
1357 1352 * for fmtopo
1358 1353 */
1359 1354 int
1360 1355 topo_prop_getprop(tnode_t *node, const char *pgname, const char *pname,
1361 1356 nvlist_t *args, nvlist_t **prop, int *err)
1362 1357 {
1363 1358 topo_hdl_t *thp = node->tn_hdl;
1364 1359 topo_propval_t *pv;
1365 1360
1366 1361 topo_node_lock(node);
1367 1362 if ((pv = prop_get(node, pgname, pname, args, err)) == NULL) {
1368 1363 (void) get_properror(node, err, *err);
1369 1364 return (-1);
1370 1365 }
1371 1366
1372 1367 if (topo_hdl_nvdup(thp, pv->tp_val, prop) != 0) {
1373 1368 (void) get_properror(node, err, ETOPO_NOMEM);
1374 1369 return (-1);
1375 1370 }
1376 1371 topo_node_unlock(node);
1377 1372
1378 1373 return (0);
1379 1374 }
1380 1375
1381 1376 static int
1382 1377 prop_val_add(tnode_t *node, nvlist_t **nvl, topo_propval_t *pv, int *err)
1383 1378 {
1384 1379 if (pv->tp_method != NULL)
1385 1380 if (prop_method_get(node, pv, pv->tp_method, NULL, err) < 0)
1386 1381 return (-1);
1387 1382
1388 1383 if (pv->tp_val == NULL) {
1389 1384 *err = ETOPO_PROP_NOENT;
1390 1385 return (-1);
1391 1386 }
1392 1387
1393 1388 if (topo_hdl_nvdup(pv->tp_hdl, pv->tp_val, nvl) != 0) {
1394 1389 *err = ETOPO_PROP_NOMEM;
1395 1390 return (-1);
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
1396 1391 }
1397 1392
1398 1393 return (0);
1399 1394 }
1400 1395
1401 1396 static int
1402 1397 get_pgrp_seterror(tnode_t *node, nvlist_t *nvl, int *errp, int err)
1403 1398 {
1404 1399 topo_node_unlock(node);
1405 1400
1406 - if (nvl != NULL)
1407 - nvlist_free(nvl);
1401 + nvlist_free(nvl);
1408 1402
1409 1403 *errp = err;
1410 1404
1411 1405 return (-1);
1412 1406 }
1413 1407
1414 1408 int
1415 1409 topo_prop_getpgrp(tnode_t *node, const char *pgname, nvlist_t **pgrp,
1416 1410 int *err)
1417 1411 {
1418 1412 int ret;
1419 1413 topo_hdl_t *thp = node->tn_hdl;
1420 1414 nvlist_t *nvl, *pvnvl;
1421 1415 topo_pgroup_t *pg;
1422 1416 topo_propval_t *pv;
1423 1417 topo_proplist_t *pvl;
1424 1418
1425 1419 if (topo_hdl_nvalloc(thp, &nvl, 0) != 0) {
1426 1420 *err = ETOPO_NOMEM;
1427 1421 return (-1);
1428 1422 }
1429 1423
1430 1424 topo_node_lock(node);
1431 1425 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
1432 1426 pg = topo_list_next(pg)) {
1433 1427
1434 1428 if (strcmp(pgname, pg->tpg_info->tpi_name) != 0)
1435 1429 continue;
1436 1430
1437 1431 if (nvlist_add_string(nvl, TOPO_PROP_GROUP_NAME,
1438 1432 pg->tpg_info->tpi_name) != 0 ||
1439 1433 nvlist_add_string(nvl, TOPO_PROP_GROUP_NSTAB,
1440 1434 topo_stability2name(pg->tpg_info->tpi_namestab)) != 0 ||
1441 1435 nvlist_add_string(nvl, TOPO_PROP_GROUP_DSTAB,
1442 1436 topo_stability2name(pg->tpg_info->tpi_datastab)) != 0 ||
1443 1437 nvlist_add_int32(nvl, TOPO_PROP_GROUP_VERSION,
1444 1438 pg->tpg_info->tpi_version) != 0)
1445 1439 return (get_pgrp_seterror(node, nvl, err,
1446 1440 ETOPO_PROP_NVL));
1447 1441
1448 1442 for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL;
1449 1443 pvl = topo_list_next(pvl)) {
1450 1444
1451 1445 pv = pvl->tp_pval;
1452 1446 if (prop_val_add(node, &pvnvl, pv, err) < 0) {
1453 1447 return (get_pgrp_seterror(node, nvl, err,
1454 1448 *err));
1455 1449 }
1456 1450 if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL,
1457 1451 pvnvl)) != 0) {
1458 1452 nvlist_free(pvnvl);
1459 1453 return (get_pgrp_seterror(node, nvl, err, ret));
1460 1454 }
1461 1455
1462 1456 nvlist_free(pvnvl);
1463 1457 }
1464 1458 topo_node_unlock(node);
1465 1459 *pgrp = nvl;
1466 1460 return (0);
1467 1461 }
1468 1462
↓ open down ↓ |
51 lines elided |
↑ open up ↑ |
1469 1463 topo_node_unlock(node);
1470 1464 *err = ETOPO_PROP_NOENT;
1471 1465 return (-1);
1472 1466 }
1473 1467
1474 1468 static nvlist_t *
1475 1469 get_all_seterror(tnode_t *node, nvlist_t *nvl, int *errp, int err)
1476 1470 {
1477 1471 topo_node_unlock(node);
1478 1472
1479 - if (nvl != NULL)
1480 - nvlist_free(nvl);
1473 + nvlist_free(nvl);
1481 1474
1482 1475 *errp = err;
1483 1476
1484 1477 return (NULL);
1485 1478 }
1486 1479
1487 1480 nvlist_t *
1488 1481 topo_prop_getprops(tnode_t *node, int *err)
1489 1482 {
1490 1483 int ret;
1491 1484 topo_hdl_t *thp = node->tn_hdl;
1492 1485 nvlist_t *nvl, *pgnvl, *pvnvl;
1493 1486 topo_pgroup_t *pg;
1494 1487 topo_propval_t *pv;
1495 1488 topo_proplist_t *pvl;
1496 1489
1497 1490 topo_node_lock(node);
1498 1491 if (topo_hdl_nvalloc(thp, &nvl, 0) != 0) {
1499 1492 return (get_all_seterror(node, NULL, err, ETOPO_NOMEM));
1500 1493 }
1501 1494
1502 1495 for (pg = topo_list_next(&node->tn_pgroups); pg != NULL;
1503 1496 pg = topo_list_next(pg)) {
1504 1497 if (topo_hdl_nvalloc(thp, &pgnvl, 0) != 0)
1505 1498 return (get_all_seterror(node, nvl, err, ETOPO_NOMEM));
1506 1499
1507 1500 if (nvlist_add_string(pgnvl, TOPO_PROP_GROUP_NAME,
1508 1501 pg->tpg_info->tpi_name) != 0 ||
1509 1502 nvlist_add_string(pgnvl, TOPO_PROP_GROUP_NSTAB,
1510 1503 topo_stability2name(pg->tpg_info->tpi_namestab)) != 0 ||
1511 1504 nvlist_add_string(pgnvl, TOPO_PROP_GROUP_DSTAB,
1512 1505 topo_stability2name(pg->tpg_info->tpi_datastab)) != 0 ||
1513 1506 nvlist_add_int32(pgnvl, TOPO_PROP_GROUP_VERSION,
1514 1507 pg->tpg_info->tpi_version) != 0)
1515 1508 return (get_all_seterror(node, nvl, err,
1516 1509 ETOPO_PROP_NVL));
1517 1510
1518 1511 for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL;
1519 1512 pvl = topo_list_next(pvl)) {
1520 1513
1521 1514 pv = pvl->tp_pval;
1522 1515 if (prop_val_add(node, &pvnvl, pv, err) < 0) {
1523 1516 nvlist_free(pgnvl);
1524 1517 return (get_all_seterror(node, nvl, err, *err));
1525 1518 }
1526 1519 if ((ret = nvlist_add_nvlist(pgnvl, TOPO_PROP_VAL,
1527 1520 pvnvl)) != 0) {
1528 1521 nvlist_free(pgnvl);
1529 1522 nvlist_free(pvnvl);
1530 1523 return (get_all_seterror(node, nvl, err, ret));
1531 1524 }
1532 1525
1533 1526 nvlist_free(pvnvl);
1534 1527 }
1535 1528 if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_GROUP, pgnvl))
1536 1529 != 0) {
1537 1530 nvlist_free(pgnvl);
1538 1531 return (get_all_seterror(node, nvl, err, ret));
1539 1532 }
1540 1533
1541 1534 nvlist_free(pgnvl);
1542 1535 }
1543 1536
1544 1537 topo_node_unlock(node);
1545 1538
1546 1539 return (nvl);
1547 1540 }
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX