xfs_db: report absolute maxlevels for each btree type

Augment the xfs_db btheight command so that the debugger can display the
absolute maximum btree height for each btree type.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
diff --git a/db/btheight.c b/db/btheight.c
index 0e6fa58..7e8f586 100644
--- a/db/btheight.c
+++ b/db/btheight.c
@@ -14,16 +14,17 @@
 
 struct btmap {
 	const char	*tag;
+	xfs_btnum_t	btnum;
 	unsigned int	(*maxrecs)(struct xfs_mount *mp, unsigned int blocklen,
 				   bool leaf);
 } maps[] = {
-	{"bnobt", libxfs_allocbt_maxrecs},
-	{"cntbt", libxfs_allocbt_maxrecs},
-	{"inobt", libxfs_inobt_maxrecs},
-	{"finobt", libxfs_inobt_maxrecs},
-	{"bmapbt", libxfs_bmbt_maxrecs},
-	{"refcountbt", libxfs_refcountbt_maxrecs},
-	{"rmapbt", libxfs_rmapbt_maxrecs},
+	{"bnobt",	XFS_BTNUM_BNO,		libxfs_allocbt_maxrecs},
+	{"cntbt",	XFS_BTNUM_CNT,		libxfs_allocbt_maxrecs},
+	{"inobt",	XFS_BTNUM_INO,		libxfs_inobt_maxrecs},
+	{"finobt",	XFS_BTNUM_FINO,		libxfs_inobt_maxrecs},
+	{"bmapbt",	XFS_BTNUM_BMAP,		libxfs_bmbt_maxrecs},
+	{"refcountbt",	XFS_BTNUM_REFC,		libxfs_refcountbt_maxrecs},
+	{"rmapbt",	XFS_BTNUM_RMAP,		libxfs_rmapbt_maxrecs},
 };
 
 static void
@@ -45,6 +46,7 @@
 "   -n -- Number of records we want to store.\n"
 "   -w max -- Show only the best case scenario.\n"
 "   -w min -- Show only the worst case scenario.\n"
+"   -w absmax -- Print the maximum possible btree height for all filesystems.\n"
 "\n"
 " Supported btree types:\n"
 "   all "
@@ -222,6 +224,23 @@
 #define REPORT_DEFAULT	(-1U)
 #define REPORT_MAX	(1 << 0)
 #define REPORT_MIN	(1 << 1)
+#define REPORT_ABSMAX	(1 << 2)
+
+static void
+report_absmax(const char *tag)
+{
+	struct btmap	*m;
+	int		i;
+
+	for (i = 0, m = maps; i < ARRAY_SIZE(maps); i++, m++) {
+		if (!strcmp(m->tag, tag)) {
+			printf("%s: %u\n", tag,
+					libxfs_btree_absolute_maxlevels(m->btnum));
+			return;
+		}
+	}
+	printf(_("%s: Don't know how to report max height.\n"), tag);
+}
 
 static void
 report(
@@ -233,6 +252,11 @@
 	unsigned int		records_per_block[2];
 	int			ret;
 
+	if (report_what == REPORT_ABSMAX) {
+		report_absmax(tag);
+		return;
+	}
+
 	ret = construct_records_per_block(tag, blocksize, records_per_block);
 	if (ret)
 		return;
@@ -334,6 +358,8 @@
 				report_what = REPORT_MIN;
 			else if (!strcmp(optarg, "max"))
 				report_what = REPORT_MAX;
+			else if (!strcmp(optarg, "absmax"))
+				report_what = REPORT_ABSMAX;
 			else {
 				btheight_help();
 				return 0;
@@ -345,20 +371,20 @@
 		}
 	}
 
-	if (nr_records == 0) {
+	if (report_what != REPORT_ABSMAX && nr_records == 0) {
 		fprintf(stderr,
 _("Number of records must be greater than zero.\n"));
 		return 0;
 	}
 
-	if (blocksize > INT_MAX) {
+	if (report_what != REPORT_ABSMAX && blocksize > INT_MAX) {
 		fprintf(stderr,
 _("The largest block size this command will consider is %u bytes.\n"),
 			INT_MAX);
 		return 0;
 	}
 
-	if (blocksize < 128) {
+	if (report_what != REPORT_ABSMAX && blocksize < 128) {
 		fprintf(stderr,
 _("The smallest block size this command will consider is 128 bytes.\n"));
 		return 0;
diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index 55dcede..8638445 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -48,6 +48,7 @@
 #define xfs_bmbt_stage_cursor		libxfs_bmbt_stage_cursor
 #define xfs_bmdr_maxrecs		libxfs_bmdr_maxrecs
 
+#define xfs_btree_absolute_maxlevels	libxfs_btree_absolute_maxlevels
 #define xfs_btree_bload			libxfs_btree_bload
 #define xfs_btree_bload_compute_geometry libxfs_btree_bload_compute_geometry
 #define xfs_btree_del_cursor		libxfs_btree_del_cursor
diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
index 307f4a0..a62e2c4 100644
--- a/man/man8/xfs_db.8
+++ b/man/man8/xfs_db.8
@@ -402,7 +402,7 @@
 Dump all keys and pointers in intermediate btree nodes, and all records in leaf btree nodes.
 .RE
 .TP
-.BI "btheight [\-b " blksz "] [\-n " recs "] [\-w " max "|\-w " min "] btree types..."
+.BI "btheight [\-b " blksz "] [\-n " recs "] [\-w " max "|" min "|" absmax "] btree types..."
 For a given number of btree records and a btree type, report the number of
 records and blocks for each level of the btree, and the total number of blocks.
 The btree type must be given after the options.
@@ -435,6 +435,9 @@
 is used to specify the number of records to store.
 This argument is required.
 .TP
+.B \-w absmax
+shows the maximum possible height for the given btree types.
+.TP
 .B \-w max
 shows only the best case scenario, which is when the btree blocks are
 maximally loaded.