From e3804b55e4358cf5a235fa1ba32204af9f7046dd Mon Sep 17 00:00:00 2001
From: Kent Overstreet <kent.overstreet@linux.dev>
Date: Wed, 28 Jun 2023 19:53:05 -0400
Subject: [PATCH] bcachefs: bch2_version_to_text()

Add a new helper for printing out metadata versions in a standard
format.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
---
 fs/bcachefs/opts.c     |  5 -----
 fs/bcachefs/opts.h     |  1 -
 fs/bcachefs/recovery.c | 27 ++++++++++++++++-----------
 fs/bcachefs/super-io.c | 19 +++++++++++++++++--
 fs/bcachefs/super-io.h |  2 ++
 fs/bcachefs/super.c    |  3 ++-
 6 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c
index 04e2989cd6b3..a05c389830dc 100644
--- a/fs/bcachefs/opts.c
+++ b/fs/bcachefs/opts.c
@@ -11,11 +11,6 @@
 
 #define x(t, n) [n] = #t,
 
-const char * const bch2_metadata_versions[] = {
-	BCH_METADATA_VERSIONS()
-	NULL
-};
-
 const char * const bch2_error_actions[] = {
 	BCH_ERROR_ACTIONS()
 	NULL
diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h
index 719693b333da..e7cf7e92f3db 100644
--- a/fs/bcachefs/opts.h
+++ b/fs/bcachefs/opts.h
@@ -8,7 +8,6 @@
 #include <linux/sysfs.h>
 #include "bcachefs_format.h"
 
-extern const char * const bch2_metadata_versions[];
 extern const char * const bch2_error_actions[];
 extern const char * const bch2_sb_features[];
 extern const char * const bch2_sb_compat[];
diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c
index 16a99edb2ea8..b86442c7c912 100644
--- a/fs/bcachefs/recovery.c
+++ b/fs/bcachefs/recovery.c
@@ -1146,17 +1146,22 @@ int bch2_fs_recovery(struct bch_fs *c)
 		goto err;
 	}
 
-	if (!c->opts.nochanges) {
-		if (c->sb.version < bcachefs_metadata_required_upgrade_below) {
-			bch_info(c, "version %s (%u) prior to %s (%u), upgrade and fsck required",
-				 bch2_metadata_versions[c->sb.version],
-				 c->sb.version,
-				 bch2_metadata_versions[bcachefs_metadata_required_upgrade_below],
-				 bcachefs_metadata_required_upgrade_below);
-			c->opts.version_upgrade	= true;
-			c->opts.fsck		= true;
-			c->opts.fix_errors	= FSCK_OPT_YES;
-		}
+	if (!c->opts.nochanges &&
+	    c->sb.version < bcachefs_metadata_required_upgrade_below) {
+		struct printbuf buf = PRINTBUF;
+
+		prt_str(&buf, "version ");
+		bch2_version_to_text(&buf, c->sb.version);
+		prt_str(&buf, " prior to ");
+		bch2_version_to_text(&buf, bcachefs_metadata_required_upgrade_below);
+		prt_str(&buf, ", upgrade and fsck required");
+
+		bch_info(c, "%s", buf.buf);
+		printbuf_exit(&buf);
+
+		c->opts.version_upgrade	= true;
+		c->opts.fsck		= true;
+		c->opts.fix_errors	= FSCK_OPT_YES;
 	}
 
 	if (c->opts.fsck && c->opts.norecovery) {
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c
index d23ed9ec30f1..2237b1b94bbc 100644
--- a/fs/bcachefs/super-io.c
+++ b/fs/bcachefs/super-io.c
@@ -26,6 +26,21 @@
 static const struct blk_holder_ops bch2_sb_handle_bdev_ops = {
 };
 
+static const char * const bch2_metadata_versions[] = {
+#define x(t, n) [n] = #t,
+	BCH_METADATA_VERSIONS()
+#undef x
+};
+
+void bch2_version_to_text(struct printbuf *out, unsigned v)
+{
+	const char *str = v < ARRAY_SIZE(bch2_metadata_versions)
+		? bch2_metadata_versions[v]
+		: "(unknown version)";
+
+	prt_printf(out, "%u: %s", v, str);
+}
+
 const char * const bch2_sb_fields[] = {
 #define x(name, nr)	#name,
 	BCH_SB_FIELDS()
@@ -1510,12 +1525,12 @@ void bch2_sb_to_text(struct printbuf *out, struct bch_sb *sb,
 
 	prt_str(out, "Version:");
 	prt_tab(out);
-	prt_printf(out, "%s", bch2_metadata_versions[le16_to_cpu(sb->version)]);
+	bch2_version_to_text(out, le16_to_cpu(sb->version));
 	prt_newline(out);
 
 	prt_printf(out, "Oldest version on disk:");
 	prt_tab(out);
-	prt_printf(out, "%s", bch2_metadata_versions[le16_to_cpu(sb->version_min)]);
+	bch2_version_to_text(out, le16_to_cpu(sb->version_min));
 	prt_newline(out);
 
 	prt_printf(out, "Created:");
diff --git a/fs/bcachefs/super-io.h b/fs/bcachefs/super-io.h
index ab0ad3248e8f..4a193add3447 100644
--- a/fs/bcachefs/super-io.h
+++ b/fs/bcachefs/super-io.h
@@ -9,6 +9,8 @@
 
 #include <asm/byteorder.h>
 
+void bch2_version_to_text(struct printbuf *, unsigned);
+
 struct bch_sb_field *bch2_sb_field_get(struct bch_sb *, enum bch_sb_field_type);
 struct bch_sb_field *bch2_sb_field_resize(struct bch_sb_handle *,
 					  enum bch_sb_field_type, unsigned);
diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c
index 5b0c7dafae2d..62da48863ffa 100644
--- a/fs/bcachefs/super.c
+++ b/fs/bcachefs/super.c
@@ -877,7 +877,8 @@ static void print_mount_opts(struct bch_fs *c)
 	struct printbuf p = PRINTBUF;
 	bool first = true;
 
-	prt_printf(&p, "mounted version=%s", bch2_metadata_versions[c->sb.version]);
+	prt_str(&p, "mounted version ");
+	bch2_version_to_text(&p, c->sb.version);
 
 	if (c->opts.read_only) {
 		prt_str(&p, " opts=");