Improve geom(8)'s 'list' command to show geoms and their providers and
consumers. Teach STRIPE, CONCAT and NOP classes about this improvement.
This commit is contained in:
parent
889c5dc22b
commit
1d723f1d51
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=132665
@ -66,7 +66,7 @@
|
||||
.Op Ar dev2 Op Ar ...
|
||||
.Nm
|
||||
.Cm list
|
||||
.Op Ar prov Op Ar ...
|
||||
.Op Ar name Op Ar ...
|
||||
.Nm
|
||||
.Cm load
|
||||
.Op Fl v
|
||||
|
@ -68,7 +68,7 @@
|
||||
.Op Ar dev2 Op Ar ...
|
||||
.Nm
|
||||
.Cm list
|
||||
.Op Ar prov Op Ar ...
|
||||
.Op Ar name Op Ar ...
|
||||
.Nm
|
||||
.Cm load
|
||||
.Op Fl v
|
||||
|
@ -50,8 +50,8 @@ Here is the list of standard commands:
|
||||
.It Cm help
|
||||
List all available commands for the given class.
|
||||
.It Cm list
|
||||
Print detailed information (within the given class) about all providers
|
||||
(if no additional arguments were specified) or the given providers.
|
||||
Print detailed information (within the given class) about all geoms
|
||||
(if no additional arguments were specified) or the given geoms.
|
||||
This command is only available if the given class exists in the kernel.
|
||||
.It Cm load
|
||||
Load the kernel module that implements the given class.
|
||||
|
@ -548,57 +548,88 @@ find_class(struct gmesh *mesh, const char *name)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct gprovider *
|
||||
find_provider(struct gclass *classp, const char *name)
|
||||
static struct ggeom *
|
||||
find_geom(struct gclass *classp, const char *name)
|
||||
{
|
||||
struct ggeom *gp;
|
||||
struct gprovider *pp;
|
||||
|
||||
LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
|
||||
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
|
||||
if (strcmp(pp->lg_name, name) == 0)
|
||||
return (pp);
|
||||
}
|
||||
if (strcmp(gp->lg_name, name) == 0)
|
||||
return (gp);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
genspaces(const char *text, size_t len)
|
||||
{
|
||||
static char spaces[256];
|
||||
size_t outlen;
|
||||
|
||||
if (strlen(text) >= len) {
|
||||
spaces[0] = '\0';
|
||||
return (spaces);
|
||||
}
|
||||
memset(spaces, ' ', sizeof(spaces));
|
||||
outlen = len - strlen(text);
|
||||
if (outlen >= sizeof(spaces)) {
|
||||
spaces[sizeof(spaces) - 1] = '\0';
|
||||
return (spaces);
|
||||
}
|
||||
spaces[outlen] = '\0';
|
||||
return (spaces);
|
||||
}
|
||||
|
||||
static void
|
||||
show_one(struct gprovider *pp)
|
||||
show_one_provider(struct gprovider *pp, const char *prefix)
|
||||
{
|
||||
struct gconfig *conf;
|
||||
char buf[5];
|
||||
|
||||
printf(" NAME: %s\n", pp->lg_name);
|
||||
printf(" geom name: %s\n", pp->lg_geom->lg_name);
|
||||
printf("Name: %s\n", pp->lg_name);
|
||||
humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
|
||||
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
|
||||
printf(" mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
|
||||
printf(" sectorsize: %u\n", pp->lg_sectorsize);
|
||||
printf(" mode: %s\n", pp->lg_mode);
|
||||
printf("%sMediasize: %jd (%s)\n", prefix, (intmax_t)pp->lg_mediasize,
|
||||
buf);
|
||||
printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize);
|
||||
printf("%sMode: %s\n", prefix, pp->lg_mode);
|
||||
LIST_FOREACH(conf, &pp->lg_config, lg_config) {
|
||||
printf("%s%s: %s\n", genspaces(conf->lg_name, 11),
|
||||
conf->lg_name, conf->lg_val);
|
||||
printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_one_consumer(struct gconsumer *cp, const char *prefix)
|
||||
{
|
||||
struct gprovider *pp;
|
||||
struct gconfig *conf;
|
||||
|
||||
pp = cp->lg_provider;
|
||||
if (pp == NULL)
|
||||
printf("[no provider]\n");
|
||||
else {
|
||||
char buf[5];
|
||||
|
||||
printf("Name: %s\n", pp->lg_name);
|
||||
humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
|
||||
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
|
||||
printf("%sMediasize: %jd (%s)\n", prefix,
|
||||
(intmax_t)pp->lg_mediasize, buf);
|
||||
printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize);
|
||||
printf("%sMode: %s\n", prefix, cp->lg_mode);
|
||||
}
|
||||
LIST_FOREACH(conf, &cp->lg_config, lg_config) {
|
||||
printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_one_geom(struct ggeom *gp)
|
||||
{
|
||||
struct gprovider *pp;
|
||||
struct gconsumer *cp;
|
||||
struct gconfig *conf;
|
||||
unsigned n;
|
||||
|
||||
printf("Geom name: %s\n", gp->lg_name);
|
||||
LIST_FOREACH(conf, &gp->lg_config, lg_config) {
|
||||
printf("%s: %s\n", conf->lg_name, conf->lg_val);
|
||||
}
|
||||
if (!LIST_EMPTY(&gp->lg_provider)) {
|
||||
printf("Providers:\n");
|
||||
n = 1;
|
||||
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
|
||||
printf("%u. ", n++);
|
||||
show_one_provider(pp, " ");
|
||||
}
|
||||
}
|
||||
if (!LIST_EMPTY(&gp->lg_consumer)) {
|
||||
printf("Consumers:\n");
|
||||
n = 1;
|
||||
LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
|
||||
printf("%u. ", n++);
|
||||
show_one_consumer(cp, " ");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
@ -632,7 +663,7 @@ std_list(struct gctl_req *req, unsigned flags __unused)
|
||||
{
|
||||
struct gmesh mesh;
|
||||
struct gclass *classp;
|
||||
struct gprovider *pp;
|
||||
struct ggeom *gp;
|
||||
int error, *nargs;
|
||||
|
||||
error = geom_gettree(&mesh);
|
||||
@ -660,21 +691,15 @@ std_list(struct gctl_req *req, unsigned flags __unused)
|
||||
snprintf(param, sizeof(param), "arg%d", i);
|
||||
name = gctl_get_asciiparam(req, param);
|
||||
assert(name != NULL);
|
||||
pp = find_provider(classp, name);
|
||||
if (pp != NULL)
|
||||
show_one(pp);
|
||||
else {
|
||||
fprintf(stderr, "No such provider: %s.\n",
|
||||
name);
|
||||
}
|
||||
gp = find_geom(classp, name);
|
||||
if (gp != NULL)
|
||||
show_one_geom(gp);
|
||||
else
|
||||
fprintf(stderr, "No such geom: %s.\n", name);
|
||||
}
|
||||
} else {
|
||||
struct ggeom *gp;
|
||||
|
||||
LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
|
||||
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
|
||||
show_one(pp);
|
||||
}
|
||||
show_one_geom(gp);
|
||||
}
|
||||
}
|
||||
geom_deletetree(&mesh);
|
||||
|
@ -798,35 +798,44 @@ g_concat_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
|
||||
|
||||
g_topology_assert();
|
||||
sc = gp->softc;
|
||||
if (sc == NULL || pp == NULL)
|
||||
if (sc == NULL)
|
||||
return;
|
||||
sbuf_printf(sb, "%s<id>%u</id>\n", indent, (u_int)sc->sc_id);
|
||||
if (pp != NULL) {
|
||||
/* Nothing here. */
|
||||
} else if (cp != NULL) {
|
||||
struct g_concat_disk *disk;
|
||||
|
||||
disk = cp->private;
|
||||
if (disk == NULL)
|
||||
return;
|
||||
sbuf_printf(sb, "%s<End>%jd</End>\n", indent,
|
||||
(intmax_t)disk->d_end);
|
||||
sbuf_printf(sb, "%s<Start>%jd</Start>\n", indent,
|
||||
(intmax_t)disk->d_start);
|
||||
} else {
|
||||
sbuf_printf(sb, "%s<ID>%u</ID>\n", indent, (u_int)sc->sc_id);
|
||||
sbuf_printf(sb, "%s<Type>", indent);
|
||||
switch (sc->sc_type) {
|
||||
case G_CONCAT_TYPE_AUTOMATIC:
|
||||
sbuf_printf(sb, "%s<type>%s</type>\n", indent, "automatic");
|
||||
sbuf_printf(sb, "AUTOMATIC");
|
||||
break;
|
||||
case G_CONCAT_TYPE_MANUAL:
|
||||
sbuf_printf(sb, "%s<type>%s</type>\n", indent, "manual");
|
||||
sbuf_printf(sb, "MANUAL");
|
||||
break;
|
||||
default:
|
||||
sbuf_printf(sb, "%s<type>%s</type>\n", indent, "unknown");
|
||||
sbuf_printf(sb, "UNKNOWN");
|
||||
break;
|
||||
}
|
||||
sbuf_printf(sb, "%s<providers>", indent);
|
||||
LIST_FOREACH(cp, &gp->consumer, consumer) {
|
||||
if (cp->provider == NULL)
|
||||
continue;
|
||||
sbuf_printf(sb, "%s", cp->provider->name);
|
||||
if (LIST_NEXT(cp, consumer) != NULL)
|
||||
sbuf_printf(sb, " ");
|
||||
}
|
||||
sbuf_printf(sb, "</providers>\n");
|
||||
sbuf_printf(sb, "%s<status>total=%u, online=%u</status>\n", indent,
|
||||
sc->sc_ndisks, g_concat_nvalid(sc));
|
||||
if (pp->error == 0)
|
||||
sbuf_printf(sb, "%s<state>UP</state>\n", indent);
|
||||
sbuf_printf(sb, "</Type>\n");
|
||||
sbuf_printf(sb, "%s<Status>Total=%u, Online=%u</Status>\n",
|
||||
indent, sc->sc_ndisks, g_concat_nvalid(sc));
|
||||
sbuf_printf(sb, "%s<State>", indent);
|
||||
if (sc->sc_provider != NULL && sc->sc_provider->error == 0)
|
||||
sbuf_printf(sb, "UP");
|
||||
else
|
||||
sbuf_printf(sb, "%s<state>DOWN</state>\n", indent);
|
||||
sbuf_printf(sb, "DOWN");
|
||||
sbuf_printf(sb, "</State>\n");
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_GEOM_CLASS(g_concat_class, g_concat);
|
||||
|
@ -468,12 +468,12 @@ g_nop_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
|
||||
{
|
||||
struct g_nop_softc *sc;
|
||||
|
||||
if (pp == NULL)
|
||||
if (pp != NULL || cp != NULL)
|
||||
return;
|
||||
sc = gp->softc;
|
||||
sbuf_printf(sb, "%s<offset>%jd</offset>\n", indent,
|
||||
sbuf_printf(sb, "%s<Offset>%jd</Offset>\n", indent,
|
||||
(intmax_t)sc->sc_offset);
|
||||
sbuf_printf(sb, "%s<failprob>%u</failprob>\n", indent, sc->sc_failprob);
|
||||
sbuf_printf(sb, "%s<Failprob>%u</Failprob>\n", indent, sc->sc_failprob);
|
||||
}
|
||||
|
||||
DECLARE_GEOM_CLASS(g_nop_class, g_nop);
|
||||
|
@ -1128,37 +1128,38 @@ g_stripe_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
|
||||
struct g_stripe_softc *sc;
|
||||
|
||||
sc = gp->softc;
|
||||
if (sc == NULL || pp == NULL)
|
||||
if (sc == NULL)
|
||||
return;
|
||||
sbuf_printf(sb, "%s<id>%u</id>\n", indent, (u_int)sc->sc_id);
|
||||
sbuf_printf(sb, "%s<stripesize>%u</stripesize>\n", indent,
|
||||
if (pp != NULL) {
|
||||
/* Nothing here. */
|
||||
} else if (cp != NULL) {
|
||||
/* Nothing here. */
|
||||
} else {
|
||||
sbuf_printf(sb, "%s<ID>%u</ID>\n", indent, (u_int)sc->sc_id);
|
||||
sbuf_printf(sb, "%s<Stripesize>%u</Stripesize>\n", indent,
|
||||
(u_int)sc->sc_stripesize);
|
||||
sbuf_printf(sb, "%s<Type>", indent);
|
||||
switch (sc->sc_type) {
|
||||
case G_STRIPE_TYPE_AUTOMATIC:
|
||||
sbuf_printf(sb, "%s<type>%s</type>\n", indent, "automatic");
|
||||
sbuf_printf(sb, "AUTOMATIC");
|
||||
break;
|
||||
case G_STRIPE_TYPE_MANUAL:
|
||||
sbuf_printf(sb, "%s<type>%s</type>\n", indent, "manual");
|
||||
sbuf_printf(sb, "MANUAL");
|
||||
break;
|
||||
default:
|
||||
sbuf_printf(sb, "%s<type>%s</type>\n", indent, "unknown");
|
||||
sbuf_printf(sb, "UNKNOWN");
|
||||
break;
|
||||
}
|
||||
sbuf_printf(sb, "%s<providers>", indent);
|
||||
LIST_FOREACH(cp, &gp->consumer, consumer) {
|
||||
if (cp->provider == NULL)
|
||||
continue;
|
||||
sbuf_printf(sb, "%s", cp->provider->name);
|
||||
if (LIST_NEXT(cp, consumer) != NULL)
|
||||
sbuf_printf(sb, " ");
|
||||
}
|
||||
sbuf_printf(sb, "</providers>\n");
|
||||
sbuf_printf(sb, "%s<status>total=%u, online=%u</status>\n", indent,
|
||||
sc->sc_ndisks, g_stripe_nvalid(sc));
|
||||
if (pp->error == 0)
|
||||
sbuf_printf(sb, "%s<state>UP</state>\n", indent);
|
||||
sbuf_printf(sb, "</Type>\n");
|
||||
sbuf_printf(sb, "%s<Status>Total=%u, Online=%u</Status>\n",
|
||||
indent, sc->sc_ndisks, g_stripe_nvalid(sc));
|
||||
sbuf_printf(sb, "%s<State>", indent);
|
||||
if (sc->sc_provider != NULL && sc->sc_provider->error == 0)
|
||||
sbuf_printf(sb, "UP");
|
||||
else
|
||||
sbuf_printf(sb, "%s<state>DOWN</state>\n", indent);
|
||||
sbuf_printf(sb, "DOWN");
|
||||
sbuf_printf(sb, "</State>\n");
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_GEOM_CLASS(g_stripe_class, g_stripe);
|
||||
|
Loading…
Reference in New Issue
Block a user