From owner-svn-src-all@freebsd.org Fri Sep 14 15:29:46 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4945A108BD87; Fri, 14 Sep 2018 15:29:46 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id C2C34865FD; Fri, 14 Sep 2018 15:29:45 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id BB52E26396; Fri, 14 Sep 2018 15:29:45 +0000 (UTC) (envelope-from trasz@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w8EFTjGY023912; Fri, 14 Sep 2018 15:29:45 GMT (envelope-from trasz@FreeBSD.org) Received: (from trasz@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w8EFTjPP023911; Fri, 14 Sep 2018 15:29:45 GMT (envelope-from trasz@FreeBSD.org) Message-Id: <201809141529.w8EFTjPP023911@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: trasz set sender to trasz@FreeBSD.org using -f From: Edward Tomasz Napierala Date: Fri, 14 Sep 2018 15:29:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r338684 - head/sbin/geom/core X-SVN-Group: head X-SVN-Commit-Author: trasz X-SVN-Commit-Paths: head/sbin/geom/core X-SVN-Commit-Revision: 338684 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Sep 2018 15:29:46 -0000 Author: trasz Date: Fri Sep 14 15:29:45 2018 New Revision: 338684 URL: https://svnweb.freebsd.org/changeset/base/338684 Log: Add the "-t" option to geom(8) utility, to display geoms hierarchy. Sample output: % geom -t Geom Class Provider da0 DISK da0 da0 PART da0s1 da0s1 PART da0s1a ffs.da0s1a VFS da0s1a DEV da0s1 DEV da0 DEV da1 DISK da1 swap SWAP da1 DEV cd0 DISK cd0 cd0 DEV Reviewed by: oshogbo Approved by: re (kib) MFC after: 2 weeks Relnotes: yes Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D17151 Modified: head/sbin/geom/core/geom.8 head/sbin/geom/core/geom.c Modified: head/sbin/geom/core/geom.8 ============================================================================== --- head/sbin/geom/core/geom.8 Fri Sep 14 15:29:35 2018 (r338683) +++ head/sbin/geom/core/geom.8 Fri Sep 14 15:29:45 2018 (r338684) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 13, 2018 +.Dd September 14, 2018 .Dt GEOM 8 .Os .Sh NAME @@ -55,6 +55,8 @@ .Nm .Fl p .Ar provider-name +.Nm +.Fl t .Sh DESCRIPTION The .Nm @@ -111,6 +113,8 @@ Additional options include: .It Fl p Ar provider-name Print detailed information about the geom which provides .Ar provider-name . +.It Fl t +Display geoms hierarchy as a tree. .El .Pp Class-specific commands are implemented as shared libraries which Modified: head/sbin/geom/core/geom.c ============================================================================== --- head/sbin/geom/core/geom.c Fri Sep 14 15:29:35 2018 (r338683) +++ head/sbin/geom/core/geom.c Fri Sep 14 15:29:45 2018 (r338684) @@ -66,8 +66,11 @@ static uint32_t *version = NULL; static int verbose = 0; static struct g_command *class_commands = NULL; -#define GEOM_CLASS_CMDS 0x01 -#define GEOM_STD_CMDS 0x02 +#define GEOM_CLASS_CMDS 0x01 +#define GEOM_STD_CMDS 0x02 + +#define GEOM_CLASS_WIDTH 10 + 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); @@ -149,6 +152,7 @@ usage(void) 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; @@ -672,22 +676,142 @@ find_geom_by_provider(struct gmesh *mesh, const char * return (NULL); } +static int +compute_tree_width_geom(struct gmesh *mesh, struct ggeom *gp, int indent) +{ + struct gclass *classp2; + struct ggeom *gp2; + struct gconsumer *cp2; + struct gprovider *pp; + int max_width, width; + + max_width = width = indent + strlen(gp->lg_name); + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + 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) + continue; + width = compute_tree_width_geom(mesh, + gp2, indent + 2); + if (width > max_width) + max_width = width; + } + } + } + } + + return (max_width); +} + +static int +compute_tree_width(struct gmesh *mesh) +{ + struct gclass *classp; + struct ggeom *gp; + int max_width, width; + + max_width = width = 0; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) { + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + if (!LIST_EMPTY(&gp->lg_consumer)) + continue; + width = compute_tree_width_geom(mesh, gp, 0); + if (width > max_width) + max_width = width; + } + } + + return (max_width); +} + +static void +show_tree_geom(struct gmesh *mesh, struct ggeom *gp, int indent, int width) +{ + struct gclass *classp2; + struct ggeom *gp2; + struct gconsumer *cp2; + struct gprovider *pp; + + if (LIST_EMPTY(&gp->lg_provider)) { + printf("%*s%-*.*s %-*.*s\n", indent, "", + width - indent, width - indent, gp->lg_name, + GEOM_CLASS_WIDTH, GEOM_CLASS_WIDTH, gp->lg_class->lg_name); + return; + } + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + printf("%*s%-*.*s %-*.*s %s\n", indent, "", + width - indent, width - indent, gp->lg_name, + GEOM_CLASS_WIDTH, GEOM_CLASS_WIDTH, gp->lg_class->lg_name, + pp->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) + continue; + show_tree_geom(mesh, gp2, + indent + 2, width); + } + } + } + } +} + +static void +show_tree(void) +{ + struct gmesh mesh; + struct gclass *classp; + struct ggeom *gp; + int error, width; + + error = geom_gettree(&mesh); + if (error != 0) + errc(EXIT_FAILURE, error, "Cannot get GEOM tree"); + + width = compute_tree_width(&mesh); + + printf("%-*.*s %-*.*s %s\n", + width, width, "Geom", + GEOM_CLASS_WIDTH, GEOM_CLASS_WIDTH, "Class", + "Provider"); + + 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, width); + } + } +} + int main(int argc, char *argv[]) { char *provider_name; + bool tflag; int ch; provider_name = NULL; + tflag = false; if (strcmp(getprogname(), "geom") == 0) { - while ((ch = getopt(argc, argv, "hp:")) != -1) { + 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(); @@ -699,8 +823,18 @@ main(int argc, char *argv[]) */ } + if (tflag && provider_name != NULL) { + errx(EXIT_FAILURE, + "At most one of -P and -t may be specified."); + } + if (provider_name != NULL) { list_one_geom_by_provider(provider_name); + return (0); + } + + if (tflag) { + show_tree(); return (0); }