Add 'show geom [addr]' ddb(4) command, which prints entire GEOM topology if

no additional argument is given or details about the given GEOM object
(class, geom, provider or consumer).

Approved by:	phk
This commit is contained in:
pjd 2006-09-15 16:36:45 +00:00
parent e168227ed2
commit 556424a17a
3 changed files with 227 additions and 3 deletions

View File

@ -58,7 +58,7 @@
.\" [90/08/30 dbg]
.\"
.\" $FreeBSD$
.Dd February 27, 2006
.Dd September 15, 2006
.Dt DDB 4
.Os
.Sh NAME
@ -423,6 +423,17 @@ The support of the
modifier depends on the machine.
If not supported, incorrect information will be displayed.
.It Xo
.Cm show geom
.Op Ar addr
.Xc
If the
.Ar addr
argument is not given, displays the entire GEOM topology.
If the
.Ar addr
is given, displays details about the given GEOM object (class, geom, provider
or consumer).
.It Xo
.Cm show map Ns Op Cm /f
.Ar addr
.Xc

View File

@ -241,8 +241,10 @@ void g_wither_geom(struct g_geom *gp, int error);
void g_wither_geom_close(struct g_geom *gp, int error);
void g_wither_provider(struct g_provider *pp, int error);
#ifdef DIAGNOSTIC
#if defined(DIAGNOSTIC) || defined(DDB)
int g_valid_obj(void const *ptr);
#endif
#ifdef DIAGNOSTIC
#define G_VALID_CLASS(foo) \
KASSERT(g_valid_obj(foo) == 1, ("%p is not a g_class", foo))
#define G_VALID_GEOM(foo) \

View File

