Index: share/man/man4/ddb.4 =================================================================== RCS file: /usr/repo/src/share/man/man4/ddb.4,v retrieving revision 1.31 diff -u -p -r1.31 ddb.4 --- share/man/man4/ddb.4 5 Sep 2006 12:17:53 -0000 1.31 +++ share/man/man4/ddb.4 5 Sep 2006 13:57:00 -0000 @@ -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 Index: sys/geom/geom.h =================================================================== RCS file: /usr/repo/src/sys/geom/geom.h,v retrieving revision 1.95 diff -u -p -r1.95 geom.h --- sys/geom/geom.h 12 Jul 2006 15:44:00 -0000 1.95 +++ sys/geom/geom.h 5 Sep 2006 13:52:56 -0000 @@ -241,8 +241,10 @@ void g_wither_geom(struct g_geom *gp, in 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) \ Index: sys/geom/geom_subr.c =================================================================== RCS file: /usr/repo/src/sys/geom/geom_subr.c,v retrieving revision 1.89 diff -u -p -r1.89 geom_subr.c --- sys/geom/geom_subr.c 10 Apr 2006 03:55:13 -0000 1.89 +++ sys/geom/geom_subr.c 5 Sep 2006 14:02:31 -0000 @@ -36,6 +36,8 @@ #include __FBSDID("$FreeBSD: src/sys/geom/geom_subr.c,v 1.89 2006/04/10 03:55:13 marcel Exp $"); +#include "opt_ddb.h" + #include #include #include @@ -53,6 +55,10 @@ __FBSDID("$FreeBSD: src/sys/geom/geom_su #include #include +#ifdef DDB +#include +#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_c 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,177 @@ g_valid_obj(void const *ptr) return(0); } #endif + +#ifdef DDB + +#define GPRINTF(...) do { \ + printf("%*s", indent, ""); \ + printf(__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) +{ + + GPRINTF("consumer: %p", cp); + if (indent == 0) { + GPRINTF(" class: %s (%p)", cp->geom->class->name, + cp->geom->class); + GPRINTF(" geom: %s (%p)", cp->geom->name, cp->geom); + } + if (cp->provider == NULL) + GPRINTF(" provider: none"); + else { + GPRINTF(" provider: %s (%p)", cp->provider->name, + cp->provider); + } + GPRINTF(" access: r%dw%de%d", cp->acr, cp->acw, cp->ace); + GPRINTF(" spoiled: %d", cp->spoiled); + GPRINTF(" nstart: %u", cp->nstart); + GPRINTF(" nend: %u", cp->nend); +} + +static void +db_show_geom_provider(int indent, struct g_provider *pp) +{ + struct g_consumer *cp; + char flags[64]; + + GPRINTF("provider: %s (%p)", pp->name, pp); + if (indent == 0) { + GPRINTF(" class: %s (%p)", pp->geom->class->name, + pp->geom->class); + GPRINTF(" geom: %s (%p)", pp->geom->name, pp->geom); + } + GPRINTF(" mediasize: %jd", (intmax_t)pp->mediasize); + GPRINTF(" sectorsize: %u", pp->sectorsize); + GPRINTF(" stripesize: %u", pp->stripesize); + GPRINTF(" stripeoffset: %u", pp->stripeoffset); + GPRINTF(" access: r%dw%de%d", pp->acr, pp->acw, pp->ace); + GPRINTF(" flags: %s (0x%04x)", + provider_flags_to_string(pp, flags, sizeof(flags)), pp->flags); + GPRINTF(" error: %d", pp->error); + GPRINTF(" nstart: %u", pp->nstart); + GPRINTF(" nend: %u", pp->nend); + if (LIST_EMPTY(&pp->consumers)) + GPRINTF(" consumers: none"); + else { + 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]; + + GPRINTF("geom: %s (%p)", gp->name, gp); + if (indent == 0) + GPRINTF(" class: %s (%p)", gp->class->name, gp->class); + GPRINTF(" flags: %s (0x%04x)", + geom_flags_to_string(gp, flags, sizeof(flags)), gp->flags); + GPRINTF(" rank: %d", gp->rank); + if (LIST_EMPTY(&gp->provider)) + GPRINTF(" providers: none"); + else { + LIST_FOREACH(pp, &gp->provider, provider) + db_show_geom_provider(indent + 2, pp); + } + if (LIST_EMPTY(&gp->consumer)) + GPRINTF(" consumers: none"); + else { + 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 ADDFLAG + +#endif /* DDB */