Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F165117475
D42572.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D42572.diff
View Options
diff --git a/usr.sbin/bhyve/config.h b/usr.sbin/bhyve/config.h
--- a/usr.sbin/bhyve/config.h
+++ b/usr.sbin/bhyve/config.h
@@ -58,6 +58,12 @@
*/
const char *get_config_value_node(const nvlist_t *parent, const char *name);
+/*
+ * Loop over duplicate values of a configuration variable.
+ */
+int config_value_node_foreach(const nvlist_t *parent, const char *name,
+ int (*cb)(const char *, void *), void *arg);
+
/*
* Similar to get_config_value_node but expects a full path to the
* leaf node.
@@ -93,12 +99,20 @@
* Adds or replaces the value of the specified variable.
*
* If 'parent' is NULL, 'name' is assumed to be a top-level variable.
+ * If 'name' is already set, the old value is overwritten.
*/
void set_config_value_node(nvlist_t *parent, const char *name,
const char *value);
/*
- * Similar to set_config_value_node but only sets value if it's unset yet.
+ * Similar to set_config_value_node, but an existing value with the same name is
+ * not overwritten.
+ */
+void set_config_value_node_dupok(nvlist_t *parent, const char *name,
+ const char *value);
+
+/*
+ * Similar to set_config_value_node but only sets value if it's unset.
*/
void set_config_value_node_if_unset(nvlist_t *const parent,
const char *const name, const char *const value);
diff --git a/usr.sbin/bhyve/config.c b/usr.sbin/bhyve/config.c
--- a/usr.sbin/bhyve/config.c
+++ b/usr.sbin/bhyve/config.c
@@ -25,7 +25,8 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
+#include <sys/cnv.h>
+
#include <assert.h>
#include <err.h>
#include <stdio.h>
@@ -36,13 +37,28 @@
static nvlist_t *config_root;
+static nvlist_t *
+config_node_alloc(void)
+{
+ nvlist_t *nvl;
+
+ /*
+ * Config nodes permit duplicate keys, but by default, an existing
+ * configuration value is overwritten when a new one is set. This
+ * behavior can be overridden by using set_config_value_node_dupok(),
+ * in which case, config_value_node_foreach() must be used to retrieve
+ * values.
+ */
+ nvl = nvlist_create(NV_FLAG_NO_UNIQUE);
+ if (nvl == NULL)
+ err(1, "nvlist_create");
+ return (nvl);
+}
+
void
init_config(void)
{
-
- config_root = nvlist_create(0);
- if (config_root == NULL)
- err(4, "Failed to create configuration root nvlist");
+ config_root = config_node_alloc();
}
static nvlist_t *
@@ -88,7 +104,7 @@
* XXX-MJ as with the case above, "new_nvl" shouldn't be
* mutated after its ownership is given to "nvl".
*/
- new_nvl = nvlist_create(0);
+ new_nvl = config_node_alloc();
if (new_nvl == NULL)
errx(4, "Failed to allocate memory");
nvlist_move_nvlist(nvl, name, new_nvl);
@@ -130,23 +146,39 @@
return (_lookup_config_node(parent, path, false));
}
-void
-set_config_value_node(nvlist_t *parent, const char *name, const char *value)
-{
+#define CONFIG_DUPOK 0x01
+static void
+set_config_value_node_flags(nvlist_t *parent, const char *name,
+ const char *value, int flags)
+{
if (strchr(name, '.') != NULL)
errx(4, "Invalid config node name %s", name);
if (parent == NULL)
parent = config_root;
- if (nvlist_exists_string(parent, name))
- nvlist_free_string(parent, name);
- else if (nvlist_exists(parent, name))
+ if (nvlist_exists_string(parent, name)) {
+ if ((flags & CONFIG_DUPOK) == 0)
+ nvlist_free_string(parent, name);
+ } else if (nvlist_exists(parent, name))
errx(4,
"Attempting to add value %s to existing node %s of list %p",
value, name, parent);
nvlist_add_string(parent, name, value);
}
+void
+set_config_value_node(nvlist_t *parent, const char *name, const char *value)
+{
+ set_config_value_node_flags(parent, name, value, 0);
+}
+
+void
+set_config_value_node_dupok(nvlist_t *parent, const char *name,
+ const char *value)
+{
+ set_config_value_node_flags(parent, name, value, CONFIG_DUPOK);
+}
+
void
set_config_value_node_if_unset(nvlist_t *const parent, const char *const name,
const char *const value)
@@ -358,6 +390,31 @@
return (expand_config_value(nvlist_get_string(parent, name)));
}
+int
+config_value_node_foreach(const nvlist_t *parent, const char *name,
+ int (*cb)(const char *, void *), void *arg)
+{
+ void *cookie;
+ const char *nvname;
+ int error, type;
+
+ if (strchr(name, '.') != NULL)
+ errx(4, "Invalid config node name %s", name);
+ if (parent == NULL)
+ parent = config_root;
+
+ for (cookie = NULL;
+ (nvname = nvlist_next(parent, &type, &cookie)) != NULL;) {
+ assert(type == NV_TYPE_STRING);
+ if (strcmp(nvname, name) == 0) {
+ error = cb(cnvlist_get_string(cookie), arg);
+ if (error != 0)
+ return (error);
+ }
+ }
+ return (0);
+}
+
static bool
_bool_value(const char *name, const char *value)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 7, 5:04 AM (4 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36147365
Default Alt Text
D42572.diff (4 KB)
Attached To
Mode
D42572: bhyve: Add partial support for multiple config node values
Attached
Detach File
Event Timeline
Log In to Comment