@ -36,6 +36,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/devicestat.h>
@ -53,6 +55,10 @@ __FBSDID("$FreeBSD$");
#include <geom/geom_int.h>
#include <machine/stdarg.h>
#ifdef DDB
#include <ddb/ddb.h>
#endif
struct class_list_head g_classes = LIST_HEAD_INITIALIZER(g_classes);
static struct g_tailq_head geoms = TAILQ_HEAD_INITIALIZER(geoms);
char *g_wait_event, *g_wait_up, *g_wait_down, *g_wait_sim;
@ -920,7 +926,7 @@ g_getattr__(const char *attr, struct g_consumer *cp, void *var, int len)
return (0);
}
#ifdef DIAGNOSTIC
#if defined(DIAGNOSTIC) || defined(DDB)
/*
* This function walks (topologically unsafely) the mesh and return a
* non-zero integer if it finds the argument pointer is an object.
@ -954,3 +960,208 @@ g_valid_obj(void const *ptr)
return(0);
}
#endif
#ifdef DDB
#define gprintf(...) do { \
printf("%*s", indent, ""); \
printf(__VA_ARGS__); \
} while (0)
#define gprintln(...) do { \
gprintf(__VA_ARGS__); \
printf("\n"); \
} while (0)
#define ADDFLAG(obj, flag, sflag) do { \
if ((obj)->flags & (flag)) { \
if (comma) \
strlcat(str, ",", size); \
strlcat(str, (sflag), size); \
comma = 1; \
} \
} while (0)
static char *
provider_flags_to_string(struct g_provider *pp, char *str, size_t size)
{
int comma = 0;
bzero(str, size);
if (pp->flags == 0) {
strlcpy(str, "NONE", size);
return (str);
}
ADDFLAG(pp, G_PF_CANDELETE, "G_PF_CANDELETE");
ADDFLAG(pp, G_PF_WITHER, "G_PF_WITHER");
ADDFLAG(pp, G_PF_ORPHAN, "G_PF_ORPHAN");
return (str);
}
static char *
geom_flags_to_string(struct g_geom *gp, char *str, size_t size)
{
int comma = 0;
bzero(str, size);
if (gp->flags == 0) {
strlcpy(str, "NONE", size);
return (str);
}
ADDFLAG(gp, G_GEOM_WITHER, "G_GEOM_WITHER");
return (str);
}
static void
db_show_geom_consumer(int indent, struct g_consumer *cp)
{
if (indent == 0) {
gprintln("consumer: %p", cp);
gprintln(" class: %s (%p)", cp->geom->class->name,
cp->geom->class);
gprintln(" geom: %s (%p)", cp->geom->name, cp->geom);
if (cp->provider == NULL)
gprintln(" provider: none");
else {
gprintln(" provider: %s (%p)", cp->provider->name,
cp->provider);
}
gprintln(" access: r%dw%de%d", cp->acr, cp->acw, cp->ace);
gprintln(" spoiled: %d", cp->spoiled);
gprintln(" nstart: %u", cp->nstart);
gprintln(" nend: %u", cp->nend);
} else {
gprintf("consumer: %p (%s), access=r%dw%de%d", cp,
cp->provider != NULL ? cp->provider->name : "none",
cp->acr, cp->acw, cp->ace);
if (cp->spoiled)
printf(", spoiled=%d", cp->spoiled);
printf("\n");
}
}
static void
db_show_geom_provider(int indent, struct g_provider *pp)
{
struct g_consumer *cp;
char flags[64];
if (indent == 0) {
gprintln("provider: %s (%p)", pp->name, pp);
gprintln(" class: %s (%p)", pp->geom->class->name,
pp->geom->class);
gprintln(" geom: %s (%p)", pp->geom->name, pp->geom);
gprintln(" mediasize: %jd", (intmax_t)pp->mediasize);
gprintln(" sectorsize: %u", pp->sectorsize);
gprintln(" stripesize: %u", pp->stripesize);
gprintln(" stripeoffset: %u", pp->stripeoffset);
gprintln(" access: r%dw%de%d", pp->acr, pp->acw,
pp->ace);
gprintln(" flags: %s (0x%04x)",
provider_flags_to_string(pp, flags, sizeof(flags)),
pp->flags);
gprintln(" error: %d", pp->error);
gprintln(" nstart: %u", pp->nstart);
gprintln(" nend: %u", pp->nend);
if (LIST_EMPTY(&pp->consumers))
gprintln(" consumers: none");
} else {
gprintf("provider: %s (%p), access=r%dw%de%d",
pp->name, pp, pp->acr, pp->acw, pp->ace);
if (pp->flags != 0) {
printf(", flags=%s (0x%04x)",
provider_flags_to_string(pp, flags, sizeof(flags)),
pp->flags);
}
printf("\n");
}
if (!LIST_EMPTY(&pp->consumers)) {
LIST_FOREACH(cp, &pp->consumers, consumers)
db_show_geom_consumer(indent + 2, cp);
}
}
static void
db_show_geom_geom(int indent, struct g_geom *gp)
{
struct g_provider *pp;
struct g_consumer *cp;
char flags[64];
if (indent == 0) {
gprintln("geom: %s (%p)", gp->name, gp);
gprintln(" class: %s (%p)", gp->class->name, gp->class);
gprintln(" flags: %s (0x%04x)",
geom_flags_to_string(gp, flags, sizeof(flags)), gp->flags);
gprintln(" rank: %d", gp->rank);
if (LIST_EMPTY(&gp->provider))
gprintln(" providers: none");
if (LIST_EMPTY(&gp->consumer))
gprintln(" consumers: none");
} else {
gprintf("geom: %s (%p), rank=%d", gp->name, gp, gp->rank);
if (gp->flags != 0) {
printf(", flags=%s (0x%04x)",
geom_flags_to_string(gp, flags, sizeof(flags)),
gp->flags);
}
printf("\n");
}
if (!LIST_EMPTY(&gp->provider)) {
LIST_FOREACH(pp, &gp->provider, provider)
db_show_geom_provider(indent + 2, pp);
}
if (!LIST_EMPTY(&gp->consumer)) {
LIST_FOREACH(cp, &gp->consumer, consumer)
db_show_geom_consumer(indent + 2, cp);
}
}
static void
db_show_geom_class(struct g_class *mp)
{
struct g_geom *gp;
printf("class: %s (%p)\n", mp->name, mp);
LIST_FOREACH(gp, &mp->geom, geom)
db_show_geom_geom(2, gp);
}
/*
* Print the GEOM topology or the given object.
*/
DB_SHOW_COMMAND(geom, db_show_geom)
{
struct g_class *mp;
if (!have_addr) {
/* No address given, print the entire topology. */
LIST_FOREACH(mp, &g_classes, class) {
db_show_geom_class(mp);
printf("\n");
}
} else {
switch (g_valid_obj((void *)addr)) {
case 1:
db_show_geom_class((struct g_class *)addr);
break;
case 2:
db_show_geom_geom(0, (struct g_geom *)addr);
break;
case 3:
db_show_geom_consumer(0, (struct g_consumer *)addr);
break;
case 4:
db_show_geom_provider(0, (struct g_provider *)addr);
break;
default:
printf("Not a GEOM object.\n");
break;
}
}
}
#undef gprintf
#undef gprintln
#undef ADDFLAG
#endif /* DDB */