dcavalca / rpms / util-linux

Forked from rpms/util-linux 2 years ago
Clone
64664a
From a0e00751052b06508f6cfe4a434ebf2e1a04bf07 Mon Sep 17 00:00:00 2001
64664a
From: Michal Humpula <michal.humpula@hudrydum.cz>
64664a
Date: Wed, 25 Feb 2015 20:25:05 +0100
64664a
Subject: [PATCH 108/116] blkid: make zfs detection more robust
64664a
64664a
Try to use all the possible uberblock locations.
64664a
64664a
Upstream: https://github.com/karelzak/util-linux/commit/5dd705ba65dc80cf8630b3b1b4f3a1ba153e7eec
64664a
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1392661
64664a
Signed-off-by: Karel Zak <kzak@redhat.com>
64664a
---
64664a
 libblkid/src/superblocks/zfs.c | 42 +++++++++++++++++++++++++++---------------
64664a
 1 file changed, 27 insertions(+), 15 deletions(-)
64664a
64664a
diff --git a/libblkid/src/superblocks/zfs.c b/libblkid/src/superblocks/zfs.c
64664a
index 86da59d..4a64a03 100644
64664a
--- a/libblkid/src/superblocks/zfs.c
64664a
+++ b/libblkid/src/superblocks/zfs.c
64664a
@@ -19,6 +19,7 @@
64664a
 #define VDEV_LABEL_UBERBLOCK	(128 * 1024ULL)
64664a
 #define VDEV_LABEL_NVPAIR	( 16 * 1024ULL)
64664a
 #define VDEV_LABEL_SIZE		(256 * 1024ULL)
64664a
+#define UBERBLOCK_SIZE		1024ULL
64664a
 
64664a
 /* #include <sys/uberblock_impl.h> */
64664a
 #define UBERBLOCK_MAGIC         0x00bab10c              /* oo-ba-bloc!  */
64664a
@@ -31,7 +32,7 @@ struct zfs_uberblock {
64664a
 	char		ub_rootbp;	/* MOS objset_phys_t		*/
64664a
 } __attribute__((packed));
64664a
 
64664a
-#define ZFS_TRIES	64
64664a
+#define ZFS_TRIES	512
64664a
 #define ZFS_WANT	 4
64664a
 
64664a
 #define DATA_TYPE_UINT64 8
64664a
@@ -162,11 +163,10 @@ static void zfs_extract_guid_name(blkid_probe pr, loff_t offset)
64664a
 #define zdebug(fmt, ...)	do {} while(0)
64664a
 /*#define zdebug(fmt, a...)	fprintf(stderr, fmt, ##a)*/
64664a
 
64664a
-/* ZFS has 128x1kB host-endian root blocks, stored in 2 areas at the start
64664a
- * of the disk, and 2 areas at the end of the disk.  Check only some of them...
64664a
- * #4 (@ 132kB) is the first one written on a new filesystem. */
64664a
-static int probe_zfs(blkid_probe pr,
64664a
-		const struct blkid_idmag *mag __attribute__((__unused__)))
64664a
+/* ZFS has 128x1kB host-endian root blocks, stored in 2 areas (labels)
64664a
+ * at the start of the disk, and 2 areas at the end of the disk.
64664a
+ */
64664a
+static int probe_zfs(blkid_probe pr, const struct blkid_idmag *mag)
64664a
 {
64664a
 	uint64_t swab_magic = swab64(UBERBLOCK_MAGIC);
64664a
 	struct zfs_uberblock *ub;
64664a
@@ -174,15 +174,29 @@ static int probe_zfs(blkid_probe pr,
64664a
 	loff_t offset, ub_offset = 0;
64664a
 	int tried;
64664a
 	int found;
64664a
+	loff_t blk_align = (pr->size % (256 * 1024ULL));
64664a
 
64664a
 	zdebug("probe_zfs\n");
64664a
-	/* Look for at least 4 uberblocks to ensure a positive match */
64664a
+	/* Look for at least 4 uberblocks to ensure a positive match.
64664a
+	   Begin with Label 0 (L0) at the start of the block device. */
64664a
 	for (tried = found = 0, offset = VDEV_LABEL_UBERBLOCK;
64664a
-	     tried < ZFS_TRIES && found < ZFS_WANT;
64664a
-	     tried++, offset += 4096) {
64664a
-		/* also try the second uberblock copy */
64664a
-		if (tried == (ZFS_TRIES / 2))
64664a
+	     found < ZFS_WANT && tried < ZFS_TRIES;
64664a
+	     tried++, offset += UBERBLOCK_SIZE)
64664a
+	{
64664a
+		/* Leave L0 to try other labels */
64664a
+		switch(tried) {
64664a
+		case 128: // jump to L1, just after L0
64664a
 			offset = VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK;
64664a
+			break;
64664a
+		case 256: // jump to L2 near the far end of the block device
64664a
+			offset = pr->size - 2 * VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK - blk_align;
64664a
+			zdebug("probe_zfs: l2 offset %llu\n", offset >> 10);
64664a
+			break;
64664a
+		case 384: // jump to L3 at the furthest end of the block device
64664a
+			offset = pr->size - VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK - blk_align;
64664a
+			zdebug("probe_zfs: l3 offset %llu\n", offset >> 10);
64664a
+			break;
64664a
+		}
64664a
 
64664a
 		ub = (struct zfs_uberblock *)
64664a
 			blkid_probe_get_buffer(pr, offset,
64664a
@@ -193,15 +207,14 @@ static int probe_zfs(blkid_probe pr,
64664a
 		if (ub->ub_magic == UBERBLOCK_MAGIC) {
64664a
 			ub_offset = offset;
64664a
 			found++;
64664a
+			zdebug("probe_zfs: found little-endian uberblock at %llu\n", offset >> 10);
64664a
 		}
64664a
 
64664a
 		if ((swab_endian = (ub->ub_magic == swab_magic))) {
64664a
 			ub_offset = offset;
64664a
 			found++;
64664a
+			zdebug("probe_zfs: found big-endian uberblock at %llu\n", offset >> 10);
64664a
 		}
64664a
-
64664a
-		zdebug("probe_zfs: found %s-endian uberblock at %llu\n",
64664a
-		       swab_endian ? "big" : "little", offset >> 10);
64664a
 	}
64664a
 
64664a
 	if (found < 4)
64664a
@@ -230,4 +243,3 @@ const struct blkid_idinfo zfs_idinfo =
64664a
 	.minsz		= 64 * 1024 * 1024,
64664a
 	.magics		= BLKID_NONE_MAGIC
64664a
 };
64664a
-
64664a
-- 
64664a
2.9.3
64664a