Index: sbin/geom/core/geom.8 =================================================================== --- sbin/geom/core/geom.8 +++ sbin/geom/core/geom.8 @@ -52,6 +52,11 @@ .Ar class .Cm unload .Op Fl v +.Nm +.Fl p +.Ar provider-name +.Nm +.Fl t .Sh DESCRIPTION The .Nm @@ -101,6 +106,15 @@ Unload the kernel module which implements the given class. This command is only available if the given class is loaded as a kernel module. +.El +.Pp +Additional options include: +.Bl -tag -width ".Cm status" +.It Fl p +Print detailed information about geom which provides +.Ar provider-name . +.It Fl t +Print provider-consumer relationship as a tree. .El .Pp Class-specific commands are implemented as shared libraries which Index: sbin/geom/core/geom.c =================================================================== --- sbin/geom/core/geom.c +++ sbin/geom/core/geom.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,7 @@ #define GEOM_CLASS_CMDS 0x01 #define GEOM_STD_CMDS 0x02 static struct g_command *find_command(const char *cmdstr, int flags); +static void list_one_geom_by_provider(const char *provider_name); static int std_available(const char *name); static void std_help(struct gctl_req *req, unsigned flags); @@ -146,6 +148,8 @@ if (class_name == NULL) { fprintf(stderr, "usage: geom [options]\n"); + fprintf(stderr, " geom -p \n"); + fprintf(stderr, " geom -t\n"); exit(EXIT_FAILURE); } else { struct g_command *cmd; @@ -650,10 +654,118 @@ usage(); } +static struct ggeom * +find_geom_by_provider(struct gmesh *mesh, const char *name) +{ + struct gclass *classp; + struct ggeom *gp; + struct gprovider *pp; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + if (strcmp(pp->lg_name, name) == 0) + return gp; + } + } + } + + return (NULL); +} + +static void +show_tree_geom(struct gmesh *mesh, struct ggeom *gp, int indent) +{ + struct gclass *classp2; + struct ggeom *gp2; + struct gconsumer *cp2; + struct gprovider *pp; + int width; + + width = 20 - indent; + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + printf("%*s%-*.*s\t%-*.*s\t%s\n", indent, "", + width, width, pp->lg_name, + width, width, gp->lg_name, + gp->lg_class->lg_name); + + LIST_FOREACH(classp2, &mesh->lg_class, lg_class) { + LIST_FOREACH(gp2, &classp2->lg_geom, lg_geom) { + LIST_FOREACH(cp2, &gp2->lg_consumer, lg_consumer) { + if (pp == cp2->lg_provider) + show_tree_geom(mesh, gp2, indent + 2); + } + } + } + } +} + +static void +show_tree(void) +{ + struct gmesh mesh; + struct gclass *classp; + struct ggeom *gp; + int error; + + error = geom_gettree(&mesh); + if (error != 0) + errc(EXIT_FAILURE, error, "Cannot get GEOM tree"); + + printf("%-*.*s\t%-*.*s\t%s\n", 20, 20, "Provider", 20, 20, "Geom", "Class"); + + LIST_FOREACH(classp, &mesh.lg_class, lg_class) { + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + if (!LIST_EMPTY(&gp->lg_consumer)) + continue; + show_tree_geom(&mesh, gp, 0); + } + } +} + int main(int argc, char *argv[]) { + char *provider_name = NULL; + bool tflag = false; + int ch; + if (strcmp(getprogname(), "geom") == 0) { + while ((ch = getopt(argc, argv, "hp:t")) != -1) { + switch (ch) { + case 'p': + provider_name = strdup(optarg); + if (provider_name == NULL) + err(1, "strdup"); + break; + case 't': + tflag = true; + break; + case 'h': + default: + usage(); + } + } + + /* + * Don't adjust argc and argv, it would break get_class(). + */ + } + + if (tflag && provider_name != NULL) + errx(EXIT_FAILURE, "at most one of -P and -t may be specified"); + + if (provider_name) { + list_one_geom_by_provider(provider_name); + return (0); + } + + if (tflag) { + show_tree(); + return (0); + } + get_class(&argc, &argv); run_command(argc, argv); /* NOTREACHED */ @@ -765,6 +877,25 @@ } } printf("\n"); +} + +static void +list_one_geom_by_provider(const char *provider_name) +{ + struct gmesh mesh; + struct ggeom *gp; + int error; + + error = geom_gettree(&mesh); + if (error != 0) + errc(EXIT_FAILURE, error, "Cannot get GEOM tree"); + + gp = find_geom_by_provider(&mesh, provider_name); + if (gp == NULL) + errx(EXIT_FAILURE, "Cannot find provider '%s'", provider_name); + + printf("Geom class: %s\n", gp->lg_class->lg_name); + list_one_geom(gp); } static void