aboutsummaryrefslogtreecommitdiff
path: root/lib/libgeom/geom_xml2tree.c
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2022-03-12 16:49:37 +0000
committerAlexander Motin <mav@FreeBSD.org>2022-03-12 16:55:52 +0000
commit7f16b501e25b6c792fefc4535e0d1b8363392fe0 (patch)
treedcc495a1a4540e1c95a02c42cffe887707750670 /lib/libgeom/geom_xml2tree.c
parentdb11c57a6cf3053fb09185975cfbe3729f2fbe44 (diff)
downloadsrc-7f16b501e25b6c792fefc4535e0d1b8363392fe0.tar.gz
src-7f16b501e25b6c792fefc4535e0d1b8363392fe0.zip
GEOM: Introduce partial confxml API
Traditionally the GEOM's primary channel of information from kernel to user-space was confxml, fetched by libgeom through kern.geom.confxml sysctl. It is convenient and informative, representing full state of GEOM in a single XML document. But problems start to arise on systems with hundreds of disks, where the full confxml size reaches many megabytes, taking significant time to first write it and then parse. This patch introduces alternative solution, allowing to fetch much smaller XML document, subset of the full confxml, limited to 64KB and representing only one specified geom and optionally its parents. It uses existing GEOM control interface, extended with new "getxml" verb. In case of any error, such as the buffer overflow, it just transparently falls back to traditional full confxml. This patch uses the new API in user-space GEOM tools where it is possible. Reviewed by: imp MFC after: 2 month Sponsored by: iXsystems, Inc. Differential Revision: https://reviews.freebsd.org/D34529
Diffstat (limited to 'lib/libgeom/geom_xml2tree.c')
-rw-r--r--lib/libgeom/geom_xml2tree.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/lib/libgeom/geom_xml2tree.c b/lib/libgeom/geom_xml2tree.c
index 824800070933..a6da0e6d163f 100644
--- a/lib/libgeom/geom_xml2tree.c
+++ b/lib/libgeom/geom_xml2tree.c
@@ -358,6 +358,17 @@ geom_lookupid(struct gmesh *gmp, const void *id)
return (NULL);
}
+static void *
+geom_lookupidptr(struct gmesh *gmp, const void *id)
+{
+ struct gident *gip;
+
+ gip = geom_lookupid(gmp, id);
+ if (gip)
+ return (gip->lg_ptr);
+ return (NULL);
+}
+
int
geom_xml2tree(struct gmesh *gmp, char *p)
{
@@ -430,22 +441,19 @@ geom_xml2tree(struct gmesh *gmp, char *p)
/* Substitute all identifiers */
LIST_FOREACH(cl, &gmp->lg_class, lg_class) {
LIST_FOREACH(ge, &cl->lg_geom, lg_geom) {
- ge->lg_class =
- geom_lookupid(gmp, ge->lg_class)->lg_ptr;
- LIST_FOREACH(pr, &ge->lg_provider, lg_provider) {
- pr->lg_geom =
- geom_lookupid(gmp, pr->lg_geom)->lg_ptr;
- }
+ ge->lg_class = geom_lookupidptr(gmp, ge->lg_class);
+ LIST_FOREACH(pr, &ge->lg_provider, lg_provider)
+ pr->lg_geom = geom_lookupidptr(gmp, pr->lg_geom);
LIST_FOREACH(co, &ge->lg_consumer, lg_consumer) {
- co->lg_geom =
- geom_lookupid(gmp, co->lg_geom)->lg_ptr;
+ co->lg_geom = geom_lookupidptr(gmp, co->lg_geom);
if (co->lg_provider != NULL) {
- co->lg_provider =
- geom_lookupid(gmp,
- co->lg_provider)->lg_ptr;
- LIST_INSERT_HEAD(
- &co->lg_provider->lg_consumers,
- co, lg_consumers);
+ co->lg_provider = geom_lookupidptr(gmp,
+ co->lg_provider);
+ if (co->lg_provider != NULL) {
+ LIST_INSERT_HEAD(
+ &co->lg_provider->lg_consumers,
+ co, lg_consumers);
+ }
}
}
}
@@ -467,6 +475,20 @@ geom_gettree(struct gmesh *gmp)
return (error);
}
+int
+geom_gettree_geom(struct gmesh *gmp, const char *c, const char *g, int parents)
+{
+ char *p;
+ int error;
+
+ p = geom_getxml_geom(c, g, parents);
+ if (p == NULL)
+ return (errno);
+ error = geom_xml2tree(gmp, p);
+ free(p);
+ return (error);
+}
+
static void
delete_config(struct gconf *gp)
{