summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2006-09-15 16:36:45 +0000
committerpjd <pjd@FreeBSD.org>2006-09-15 16:36:45 +0000
commit556424a17a50f0a584e5094340bdc64e10e707d3 (patch)
treeb98ee1fea8efdb2f36d1cbba4896f419c50be742 /sys/geom
parente168227ed2fb2c85707431a1167890c349968718 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/geom/geom.h4
-rw-r--r--sys/geom/geom_subr.c213
2 files changed, 215 insertions, 2 deletions
diff --git a/sys/geom/geom.h b/sys/geom/geom.h
index 715d9c7..76ebcb6 100644
--- a/sys/geom/geom.h
+++ b/sys/geom/geom.h
@@ -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) \
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 */
OpenPOWER on IntegriCloud