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]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
46 #include <sys/priocntl.h>
47 #include <sys/types.h>
51 #include "pool_internal.h"
52 #include "pool_impl.h"
55 * libpool Interface Routines
57 * pool.c implements (most of) the external interface to libpool
58 * users. Some of the interface is implemented in pool_internal.c for
59 * reasons of internal code organisation. The core requirements for
64 * The abstraction of the actual datastore so that no details of the
65 * underlying data representation mechanism are revealed to users of
66 * the library. For instance, the fact that we use the kernel or files
67 * to store our configurations is completely abstracted via the
68 * various libpool APIs.
70 * External Interaction
72 * libpool users manipulate configuration components via the API
73 * defined in pool.h. Most functions in this file act as interceptors,
74 * validating parameters before redirecting the request into a
75 * specific datastore implementation for the actual work to be done.
77 * These main sets of requirements have driven the design so that it
78 * is possible to replace the entire datastore type without having to
79 * modify the external (or internal provider) APIs. It is possible to
80 * modify the storage technology used by libpool by implementing a new
81 * set of datastore provider operations. Simply modify the
82 * pool_conf_open() routine to establish a new datastore as the
83 * provider for a configuration.
85 * The key components in a libpool configuration are :
86 * pool_conf_t - This represents a complete configuration instance
87 * pool_t - A pool inside a configuration
88 * pool_resource_t - A resource inside a configuration
89 * pool_component_t - A component of a resource
94 * Used to control transfer setup.
96 #define XFER_FAIL PO_FAIL
97 #define XFER_SUCCESS PO_SUCCESS
98 #define XFER_CONTINUE 1
100 #define SMF_SVC_INSTANCE "svc:/system/pools:default"
101 #define E_ERROR 1 /* Exit status for error */
104 #define TEXT_DOMAIN "SYS_TEST"
105 #endif /* TEXT_DOMAIN */
107 const char pool_info_location
[] = "/dev/pool";
112 static const char static_location
[] = "/etc/pooladm.conf";
113 static const char dynamic_location
[] = "/dev/poolctl";
114 static thread_key_t errkey
= THR_ONCE_KEY
;
119 static int pool_errval
= POE_OK
;
124 static uint_t pool_workver
= POOL_VER_CURRENT
;
126 static const char *data_type_tags
[] = {
137 static int pool_elem_remove(pool_elem_t
*);
138 static int is_valid_prop_name(const char *);
139 static int prop_buf_build_cb(pool_conf_t
*, pool_elem_t
*, const char *,
140 pool_value_t
*, void *);
141 static char *pool_base_info(const pool_elem_t
*, char_buf_t
*, int);
142 static int choose_components(pool_resource_t
*, pool_resource_t
*, uint64_t);
143 static int pool_conf_check(const pool_conf_t
*);
144 static void free_value_list(int, pool_value_t
**);
145 static int setup_transfer(pool_conf_t
*, pool_resource_t
*, pool_resource_t
*,
146 uint64_t, uint64_t *, uint64_t *);
149 * Return the "static" location string for libpool.
152 pool_static_location(void)
154 return (static_location
);
158 * Return the "dynamic" location string for libpool.
161 pool_dynamic_location(void)
163 return (dynamic_location
);
167 * Return the status for a configuration. If the configuration has
168 * been successfully opened, then the status will be POF_VALID or
169 * POF_DESTROY. If the configuration failed to open properly or has
170 * been closed or removed, then the status will be POF_INVALID.
173 pool_conf_status(const pool_conf_t
*conf
)
175 return (conf
->pc_state
);
179 * Bind idtype id to the pool name.
182 pool_set_binding(const char *pool_name
, idtype_t idtype
, id_t id
)
187 if ((conf
= pool_conf_alloc()) == NULL
)
190 if (pool_conf_open(conf
, pool_dynamic_location(), PO_RDONLY
) < 0) {
191 pool_conf_free(conf
);
192 pool_seterror(POE_INVALID_CONF
);
196 result
= conf
->pc_prov
->pc_set_binding(conf
, pool_name
, idtype
, id
);
198 (void) pool_conf_close(conf
);
199 pool_conf_free(conf
);
204 * pool_get_resource_binding() returns the binding for a pid to the supplied
205 * type of resource. If a binding cannot be determined, NULL is returned.
208 pool_get_resource_binding(const char *sz_type
, pid_t pid
)
212 pool_resource_elem_class_t type
;
214 if ((type
= pool_resource_elem_class_from_string(sz_type
)) ==
216 pool_seterror(POE_BADPARAM
);
220 if ((conf
= pool_conf_alloc()) == NULL
)
223 if (pool_conf_open(conf
, pool_dynamic_location(), PO_RDONLY
)
225 pool_seterror(POE_INVALID_CONF
);
226 pool_conf_free(conf
);
229 result
= conf
->pc_prov
->pc_get_resource_binding(conf
, type
, pid
);
230 (void) pool_conf_close(conf
);
231 pool_conf_free(conf
);
236 * pool_get_binding() returns the binding for a pid to a pool. If a
237 * binding cannot be determined, NULL is returned.
240 pool_get_binding(pid_t pid
)
245 if ((conf
= pool_conf_alloc()) == NULL
)
248 if (pool_conf_open(conf
, pool_dynamic_location(), PO_RDONLY
)
250 pool_seterror(POE_INVALID_CONF
);
251 pool_conf_free(conf
);
254 result
= conf
->pc_prov
->pc_get_binding(conf
, pid
);
255 (void) pool_conf_close(conf
);
256 pool_conf_free(conf
);
262 prop_buf_build_cb(pool_conf_t
*UNUSED
, pool_elem_t
*pe
, const char *name
,
263 pool_value_t
*pval
, void *user
)
270 char_buf_t
*cb
= (char_buf_t
*)user
;
271 int type
= pool_value_get_type(pval
);
274 * Ignore "type" and "<type>.name" properties as these are not
275 * to be displayed by this function
277 if (strcmp(name
, c_type
) == 0 ||
278 strcmp(property_name_minus_ns(pe
, name
), c_name
) == 0)
280 if (append_char_buf(cb
, "\n%s\t%s\t%s ", cb
->cb_tab_buf
,
281 data_type_tags
[type
], name
) == PO_FAIL
)
285 (void) pool_value_get_uint64(pval
, &u
);
286 if (append_char_buf(cb
, "%llu", (u_longlong_t
)u
) == PO_FAIL
)
290 (void) pool_value_get_int64(pval
, &i
);
291 if (append_char_buf(cb
, "%lld", (longlong_t
)i
) == PO_FAIL
)
295 (void) pool_value_get_string(pval
, &str
);
296 if (append_char_buf(cb
, "%s", str
) == PO_FAIL
)
300 (void) pool_value_get_bool(pval
, &bool);
302 if (append_char_buf(cb
, "%s", "false") == PO_FAIL
)
305 if (append_char_buf(cb
, "%s", "true") == PO_FAIL
)
310 (void) pool_value_get_double(pval
, &d
);
311 if (append_char_buf(cb
, "%g", d
) == PO_FAIL
)
314 case POC_INVAL
: /* Do nothing */
323 * Return a buffer which describes the element
324 * pe is a pointer to the element
325 * deep is PO_TRUE/PO_FALSE to indicate whether children should be included
328 pool_base_info(const pool_elem_t
*pe
, char_buf_t
*cb
, int deep
)
334 pool_value_t val
= POOL_VALUE_INITIALIZER
;
335 pool_resource_t
**rs
;
337 pool_conf_t
*conf
= TO_CONF(pe
);
342 if ((cb
= alloc_char_buf(CB_DEFAULT_LEN
)) == NULL
)
346 * Populate the buffer with element details
348 (void) pool_base_info(pe
, cb
, deep
);
350 ret
= strdup(cb
->cb_buf
);
355 if (append_char_buf(cb
, "\n%s%s", cb
->cb_tab_buf
,
356 pool_elem_class_string(pe
)) == PO_FAIL
) {
360 if (pool_get_ns_property(pe
, c_name
, &val
) == POC_STRING
) {
361 (void) pool_value_get_string(&val
, &sres
);
362 if (append_char_buf(cb
, " %s", sres
) == PO_FAIL
) {
368 * Add in some details about the element
370 if (pool_walk_properties(conf
, (pool_elem_t
*)pe
, cb
,
371 prop_buf_build_cb
) == PO_FAIL
) {
372 (void) append_char_buf(cb
, "\n%s%s\n", cb
->cb_tab_buf
,
373 "Cannot access the properties of this element.");
376 if (append_char_buf(cb
, "%s", "\n") == PO_FAIL
)
379 if (pe
->pe_class
== PEC_POOL
) {
381 * A shallow display of a pool only lists the resources by name
384 if ((rs
= pool_query_pool_resources(conf
, pool_elem_pool(pe
),
385 &nelem
, NULL
)) == NULL
) {
389 for (i
= 0; i
< nelem
; i
++) {
392 elem
= TO_ELEM(rs
[i
]);
394 if (append_char_buf(cb
, "\t%s%s", cb
->cb_tab_buf
,
395 pool_elem_class_string(elem
)) == PO_FAIL
) {
400 if (pool_get_ns_property(elem
, c_name
, &val
) !=
403 pool_seterror(POE_INVALID_CONF
);
406 (void) pool_value_get_string(&val
, &str
);
407 if (append_char_buf(cb
, "\t%s\n", str
) == PO_FAIL
) {
414 if (deep
== PO_TRUE
) {
416 pool_component_t
**cs
;
418 if (strlcat(cb
->cb_tab_buf
, "\t", CB_TAB_BUF_SIZE
)
419 >= CB_TAB_BUF_SIZE
) {
420 pool_seterror(POE_SYSTEM
);
423 switch (pe
->pe_class
) {
425 if ((ps
= pool_query_pools(conf
, &nelem
, NULL
)) !=
426 NULL
) { /* process the pools */
427 for (i
= 0; i
< nelem
; i
++) {
428 elem
= TO_ELEM(ps
[i
]);
429 if (pool_base_info(elem
, cb
,
437 if ((rs
= pool_query_resources(conf
, &nelem
, NULL
)) !=
439 for (i
= 0; i
< nelem
; i
++) {
440 elem
= TO_ELEM(rs
[i
]);
441 if (pool_base_info(elem
, cb
,
451 if ((rs
= pool_query_pool_resources(conf
,
452 pool_elem_pool(pe
), &nelem
, NULL
)) == NULL
)
454 for (i
= 0; i
< nelem
; i
++) {
455 elem
= TO_ELEM(rs
[i
]);
456 if (pool_base_info(elem
, cb
, PO_TRUE
) == NULL
) {
464 if ((cs
= pool_query_resource_components(conf
,
465 pool_elem_res(pe
), &nelem
, NULL
)) != NULL
) {
466 for (i
= 0; i
< nelem
; i
++) {
467 elem
= TO_ELEM(cs
[i
]);
468 if (pool_base_info(elem
, cb
,
484 if (cb
->cb_tab_buf
[0] != 0)
485 cb
->cb_tab_buf
[strlen(cb
->cb_tab_buf
) - 1] = 0;
491 * Returns The information on the specified pool or NULL.
493 * Errors If the status of the conf is INVALID or the supplied
494 * value of deep is illegal, POE_BADPARAM.
496 * The caller is responsible for free(3c)ing the string returned.
499 pool_info(const pool_conf_t
*conf
, const pool_t
*pool
, int deep
)
505 if (TO_CONF(pe
) != conf
) {
506 pool_seterror(POE_BADPARAM
);
510 if (pool_conf_status(conf
) == POF_INVALID
|| (deep
& ~1)) {
511 pool_seterror(POE_BADPARAM
);
515 return (pool_base_info(pe
, NULL
, deep
));
519 * Returns The information on the specified resource or NULL.
521 * Errors If the status of the conf is INVALID or the supplied
522 * value of deep is illegal, POE_BADPARAM.
524 * The caller is responsible for free(3c)ing the string returned.
527 pool_resource_info(const pool_conf_t
*conf
, const pool_resource_t
*res
,
534 if (TO_CONF(pe
) != conf
) {
535 pool_seterror(POE_BADPARAM
);
539 if (pool_conf_status(conf
) == POF_INVALID
|| (deep
& ~1)) {
540 pool_seterror(POE_BADPARAM
);
544 return (pool_base_info(pe
, NULL
, deep
));
548 * Returns The information on the specified component or NULL.
550 * Errors If the status of the conf is INVALID or the supplied
551 * value of deep is illegal, POE_BADPARAM.
553 * The caller is responsible for free(3c)ing the string returned.
556 pool_component_info(const pool_conf_t
*conf
, const pool_component_t
*comp
,
563 if (TO_CONF(pe
) != conf
) {
564 pool_seterror(POE_BADPARAM
);
568 if (pool_conf_status(conf
) == POF_INVALID
|| (deep
& ~1)) {
569 pool_seterror(POE_BADPARAM
);
573 return (pool_base_info(pe
, NULL
, deep
));
577 * Returns The information on the specified conf or NULL.
579 * Errors If the status of the conf is INVALID or the supplied
580 * value of deep is illegal, POE_BADPARAM.
582 * The caller is responsible for free(3c)ing the string returned.
585 pool_conf_info(const pool_conf_t
*conf
, int deep
)
589 if (pool_conf_status(conf
) == POF_INVALID
|| (deep
& ~1)) {
590 pool_seterror(POE_BADPARAM
);
593 if ((pe
= pool_conf_to_elem(conf
)) == NULL
) {
594 pool_seterror(POE_BADPARAM
);
597 return (pool_base_info(pe
, NULL
, deep
));
602 * Set the thread specific error value.
605 pool_seterror(int errval
)
608 pool_errval
= errval
;
611 (void) thr_keycreate_once(&errkey
, 0);
612 (void) thr_setspecific(errkey
, (void *)(intptr_t)errval
);
616 * Return the current value of the error code.
617 * Returns: int error code
623 return (pool_errval
);
624 if (errkey
== THR_ONCE_KEY
)
626 return ((uintptr_t)pthread_getspecific(errkey
));
630 * Return the text represenation for the current value of the error code.
631 * Returns: const char * error string
634 pool_strerror(int error
)
640 str
= dgettext(TEXT_DOMAIN
, "Operation successful");
642 case POE_BAD_PROP_TYPE
:
643 str
= dgettext(TEXT_DOMAIN
,
644 "Attempted to retrieve the wrong property type");
646 case POE_INVALID_CONF
:
647 str
= dgettext(TEXT_DOMAIN
, "Invalid configuration");
650 str
= dgettext(TEXT_DOMAIN
, "Operation is not supported");
652 case POE_INVALID_SEARCH
:
653 str
= dgettext(TEXT_DOMAIN
, "Invalid search");
656 str
= dgettext(TEXT_DOMAIN
, "Bad parameter supplied");
659 str
= dgettext(TEXT_DOMAIN
, "Error putting property");
662 str
= dgettext(TEXT_DOMAIN
, "Pools repository error");
665 str
= dgettext(TEXT_DOMAIN
, "System error");
668 str
= dgettext(TEXT_DOMAIN
, "Permission denied");
678 pool_get_status(int *state
)
681 pool_status_t status
;
683 if ((fd
= open(pool_info_location
, O_RDONLY
)) < 0) {
684 pool_seterror(POE_SYSTEM
);
687 if (ioctl(fd
, POOL_STATUSQ
, &status
) < 0) {
689 pool_seterror(POE_SYSTEM
);
694 *state
= status
.ps_io_state
;
700 pool_set_status(int state
)
704 if (pool_get_status(&old_state
) != PO_SUCCESS
) {
705 pool_seterror(POE_SYSTEM
);
709 if (old_state
!= state
) {
711 pool_status_t status
;
715 * Changing the status of pools is performed by enabling
716 * or disabling the pools service instance. If this
717 * function has not been invoked by startd then we simply
718 * enable/disable the service and return success.
720 * There is no way to specify that state changes must be
721 * synchronous using the library API as yet, so we use
722 * the -s option provided by svcadm.
724 fmri
= getenv("SMF_FMRI");
730 cmd
= "/usr/sbin/svcadm enable -s " \
733 cmd
= "/usr/sbin/svcadm disable -s " \
736 if ((p
= popen(cmd
, "wF")) == NULL
|| pclose(p
) != 0) {
737 pool_seterror(POE_SYSTEM
);
743 if ((fd
= open(pool_dynamic_location(), O_RDWR
| O_EXCL
)) < 0) {
744 pool_seterror(POE_SYSTEM
);
749 * If pools are being enabled/disabled by another smf service,
750 * enable the smf service instance. This must be done
751 * asynchronously as one service cannot synchronously
752 * enable/disable another.
754 if (strcmp(fmri
, SMF_SVC_INSTANCE
) != 0) {
758 res
= smf_enable_instance(SMF_SVC_INSTANCE
, 0);
760 res
= smf_disable_instance(SMF_SVC_INSTANCE
, 0);
764 pool_seterror(POE_SYSTEM
);
768 status
.ps_io_state
= state
;
770 if (ioctl(fd
, POOL_STATUS
, &status
) < 0) {
772 pool_seterror(POE_SYSTEM
);
783 * General Data Provider Independent Access Methods
787 * Property manipulation code.
789 * The pool_(get|rm|set)_property() functions consult the plugins before
790 * looking at the actual configuration. This allows plugins to provide
791 * "virtual" properties that may not exist in the configuration file per se,
792 * but behave like regular properties. This also allows plugins to reserve
793 * certain properties as read-only, non-removable, etc.
795 * A negative value returned from the plugin denotes error, 0 means that the
796 * property request should be forwarded to the backend, and 1 means the request
797 * was satisfied by the plugin and should not be processed further.
799 * The (get|rm|set)_property() functions bypass the plugin layer completely,
800 * and hence should not be generally used.
804 * Return true if the string passed in matches the pattern
805 * [A-Za-z][A-Za-z0-9,._-]*
808 is_valid_name(const char *name
)
815 if (!isalpha(name
[0]))
817 for (i
= 1; (c
= name
[i
]) != '\0'; i
++) {
818 if (!isalnum(c
) && c
!= ',' && c
!= '.' && c
!= '_' && c
!= '-')
825 * Return true if the string passed in matches the pattern
826 * [A-Za-z_][A-Za-z0-9,._-]*
827 * A property name starting with a '_' is an "invisible" property that does not
828 * show up in a property walk.
831 is_valid_prop_name(const char *prop_name
)
836 if (prop_name
== NULL
)
838 if (!isalpha(prop_name
[0]) && prop_name
[0] != '_')
840 for (i
= 1; (c
= prop_name
[i
]) != '\0'; i
++) {
841 if (!isalnum(c
) && c
!= ',' && c
!= '.' && c
!= '_' && c
!= '-')
848 * Return the specified property value.
850 * POC_INVAL is returned if an error is detected and the error code is updated
851 * to indicate the cause of the error.
854 pool_get_property(const pool_conf_t
*conf
, const pool_elem_t
*pe
,
855 const char *name
, pool_value_t
*val
)
857 const pool_prop_t
*prop_info
;
859 if (pool_conf_status(conf
) == POF_INVALID
) {
860 pool_seterror(POE_BADPARAM
);
863 if (pool_value_set_name(val
, name
) != PO_SUCCESS
) {
867 * Check to see if this is a property we are managing. If it
868 * is and it has an interceptor installed for property
871 if ((prop_info
= provider_get_prop(pe
, name
)) != NULL
&&
872 prop_info
->pp_op
.ppo_get_value
!= NULL
) {
873 if (prop_info
->pp_op
.ppo_get_value(pe
, val
) == PO_FAIL
)
876 return (pool_value_get_type(val
));
878 return (pe
->pe_get_prop(pe
, name
, val
));
882 * Return the specified property value with the namespace prepended.
883 * e.g. If this function is used to get the property "name" on a pool, it will
884 * attempt to retrieve "pool.name".
886 * POC_INVAL is returned if an error is detected and the error code is updated
887 * to indicate the cause of the error.
890 pool_get_ns_property(const pool_elem_t
*pe
, const char *name
, pool_value_t
*val
)
895 if ((cb
= alloc_char_buf(CB_DEFAULT_LEN
)) == NULL
)
897 if (set_char_buf(cb
, "%s.%s", pool_elem_class_string(pe
), name
) ==
902 ret
= pool_get_property(TO_CONF(pe
), pe
, cb
->cb_buf
, val
);
908 * Update the specified property value.
910 * PO_FAIL is returned if an error is detected and the error code is updated
911 * to indicate the cause of the error.
914 pool_put_property(pool_conf_t
*conf
, pool_elem_t
*pe
, const char *name
,
915 const pool_value_t
*val
)
917 const pool_prop_t
*prop_info
;
919 if (pool_conf_check(conf
) != PO_SUCCESS
)
922 if (TO_CONF(pe
) != conf
) {
923 pool_seterror(POE_BADPARAM
);
927 /* Don't allow (re)setting of the "temporary" property */
928 if (!is_valid_prop_name(name
) || strstr(name
, ".temporary") != NULL
) {
929 pool_seterror(POE_BADPARAM
);
933 /* Don't allow rename of temporary pools/resources */
934 if (strstr(name
, ".name") != NULL
&& elem_is_tmp(pe
)) {
935 boolean_t rename
= B_TRUE
;
936 pool_value_t
*pv
= pool_value_alloc();
938 if (pe
->pe_get_prop(pe
, name
, pv
) != POC_INVAL
) {
939 const char *s1
= NULL
;
940 const char *s2
= NULL
;
942 (void) pool_value_get_string(pv
, &s1
);
943 (void) pool_value_get_string(val
, &s2
);
944 if (s1
!= NULL
&& s2
!= NULL
&& strcmp(s1
, s2
) == 0)
950 pool_seterror(POE_BADPARAM
);
956 * Check to see if this is a property we are managing. If it is,
957 * ensure that we are happy with what the user is doing.
959 if ((prop_info
= provider_get_prop(pe
, name
)) != NULL
) {
960 if (prop_is_readonly(prop_info
) == PO_TRUE
) {
961 pool_seterror(POE_BADPARAM
);
964 if (prop_info
->pp_op
.ppo_set_value
&&
965 prop_info
->pp_op
.ppo_set_value(pe
, val
) == PO_FAIL
)
969 return (pe
->pe_put_prop(pe
, name
, val
));
973 * Set temporary property to flag as a temporary element.
975 * PO_FAIL is returned if an error is detected and the error code is updated
976 * to indicate the cause of the error.
979 pool_set_temporary(pool_conf_t
*conf
, pool_elem_t
*pe
)
985 if (pool_conf_check(conf
) != PO_SUCCESS
)
988 if (TO_CONF(pe
) != conf
) {
989 pool_seterror(POE_BADPARAM
);
993 /* create property name based on element type */
994 if (snprintf(name
, sizeof (name
), "%s.temporary",
995 pool_elem_class_string(pe
)) > sizeof (name
)) {
996 pool_seterror(POE_SYSTEM
);
1000 if ((val
= pool_value_alloc()) == NULL
)
1003 pool_value_set_bool(val
, (uchar_t
)1);
1005 res
= pe
->pe_put_prop(pe
, name
, val
);
1007 pool_value_free(val
);
1013 * Update the specified property value with the namespace prepended.
1014 * e.g. If this function is used to update the property "name" on a pool, it
1015 * will attempt to update "pool.name".
1017 * PO_FAIL is returned if an error is detected and the error code is updated
1018 * to indicate the cause of the error.
1021 pool_put_ns_property(pool_elem_t
*pe
, const char *name
,
1022 const pool_value_t
*val
)
1027 if ((cb
= alloc_char_buf(CB_DEFAULT_LEN
)) == NULL
)
1029 if (set_char_buf(cb
, "%s.%s", pool_elem_class_string(pe
), name
) ==
1034 ret
= pool_put_property(TO_CONF(pe
), pe
, cb
->cb_buf
, val
);
1040 * Update the specified property value. Do not use the property
1041 * protection mechanism. This function should only be used for cases
1042 * where the library must bypass the normal property protection
1043 * mechanism. The only known use is to update properties in the static
1044 * configuration when performing a commit.
1046 * PO_FAIL is returned if an error is detected and the error code is
1047 * updated to indicate the cause of the error.
1050 pool_put_any_property(pool_elem_t
*pe
, const char *name
,
1051 const pool_value_t
*val
)
1053 if (!is_valid_prop_name(name
)) {
1054 pool_seterror(POE_BADPARAM
);
1058 return (pe
->pe_put_prop(pe
, name
, val
));
1062 * Update the specified property value with the namespace prepended.
1063 * e.g. If this function is used to update the property "name" on a pool, it
1064 * will attempt to update "pool.name".
1066 * PO_FAIL is returned if an error is detected and the error code is updated
1067 * to indicate the cause of the error.
1070 pool_put_any_ns_property(pool_elem_t
*pe
, const char *name
,
1071 const pool_value_t
*val
)
1076 if ((cb
= alloc_char_buf(CB_DEFAULT_LEN
)) == NULL
)
1078 if (set_char_buf(cb
, "%s.%s", pool_elem_class_string(pe
), name
) ==
1083 ret
= pool_put_any_property(pe
, cb
->cb_buf
, val
);
1089 * Remove the specified property value. Note that some properties are
1090 * mandatory and thus failure to remove these properties is inevitable.
1091 * PO_FAIL is returned if an error is detected and the error code is updated
1092 * to indicate the cause of the error.
1095 pool_rm_property(pool_conf_t
*conf
, pool_elem_t
*pe
, const char *name
)
1097 const pool_prop_t
*prop_info
;
1099 if (pool_conf_check(conf
) != PO_SUCCESS
)
1102 if (TO_CONF(pe
) != conf
) {
1103 pool_seterror(POE_BADPARAM
);
1107 /* Don't allow removal of the "temporary" property */
1108 if (strstr(name
, ".temporary") != NULL
) {
1109 pool_seterror(POE_BADPARAM
);
1114 * Check to see if this is a property we are managing. If it is,
1115 * ensure that we are happy with what the user is doing.
1117 if ((prop_info
= provider_get_prop(pe
, name
)) != NULL
) {
1118 if (prop_is_optional(prop_info
) == PO_FALSE
) {
1119 pool_seterror(POE_BADPARAM
);
1123 return (pe
->pe_rm_prop(pe
, name
));
1127 * Check if the supplied name is a namespace protected property for the supplied
1128 * element, pe. If it is, return the prefix, otherwise just return NULL.
1131 is_ns_property(const pool_elem_t
*pe
, const char *name
)
1135 if ((prefix
= pool_elem_class_string(pe
)) != NULL
) {
1136 if (strncmp(name
, prefix
, strlen(prefix
)) == 0)
1143 * Check if the supplied name is a namespace protected property for the supplied
1144 * element, pe. If it is, return the property name with the namespace stripped,
1145 * otherwise just return the name.
1148 property_name_minus_ns(const pool_elem_t
*pe
, const char *name
)
1151 if ((prefix
= is_ns_property(pe
, name
)) != NULL
) {
1152 return (name
+ strlen(prefix
) + 1);
1158 * Create an element to represent a pool and add it to the supplied
1162 pool_create(pool_conf_t
*conf
, const char *name
)
1165 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1166 const pool_prop_t
*default_props
;
1168 if (pool_conf_check(conf
) != PO_SUCCESS
)
1171 if (!is_valid_name(name
) || pool_get_pool(conf
, name
) != NULL
) {
1173 * A pool with the same name exists. Reject.
1175 pool_seterror(POE_BADPARAM
);
1178 if ((pe
= conf
->pc_prov
->pc_elem_create(conf
, PEC_POOL
, PREC_INVALID
,
1179 PCEC_INVALID
)) == NULL
) {
1180 pool_seterror(POE_INVALID_CONF
);
1183 if ((default_props
= provider_get_props(pe
)) != NULL
) {
1185 for (i
= 0; default_props
[i
].pp_pname
!= NULL
; i
++) {
1186 if (prop_is_init(&default_props
[i
]) &&
1187 (pool_put_any_property(pe
,
1188 default_props
[i
].pp_pname
,
1189 &default_props
[i
].pp_value
) == PO_FAIL
)) {
1190 (void) pool_destroy(conf
, pool_elem_pool(pe
));
1195 if (pool_value_set_string(&val
, name
) != PO_SUCCESS
) {
1196 (void) pool_destroy(conf
, pool_elem_pool(pe
));
1197 pool_seterror(POE_SYSTEM
);
1200 if (pool_put_property(conf
, pe
, "pool.name", &val
) == PO_FAIL
) {
1201 (void) pool_destroy(conf
, pool_elem_pool(pe
));
1202 pool_seterror(POE_PUTPROP
);
1207 * If we are creating a temporary pool configuration, flag the pool.
1209 if (conf
->pc_prov
->pc_oflags
& PO_TEMP
) {
1210 if (pool_set_temporary(conf
, pe
) == PO_FAIL
) {
1211 (void) pool_destroy(conf
, pool_elem_pool(pe
));
1216 return (pool_elem_pool(pe
));
1220 * Create an element to represent a res.
1223 pool_resource_create(pool_conf_t
*conf
, const char *sz_type
, const char *name
)
1226 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1227 const pool_prop_t
*default_props
;
1228 pool_resource_t
**resources
;
1231 pool_elem_class_t elem_class
;
1232 pool_resource_elem_class_t type
;
1233 pool_value_t
*props
[] = { NULL
, NULL
};
1235 if (pool_conf_check(conf
) != PO_SUCCESS
)
1238 if ((type
= pool_resource_elem_class_from_string(sz_type
)) ==
1240 pool_seterror(POE_BADPARAM
);
1244 if (strcmp(sz_type
, "pset") != 0) {
1245 pool_seterror(POE_BADPARAM
);
1249 if (!is_valid_name(name
) || pool_get_resource(conf
, sz_type
, name
) !=
1252 * Resources must be unique by name+type.
1254 pool_seterror(POE_BADPARAM
);
1260 if (pool_value_set_string(props
[0], sz_type
) != PO_SUCCESS
||
1261 pool_value_set_name(props
[0], c_type
) != PO_SUCCESS
) {
1265 if ((resources
= pool_query_resources(conf
, &nelem
, props
)) == NULL
) {
1267 * This is the first representative of this type; when it's
1268 * created it should be created with 'default' = 'true'.
1275 * TODO: If Additional PEC_RES_COMP types are added to
1276 * pool_impl.h, this would need to be extended.
1280 elem_class
= PEC_RES_COMP
;
1283 elem_class
= PEC_RES_AGG
;
1286 if ((pe
= conf
->pc_prov
->pc_elem_create(conf
, elem_class
, type
,
1287 PCEC_INVALID
)) == NULL
) {
1288 pool_seterror(POE_INVALID_CONF
);
1293 * The plugins contain a list of default properties and their values
1294 * for resources. The resource returned, hence, is fully initialized.
1296 if ((default_props
= provider_get_props(pe
)) != NULL
) {
1298 for (i
= 0; default_props
[i
].pp_pname
!= NULL
; i
++) {
1299 if (prop_is_init(&default_props
[i
]) &&
1300 pool_put_any_property(pe
, default_props
[i
].pp_pname
,
1301 &default_props
[i
].pp_value
) == PO_FAIL
) {
1302 (void) pool_resource_destroy(conf
,
1308 if (pool_value_set_string(&val
, name
) != PO_SUCCESS
||
1309 pool_put_ns_property(pe
, "name", &val
) != PO_SUCCESS
) {
1310 (void) pool_resource_destroy(conf
, pool_elem_res(pe
));
1314 pool_value_set_bool(&val
, PO_TRUE
);
1315 if (pool_put_any_ns_property(pe
, "default", &val
) !=
1317 (void) pool_resource_destroy(conf
, pool_elem_res(pe
));
1323 * If we are creating a temporary pool configuration, flag the resource.
1325 if (conf
->pc_prov
->pc_oflags
& PO_TEMP
) {
1326 if (pool_set_temporary(conf
, pe
) != PO_SUCCESS
) {
1327 (void) pool_resource_destroy(conf
, pool_elem_res(pe
));
1332 return (pool_elem_res(pe
));
1336 * Create an element to represent a resource component.
1339 pool_component_create(pool_conf_t
*conf
, const pool_resource_t
*res
,
1343 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1344 const pool_prop_t
*default_props
;
1345 char refbuf
[KEY_BUFFER_SIZE
];
1347 if ((pe
= conf
->pc_prov
->pc_elem_create(conf
, PEC_COMP
,
1348 PREC_INVALID
, PCEC_CPU
)) == NULL
) {
1349 pool_seterror(POE_INVALID_CONF
);
1353 * TODO: If additional PEC_COMP types are added in pool_impl.h,
1354 * this would need to be extended.
1356 pe
->pe_component_class
= PCEC_CPU
;
1357 /* Now set the container for this comp */
1358 if (pool_set_container(TO_ELEM(res
), pe
) == PO_FAIL
) {
1359 (void) pool_component_destroy(pool_elem_comp(pe
));
1363 * The plugins contain a list of default properties and their values
1364 * for resources. The resource returned, hence, is fully initialized.
1366 if ((default_props
= provider_get_props(pe
)) != NULL
) {
1368 for (i
= 0; default_props
[i
].pp_pname
!= NULL
; i
++) {
1369 if (prop_is_init(&default_props
[i
]) &&
1370 pool_put_any_property(pe
,
1371 default_props
[i
].pp_pname
,
1372 &default_props
[i
].pp_value
) == PO_FAIL
) {
1373 (void) pool_component_destroy(
1374 pool_elem_comp(pe
));
1380 * Set additional attributes/properties on component.
1382 pool_value_set_int64(&val
, sys_id
);
1383 if (pool_put_any_ns_property(pe
, c_sys_prop
, &val
) != PO_SUCCESS
) {
1384 (void) pool_component_destroy(pool_elem_comp(pe
));
1387 if (snprintf(refbuf
, KEY_BUFFER_SIZE
, "%s_%lld",
1388 pool_elem_class_string(pe
), sys_id
) > KEY_BUFFER_SIZE
) {
1389 (void) pool_component_destroy(pool_elem_comp(pe
));
1392 if (pool_value_set_string(&val
, refbuf
) != PO_SUCCESS
) {
1393 (void) pool_component_destroy(pool_elem_comp(pe
));
1396 if (pool_put_any_ns_property(pe
, c_ref_id
, &val
) != PO_SUCCESS
) {
1397 (void) pool_component_destroy(pool_elem_comp(pe
));
1400 return (pool_elem_comp(pe
));
1404 * Return the location of a configuration.
1407 pool_conf_location(const pool_conf_t
*conf
)
1409 if (pool_conf_status(conf
) == POF_INVALID
) {
1410 pool_seterror(POE_BADPARAM
);
1413 return (conf
->pc_location
);
1416 * Close a configuration, freeing all associated resources. Once a
1417 * configuration is closed, it can no longer be used.
1420 pool_conf_close(pool_conf_t
*conf
)
1424 if (pool_conf_status(conf
) == POF_INVALID
) {
1425 pool_seterror(POE_BADPARAM
);
1428 rv
= conf
->pc_prov
->pc_close(conf
);
1429 conf
->pc_prov
= NULL
;
1430 free((void *)conf
->pc_location
);
1431 conf
->pc_location
= NULL
;
1432 conf
->pc_state
= POF_INVALID
;
1437 * Remove a configuration, freeing all associated resources. Once a
1438 * configuration is removed, it can no longer be accessed and is forever
1442 pool_conf_remove(pool_conf_t
*conf
)
1446 if (pool_conf_status(conf
) == POF_INVALID
) {
1447 pool_seterror(POE_BADPARAM
);
1450 rv
= conf
->pc_prov
->pc_remove(conf
);
1451 conf
->pc_state
= POF_INVALID
;
1456 * pool_conf_alloc() allocate the resources to represent a configuration.
1459 pool_conf_alloc(void)
1463 if ((conf
= calloc(1, sizeof (pool_conf_t
))) == NULL
) {
1464 pool_seterror(POE_SYSTEM
);
1467 conf
->pc_state
= POF_INVALID
;
1472 * pool_conf_free() frees the resources associated with a configuration.
1475 pool_conf_free(pool_conf_t
*conf
)
1481 * pool_conf_open() opens a configuration, establishing all required
1482 * connections to the data source.
1485 pool_conf_open(pool_conf_t
*conf
, const char *location
, int oflags
)
1488 * Since you can't do anything to a pool configuration without opening
1489 * it, this represents a good point to intialise structures that would
1490 * otherwise need to be initialised in a .init section.
1494 if (pool_conf_status(conf
) != POF_INVALID
) {
1496 * Already opened configuration, return PO_FAIL
1498 pool_seterror(POE_BADPARAM
);
1501 if (oflags
& ~(PO_RDONLY
| PO_RDWR
| PO_CREAT
| PO_DISCO
| PO_UPDATE
|
1503 pool_seterror(POE_BADPARAM
);
1508 * Creating a configuration implies read-write access, so make
1509 * sure that PO_RDWR is set in addition if PO_CREAT is set.
1511 if (oflags
& PO_CREAT
)
1514 /* location is ignored when creating a temporary configuration */
1515 if (oflags
& PO_TEMP
)
1518 if ((conf
->pc_location
= strdup(location
)) == NULL
) {
1519 pool_seterror(POE_SYSTEM
);
1523 * This is the crossover point into the actual data provider
1524 * implementation, allocate a data provider of the appropriate
1525 * type for your data storage medium. In this case it's either a kernel
1526 * or xml data provider. To use a different data provider, write some
1527 * code to implement all the required interfaces and then change the
1528 * following code to allocate a data provider which uses your new code.
1529 * All data provider routines can be static, apart from the allocation
1532 * For temporary pools (PO_TEMP) we start with a copy of the current
1533 * dynamic configuration and do all of the updates in-memory.
1535 if (oflags
& PO_TEMP
) {
1536 if (pool_knl_connection_alloc(conf
, PO_TEMP
) != PO_SUCCESS
) {
1537 conf
->pc_state
= POF_INVALID
;
1540 /* set rdwr flag so we can updated the in-memory config. */
1541 conf
->pc_prov
->pc_oflags
|= PO_RDWR
;
1543 } else if (strcmp(location
, pool_dynamic_location()) == 0) {
1544 if (pool_knl_connection_alloc(conf
, oflags
) != PO_SUCCESS
) {
1545 conf
->pc_state
= POF_INVALID
;
1549 if (pool_xml_connection_alloc(conf
, oflags
) != PO_SUCCESS
) {
1550 conf
->pc_state
= POF_INVALID
;
1554 return (PO_SUCCESS
);
1558 * Rollback a configuration. This will undo all changes to the configuration
1559 * since the last time pool_conf_commit was called.
1562 pool_conf_rollback(pool_conf_t
*conf
)
1564 if (pool_conf_status(conf
) == POF_INVALID
) {
1565 pool_seterror(POE_BADPARAM
);
1568 return (conf
->pc_prov
->pc_rollback(conf
));
1572 * Commit a configuration. This will apply all changes to the
1573 * configuration to the permanent data store. The active parameter
1574 * indicates whether the configuration should be used to update the
1575 * dynamic configuration from the supplied (static) configuration or
1576 * whether it should be written back to persistent store.
1579 pool_conf_commit(pool_conf_t
*conf
, int active
)
1583 if (pool_conf_status(conf
) == POF_INVALID
) {
1584 pool_seterror(POE_BADPARAM
);
1590 if (conf_is_dynamic(conf
) == PO_TRUE
) {
1591 pool_seterror(POE_BADPARAM
);
1595 * Pretend that the configuration was opened PO_RDWR
1596 * so that a configuration which was opened PO_RDONLY
1597 * can be committed. The original flags are preserved
1598 * in oflags and restored after pool_conf_commit_sys()
1601 oflags
= conf
->pc_prov
->pc_oflags
;
1602 conf
->pc_prov
->pc_oflags
|= PO_RDWR
;
1603 retval
= pool_conf_commit_sys(conf
, active
);
1604 conf
->pc_prov
->pc_oflags
= oflags
;
1607 * Write the configuration back to the backing store.
1609 retval
= conf
->pc_prov
->pc_commit(conf
);
1615 * Export a configuration. This will export a configuration in the specified
1616 * format (fmt) to the specified location.
1619 pool_conf_export(const pool_conf_t
*conf
, const char *location
,
1620 pool_export_format_t fmt
)
1622 if (pool_conf_status(conf
) == POF_INVALID
) {
1623 pool_seterror(POE_BADPARAM
);
1626 return (conf
->pc_prov
->pc_export(conf
, location
, fmt
));
1630 * Validate a configuration. This will validate a configuration at the
1634 pool_conf_validate(const pool_conf_t
*conf
, pool_valid_level_t level
)
1636 if (pool_conf_status(conf
) == POF_INVALID
) {
1637 pool_seterror(POE_BADPARAM
);
1640 return (conf
->pc_prov
->pc_validate(conf
, level
));
1644 * Update the snapshot of a configuration. This can only be used on a
1645 * dynamic configuration.
1648 pool_conf_update(const pool_conf_t
*conf
, int *changed
)
1650 if (pool_conf_status(conf
) == POF_INVALID
||
1651 conf_is_dynamic(conf
) == PO_FALSE
) {
1652 pool_seterror(POE_BADPARAM
);
1656 * Since this function only makes sense for dynamic
1657 * configurations, just call directly into the appropriate
1658 * function. This could be added into the pool_connection_t
1659 * interface if it was ever required.
1663 return (pool_knl_update((pool_conf_t
*)conf
, changed
));
1667 * Walk the properties of the supplied elem, calling the user supplied
1668 * function repeatedly as long as the user function returns
1672 pool_walk_properties(pool_conf_t
*conf
, pool_elem_t
*elem
, void *arg
,
1673 int (*prop_callback
)(pool_conf_t
*, pool_elem_t
*, const char *,
1674 pool_value_t
*, void *))
1676 return (pool_walk_any_properties(conf
, elem
, arg
, prop_callback
, 0));
1680 free_value_list(int npvals
, pool_value_t
**pvals
)
1684 for (j
= 0; j
< npvals
; j
++) {
1686 pool_value_free(pvals
[j
]);
1692 * Walk the properties of the supplied elem, calling the user supplied
1693 * function repeatedly as long as the user function returns
1695 * The list of properties to be walked is retrieved from the element
1698 pool_walk_any_properties(pool_conf_t
*conf
, pool_elem_t
*elem
, void *arg
,
1699 int (*prop_callback
)(pool_conf_t
*, pool_elem_t
*, const char *,
1700 pool_value_t
*, void *), int any
)
1702 pool_value_t
**pvals
;
1704 const pool_prop_t
*props
= provider_get_props(elem
);
1707 if (pool_conf_status(conf
) == POF_INVALID
) {
1708 pool_seterror(POE_BADPARAM
);
1712 if (props
== NULL
) {
1713 pool_seterror(POE_INVALID_CONF
);
1717 if ((pvals
= elem
->pe_get_props(elem
, &npvals
)) == NULL
)
1721 * Now walk the managed properties. As we find managed
1722 * properties removed them from the list of all properties to
1723 * prevent duplication.
1725 for (i
= 0; props
[i
].pp_pname
!= NULL
; i
++) {
1729 * Special processing for type
1731 if (strcmp(props
[i
].pp_pname
, c_type
) == 0) {
1732 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1734 if (pool_value_set_name(&val
, props
[i
].pp_pname
) ==
1736 free_value_list(npvals
, pvals
);
1739 if (props
[i
].pp_op
.ppo_get_value(elem
, &val
) ==
1741 free_value_list(npvals
, pvals
);
1744 if (any
== 1 || prop_is_hidden(&props
[i
]) == PO_FALSE
) {
1745 if (prop_callback(conf
, elem
, props
[i
].pp_pname
,
1746 &val
, arg
) != PO_SUCCESS
) {
1747 free_value_list(npvals
, pvals
);
1748 pool_seterror(POE_BADPARAM
);
1755 for (j
= 0; j
< npvals
; j
++) {
1756 if (pvals
[j
] && strcmp(pool_value_get_name(pvals
[j
]),
1757 props
[i
].pp_pname
) == 0)
1761 * If we have found the property, then j < npvals. Process it
1762 * according to our property attributes. Otherwise, it's not
1763 * a managed property, so just ignore it until later.
1766 if (any
== 1 || prop_is_hidden(&props
[i
]) == PO_FALSE
) {
1767 if (props
[i
].pp_op
.ppo_get_value
) {
1768 if (pool_value_set_name(pvals
[j
],
1769 props
[i
].pp_pname
) == PO_FAIL
) {
1770 free_value_list(npvals
, pvals
);
1773 if (props
[i
].pp_op
.ppo_get_value(elem
,
1774 pvals
[j
]) == PO_FAIL
) {
1775 free_value_list(npvals
, pvals
);
1779 if (prop_callback(conf
, elem
, props
[i
].pp_pname
,
1780 pvals
[j
], arg
) != PO_SUCCESS
) {
1781 free_value_list(npvals
, pvals
);
1782 pool_seterror(POE_BADPARAM
);
1786 pool_value_free(pvals
[j
]);
1790 for (i
= 0; i
< npvals
; i
++) {
1792 const char *name
= pool_value_get_name(pvals
[i
]);
1793 char *qname
= strrchr(name
, '.');
1794 if ((qname
&& qname
[1] != '_') ||
1795 (!qname
&& name
[0] != '_')) {
1796 if (prop_callback(conf
, elem
, name
, pvals
[i
],
1797 arg
) != PO_SUCCESS
) {
1798 free_value_list(npvals
, pvals
);
1799 pool_seterror(POE_BADPARAM
);
1803 pool_value_free(pvals
[i
]);
1808 return (PO_SUCCESS
);
1812 * Return a pool, searching the supplied configuration for a pool with the
1813 * supplied name. The search is case sensitive.
1816 pool_get_pool(const pool_conf_t
*conf
, const char *name
)
1818 pool_value_t
*props
[] = { NULL
, NULL
};
1822 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1826 if (pool_conf_status(conf
) == POF_INVALID
) {
1827 pool_seterror(POE_BADPARAM
);
1831 if (pool_value_set_name(props
[0], "pool.name") != PO_SUCCESS
||
1832 pool_value_set_string(props
[0], name
) != PO_SUCCESS
) {
1835 rs
= pool_query_pools(conf
, &size
, props
);
1836 if (rs
== NULL
) { /* Can't find a pool to match the name */
1841 pool_seterror(POE_INVALID_CONF
);
1850 * Return a result set of pools, searching the supplied configuration
1851 * for pools which match the supplied property criteria. props is a null
1852 * terminated list of properties which will be used to match qualifying
1853 * pools. size is updated with the size of the pool
1856 pool_query_pools(const pool_conf_t
*conf
, uint_t
*size
, pool_value_t
**props
)
1858 pool_result_set_t
*rs
;
1860 pool_t
**result
= NULL
;
1863 if (pool_conf_status(conf
) == POF_INVALID
) {
1864 pool_seterror(POE_BADPARAM
);
1867 rs
= pool_exec_query(conf
, NULL
, NULL
, PEC_QRY_POOL
, props
);
1871 if ((*size
= pool_rs_count(rs
)) == 0) {
1872 (void) pool_rs_close(rs
);
1875 if ((result
= malloc(sizeof (pool_t
*) * (*size
+ 1))) == NULL
) {
1876 pool_seterror(POE_SYSTEM
);
1877 (void) pool_rs_close(rs
);
1880 (void) memset(result
, 0, sizeof (pool_t
*) * (*size
+ 1));
1881 for (pe
= rs
->prs_next(rs
); pe
!= NULL
; pe
= rs
->prs_next(rs
)) {
1882 if (pool_elem_class(pe
) != PEC_POOL
) {
1883 pool_seterror(POE_INVALID_CONF
);
1885 (void) pool_rs_close(rs
);
1888 result
[i
++] = pool_elem_pool(pe
);
1890 (void) pool_rs_close(rs
);
1895 * Return an res, searching the supplied configuration for an res with the
1896 * supplied name. The search is case sensitive.
1899 pool_get_resource(const pool_conf_t
*conf
, const char *sz_type
,
1902 pool_value_t
*props
[] = { NULL
, NULL
, NULL
};
1903 pool_resource_t
**rs
;
1904 pool_resource_t
*ret
;
1906 char_buf_t
*cb
= NULL
;
1907 pool_value_t val0
= POOL_VALUE_INITIALIZER
;
1908 pool_value_t val1
= POOL_VALUE_INITIALIZER
;
1910 if (pool_conf_status(conf
) == POF_INVALID
) {
1911 pool_seterror(POE_BADPARAM
);
1915 if (sz_type
== NULL
) {
1916 pool_seterror(POE_BADPARAM
);
1923 if (pool_value_set_string(props
[0], sz_type
) != PO_SUCCESS
||
1924 pool_value_set_name(props
[0], c_type
) != PO_SUCCESS
)
1927 if ((cb
= alloc_char_buf(CB_DEFAULT_LEN
)) == NULL
) {
1930 if (set_char_buf(cb
, "%s.name", sz_type
) != PO_SUCCESS
) {
1934 if (pool_value_set_name(props
[1], cb
->cb_buf
) != PO_SUCCESS
) {
1938 if (pool_value_set_string(props
[1], name
) != PO_SUCCESS
) {
1943 rs
= pool_query_resources(conf
, &size
, props
);
1949 pool_seterror(POE_INVALID_CONF
);
1958 * Return a result set of res (actually as pool_elem_ts), searching the
1959 * supplied configuration for res which match the supplied property
1960 * criteria. props is a null terminated list of properties which will be used
1961 * to match qualifying res.
1964 pool_query_resources(const pool_conf_t
*conf
, uint_t
*size
,
1965 pool_value_t
**props
)
1967 pool_result_set_t
*rs
;
1969 pool_resource_t
**result
= NULL
;
1972 if (pool_conf_status(conf
) == POF_INVALID
) {
1973 pool_seterror(POE_BADPARAM
);
1979 rs
= pool_exec_query(conf
, NULL
, NULL
, PEC_QRY_RES
, props
);
1983 if ((*size
= pool_rs_count(rs
)) == 0) {
1984 (void) pool_rs_close(rs
);
1987 if ((result
= malloc(sizeof (pool_resource_t
*) * (*size
+ 1)))
1989 pool_seterror(POE_SYSTEM
);
1990 (void) pool_rs_close(rs
);
1993 (void) memset(result
, 0, sizeof (pool_resource_t
*) * (*size
+ 1));
1994 for (pe
= rs
->prs_next(rs
); pe
!= NULL
; pe
= rs
->prs_next(rs
)) {
1995 if (pool_elem_class(pe
) != PEC_RES_COMP
&&
1996 pool_elem_class(pe
) != PEC_RES_AGG
) {
1997 pool_seterror(POE_INVALID_CONF
);
1999 (void) pool_rs_close(rs
);
2002 result
[i
++] = pool_elem_res(pe
);
2004 (void) pool_rs_close(rs
);
2009 * Return a result set of comp (actually as pool_elem_ts), searching the
2010 * supplied configuration for comp which match the supplied property
2011 * criteria. props is a null terminated list of properties which will be used
2012 * to match qualifying comp.
2015 pool_query_components(const pool_conf_t
*conf
, uint_t
*size
,
2016 pool_value_t
**props
)
2018 return (pool_query_resource_components(conf
, NULL
, size
, props
));
2022 * Destroy a pool. If the pool cannot be found or removed an error is
2023 * returned. This is basically a wrapper around pool_elem_remove to ensure
2024 * some type safety for the pool subtype.
2027 pool_destroy(pool_conf_t
*conf
, pool_t
*pp
)
2031 if (pool_conf_check(conf
) != PO_SUCCESS
)
2037 * Cannot destroy the default pool.
2039 if (elem_is_default(pe
) == PO_TRUE
) {
2040 pool_seterror(POE_BADPARAM
);
2043 if (pool_elem_remove(pe
) != PO_SUCCESS
)
2045 return (PO_SUCCESS
);
2049 * Destroy an res. If the res cannot be found or removed an error is
2050 * returned. This is basically a wrapper around pool_elem_remove to ensure
2051 * some type safety for the res subtype.
2054 pool_resource_destroy(pool_conf_t
*conf
, pool_resource_t
*prs
)
2057 pool_component_t
**rl
;
2063 if (pool_conf_check(conf
) != PO_SUCCESS
)
2068 if (resource_is_system(prs
) == PO_TRUE
) {
2069 pool_seterror(POE_BADPARAM
);
2073 * Walk all the pools and dissociate any pools which are using
2076 if ((pl
= pool_query_pools(conf
, &npool
, NULL
)) != NULL
) {
2077 for (i
= 0; i
< npool
; i
++) {
2078 pool_resource_t
**rl
;
2082 if ((rl
= pool_query_pool_resources(conf
, pl
[i
], &nres
,
2084 for (j
= 0; j
< nres
; j
++) {
2086 if (pool_dissociate(conf
, pl
[i
],
2087 rl
[j
]) != PO_SUCCESS
) {
2100 if (pe
->pe_class
== PEC_RES_COMP
) {
2101 pool_resource_t
*default_set_res
;
2104 * Use the xtransfer option to move comp around
2106 default_set_res
= (pool_resource_t
*)get_default_resource(prs
);
2108 if ((rl
= pool_query_resource_components(conf
, prs
, &res_size
,
2110 int ostate
= conf
->pc_state
;
2111 conf
->pc_state
= POF_DESTROY
;
2112 if (pool_resource_xtransfer(conf
, prs
, default_set_res
,
2115 conf
->pc_state
= ostate
;
2118 conf
->pc_state
= ostate
;
2122 if (pool_elem_remove(pe
) != PO_SUCCESS
)
2124 return (PO_SUCCESS
);
2128 * Destroy a comp. If the comp cannot be found or removed an error is
2129 * returned. This is basically a wrapper around pool_elem_remove to ensure
2130 * some type safety for the comp subtype.
2133 pool_component_destroy(pool_component_t
*pr
)
2135 pool_elem_t
*pe
= TO_ELEM(pr
);
2137 if (pool_elem_remove(pe
) != PO_SUCCESS
)
2139 return (PO_SUCCESS
);
2143 * Remove a pool_elem_t from a configuration. This has been "hidden" away as
2144 * a static routine since the only elements which are currently being removed
2145 * are pools, res & comp and the wrapper functions above provide type-safe
2146 * access. However, if there is a need to remove other types of elements
2147 * then this could be promoted to pool_impl.h or more wrappers could
2148 * be added to pool_impl.h.
2151 pool_elem_remove(pool_elem_t
*pe
)
2153 return (pe
->pe_remove(pe
));
2157 * Execute a query to search for a qualifying set of elements.
2160 pool_exec_query(const pool_conf_t
*conf
, const pool_elem_t
*src
,
2161 const char *src_attr
, pool_elem_class_t classes
, pool_value_t
**props
)
2163 return (conf
->pc_prov
->pc_exec_query(conf
, src
, src_attr
, classes
,
2168 * Get the next result from a result set of elements.
2171 pool_rs_next(pool_result_set_t
*set
)
2173 return (set
->prs_next(set
));
2177 * Get the previous result from a result set of elements.
2180 pool_rs_prev(pool_result_set_t
*set
)
2182 return (set
->prs_prev(set
));
2186 * Get the first result from a result set of elements.
2189 pool_rs_first(pool_result_set_t
*set
)
2191 return (set
->prs_first(set
));
2195 * Get the last result from a result set of elements.
2198 pool_rs_last(pool_result_set_t
*set
)
2200 return (set
->prs_last(set
));
2205 * Get the count for a result set of elements.
2208 pool_rs_count(pool_result_set_t
*set
)
2210 return (set
->prs_count(set
));
2214 * Get the index for a result set of elements.
2217 pool_rs_get_index(pool_result_set_t
*set
)
2219 return (set
->prs_get_index(set
));
2223 * Set the index for a result set of elements.
2226 pool_rs_set_index(pool_result_set_t
*set
, int index
)
2228 return (set
->prs_set_index(set
, index
));
2232 * Close a result set of elements, freeing all associated resources.
2235 pool_rs_close(pool_result_set_t
*set
)
2237 return (set
->prs_close(set
));
2241 * When transferring resource components using pool_resource_transfer,
2242 * this function is invoked to choose which actual components will be
2246 choose_components(pool_resource_t
*src
, pool_resource_t
*dst
, uint64_t size
)
2248 pool_component_t
**components
= NULL
, *moved
[] = { NULL
, NULL
};
2251 pool_conf_t
*conf
= TO_CONF(TO_ELEM(src
));
2254 return (PO_SUCCESS
);
2256 * Get the component list from our src component.
2258 if ((components
= pool_query_resource_components(conf
, src
, &ncomponent
,
2260 pool_seterror(POE_BADPARAM
);
2263 qsort(components
, ncomponent
, sizeof (pool_elem_t
*),
2264 qsort_elem_compare
);
2266 * Components that aren't specifically requested by the resource
2267 * should be transferred out first.
2269 for (i
= 0; size
> 0 && components
[i
] != NULL
; i
++) {
2270 if (!cpu_is_requested(components
[i
])) {
2271 moved
[0] = components
[i
];
2272 if (pool_resource_xtransfer(conf
, src
, dst
, moved
) ==
2280 * If we couldn't find enough "un-requested" components, select random
2281 * requested components.
2283 for (i
= 0; size
> 0 && components
[i
] != NULL
; i
++) {
2284 if (cpu_is_requested(components
[i
])) {
2285 moved
[0] = components
[i
];
2286 if (pool_resource_xtransfer(conf
, src
, dst
, moved
) ==
2295 * If we couldn't transfer out all the resources we asked for, then
2298 return (size
== 0 ? PO_SUCCESS
: PO_FAIL
);
2302 * Common processing for a resource transfer (xfer or xxfer).
2304 * - Return XFER_CONTINUE if the transfer should proceeed
2305 * - Return XFER_FAIL if the transfer should be stopped in failure
2306 * - Return XFER_SUCCESS if the transfer should be stopped in success
2309 setup_transfer(pool_conf_t
*conf
, pool_resource_t
*src
, pool_resource_t
*tgt
,
2310 uint64_t size
, uint64_t *src_size
, uint64_t *tgt_size
)
2315 if (pool_conf_check(conf
) != PO_SUCCESS
)
2319 * Makes sure the two resources are of the same type
2321 if (pool_resource_elem_class(TO_ELEM(src
)) !=
2322 pool_resource_elem_class(TO_ELEM(tgt
))) {
2323 pool_seterror(POE_BADPARAM
);
2328 * Transferring to yourself is a no-op
2331 return (XFER_SUCCESS
);
2334 * Transferring nothing is a no-op
2337 return (XFER_SUCCESS
);
2339 if (resource_get_min(src
, &src_min
) != PO_SUCCESS
||
2340 resource_get_size(src
, src_size
) != PO_SUCCESS
||
2341 resource_get_max(tgt
, &tgt_max
) != PO_SUCCESS
||
2342 resource_get_size(tgt
, tgt_size
) != PO_SUCCESS
) {
2343 pool_seterror(POE_BADPARAM
);
2346 if (pool_conf_status(conf
) != POF_DESTROY
) {
2348 * src_size - donating >= src.min
2349 * size + receiving <= tgt.max (except for default)
2352 dprintf("conf is %s\n", pool_conf_location(conf
));
2353 dprintf("setup_transfer: src_size %llu\n", *src_size
);
2354 pool_elem_dprintf(TO_ELEM(src
));
2355 dprintf("setup_transfer: tgt_size %llu\n", *tgt_size
);
2356 pool_elem_dprintf(TO_ELEM(tgt
));
2358 if (*src_size
- size
< src_min
||
2359 (resource_is_default(tgt
) == PO_FALSE
&&
2360 *tgt_size
+ size
> tgt_max
)) {
2361 pool_seterror(POE_INVALID_CONF
);
2365 return (XFER_CONTINUE
);
2369 * Transfer resource quantities from one resource set to another.
2372 pool_resource_transfer(pool_conf_t
*conf
, pool_resource_t
*src
,
2373 pool_resource_t
*tgt
, uint64_t size
)
2379 if ((ret
= setup_transfer(conf
, src
, tgt
, size
, &src_size
, &tgt_size
))
2383 * If this resource is a res_comp we must call move components
2385 if (pool_elem_class(TO_ELEM(src
)) == PEC_RES_COMP
)
2386 return (choose_components(src
, tgt
, size
));
2388 * Now do the transfer.
2390 ret
= conf
->pc_prov
->pc_res_xfer(src
, tgt
, size
);
2392 * Modify the sizes of the resource sets if the process was
2395 if (ret
== PO_SUCCESS
) {
2396 pool_value_t val
= POOL_VALUE_INITIALIZER
;
2400 pool_value_set_uint64(&val
, src_size
);
2401 (void) pool_put_any_ns_property(TO_ELEM(src
), c_size_prop
,
2403 pool_value_set_uint64(&val
, tgt_size
);
2404 (void) pool_put_any_ns_property(TO_ELEM(tgt
), c_size_prop
,
2411 * Transfer resource components from one resource set to another.
2414 pool_resource_xtransfer(pool_conf_t
*conf
, pool_resource_t
*src
,
2415 pool_resource_t
*tgt
,
2416 pool_component_t
**rl
)
2425 * Make sure the components are all contained in 'src'. This
2426 * processing must be done before setup_transfer so that size
2429 for (i
= 0; rl
[i
] != NULL
; i
++) {
2431 dprintf("resource xtransfer\n");
2432 dprintf("in conf %s\n", pool_conf_location(conf
));
2433 dprintf("transferring component\n");
2434 pool_elem_dprintf(TO_ELEM(rl
[i
]));
2436 pool_elem_dprintf(TO_ELEM(src
));
2438 pool_elem_dprintf(TO_ELEM(tgt
));
2441 if (pool_get_owning_resource(conf
, rl
[i
]) != src
) {
2442 pool_seterror(POE_BADPARAM
);
2449 if ((ret
= setup_transfer(conf
, src
, tgt
, size
, &src_size
, &tgt_size
))
2453 ret
= conf
->pc_prov
->pc_res_xxfer(src
, tgt
, rl
);
2455 * Modify the sizes of the resource sets if the process was
2458 if (ret
== PO_SUCCESS
) {
2459 pool_value_t val
= POOL_VALUE_INITIALIZER
;
2462 dprintf("src_size %llu\n", src_size
);
2463 dprintf("tgt_size %llu\n", tgt_size
);
2464 dprintf("size %llu\n", size
);
2468 pool_value_set_uint64(&val
, src_size
);
2469 (void) pool_put_any_ns_property(TO_ELEM(src
), c_size_prop
,
2471 pool_value_set_uint64(&val
, tgt_size
);
2472 (void) pool_put_any_ns_property(TO_ELEM(tgt
), c_size_prop
,
2479 * Find the owning resource for a resource component.
2482 pool_get_owning_resource(const pool_conf_t
*conf
, const pool_component_t
*comp
)
2484 if (pool_conf_status(conf
) == POF_INVALID
) {
2485 pool_seterror(POE_BADPARAM
);
2488 return (pool_elem_res(pool_get_container(TO_ELEM(comp
))));
2492 * pool_get_container() returns the container of pc.
2495 pool_get_container(const pool_elem_t
*pc
)
2497 return (pc
->pe_get_container(pc
));
2501 * pool_set_container() moves pc so that it is contained by pp.
2503 * Returns PO_SUCCESS/PO_FAIL
2506 pool_set_container(pool_elem_t
*pp
, pool_elem_t
*pc
)
2508 return (pc
->pe_set_container(pp
, pc
));
2512 * Conversion routines for converting to and from elem and it's various
2513 * subtypes of system, pool, res and comp.
2516 pool_system_elem(const pool_system_t
*ph
)
2518 return ((pool_elem_t
*)ph
);
2522 pool_conf_to_elem(const pool_conf_t
*conf
)
2526 if (pool_conf_status(conf
) == POF_INVALID
) {
2527 pool_seterror(POE_BADPARAM
);
2530 if ((sys
= pool_conf_system(conf
)) == NULL
) {
2531 pool_seterror(POE_BADPARAM
);
2534 return (pool_system_elem(sys
));
2538 pool_to_elem(const pool_conf_t
*conf
, const pool_t
*pp
)
2540 if (pool_conf_status(conf
) == POF_INVALID
) {
2541 pool_seterror(POE_BADPARAM
);
2544 return ((pool_elem_t
*)pp
);
2548 pool_resource_to_elem(const pool_conf_t
*conf
, const pool_resource_t
*prs
)
2550 if (pool_conf_status(conf
) == POF_INVALID
) {
2551 pool_seterror(POE_BADPARAM
);
2554 return ((pool_elem_t
*)prs
);
2558 pool_component_to_elem(const pool_conf_t
*conf
, const pool_component_t
*pr
)
2560 if (pool_conf_status(conf
) == POF_INVALID
) {
2561 pool_seterror(POE_BADPARAM
);
2564 return ((pool_elem_t
*)pr
);
2568 * Walk all the pools of the configuration calling the user supplied function
2569 * as long as the user function continues to return PO_TRUE
2572 pool_walk_pools(pool_conf_t
*conf
, void *arg
,
2573 int (*callback
)(pool_conf_t
*conf
, pool_t
*pool
, void *arg
))
2578 int error
= PO_SUCCESS
;
2580 if (pool_conf_status(conf
) == POF_INVALID
) {
2581 pool_seterror(POE_BADPARAM
);
2585 if ((rs
= pool_query_pools(conf
, &size
, NULL
)) == NULL
) /* None */
2586 return (PO_SUCCESS
);
2587 for (i
= 0; i
< size
; i
++)
2588 if (callback(conf
, rs
[i
], arg
) != PO_SUCCESS
) {
2597 * Walk all the comp of the res calling the user supplied function
2598 * as long as the user function continues to return PO_TRUE
2601 pool_walk_components(pool_conf_t
*conf
, pool_resource_t
*prs
, void *arg
,
2602 int (*callback
)(pool_conf_t
*conf
, pool_component_t
*pr
, void *arg
))
2604 pool_component_t
**rs
;
2607 int error
= PO_SUCCESS
;
2609 if (pool_conf_status(conf
) == POF_INVALID
) {
2610 pool_seterror(POE_BADPARAM
);
2614 if ((rs
= pool_query_resource_components(conf
, prs
, &size
, NULL
)) ==
2616 return (PO_SUCCESS
); /* None */
2617 for (i
= 0; i
< size
; i
++)
2618 if (callback(conf
, rs
[i
], arg
) != PO_SUCCESS
) {
2627 * Return an array of all matching res for the supplied pool.
2630 pool_query_pool_resources(const pool_conf_t
*conf
, const pool_t
*pp
,
2631 uint_t
*size
, pool_value_t
**props
)
2633 pool_result_set_t
*rs
;
2635 pool_resource_t
**result
= NULL
;
2638 if (pool_conf_status(conf
) == POF_INVALID
) {
2639 pool_seterror(POE_BADPARAM
);
2645 rs
= pool_exec_query(conf
, pe
, "res", PEC_QRY_RES
, props
);
2649 if ((*size
= pool_rs_count(rs
)) == 0) {
2650 (void) pool_rs_close(rs
);
2653 if ((result
= malloc(sizeof (pool_resource_t
*) * (*size
+ 1)))
2655 pool_seterror(POE_SYSTEM
);
2656 (void) pool_rs_close(rs
);
2659 (void) memset(result
, 0, sizeof (pool_resource_t
*) * (*size
+ 1));
2660 for (pe
= rs
->prs_next(rs
); pe
!= NULL
; pe
= rs
->prs_next(rs
)) {
2661 if (pool_elem_class(pe
) != PEC_RES_COMP
&&
2662 pool_elem_class(pe
) != PEC_RES_AGG
) {
2663 pool_seterror(POE_INVALID_CONF
);
2665 (void) pool_rs_close(rs
);
2668 result
[i
++] = pool_elem_res(pe
);
2670 (void) pool_rs_close(rs
);
2675 * Walk all the res of the pool calling the user supplied function
2676 * as long as the user function continues to return PO_TRUE
2679 pool_walk_resources(pool_conf_t
*conf
, pool_t
*pp
, void *arg
,
2680 int (*callback
)(pool_conf_t
*, pool_resource_t
*, void *))
2682 pool_resource_t
**rs
;
2685 int error
= PO_SUCCESS
;
2687 if (pool_conf_status(conf
) == POF_INVALID
) {
2688 pool_seterror(POE_BADPARAM
);
2691 if ((rs
= pool_query_pool_resources(conf
, pp
, &size
, NULL
)) == NULL
)
2692 return (PO_SUCCESS
); /* None */
2693 for (i
= 0; i
< size
; i
++)
2694 if (callback(conf
, rs
[i
], arg
) != PO_SUCCESS
) {
2703 * Return a result set of all comp for the supplied res.
2706 pool_query_resource_components(const pool_conf_t
*conf
,
2707 const pool_resource_t
*prs
, uint_t
*size
, pool_value_t
**props
)
2709 pool_result_set_t
*rs
;
2711 pool_component_t
**result
= NULL
;
2714 if (pool_conf_status(conf
) == POF_INVALID
) {
2715 pool_seterror(POE_BADPARAM
);
2720 rs
= pool_exec_query(conf
, pe
, NULL
, PEC_QRY_COMP
, props
);
2724 if ((*size
= pool_rs_count(rs
)) == 0) {
2725 (void) pool_rs_close(rs
);
2728 if ((result
= malloc(sizeof (pool_component_t
*) * (*size
+ 1)))
2730 pool_seterror(POE_SYSTEM
);
2731 (void) pool_rs_close(rs
);
2734 (void) memset(result
, 0, sizeof (pool_component_t
*) * (*size
+ 1));
2735 for (pe
= rs
->prs_next(rs
); pe
!= NULL
; pe
= rs
->prs_next(rs
)) {
2736 if (pool_elem_class(pe
) != PEC_COMP
) {
2737 pool_seterror(POE_INVALID_CONF
);
2739 (void) pool_rs_close(rs
);
2742 result
[i
++] = pool_elem_comp(pe
);
2744 (void) pool_rs_close(rs
);
2749 * pool_version() returns the version of this library, depending on the supplied
2752 * Returns: library version depening on the supplied ver parameter.
2755 pool_version(uint_t ver
)
2760 case POOL_VER_CURRENT
:
2764 return (POOL_VER_NONE
);
2766 return (pool_workver
);
2770 * pool_associate() associates the supplied resource to the supplied pool.
2772 * Returns: PO_SUCCESS/PO_FAIL
2775 pool_associate(pool_conf_t
*conf
, pool_t
*pool
, const pool_resource_t
*res
)
2777 if (pool_conf_check(conf
) != PO_SUCCESS
)
2780 return (pool
->pp_associate(pool
, res
));
2784 * pool_dissociate() dissociates the supplied resource from the supplied pool.
2786 * Returns: PO_SUCCESS/PO_FAIL
2789 pool_dissociate(pool_conf_t
*conf
, pool_t
*pool
, const pool_resource_t
*res
)
2791 if (pool_conf_check(conf
) != PO_SUCCESS
)
2794 if (elem_is_default(TO_ELEM(res
)))
2795 return (PO_SUCCESS
);
2796 return (pool
->pp_dissociate(pool
, res
));
2800 * Compare two elements for purposes of ordering.
2802 * < 0 if e1 is "before" e2
2803 * 0 if e1 "equals" e2
2804 * > 0 if e1 comes after e2
2807 pool_elem_compare_name(const pool_elem_t
*e1
, const pool_elem_t
*e2
)
2809 char *name1
, *name2
;
2810 pool_value_t val
= POOL_VALUE_INITIALIZER
;
2814 * We may be asked to compare two elements from different classes.
2815 * They are different so return (1).
2817 if (pool_elem_same_class(e1
, e2
) != PO_TRUE
)
2821 * If the class is PEC_SYSTEM, always match them
2823 if (pool_elem_class(e1
) == PEC_SYSTEM
)
2827 * If we are going to compare components, then use sys_id
2829 if (pool_elem_class(e1
) == PEC_COMP
) {
2830 int64_t sys_id1
, sys_id2
;
2832 if (pool_get_ns_property(e1
, c_sys_prop
, &val
) == POC_INVAL
) {
2835 (void) pool_value_get_int64(&val
, &sys_id1
);
2836 if (pool_get_ns_property(e2
, c_sys_prop
, &val
) == POC_INVAL
) {
2839 (void) pool_value_get_int64(&val
, &sys_id2
);
2840 retval
= (sys_id1
- sys_id2
);
2842 if (pool_get_ns_property(e1
, "name", &val
) == POC_INVAL
) {
2845 (void) pool_value_get_string(&val
, (const char **)&name1
);
2846 if ((name1
= strdup(name1
)) == NULL
) {
2850 if (pool_get_ns_property(e2
, "name", &val
) == POC_INVAL
) {
2854 (void) pool_value_get_string(&val
, (const char **)&name2
);
2855 retval
= strcmp(name1
, name2
);
2862 * Compare two elements for purposes of ordering.
2864 * < 0 if e1 is "before" e2
2865 * 0 if e1 "equals" e2
2866 * > 0 if e1 comes after e2
2869 pool_elem_compare(const pool_elem_t
*e1
, const pool_elem_t
*e2
)
2871 pool_value_t val
= POOL_VALUE_INITIALIZER
;
2872 int64_t sys_id1
, sys_id2
;
2875 * We may be asked to compare two elements from different classes.
2876 * They are different so return the difference in their classes
2878 if (pool_elem_same_class(e1
, e2
) != PO_TRUE
)
2882 * If the class is PEC_SYSTEM, always match them
2884 if (pool_elem_class(e1
) == PEC_SYSTEM
)
2888 * Compare with sys_id
2890 if (pool_get_ns_property(e1
, c_sys_prop
, &val
) == POC_INVAL
) {
2891 assert(!"no sys_id on e1\n");
2893 (void) pool_value_get_int64(&val
, &sys_id1
);
2894 if (pool_get_ns_property(e2
, c_sys_prop
, &val
) == POC_INVAL
) {
2895 assert(!"no sys_id on e2\n");
2897 (void) pool_value_get_int64(&val
, &sys_id2
);
2898 return (sys_id1
- sys_id2
);
2902 * Return PO_TRUE if the supplied elems are of the same class.
2905 pool_elem_same_class(const pool_elem_t
*e1
, const pool_elem_t
*e2
)
2907 if (pool_elem_class(e1
) != pool_elem_class(e2
))
2911 * Check to make sure the fundamental class of the elements match
2913 if (pool_elem_class(e1
) == PEC_RES_COMP
||
2914 pool_elem_class(e1
) == PEC_RES_AGG
)
2915 if (pool_resource_elem_class(e1
) !=
2916 pool_resource_elem_class(e2
))
2918 if (pool_elem_class(e1
) == PEC_COMP
)
2919 if (pool_component_elem_class(e1
) !=
2920 pool_component_elem_class(e2
))
2926 * pool_conf_check() checks that the configuration state isn't invalid
2927 * and that the configuration was opened for modification.
2930 pool_conf_check(const pool_conf_t
*conf
)
2932 if (pool_conf_status(conf
) == POF_INVALID
) {
2933 pool_seterror(POE_BADPARAM
);
2937 if ((conf
->pc_prov
->pc_oflags
& PO_RDWR
) == 0) {
2938 pool_seterror(POE_BADPARAM
);
2941 return (PO_SUCCESS
);