From cd85e0d443a40fe5e0814023e1c976127b761351 Mon Sep 17 00:00:00 2001
From: WHR <whr@rivoreo.one>
Date: Wed, 1 May 2024 00:28:32 +0800
Subject: [PATCH] zfs: recognize zpools formatted with features support

Currently no features are implemented, only the zpool version 5000 that
indicating the features support, is recognized. Since it is possible for
OpenZFS to create a pool with features support enabled, but without
enabling any actual feature, this change enables U-Boot to read such
pools.

Signed-off-by: WHR <msl0000023508@gmail.com>
---
 fs/zfs/zfs.c      | 18 +++++++++++-------
 include/zfs/zfs.h |  1 +
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/fs/zfs/zfs.c b/fs/zfs/zfs.c
index c44e7ece5d..06221e68b3 100644
--- a/fs/zfs/zfs.c
+++ b/fs/zfs/zfs.c
@@ -333,6 +333,12 @@ vdev_uberblock_compare(uberblock_t *ub1, uberblock_t *ub2)
 	return 0;
 }
 
+static inline int
+is_supported_spa_version(uint64_t version) {
+	return version == FEATURES_SUPPORTED_SPA_VERSION ||
+		(version > 0 && version <= SPA_VERSION);
+}
+
 /*
  * Three pieces of information are needed to verify an uberblock: the magic
  * number, the version number, and the checksum.
@@ -354,14 +360,12 @@ uberblock_verify(uberblock_t *uber, int offset, struct zfs_data *data)
 		return ZFS_ERR_BAD_FS;
 	}
 
-	if (zfs_to_cpu64(uber->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC
-		&& zfs_to_cpu64(uber->ub_version, LITTLE_ENDIAN) > 0
-		&& zfs_to_cpu64(uber->ub_version, LITTLE_ENDIAN) <= SPA_VERSION)
+	if (zfs_to_cpu64(uber->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC &&
+		is_supported_spa_version(zfs_to_cpu64(uber->ub_version, LITTLE_ENDIAN)))
 		endian = LITTLE_ENDIAN;
 
-	if (zfs_to_cpu64(uber->ub_magic, BIG_ENDIAN) == UBERBLOCK_MAGIC
-		&& zfs_to_cpu64(uber->ub_version, BIG_ENDIAN) > 0
-		&& zfs_to_cpu64(uber->ub_version, BIG_ENDIAN) <= SPA_VERSION)
+	if (zfs_to_cpu64(uber->ub_magic, BIG_ENDIAN) == UBERBLOCK_MAGIC &&
+		is_supported_spa_version(zfs_to_cpu64(uber->ub_version, BIG_ENDIAN)))
 		endian = BIG_ENDIAN;
 
 	if (endian == UNKNOWN_ENDIAN) {
@@ -1787,7 +1791,7 @@ check_pool_label(struct zfs_data *data)
 		return ZFS_ERR_BAD_FS;
 	}
 
-	if (version > SPA_VERSION) {
+	if (!is_supported_spa_version(version)) {
 		free(nvlist);
 		printf("SPA version too new %llu > %llu\n",
 			   (unsigned long long) version,
diff --git a/include/zfs/zfs.h b/include/zfs/zfs.h
index 17b93c10c8..72d87452dd 100644
--- a/include/zfs/zfs.h
+++ b/include/zfs/zfs.h
@@ -15,6 +15,7 @@
  * On-disk version number.
  */
 #define	SPA_VERSION			28ULL
+#define	FEATURES_SUPPORTED_SPA_VERSION	5000ULL
 
 /*
  * The following are configuration names used in the nvlist describing a pool's
-- 
2.39.5