diff options
author | pjd <pjd@FreeBSD.org> | 2006-09-15 16:36:45 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2006-09-15 16:36:45 +0000 |
commit | 556424a17a50f0a584e5094340bdc64e10e707d3 (patch) | |
tree | b98ee1fea8efdb2f36d1cbba4896f419c50be742 /sys/geom/geom_subr.c | |
parent | e168227ed2fb2c85707431a1167890c349968718 (diff) | |
download | FreeBSD-src-556424a17a50f0a584e5094340bdc64e10e707d3.zip FreeBSD-src-556424a17a50f0a584e5094340bdc64e10e707d3.tar.gz |
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
Diffstat (limited to 'sys/geom/geom_subr.c')
-rw-r--r-- | sys/geom/geom_subr.c | 213 |
1 files changed, 212 insertions, 1 deletions
diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index 623650a..eec44c3 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -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 */ |