import less(1)
[unleashed/tickless.git] / usr / src / lib / libpool / common / pool_internal.c
blob5e572f6eaf3140fb0610cf23dcac63dde5f9df6c
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <limits.h>
29 #include <pool.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <synch.h>
34 #include <thread.h>
36 #include <sys/loadavg.h>
37 #include <sys/types.h>
38 #include <sys/utsname.h>
40 #include "dict.h"
41 #include "pool_internal.h"
42 #include "pool_impl.h"
45 * Atom structure, used to reference count string atoms.
47 typedef struct {
48 char *a_string; /* String atom */
49 uint_t a_count; /* String reference count */
50 } atom_t;
53 * The _internal_lock is used to lock the state of libpool during
54 * internal initialisation operations.
56 mutex_t _internal_lock;
58 static int _libpool_debug = 0; /* debugging messages */
59 static dict_hdl_t *_pv_atoms; /* pool_value_t atoms */
60 static mutex_t _atom_lock; /* atom table lock */
61 static int _libpool_internal_initialised = PO_FALSE;
64 * Various useful constant strings which are often encountered
66 const char *c_a_dtype = "a-dtype";
67 const char *c_name = "name";
68 const char *c_type = "type";
69 const char *c_ref_id = "ref_id";
70 const char *c_max_prop = "max";
71 const char *c_min_prop = "min";
72 const char *c_size_prop = "size";
73 const char *c_sys_prop = "sys_id";
76 * prop_is_type() checks the supplied property and returns PO_TRUE if the
77 * property value is set for the property else PO_FALSE
79 static int prop_is_type(int, const pool_prop_t *);
80 static int resource_get_common(const pool_resource_t *, const char *,
81 uint64_t *);
82 static int64_t elem_get_expected_int64(const pool_elem_t *, const char *);
85 * The following returns a malloc'ed string which must be free'd by the
86 * caller.
88 static char *elem_get_expected_string(const pool_elem_t *, const char *);
89 static int element_props_init(pool_prop_t *);
92 * Each element class/sub-class has a set of properties and behaviours
93 * which are used to create the element with appropriate property
94 * values and to ensure correct property manipulations. The details
95 * are all stored in the following arrays.
98 static int elem_name_init(pool_prop_t *);
99 static int elem_comment_init(pool_prop_t *);
101 static int pool_importance_init(pool_prop_t *);
102 static int pool_active_init(pool_prop_t *);
104 static int res_max_init(pool_prop_t *);
105 static int res_min_init(pool_prop_t *);
106 static int res_size_init(pool_prop_t *);
107 static int res_load_init(pool_prop_t *);
109 static int pset_units_init(pool_prop_t *);
111 static int cpu_status_init(pool_prop_t *);
113 static int elem_no_set(pool_elem_t *, const pool_value_t *);
114 static int elem_set_name(pool_elem_t *, const pool_value_t *);
115 static int elem_get_type(const pool_elem_t *, pool_value_t *);
116 static int elem_set_string(pool_elem_t *, const pool_value_t *);
117 static int elem_set_bool(pool_elem_t *, const pool_value_t *);
118 static int elem_set_uint(pool_elem_t *, const pool_value_t *);
120 static int system_set_allocate(pool_elem_t *, const pool_value_t *);
122 static int pool_set_scheduler(pool_elem_t *, const pool_value_t *);
123 static int pool_set_active(pool_elem_t *, const pool_value_t *);
125 static int res_set_max(pool_elem_t *, const pool_value_t *);
126 static int res_set_min(pool_elem_t *, const pool_value_t *);
128 static int cpu_set_status(pool_elem_t *, const pool_value_t *);
130 static const char *pool_elem_class_name[] = {
131 "invalid",
132 "system",
133 "pool",
134 "component resource",
135 "aggregate resource",
136 "component"
140 * This must be kept in sync with the pool_resource_elem_ctl array and
141 * the "enum pool_resource_elem_class" type.
143 static const char *pool_resource_elem_class_name[] = {
144 "invalid",
145 "pset"
148 static const char *pool_component_elem_class_name[] = {
149 "invalid",
150 "cpu"
153 static pool_prop_t system_props[] = {
154 { "system.name", POOL_VALUE_INITIALIZER, PP_STORED, NULL,
155 { NULL, elem_set_name } },
156 { "system.ref_id", POOL_VALUE_INITIALIZER,
157 PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
158 { "system.comment", POOL_VALUE_INITIALIZER, PP_STORED, NULL, NULL },
159 { "system.version", POOL_VALUE_INITIALIZER,
160 PP_STORED | PP_READ, NULL, NULL },
161 { "system.bind-default", POOL_VALUE_INITIALIZER,
162 PP_STORED, NULL, NULL },
163 { "system.allocate-method", POOL_VALUE_INITIALIZER,
164 PP_STORED | PP_OPTIONAL, NULL, { NULL, system_set_allocate } },
165 { "system.poold.log-level", POOL_VALUE_INITIALIZER,
166 PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
167 { "system.poold.log-location", POOL_VALUE_INITIALIZER,
168 PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
169 { "system.poold.monitor-interval", POOL_VALUE_INITIALIZER,
170 PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_uint } },
171 { "system.poold.history-file", POOL_VALUE_INITIALIZER,
172 PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
173 { "system.poold.objectives", POOL_VALUE_INITIALIZER,
174 PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
175 NULL
178 static pool_prop_t pool_props[] = {
179 { "pool.sys_id", POOL_VALUE_INITIALIZER,
180 PP_STORED | PP_READ, NULL, NULL },
181 { "pool.name", POOL_VALUE_INITIALIZER,
182 PP_STORED | PP_INIT, elem_name_init, { NULL, elem_set_name } },
183 { "pool.res", POOL_VALUE_INITIALIZER,
184 PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
185 { "pool.ref_id", POOL_VALUE_INITIALIZER,
186 PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
187 { "pool.active", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
188 pool_active_init, { NULL, pool_set_active } },
189 { "pool.default", POOL_VALUE_INITIALIZER,
190 PP_STORED | PP_READ, NULL, NULL },
191 { "pool.scheduler", POOL_VALUE_INITIALIZER,
192 PP_STORED | PP_OPTIONAL, NULL,
193 { NULL, pool_set_scheduler } },
194 { "pool.importance", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
195 pool_importance_init, NULL },
196 { "pool.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
197 elem_comment_init, NULL },
198 NULL
201 static pool_prop_t pset_props[] = {
202 { "type", POOL_VALUE_INITIALIZER, PP_HIDDEN | PP_STORED | PP_READ, NULL,
203 { elem_get_type, NULL } },
204 { "pset.sys_id", POOL_VALUE_INITIALIZER,
205 PP_STORED | PP_READ, NULL, NULL },
206 { "pset.name", POOL_VALUE_INITIALIZER,
207 PP_STORED | PP_INIT, elem_name_init, { NULL, elem_set_name } },
208 { "pset.ref_id", POOL_VALUE_INITIALIZER,
209 PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
210 { "pset.default", POOL_VALUE_INITIALIZER,
211 PP_STORED | PP_READ, NULL, NULL },
212 { "pset.min", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, res_min_init,
213 { NULL, res_set_min } },
214 { "pset.max", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT, res_max_init,
215 { NULL, res_set_max } },
216 { "pset.units", POOL_VALUE_INITIALIZER,
217 PP_STORED | PP_INIT, pset_units_init, NULL },
218 { "pset.load", POOL_VALUE_INITIALIZER, PP_READ | PP_INIT,
219 res_load_init, NULL },
220 { "pset.size", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT | PP_READ,
221 res_size_init, NULL },
222 { "pset.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
223 elem_comment_init, NULL },
224 { "pset.poold.objectives", POOL_VALUE_INITIALIZER,
225 PP_STORED | PP_OPTIONAL, NULL, { NULL, elem_set_string } },
226 NULL
229 static pool_prop_t cpu_props[] = {
230 { "type", POOL_VALUE_INITIALIZER, PP_HIDDEN | PP_STORED | PP_READ, NULL,
231 { elem_get_type, NULL } },
232 { "cpu.sys_id", POOL_VALUE_INITIALIZER, PP_STORED | PP_READ, NULL,
233 NULL },
234 { "cpu.ref_id", POOL_VALUE_INITIALIZER,
235 PP_HIDDEN | PP_STORED | PP_READ, NULL, { NULL, elem_no_set } },
236 { "cpu.comment", POOL_VALUE_INITIALIZER, PP_STORED | PP_INIT,
237 elem_comment_init, NULL },
238 { "cpu.status", POOL_VALUE_INITIALIZER, PP_INIT, cpu_status_init,
239 { NULL, cpu_set_status } },
240 { "cpu.pinned", POOL_VALUE_INITIALIZER, PP_STORED | PP_OPTIONAL, NULL,
241 { NULL, elem_set_bool } },
242 NULL
245 static pool_prop_t *pool_elem_ctl[] = {
246 NULL,
247 system_props,
248 pool_props,
249 NULL,
250 NULL,
251 NULL
255 * This must be kept in sync with the pool_resource_elem_class_name array and
256 * the "enum pool_resource_elem_class" type.
258 static pool_prop_t *pool_resource_elem_ctl[] = {
259 NULL,
260 pset_props
263 static pool_prop_t *pool_component_elem_ctl[] = {
264 NULL,
265 cpu_props
268 static void
269 atom_init(void)
271 (void) mutex_lock(&_atom_lock);
273 * Initialize pool_value_t atom dictionary
275 if (_pv_atoms == NULL)
276 if ((_pv_atoms = dict_new((int (*)(const void *, const void *))
277 strcmp, (uint64_t (*)(const void *))hash_str)) == NULL)
278 abort();
279 (void) mutex_unlock(&_atom_lock);
283 * Initializer, called when the library is initialized.
285 void
286 internal_init(void)
288 (void) mutex_lock(&_internal_lock);
289 if (_libpool_internal_initialised == PO_TRUE) {
290 (void) mutex_unlock(&_internal_lock);
291 return;
293 atom_init();
295 * Initialize all available property arrays.
297 if (element_props_init(system_props) == PO_FAIL)
298 abort();
299 if (element_props_init(pool_props) == PO_FAIL)
300 abort();
301 if (element_props_init(pset_props) == PO_FAIL)
302 abort();
303 if (element_props_init(cpu_props) == PO_FAIL)
304 abort();
305 _libpool_internal_initialised = PO_TRUE;
306 (void) mutex_unlock(&_internal_lock);
310 static int
311 element_props_init(pool_prop_t *props)
313 int i;
315 for (i = 0; props[i].pp_pname != NULL; i++) {
317 * Initialise each of the properties
319 if (pool_value_set_name(&props[i].pp_value,
320 props[i].pp_pname) != PO_SUCCESS) {
321 return (PO_FAIL);
323 if (props[i].pp_init &&
324 props[i].pp_init(&props[i]) != PO_SUCCESS) {
325 return (PO_FAIL);
328 return (PO_SUCCESS);
333 * These functions intialise the properties of this plugin. The only reason
334 * they exist is because the ability to perform the static initialisation of
335 * union members properly was only introduced in the C99 standard. i.e. if you
336 * could do {.f = 1.0} like in the proposed C99 standard then that would
337 * be the preferred way to do this as it keeps the data in the array and
338 * minimises the scope for errors. However, until that time these functions
339 * are the best way to minimise the scope for errors and to maximise
340 * maintainability.
342 * There is one function for each property, and the initial value for each
343 * property is hard-coded into each function.
346 static int
347 elem_name_init(pool_prop_t *prop)
349 return (string_init(prop, "default"));
352 static int
353 elem_comment_init(pool_prop_t *prop)
355 return (string_init(prop, ""));
358 static int
359 pool_importance_init(pool_prop_t *prop)
361 return (int_init(prop, 1));
364 static int
365 pool_active_init(pool_prop_t *prop)
367 return (bool_init(prop, PO_TRUE));
370 static int
371 res_max_init(pool_prop_t *prop)
373 return (uint_init(prop, 0));
376 static int
377 res_min_init(pool_prop_t *prop)
379 return (uint_init(prop, 0));
382 static int
383 res_size_init(pool_prop_t *prop)
385 return (uint_init(prop, 0));
388 static int
389 res_load_init(pool_prop_t *prop)
391 return (uint_init(prop, 0));
394 static int
395 pset_units_init(pool_prop_t *prop)
397 return (string_init(prop, "population"));
400 static int
401 cpu_status_init(pool_prop_t *prop)
403 return (string_init(prop, PS_ONLINE));
407 * Individual property manipulation routines for use by the generic
408 * get/put property routines
412 * Many properties cannot be modified. This function prevents property
413 * modification.
415 /* ARGSUSED */
416 static int
417 elem_no_set(pool_elem_t *elem, const pool_value_t *pval)
419 return (PO_FAIL);
423 * Duplicate names for a pool or resource type are illegal.
425 static int
426 elem_set_name(pool_elem_t *elem, const pool_value_t *pval)
428 const char *nm;
429 pool_t *pool;
430 pool_resource_t *res;
432 if (pool_value_get_string(pval, &nm) != PO_SUCCESS) {
433 return (PO_FAIL);
435 if (!is_valid_name(nm)) {
436 pool_seterror(POE_PUTPROP);
437 return (PO_FAIL);
439 switch (pool_elem_class(elem)) {
440 case PEC_SYSTEM:
441 break;
442 case PEC_POOL:
443 pool = pool_get_pool(TO_CONF(elem), nm);
444 if (pool != NULL && pool != pool_elem_pool(elem)) {
445 pool_seterror(POE_PUTPROP);
446 return (PO_FAIL);
448 break;
449 case PEC_RES_COMP:
450 case PEC_RES_AGG:
451 res = pool_get_resource(TO_CONF(elem),
452 pool_elem_class_string(elem), nm);
453 if (res != NULL && res != pool_elem_res(elem)) {
454 pool_seterror(POE_PUTPROP);
455 return (PO_FAIL);
457 break;
458 default:
459 return (PO_FAIL);
461 return (PO_SUCCESS);
465 * Ensure the type is a string.
467 /* ARGSUSED */
468 static int
469 elem_set_string(pool_elem_t *elem, const pool_value_t *pval)
471 if (pool_value_get_type(pval) == POC_STRING)
472 return (PO_SUCCESS);
473 else {
474 pool_seterror(POE_BADPARAM);
475 return (PO_FAIL);
480 * Ensure the type is a boolean.
482 /* ARGSUSED */
483 static int
484 elem_set_bool(pool_elem_t *elem, const pool_value_t *pval)
486 if (pool_value_get_type(pval) == POC_BOOL)
487 return (PO_SUCCESS);
488 else {
489 pool_seterror(POE_BADPARAM);
490 return (PO_FAIL);
495 * Ensure the type is an unsigned int.
497 /* ARGSUSED */
498 static int
499 elem_set_uint(pool_elem_t *elem, const pool_value_t *pval)
501 if (pool_value_get_type(pval) == POC_UINT)
502 return (PO_SUCCESS);
503 else {
504 pool_seterror(POE_BADPARAM);
505 return (PO_FAIL);
509 /* ARGSUSED */
511 system_set_allocate(pool_elem_t *elem, const pool_value_t *pval)
513 const char *sval;
515 if (pool_value_get_string(pval, &sval) != PO_SUCCESS) {
516 pool_seterror(POE_PUTPROP);
517 return (PO_FAIL);
519 if (strcmp(POA_IMPORTANCE, sval) != 0 &&
520 strcmp(POA_SURPLUS_TO_DEFAULT, sval) != 0) {
521 pool_seterror(POE_PUTPROP);
522 return (PO_FAIL);
524 return (PO_SUCCESS);
527 /* ARGSUSED */
529 pool_set_active(pool_elem_t *elem, const pool_value_t *pval)
531 uchar_t bval;
533 if (pool_value_get_type(pval) != POC_BOOL) {
534 pool_seterror(POE_BADPARAM);
535 return (PO_FAIL);
537 (void) pool_value_get_bool(pval, &bval);
538 if (bval != 1) {
540 * "active" must be true on pools for
541 * now.
543 pool_seterror(POE_BADPARAM);
544 return (PO_FAIL);
546 return (PO_SUCCESS);
549 /* ARGSUSED */
551 pool_set_scheduler(pool_elem_t *elem, const pool_value_t *pval)
553 pcinfo_t pcinfo;
554 const char *sched;
556 if (pool_value_get_string(pval, &sched) != 0) {
557 pool_seterror(POE_PUTPROP);
558 return (PO_FAIL);
560 (void) strncpy(pcinfo.pc_clname, sched, PC_CLNMSZ);
561 if (priocntl(0, 0, PC_GETCID, &pcinfo) == -1) {
562 pool_seterror(POE_PUTPROP);
563 return (PO_FAIL);
565 return (PO_SUCCESS);
568 static int
569 res_set_max(pool_elem_t *elem, const pool_value_t *pval)
571 uint64_t min, max;
572 pool_value_t val = POOL_VALUE_INITIALIZER;
575 * max must be a uint
577 if (pool_value_get_uint64(pval, &max) != PO_SUCCESS) {
578 pool_seterror(POE_PUTPROP);
579 return (PO_FAIL);
582 * max can't be less than min (if it exists)
584 if (pool_get_ns_property(elem, c_min_prop, &val) == POC_INVAL)
585 return (PO_SUCCESS);
586 if (pool_value_get_uint64(&val, &min) != PO_SUCCESS) {
587 pool_seterror(POE_PUTPROP);
588 return (PO_FAIL);
590 if (max < min) {
591 pool_seterror(POE_PUTPROP);
592 return (PO_FAIL);
595 * Ensure that changes to the max in a dynamic configuration
596 * are still valid.
598 if (conf_is_dynamic(TO_CONF(elem)) == PO_TRUE) {
599 uint64_t oldmax;
601 if (pool_get_ns_property(elem, c_max_prop, &val) == POC_INVAL) {
602 pool_seterror(POE_PUTPROP);
603 return (PO_FAIL);
605 if (pool_value_get_uint64(&val, &oldmax) != PO_SUCCESS) {
606 pool_seterror(POE_PUTPROP);
607 return (PO_FAIL);
609 if (max < oldmax) {
611 * Ensure that the modified total max is >= size
612 * of all resources of this type
614 return (pool_validate_resource(TO_CONF(elem),
615 pool_elem_class_string(elem), c_max_prop,
616 max - oldmax));
619 return (PO_SUCCESS);
622 static int
623 res_set_min(pool_elem_t *elem, const pool_value_t *pval)
625 uint64_t min, max;
626 pool_value_t val = POOL_VALUE_INITIALIZER;
629 * min must be a uint
631 if (pool_value_get_uint64(pval, &min) != PO_SUCCESS) {
632 pool_seterror(POE_PUTPROP);
633 return (PO_FAIL);
636 * min can't be more than max (if it exists)
638 if (pool_get_ns_property(elem, c_max_prop, &val) == POC_INVAL)
639 return (PO_SUCCESS);
640 if (pool_value_get_uint64(&val, &max) != PO_SUCCESS) {
641 pool_seterror(POE_PUTPROP);
642 return (PO_FAIL);
644 if (min > max) {
645 pool_seterror(POE_PUTPROP);
646 return (PO_FAIL);
649 switch (pool_resource_elem_class(elem)) {
650 case PREC_PSET:
651 if (resource_is_default(pool_elem_res(elem))) {
652 if (min < 1) {
653 pool_seterror(POE_PUTPROP);
654 return (PO_FAIL);
657 break;
658 default:
659 break;
663 * Ensure that changes to the min in a dynamic configuration
664 * are still valid.
666 if (conf_is_dynamic(TO_CONF(elem)) == PO_TRUE) {
667 uint64_t oldmin;
669 if (pool_get_ns_property(elem, c_min_prop, &val) == POC_INVAL) {
670 pool_seterror(POE_PUTPROP);
671 return (PO_FAIL);
673 if (pool_value_get_uint64(&val, &oldmin) != PO_SUCCESS) {
674 pool_seterror(POE_PUTPROP);
675 return (PO_FAIL);
677 if (min > oldmin) {
679 * Ensure that the modified total min is <= size
680 * of all resources of this type
682 return (pool_validate_resource(TO_CONF(elem),
683 pool_elem_class_string(elem), c_min_prop,
684 min - oldmin));
687 return (PO_SUCCESS);
690 /* ARGSUSED */
692 cpu_set_status(pool_elem_t *elem, const pool_value_t *pval)
694 const char *status;
696 if (pool_value_get_string(pval, &status) != 0) {
697 pool_seterror(POE_PUTPROP);
698 return (PO_FAIL);
701 if (strcmp(PS_ONLINE, status) != 0 &&
702 strcmp(PS_OFFLINE, status) != 0 &&
703 strcmp(PS_NOINTR, status) != 0 &&
704 strcmp(PS_SPARE, status) != 0 &&
705 strcmp(PS_FAULTED, status) != 0) {
706 pool_seterror(POE_PUTPROP);
707 return (PO_FAIL);
709 return (PO_SUCCESS);
712 static int
713 elem_get_type(const pool_elem_t *elem, pool_value_t *pval)
715 if (pool_value_set_string(pval, pool_elem_class_string(elem)) ==
716 PO_FAIL)
717 return (PO_FAIL);
718 return (PO_SUCCESS);
722 * More general utilities
725 * Is the supplied configuration the dynamic configuration
726 * Return: PO_TRUE/PO_FALSE
729 conf_is_dynamic(const pool_conf_t *conf)
731 if (strcmp(pool_conf_location(conf), pool_dynamic_location()) == 0)
732 return (PO_TRUE);
733 return (PO_FALSE);
737 * uint_init() initialises the value of the supplied property with the
738 * supplied value.
739 * Returns PO_SUCCESS
742 uint_init(pool_prop_t *prop, uint64_t val)
744 pool_value_set_uint64(&prop->pp_value, val);
745 return (PO_SUCCESS);
749 * int_init() initialises the value of the supplied property with the
750 * supplied value.
751 * Returns PO_SUCCESS
754 int_init(pool_prop_t *prop, int64_t val)
756 pool_value_set_int64(&prop->pp_value, val);
757 return (PO_SUCCESS);
761 * double_init() initialises the value of the supplied property with the
762 * supplied value.
763 * Returns PO_SUCCESS
766 double_init(pool_prop_t *prop, double val)
768 pool_value_set_double(&prop->pp_value, val);
769 return (PO_SUCCESS);
773 * bool_init() initialises the value of the supplied property with the
774 * supplied value.
775 * Returns PO_SUCCESS
778 bool_init(pool_prop_t *prop, uchar_t val)
780 pool_value_set_bool(&prop->pp_value, val);
781 return (PO_SUCCESS);
785 * string_init() initialises the value of the supplied property with the
786 * supplied value.
787 * Returns PO_SUCCESS/PO_FAIL
790 string_init(pool_prop_t *prop, const char *val)
792 return (pool_value_set_string(&prop->pp_value, val));
796 * pool_get_provider_count() returns the count of registered providers.
798 * Returns count of registered providers
800 uint_t
801 pool_get_provider_count(void)
803 uint_t count = 0;
804 int i;
806 for (i = 0; i < sizeof (pool_resource_elem_ctl) /
807 sizeof (pool_resource_elem_ctl[0]); i++) {
808 if (pool_resource_elem_ctl[i] != NULL)
809 count++;
811 return (count);
815 * Return all the props for a specified provider
817 const pool_prop_t *
818 provider_get_props(const pool_elem_t *elem)
820 const pool_prop_t *prop_list = NULL;
821 pool_elem_class_t elem_class = pool_elem_class(elem);
823 switch (elem_class) {
824 case PEC_SYSTEM:
825 case PEC_POOL:
826 prop_list = pool_elem_ctl[elem_class];
827 break;
828 case PEC_RES_AGG:
829 case PEC_RES_COMP:
830 prop_list = pool_resource_elem_ctl
831 [pool_resource_elem_class(elem)];
832 break;
833 case PEC_COMP:
834 prop_list = pool_component_elem_ctl
835 [pool_component_elem_class(elem)];
836 break;
838 return (prop_list);
842 * provider_get_prop() return the pool_prop_t structure which
843 * describes the supplied property name for the supplied provider.
845 * Returns the property description or NULL if it doesn't exist.
847 const pool_prop_t *
848 provider_get_prop(const pool_elem_t *elem, const char *name)
850 int i;
851 const pool_prop_t *prop_list;
853 if ((prop_list = provider_get_props(elem)) == NULL)
854 return (NULL);
856 for (i = 0; prop_list[i].pp_pname != NULL; i++) {
857 if (strcmp(name, prop_list[i].pp_pname) == 0) {
858 return (&prop_list[i]);
861 return (NULL);
865 * prop_is_type() checks the supplied property and returns PO_TRUE if the
866 * property value is 1 else PO_FALSE
868 static int
869 prop_is_type(int prop_type, const pool_prop_t *prop)
871 return ((prop->pp_perms & prop_type) ? PO_TRUE : PO_FALSE);
875 * prop_is_stored() returns PO_TRUE if the property is stored in the backing
876 * configuration and PO_FALSE else.
879 prop_is_stored(const pool_prop_t *prop)
881 return (prop_is_type(PP_STORED, prop));
885 * prop_is_readonly() returns PO_TRUE if the property is a read-only property
886 * and PO_FALSE else.
889 prop_is_readonly(const pool_prop_t *prop)
891 return (prop_is_type(PP_READ, prop));
895 * prop_is_init() returns PO_TRUE if the property should be
896 * initialised when an element of this type is created and PO_FALSE
897 * else.
900 prop_is_init(const pool_prop_t *prop)
902 return (prop_is_type(PP_INIT, prop));
906 * prop_is_hidden() returns PO_TRUE if the property should be hidden
907 * from access by the external property access mechanisms.
910 prop_is_hidden(const pool_prop_t *prop)
912 return (prop_is_type(PP_HIDDEN, prop));
916 * prop_is_optional() returns PO_TRUE if the property is optional and
917 * can be removed by external property access mechanisms.
920 prop_is_optional(const pool_prop_t *prop)
922 return (prop_is_type(PP_OPTIONAL, prop));
926 cpu_is_requested(pool_component_t *component)
928 pool_value_t val = POOL_VALUE_INITIALIZER;
929 uchar_t requested;
931 if (pool_get_property(TO_CONF(TO_ELEM(component)), TO_ELEM(component),
932 "cpu.requested", &val) != POC_BOOL) {
933 return (PO_FALSE);
935 if (pool_value_get_bool(&val, &requested) != PO_SUCCESS) {
936 return (PO_FALSE);
938 return ((int)requested);
942 * Common code for various resource get functions
944 static int
945 resource_get_common(const pool_resource_t *res, const char *name,
946 uint64_t *uval)
948 pool_value_t val = POOL_VALUE_INITIALIZER;
949 pool_value_class_t pvc;
950 int retval = PO_SUCCESS;
952 pvc = pool_get_ns_property(TO_ELEM(res), name, &val);
953 if (pvc == POC_INVAL) {
954 *uval = 0;
955 #ifdef DEBUG
956 dprintf("can't retrieve %s\n");
957 pool_elem_dprintf(TO_ELEM(res));
958 #endif /* DEBUG */
959 } else if (pvc == POC_UINT) {
960 retval = pool_value_get_uint64(&val, uval);
962 return (retval);
966 * resource_get_size() updates size with the size of the supplied resource.
968 * Returns PO_SUCCESS/PO_FAIL
971 resource_get_size(const pool_resource_t *res, uint64_t *size)
973 return (resource_get_common(res, c_size_prop, size));
977 * resource_get_pinned() updates pinned with the size of the
978 * pinned part of a supplied resource. Resource is not available for
979 * allocation if it is marked as "pinned".
981 * Returns PO_SUCCESS/PO_FAIL
984 resource_get_pinned(const pool_resource_t *res, uint64_t *pinned)
986 pool_value_t *props[] = { NULL, NULL };
987 pool_value_t val = POOL_VALUE_INITIALIZER;
988 pool_component_t **cs = NULL;
989 uint_t ncompelem;
991 props[0] = &val;
993 pool_value_set_bool(props[0], PO_TRUE);
994 if (pool_value_set_name(props[0], "cpu.pinned") != PO_SUCCESS)
995 return (PO_FAIL);
997 if ((cs = pool_query_resource_components(TO_CONF(TO_ELEM(res)), res,
998 &ncompelem, props)) != NULL) {
999 *pinned = ncompelem;
1000 free(cs);
1001 } else
1002 *pinned = 0;
1003 return (PO_SUCCESS);
1007 * resource_get_min() updates min with the minimum size of the supplied
1008 * resource.
1010 * Returns PO_SUCCESS/PO_FAIL
1013 resource_get_min(const pool_resource_t *res, uint64_t *min)
1015 return (resource_get_common(res, c_min_prop, min));
1019 * resource_get_max() updates max with the maximum size of the supplied
1020 * resource.
1022 * Returns PO_SUCCESS/PO_FAIL
1025 resource_get_max(const pool_resource_t *res, uint64_t *max)
1027 return (resource_get_common(res, c_max_prop, max));
1031 * TODO: This is pset specific
1033 * get_default_resource() returns the default resource for type of the supplied
1034 * resource.
1036 * Returns A pointer to the default resource of the same type as the supplied
1037 * resource.
1039 const pool_resource_t *
1040 get_default_resource(const pool_resource_t *res)
1042 return (resource_by_sysid(TO_CONF(TO_ELEM(res)), PS_NONE,
1043 pool_elem_class_string(TO_ELEM(res))));
1047 * resource_is_default() returns 1 if the supplied resource is the default
1048 * resource for it's type.
1051 resource_is_default(const pool_resource_t *res)
1054 return (get_default_resource(res) == res);
1058 * resource_is_system() determines if the resource is a system resource.
1061 resource_is_system(const pool_resource_t *res)
1063 return (res->pr_is_system(res));
1068 * resource_can_associate() determines if it is possible to associate
1069 * with the supplied resource.
1072 resource_can_associate(const pool_resource_t *res)
1074 return (res->pr_can_associate(res));
1078 * Common code to get an int64 property.
1079 * Unfortunately (-1) is a valid psetid, so we'll return (-2) in case of
1080 * error.
1082 static int64_t
1083 elem_get_expected_int64(const pool_elem_t *elem, const char *name)
1085 int64_t val64;
1086 pool_value_t val = POOL_VALUE_INITIALIZER;
1088 if (pool_get_ns_property(elem, name, &val) != POC_INT) {
1089 return (POOL_SYSID_BAD);
1091 (void) pool_value_get_int64(&val, &val64);
1093 return (val64);
1097 * The following returns a malloc'ed string which must be free'd by the
1098 * caller.
1100 static char *
1101 elem_get_expected_string(const pool_elem_t *elem, const char *name)
1103 pool_value_t val = POOL_VALUE_INITIALIZER;
1104 char *retval;
1106 if (pool_get_ns_property(elem, name, &val) != POC_STRING) {
1107 return (NULL);
1109 (void) pool_value_get_string(&val, (const char **)&retval);
1110 retval = strdup(retval);
1111 return (retval);
1115 * elem_get_sysid() returns the sys_id for the supplied elem.
1117 id_t
1118 elem_get_sysid(const pool_elem_t *elem)
1120 return ((id_t)elem_get_expected_int64(elem, c_sys_prop));
1124 * elem_get_name() returns the name for the supplied elem. Note that
1125 * it is the caller's responsibility to free this memory.
1127 char *
1128 elem_get_name(const pool_elem_t *elem)
1130 return (elem_get_expected_string(elem, c_name));
1134 * elem_is_default() returns 1 if the supplied elem is the default
1135 * elem for it's type.
1138 elem_is_default(const pool_elem_t *res)
1141 return (get_default_elem(res) == res);
1145 * Return B_TRUE if the element has the 'temporary' property set.
1147 boolean_t
1148 elem_is_tmp(const pool_elem_t *elem)
1150 pool_value_t val = POOL_VALUE_INITIALIZER;
1151 uchar_t bval;
1153 if (pool_get_ns_property(elem, "temporary", &val) != POC_BOOL)
1154 return (B_FALSE);
1156 (void) pool_value_get_bool(&val, &bval);
1158 return (bval != 0);
1162 * get_default_elem() returns the default elem for type of the supplied
1163 * elem.
1165 * Returns A pointer to the default elem of the same type as the
1166 * supplied elem or NULL on error. Trying to access the default elem
1167 * for a type of element which doesn't support the notion of default
1168 * is an error.
1170 const pool_elem_t *
1171 get_default_elem(const pool_elem_t *pe)
1173 pool_result_set_t *rs;
1174 pool_value_t *props[] = { NULL, NULL };
1175 pool_value_t val = POOL_VALUE_INITIALIZER;
1176 char_buf_t *cb;
1177 const pool_elem_t *pe_default;
1179 props[0] = &val;
1180 if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
1181 return (NULL);
1183 if (set_char_buf(cb, "%s.default", pool_elem_class_string(pe)) !=
1184 PO_SUCCESS) {
1185 free_char_buf(cb);
1186 return (NULL);
1188 if (pool_value_set_name(props[0], cb->cb_buf) != PO_SUCCESS) {
1189 free_char_buf(cb);
1190 return (NULL);
1192 free_char_buf(cb);
1193 pool_value_set_bool(props[0], PO_TRUE);
1195 if ((rs = pool_exec_query(TO_CONF(pe), NULL, NULL,
1196 PEC_QRY_ELEM(pe), props)) == NULL) {
1197 pool_seterror(POE_INVALID_CONF);
1198 return (NULL);
1200 if (pool_rs_count(rs) != 1) {
1201 (void) pool_rs_close(rs);
1202 pool_seterror(POE_INVALID_CONF);
1203 return (NULL);
1206 pe_default = rs->prs_next(rs);
1207 (void) pool_rs_close(rs);
1208 return (pe_default);
1212 * is_a_known_prefix() determines if the supplied prop_name is a known
1213 * name for the supplied class.
1215 * Returns a pointer to the prefix if it is found or NULL
1217 const char *
1218 is_a_known_prefix(pool_elem_class_t class, const char *prop_name)
1220 int i;
1221 int len;
1223 switch (class) {
1224 case PEC_SYSTEM:
1225 case PEC_POOL:
1226 len = strlen(pool_elem_class_name[class]);
1227 if (strncmp(prop_name, pool_elem_class_name[class], len) == 0 &&
1228 prop_name[len] == '.' || strcmp(prop_name, c_type) == 0)
1229 return (pool_elem_class_name[class]);
1230 break;
1231 case PEC_RES_COMP:
1232 case PEC_RES_AGG:
1233 for (i = 0; i < sizeof (pool_resource_elem_class_name) /
1234 sizeof (pool_resource_elem_class_name[0]); i++) {
1235 len = strlen(pool_resource_elem_class_name[i]);
1236 if (strncmp(prop_name,
1237 pool_resource_elem_class_name[i], len) == 0 &&
1238 prop_name[len] == '.' ||
1239 strcmp(prop_name, c_type) == 0)
1240 return (pool_resource_elem_class_name[i]);
1242 break;
1243 case PEC_COMP:
1244 for (i = 0; i < sizeof (pool_component_elem_class_name) /
1245 sizeof (pool_component_elem_class_name[0]); i++) {
1246 len = strlen(pool_component_elem_class_name[i]);
1247 if (strncmp(prop_name,
1248 pool_component_elem_class_name[i], len) == 0 &&
1249 prop_name[len] == '.' ||
1250 strcmp(prop_name, c_type) == 0)
1251 return (pool_component_elem_class_name[i]);
1253 break;
1254 default:
1255 break;
1257 return (NULL);
1261 const char *
1262 pool_elem_class_string(const pool_elem_t *pe)
1264 switch (pool_elem_class(pe)) {
1265 case PEC_SYSTEM:
1266 case PEC_POOL:
1267 return (pool_elem_class_name[pool_elem_class(pe)]);
1268 case PEC_RES_COMP:
1269 case PEC_RES_AGG:
1270 return (pool_resource_elem_class_name
1271 [pool_resource_elem_class(pe)]);
1272 case PEC_COMP:
1273 return (pool_component_elem_class_name
1274 [pool_component_elem_class(pe)]);
1275 default:
1276 return (pool_elem_class_name[PEC_INVALID]);
1280 const char *
1281 pool_resource_type_string(pool_resource_elem_class_t type)
1283 return (pool_resource_elem_class_name[type]);
1286 const char *
1287 pool_component_type_string(pool_component_elem_class_t type)
1289 return (pool_component_elem_class_name[type]);
1293 * resource_by_sysid() finds a resource from it's supplied sysid and type.
1295 * Returns a pointer to the resource or NULL if it doesn't exist.
1297 pool_resource_t *
1298 resource_by_sysid(const pool_conf_t *conf, id_t sysid, const char *type)
1300 pool_value_t *props[] = { NULL, NULL, NULL };
1301 pool_resource_t **resources = NULL;
1302 pool_resource_t *retval = NULL;
1303 uint_t nelem;
1304 char_buf_t *cb;
1305 pool_value_t val0 = POOL_VALUE_INITIALIZER;
1306 pool_value_t val1 = POOL_VALUE_INITIALIZER;
1308 props[0] = &val0;
1309 props[1] = &val1;
1311 if (pool_value_set_string(props[0], type) != PO_SUCCESS ||
1312 pool_value_set_name(props[0], c_type) != PO_SUCCESS)
1313 return (NULL);
1315 if ((cb = alloc_char_buf(CB_DEFAULT_LEN)) == NULL) {
1316 return (NULL);
1318 if (set_char_buf(cb, "%s.sys_id", type) != PO_SUCCESS) {
1319 free_char_buf(cb);
1320 return (NULL);
1322 if (pool_value_set_name(props[1], cb->cb_buf) != PO_SUCCESS) {
1323 free_char_buf(cb);
1324 return (NULL);
1326 free_char_buf(cb);
1327 pool_value_set_int64(props[1], sysid);
1329 resources = pool_query_resources(conf, &nelem, props);
1331 if (resources != NULL) {
1332 retval = resources[0];
1333 free(resources);
1335 return (retval);
1338 pool_elem_class_t
1339 pool_elem_class_from_string(const char *type)
1341 int i;
1343 for (i = 0; i < sizeof (pool_elem_class_name) /
1344 sizeof (pool_elem_class_name[0]); i++) {
1345 if (strcmp(pool_elem_class_name[i], type) == 0)
1346 break;
1348 if (i == sizeof (pool_elem_class_name) /
1349 sizeof (pool_elem_class_name[0]))
1350 return (PEC_INVALID);
1351 return ((pool_elem_class_t)i);
1354 pool_resource_elem_class_t
1355 pool_resource_elem_class_from_string(const char *type)
1357 int i;
1359 for (i = 0; i < sizeof (pool_resource_elem_class_name) /
1360 sizeof (pool_resource_elem_class_name[0]); i++) {
1361 if (strcmp(pool_resource_elem_class_name[i], type) == 0)
1362 break;
1364 if (i == sizeof (pool_resource_elem_class_name) /
1365 sizeof (pool_resource_elem_class_name[0]))
1366 return (PREC_INVALID);
1367 return ((pool_resource_elem_class_t)i);
1370 pool_component_elem_class_t
1371 pool_component_elem_class_from_string(const char *type)
1373 int i;
1375 for (i = 0; i < sizeof (pool_component_elem_class_name) /
1376 sizeof (pool_component_elem_class_name[0]); i++) {
1377 if (strcmp(pool_component_elem_class_name[i], type) == 0)
1378 break;
1380 if (i == sizeof (pool_component_elem_class_name) /
1381 sizeof (pool_component_elem_class_name[0]))
1382 return (PCEC_INVALID);
1383 return ((pool_component_elem_class_t)i);
1387 * pool_resource_type_list() populates the supplied array of pointers
1388 * with the names of the available resource types on this system.
1391 pool_resource_type_list(const char **types, uint_t *numtypes)
1393 int i, j;
1394 uint_t maxnum = *numtypes;
1396 *numtypes = pool_get_provider_count();
1398 if (types) {
1399 for (i = 0, j = 0; i < sizeof (pool_resource_elem_ctl) /
1400 sizeof (pool_resource_elem_ctl[0]) && j < maxnum; i++) {
1401 if (pool_resource_elem_ctl[i] != NULL)
1402 types[j++] = pool_resource_elem_class_name[i];
1405 return (PO_SUCCESS);
1409 * Return the system element for the supplied conf.
1410 * NULL is returned if an error is detected and the error code is updated
1411 * to indicate the cause of the error.
1413 pool_system_t *
1414 pool_conf_system(const pool_conf_t *conf)
1416 pool_elem_t *system;
1417 pool_result_set_t *rs;
1419 if ((rs = pool_exec_query(conf, NULL, NULL, PEC_QRY_SYSTEM, NULL)) ==
1420 NULL) {
1421 pool_seterror(POE_INVALID_CONF);
1422 return (NULL);
1424 /* There should only be one system record */
1425 if (pool_rs_count(rs) != 1) {
1426 pool_seterror(POE_INVALID_CONF);
1427 (void) pool_rs_close(rs);
1428 return (NULL);
1430 system = rs->prs_next(rs);
1431 (void) pool_rs_close(rs);
1432 return (pool_elem_system(system));
1435 pool_system_t *
1436 pool_elem_system(const pool_elem_t *pe)
1438 if (pe->pe_class != PEC_SYSTEM) {
1439 pool_seterror(POE_BADPARAM);
1440 return (NULL);
1442 return ((pool_system_t *)pe);
1445 pool_t *
1446 pool_elem_pool(const pool_elem_t *pe)
1448 if (pe->pe_class != PEC_POOL) {
1449 pool_seterror(POE_BADPARAM);
1450 return (NULL);
1452 return ((pool_t *)pe);
1455 pool_resource_t *
1456 pool_elem_res(const pool_elem_t *pe)
1458 if (pe->pe_class != PEC_RES_COMP &&
1459 pool_elem_class(pe) != PEC_RES_AGG) {
1460 pool_seterror(POE_BADPARAM);
1461 return (NULL);
1463 return ((pool_resource_t *)pe);
1466 pool_component_t *
1467 pool_elem_comp(const pool_elem_t *pe)
1469 if (pe->pe_class != PEC_COMP) {
1470 pool_seterror(POE_BADPARAM);
1471 return (NULL);
1473 return ((pool_component_t *)pe);
1477 * qsort_elem_compare() is used for qsort elemement comparison.
1479 * Returns see qsort(3c)
1482 qsort_elem_compare(const void *a, const void *b)
1484 const pool_elem_t *e1 = *(const pool_elem_t **)a;
1485 const pool_elem_t *e2 = *(const pool_elem_t **)b;
1488 * Special case for handling name changes on default elements
1489 * If both elements are default elements then always return 0
1491 if (pool_elem_same_class(e1, e2) == PO_TRUE &&
1492 (elem_is_default(e1) && elem_is_default(e2)))
1493 return (0);
1494 else
1495 return (pool_elem_compare_name(e1, e2));
1499 * Dynamic character buffers.
1503 * Resize the supplied character buffer to the new size.
1505 static int
1506 resize_char_buf(char_buf_t *cb, size_t size)
1508 char *re_cb = NULL;
1510 if ((re_cb = realloc(cb->cb_buf, size)) == NULL) {
1511 pool_seterror(POE_SYSTEM);
1512 return (PO_FAIL);
1514 /* If inital allocation, make sure buffer is zeroed */
1515 if (cb->cb_buf == NULL)
1516 (void) memset(re_cb, 0, sizeof (re_cb));
1517 /* If resized smaller, make sure buffer NULL terminated */
1518 if (size < cb->cb_size)
1519 re_cb[size] = 0;
1520 cb->cb_buf = re_cb;
1521 cb->cb_size = size;
1522 return (PO_SUCCESS);
1526 * Allocate a new char_buf_t structure. If there isn't enough memory, return
1527 * NULL. Initialise the new char_buf_t to 0 and then call resize_char_buf
1528 * to initialise the character buffer. Return a pointer to the new
1529 * char_buf_t if the operation succeeds.
1531 char_buf_t *
1532 alloc_char_buf(size_t size)
1534 char_buf_t *cb;
1536 if ((cb = malloc(sizeof (char_buf_t))) == NULL) {
1537 pool_seterror(POE_SYSTEM);
1538 return (NULL);
1540 (void) memset(cb, 0, sizeof (char_buf_t));
1542 if (resize_char_buf(cb, size + 1) == PO_FAIL) {
1543 free(cb);
1544 return (NULL);
1546 return (cb);
1550 * Free the character buffer and then free the char_buf_t.
1552 void
1553 free_char_buf(char_buf_t *cb)
1555 free((void *)cb->cb_buf);
1556 free(cb);
1560 * Set the character buffer to the supplied data. The user supplies a printf
1561 * like format string and then an appropriate number of parameters for the
1562 * specified format. The character buffer is automatically resized to fit
1563 * the data as determined by resize_char_buf.
1565 /*PRINTFLIKE2*/
1567 set_char_buf(char_buf_t *cb, const char *fmt, ...)
1569 va_list ap;
1570 int new_size;
1572 va_start(ap, fmt);
1573 if ((new_size = vsnprintf(cb->cb_buf, cb->cb_size, fmt, ap)) >=
1574 cb->cb_size) {
1575 if (resize_char_buf(cb, new_size + 1) != PO_SUCCESS) {
1576 pool_seterror(POE_SYSTEM);
1577 return (PO_FAIL);
1579 (void) vsnprintf(cb->cb_buf, cb->cb_size, fmt, ap);
1581 va_end(ap);
1582 return (PO_SUCCESS);
1586 * Append the supplied data to the character buffer. The user supplies a printf
1587 * like format string and then an appropriate number of parameters for the
1588 * specified format. The character buffer is automatically resized to fit
1589 * the data as determined by resize_char_buf.
1591 /*PRINTFLIKE2*/
1593 append_char_buf(char_buf_t *cb, const char *fmt, ...)
1595 va_list ap;
1596 int new_len;
1597 char size_buf[1];
1598 int old_len = 0;
1600 if (cb->cb_buf != NULL)
1601 old_len = strlen(cb->cb_buf);
1602 va_start(ap, fmt);
1603 new_len = vsnprintf(size_buf, sizeof (size_buf), fmt, ap);
1604 if (new_len + old_len >= cb->cb_size) {
1605 if (resize_char_buf(cb, old_len + new_len + 1) !=
1606 PO_SUCCESS) {
1607 pool_seterror(POE_SYSTEM);
1608 return (PO_FAIL);
1612 * Resized the buffer to the right size, now append the new data
1614 (void) vsnprintf(&cb->cb_buf[old_len], cb->cb_size - old_len, fmt, ap);
1615 va_end(ap);
1616 return (PO_SUCCESS);
1620 * Return the class for the supplied elem.
1621 * If the return is PEC_INVALID, the error code will be set to reflect cause.
1623 pool_elem_class_t
1624 pool_elem_class(const pool_elem_t *elem)
1626 return (elem->pe_class);
1631 * Return the resource class for the supplied elem.
1633 pool_resource_elem_class_t
1634 pool_resource_elem_class(const pool_elem_t *elem)
1636 return (elem->pe_resource_class);
1640 * Return the component class for the supplied elem.
1642 pool_component_elem_class_t
1643 pool_component_elem_class(const pool_elem_t *elem)
1645 return (elem->pe_component_class);
1648 pool_elem_t *
1649 pool_get_pair(const pool_elem_t *pe)
1651 return (pe->pe_pair);
1654 void
1655 pool_set_pair(pool_elem_t *pe1, pool_elem_t *pe2)
1657 pe1->pe_pair = pe2;
1661 pool_validate_resource(const pool_conf_t *conf, const char *type,
1662 const char *prop, int64_t delta)
1664 pool_conf_t *dyn;
1665 uint_t nelem;
1666 uint64_t available, required, uval;
1667 int i;
1668 pool_resource_t **rl;
1669 pool_value_t val = POOL_VALUE_INITIALIZER;
1670 pool_value_t val1 = POOL_VALUE_INITIALIZER;
1671 pool_value_t *pvals[] = { NULL, NULL };
1673 if (strcmp(prop, c_min_prop) && strcmp(prop, c_max_prop)) {
1674 pool_seterror(POE_BADPARAM);
1675 return (PO_FAIL);
1678 pvals[0] = &val;
1679 (void) pool_value_set_string(&val, type);
1680 (void) pool_value_set_name(&val, c_type);
1683 * Check that there are available resources on this
1684 * system for this configuration to be applied. Find
1685 * each resource type and then find all resources of
1686 * each type and total ".min". Find all available
1687 * resources and ensure >= total min.
1690 available = 0;
1691 required = delta;
1693 if ((rl = (pool_query_resources(conf, &nelem, pvals))) == NULL)
1694 return (PO_FAIL);
1696 for (i = 0; i < nelem; i++) {
1697 if (pool_get_ns_property(TO_ELEM(rl[i]), prop,
1698 &val1) == POC_INVAL ||
1699 pool_value_get_uint64(&val1, &uval) != PO_SUCCESS) {
1700 free(rl);
1701 return (PO_FAIL);
1704 * Watch out for overflow
1706 if (required + uval < required) {
1707 required = UINT64_MAX;
1708 break;
1709 } else
1710 required += uval;
1713 if (conf_is_dynamic(conf) == PO_TRUE) {
1714 dyn = (pool_conf_t *)conf;
1715 } else {
1716 free(rl);
1717 if ((dyn = pool_conf_alloc()) == NULL)
1718 return (PO_FAIL);
1719 if (pool_conf_open(dyn, pool_dynamic_location(), PO_RDONLY) !=
1720 PO_SUCCESS) {
1721 pool_conf_free(dyn);
1722 return (PO_FAIL);
1724 if ((rl = (pool_query_resources(dyn, &nelem, pvals))) ==
1725 NULL) {
1726 (void) pool_conf_close(dyn);
1727 pool_conf_free(dyn);
1728 return (PO_FAIL);
1731 for (i = 0; i < nelem; i++) {
1732 if (pool_get_ns_property(TO_ELEM(rl[i]), c_size_prop,
1733 &val1) == POC_INVAL ||
1734 pool_value_get_uint64(&val1, &uval) != PO_SUCCESS) {
1735 free(rl);
1736 if (conf != dyn) {
1737 (void) pool_conf_close(dyn);
1738 pool_conf_free(dyn);
1740 return (PO_FAIL);
1742 available += uval;
1744 free(rl);
1745 if (conf != dyn) {
1746 (void) pool_conf_close(dyn);
1747 pool_conf_free(dyn);
1749 if (strcmp(prop, c_min_prop) == 0) {
1750 if (available < required) {
1751 pool_seterror(POE_INVALID_CONF);
1752 return (PO_FAIL);
1754 } else {
1755 if (available > required) {
1756 pool_seterror(POE_INVALID_CONF);
1757 return (PO_FAIL);
1760 return (PO_SUCCESS);
1764 * If _libpool_debug is set, printf the debug message to stderr with an
1765 * appropriate prefix in front of it.
1767 void
1768 do_dprintf(const char *format, va_list ap)
1770 if (_libpool_debug) {
1771 (void) fputs("libpool DEBUG: ", stderr);
1772 (void) vfprintf(stderr, format, ap);
1776 /*PRINTFLIKE1*/
1777 void
1778 dprintf(const char *format, ...)
1780 if (_libpool_debug) {
1781 va_list alist;
1782 va_start(alist, format);
1783 do_dprintf(format, alist);
1784 va_end(alist);
1789 * log_alloc() allocates a new, empty transaction log.
1791 * Returns a pointer to the new log or NULL on failure.
1793 log_t *
1794 log_alloc(pool_conf_t *conf)
1796 log_t *l;
1798 if ((l = calloc(1, sizeof (log_t))) == NULL) {
1799 pool_seterror(POE_SYSTEM);
1800 return (NULL);
1802 l->l_state = LS_DO;
1803 l->l_conf = conf;
1804 if ((l->l_sentinel = log_item_alloc(l, 0, NULL))
1805 == NULL) {
1806 free(l);
1807 pool_seterror(POE_SYSTEM);
1808 return (NULL);
1810 l->l_sentinel->li_next = l->l_sentinel;
1811 l->l_sentinel->li_prev = l->l_sentinel;
1813 return (l);
1817 * log_free() reclaims the resources associated with a transaction log.
1819 void
1820 log_free(log_t *l)
1822 (void) log_walk(l, log_item_free);
1823 (void) log_item_free(l->l_sentinel);
1824 free(l);
1827 * log_empty() removes all items from a transaction log. It is the
1828 * users responsibility to ensure that any resources associated with
1829 * an item are reclaimed before this function is invoked.
1831 void
1832 log_empty(log_t *l)
1834 (void) log_walk(l, log_item_free);
1838 * log_walk() visits each log item in turn and executes the supplied action
1839 * using the item as a parameter. If no action is supplied, then the item
1840 * uses it's own stored action.
1842 * Returns PO_SUCCESS/PO_FAIL
1845 log_walk(log_t *l, log_item_action_t action)
1847 log_item_t *li, *li_next;
1849 li = l->l_sentinel->li_next;
1850 while (li != l->l_sentinel) {
1851 li_next = li->li_next;
1852 if ((action(li)) != PO_SUCCESS)
1853 return (PO_FAIL);
1854 li = li_next;
1856 return (PO_SUCCESS);
1860 * log_reverse_walk() visits each log item in turn (in reverse order)
1861 * and executes the supplied action using the item as a parameter.
1863 * Returns PO_SUCCESS/PO_FAIL
1866 log_reverse_walk(log_t *l, log_item_action_t action)
1868 log_item_t *li, *li_prev;
1870 li = l->l_sentinel->li_prev;
1871 while (li != l->l_sentinel) {
1872 li_prev = li->li_prev;
1873 if ((action(li)) != PO_SUCCESS)
1874 return (PO_FAIL);
1875 li = li_prev;
1877 return (PO_SUCCESS);
1881 * log_size() returns the size of the log, i.e. the number of items pending in
1882 * the log.
1884 uint_t
1885 log_size(log_t *l)
1887 log_item_t *li;
1888 uint_t size = 0;
1890 for (li = l->l_sentinel->li_next; li != l->l_sentinel; li = li->li_next)
1891 size++;
1892 return (size);
1896 * log_append() allocates a new log item to hold the supplied details and
1897 * appends the newly created item to the supplied log.
1899 * Returns PO_SUCCESS/PO_FAIL
1902 log_append(log_t *l, int op, void *details)
1904 log_item_t *li;
1906 if ((li = log_item_alloc(l, op, details)) == NULL) {
1907 l->l_state = LS_UNDO;
1908 return (PO_FAIL);
1911 * Link it in
1913 li->li_prev = l->l_sentinel->li_prev;
1914 li->li_next = l->l_sentinel;
1915 l->l_sentinel->li_prev->li_next = li;
1916 l->l_sentinel->li_prev = li;
1917 return (PO_SUCCESS);
1921 * log_item_alloc() allocates a new transaction log item. The item should be
1922 * used to store details about a transaction which may need to be undone if
1923 * commit processing fails.
1925 * Returns a pointer to a new transaction log item or NULL.
1927 log_item_t *
1928 log_item_alloc(log_t *l, int op, void *details)
1930 log_item_t *li;
1932 if ((li = malloc(sizeof (log_item_t))) == NULL) {
1933 pool_seterror(POE_SYSTEM);
1934 return (NULL);
1937 (void) memset(li, 0, sizeof (log_item_t));
1938 li->li_log = l;
1939 li->li_op = op;
1940 li->li_details = details;
1941 li->li_state = LS_DO;
1943 return (li);
1947 * log_item_free() reclaims the resources associated with a log_item_t.
1950 log_item_free(log_item_t *li)
1952 li->li_prev->li_next = li->li_next;
1953 li->li_next->li_prev = li->li_prev;
1954 free(li);
1955 return (PO_SUCCESS);
1959 * atom_string() checks the string table to see if a string is already
1960 * stored. If it is, return a pointer to it. If not, duplicate the
1961 * string and return a pointer to the duplicate.
1963 const char *
1964 atom_string(const char *s)
1966 atom_t *atom;
1969 * atom_init() must have completed successfully
1971 atom_init();
1972 (void) mutex_lock(&_atom_lock);
1973 if ((atom = dict_get(_pv_atoms, s)) == NULL) {
1974 if ((atom = calloc(1, sizeof (atom_t))) == NULL) {
1975 pool_seterror(POE_SYSTEM);
1976 (void) mutex_unlock(&_atom_lock);
1977 return (NULL);
1979 if ((atom->a_string = strdup(s)) == NULL) {
1980 (void) mutex_unlock(&_atom_lock);
1981 free(atom);
1982 pool_seterror(POE_SYSTEM);
1983 return (NULL);
1985 (void) dict_put(_pv_atoms, atom->a_string, atom);
1987 atom->a_count++;
1988 (void) mutex_unlock(&_atom_lock);
1989 return (atom->a_string);
1993 * atom_free() decrements the reference count for the supplied
1994 * string. If the reference count reaches zero, then the atom is
1995 * destroyed.
1997 void
1998 atom_free(const char *s)
2000 atom_t *atom;
2002 (void) mutex_lock(&_atom_lock);
2003 if ((atom = dict_get(_pv_atoms, s)) != NULL) {
2004 if (--atom->a_count == 0) {
2005 (void) dict_remove(_pv_atoms, s);
2006 free(atom->a_string);
2007 free(atom);
2010 (void) mutex_unlock(&_atom_lock);
2013 #ifdef DEBUG
2015 * log_item_dprintf() prints the contents of the supplied log item using the
2016 * pools dprintf() trace mechanism.
2018 * Returns PO_SUCCESS
2020 void
2021 log_item_dprintf(log_item_t *li)
2023 dprintf("LOGDUMP: %d operation, %p\n", li->li_op, li->li_details);
2027 * log_item_dprintf() prints the contents of the supplied log item using the
2028 * pools dprintf() trace mechanism.
2030 * Returns PO_SUCCESS
2032 void
2033 pool_elem_dprintf(const pool_elem_t *pe)
2035 if (pool_elem_class(pe) != PEC_COMP) {
2036 const char *name = elem_get_name(pe);
2037 dprintf("element type: %s name: %s\n",
2038 pool_elem_class_string(pe), name);
2039 free((void *)name);
2040 } else {
2041 id_t sys_id = elem_get_sysid(pe);
2042 dprintf("element type: %s sys_id: %d\n",
2043 pool_elem_class_string(pe), sys_id);
2046 #endif /* DEBUG */