changeset 13421:a4721c685d96

1303 Grub should support large sector disks Reviewed by: Garrett D'Amore <garrett@nexenta.com> Reviewed by: Albert Lee <trisk@opensolaris.org> Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Approved by: Garrett D'Amore <garrett@nexenta.com>
author Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
date Mon, 08 Aug 2011 15:10:27 -0700
parents b33ae82cafa3
children c9ad235c2ec1
files usr/src/grub/grub-0.97/stage2/fsys_zfs.c usr/src/grub/grub-0.97/stage2/fsys_zfs.h usr/src/grub/grub-0.97/stage2/zfs-include/vdev_impl.h
diffstat 3 files changed, 65 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/grub/grub-0.97/stage2/fsys_zfs.c	Wed Jul 27 20:30:31 2011 +0100
+++ b/usr/src/grub/grub-0.97/stage2/fsys_zfs.c	Mon Aug 08 15:10:27 2011 -0700
@@ -225,10 +225,8 @@
  *    -1 - Failure
  */
 static int
-uberblock_verify(uberblock_phys_t *ub, uint64_t offset)
+uberblock_verify(uberblock_t *uber, uint64_t ub_size, uint64_t offset)
 {
-
-	uberblock_t *uber = &ub->ubp_uberblock;
 	blkptr_t bp;
 
 	BP_ZERO(&bp);
@@ -236,7 +234,7 @@
 	BP_SET_BYTEORDER(&bp, ZFS_HOST_BYTEORDER);
 	ZIO_SET_CHECKSUM(&bp.blk_cksum, offset, 0, 0, 0);
 
-	if (zio_checksum_verify(&bp, (char *)ub, UBERBLOCK_SIZE) != 0)
+	if (zio_checksum_verify(&bp, (char *)uber, ub_size) != 0)
 		return (-1);
 
 	if (uber->ub_magic == UBERBLOCK_MAGIC &&
@@ -252,25 +250,28 @@
  *    Success - Pointer to the best uberblock.
  *    Failure - NULL
  */
-static uberblock_phys_t *
-find_bestub(uberblock_phys_t *ub_array, uint64_t sector)
+static uberblock_t *
+find_bestub(char *ub_array, uint64_t ashift, uint64_t sector)
 {
-	uberblock_phys_t *ubbest = NULL;
-	uint64_t offset;
+	uberblock_t *ubbest = NULL;
+	uberblock_t *ubnext;
+	uint64_t offset, ub_size;
 	int i;
 
-	for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++) {
+	ub_size = VDEV_UBERBLOCK_SIZE(ashift);
+
+	for (i = 0; i < VDEV_UBERBLOCK_COUNT(ashift); i++) {
+		ubnext = (uberblock_t *)ub_array;
+		ub_array += ub_size;
 		offset = (sector << SPA_MINBLOCKSHIFT) +
-		    VDEV_UBERBLOCK_OFFSET(i);
-		if (uberblock_verify(&ub_array[i], offset) == 0) {
-			if (ubbest == NULL) {
-				ubbest = &ub_array[i];
-			} else if (vdev_uberblock_compare(
-			    &(ub_array[i].ubp_uberblock),
-			    &(ubbest->ubp_uberblock)) > 0) {
-				ubbest = &ub_array[i];
-			}
-		}
+		    VDEV_UBERBLOCK_OFFSET(ashift, i);
+
+		if (uberblock_verify(ubnext, ub_size, offset) != 0)
+			continue;
+
+		if (ubbest == NULL ||
+		    vdev_uberblock_compare(ubnext, ubbest) > 0)
+			ubbest = ubnext;
 	}
 
 	return (ubbest);
@@ -1209,7 +1210,7 @@
  */
 int
 check_pool_label(uint64_t sector, char *stack, char *outdevid,
-    char *outpath, uint64_t *outguid)
+    char *outpath, uint64_t *outguid, uint64_t *outashift)
 {
 	vdev_phys_t *vdev;
 	uint64_t pool_state, txg = 0;
@@ -1259,6 +1260,9 @@
 	if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_GUID, &diskguid,
 	    DATA_TYPE_UINT64, NULL))
 		return (ERR_FSYS_CORRUPT);
+	if (nvlist_lookup_value(nv, ZPOOL_CONFIG_ASHIFT, outashift,
+	    DATA_TYPE_UINT64, NULL) != 0)
+		return (ERR_FSYS_CORRUPT);
 	if (vdev_get_bootpath(nv, diskguid, outdevid, outpath, 0))
 		return (ERR_NO_BOOTPATH);
 	if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_POOL_GUID, outguid,
@@ -1278,13 +1282,13 @@
 int
 zfs_mount(void)
 {
-	char *stack;
+	char *stack, *ub_array;
 	int label = 0;
-	uberblock_phys_t *ub_array, *ubbest;
+	uberblock_t *ubbest;
 	objset_phys_t *osp;
 	char tmp_bootpath[MAXNAMELEN];
 	char tmp_devid[MAXNAMELEN];
-	uint64_t tmp_guid;
+	uint64_t tmp_guid, ashift;
 	uint64_t adjpl = (uint64_t)part_length << SPA_MINBLOCKSHIFT;
 	int err = errnum; /* preserve previous errnum state */
 
@@ -1296,7 +1300,7 @@
 
 	stackbase = ZFS_SCRATCH;
 	stack = stackbase;
-	ub_array = (uberblock_phys_t *)stack;
+	ub_array = stack;
 	stack += VDEV_UBERBLOCK_RING;
 
 	osp = (objset_phys_t *)stack;
@@ -1322,39 +1326,34 @@
 
 		/* Read in the uberblock ring (128K). */
 		if (devread(sector  +
-		    ((VDEV_SKIP_SIZE + VDEV_PHYS_SIZE) >>
-		    SPA_MINBLOCKSHIFT), 0, VDEV_UBERBLOCK_RING,
-		    (char *)ub_array) == 0)
+		    ((VDEV_SKIP_SIZE + VDEV_PHYS_SIZE) >> SPA_MINBLOCKSHIFT),
+		    0, VDEV_UBERBLOCK_RING, ub_array) == 0)
+			continue;
+
+		if (check_pool_label(sector, stack, tmp_devid,
+		    tmp_bootpath, &tmp_guid, &ashift))
 			continue;
 
-		if ((ubbest = find_bestub(ub_array, sector)) != NULL &&
-		    zio_read(&ubbest->ubp_uberblock.ub_rootbp, osp, stack)
-		    == 0) {
-
-			VERIFY_OS_TYPE(osp, DMU_OST_META);
+		if (pool_guid == 0)
+			pool_guid = tmp_guid;
 
-			if (check_pool_label(sector, stack, tmp_devid,
-			    tmp_bootpath, &tmp_guid))
-				continue;
-			if (pool_guid == 0)
-				pool_guid = tmp_guid;
+		if ((ubbest = find_bestub(ub_array, ashift, sector)) == NULL ||
+		    zio_read(&ubbest->ub_rootbp, osp, stack) != 0)
+			continue;
+
+		VERIFY_OS_TYPE(osp, DMU_OST_META);
 
-			if (find_best_root && ((pool_guid != tmp_guid) ||
-			    vdev_uberblock_compare(&ubbest->ubp_uberblock,
-			    &(current_uberblock)) <= 0))
-				continue;
+		if (find_best_root && ((pool_guid != tmp_guid) ||
+		    vdev_uberblock_compare(ubbest, &(current_uberblock)) <= 0))
+			continue;
 
-			/* Got the MOS. Save it at the memory addr MOS. */
-			grub_memmove(MOS, &osp->os_meta_dnode, DNODE_SIZE);
-			grub_memmove(&current_uberblock,
-			    &ubbest->ubp_uberblock, sizeof (uberblock_t));
-			grub_memmove(current_bootpath, tmp_bootpath,
-			    MAXNAMELEN);
-			grub_memmove(current_devid, tmp_devid,
-			    grub_strlen(tmp_devid));
-			is_zfs_mount = 1;
-			return (1);
-		}
+		/* Got the MOS. Save it at the memory addr MOS. */
+		grub_memmove(MOS, &osp->os_meta_dnode, DNODE_SIZE);
+		grub_memmove(&current_uberblock, ubbest, sizeof (uberblock_t));
+		grub_memmove(current_bootpath, tmp_bootpath, MAXNAMELEN);
+		grub_memmove(current_devid, tmp_devid, grub_strlen(tmp_devid));
+		is_zfs_mount = 1;
+		return (1);
 	}
 
 	/*
--- a/usr/src/grub/grub-0.97/stage2/fsys_zfs.h	Wed Jul 27 20:30:31 2011 +0100
+++ b/usr/src/grub/grub-0.97/stage2/fsys_zfs.h	Mon Aug 08 15:10:27 2011 -0700
@@ -95,27 +95,8 @@
 #define	BSWAP_64(x)	((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32))
 #define	P2ROUNDUP(x, align)	(-(-(x) & -(align)))
 
-/*
- * XXX Match these macro up with real zfs once we have nvlist support so that we
- * can support large sector disks.
- */
-#define	UBERBLOCK_SIZE		(1ULL << UBERBLOCK_SHIFT)
-#undef	offsetof
-#define	offsetof(t, m)   ((int)&(((t *)0)->m))
-#define	VDEV_UBERBLOCK_SHIFT	UBERBLOCK_SHIFT
-#define	VDEV_UBERBLOCK_OFFSET(n) \
-offsetof(vdev_label_t, vl_uberblock[(n) << VDEV_UBERBLOCK_SHIFT])
-
 typedef struct uberblock uberblock_t;
 
-/* XXX Uberblock_phys_t is no longer in the kernel zfs */
-typedef struct uberblock_phys {
-	uberblock_t	ubp_uberblock;
-	char		ubp_pad[UBERBLOCK_SIZE - sizeof (uberblock_t) -
-				sizeof (zio_eck_t)];
-	zio_eck_t	ubp_zec;
-} uberblock_phys_t;
-
 /*
  * Macros to get fields in a bp or DVA.
  */
--- a/usr/src/grub/grub-0.97/stage2/zfs-include/vdev_impl.h	Wed Jul 27 20:30:31 2011 +0100
+++ b/usr/src/grub/grub-0.97/stage2/zfs-include/vdev_impl.h	Mon Aug 08 15:10:27 2011 -0700
@@ -24,12 +24,26 @@
 #ifndef _SYS_VDEV_IMPL_H
 #define	_SYS_VDEV_IMPL_H
 
+/* helper macros */
+#undef	offsetof
+#define	offsetof(t, m)		((int)&(((t *)0)->m))
+#define	MAX(x, y)		((x) > (y) ? (x) : (y))
+
 #define	VDEV_PAD_SIZE 		(8 << 10)
 /* 2 padding areas (vl_pad1 and vl_pad2) to skip */
 #define	VDEV_SKIP_SIZE		VDEV_PAD_SIZE * 2
 #define	VDEV_PHYS_SIZE		(112 << 10)
 #define	VDEV_UBERBLOCK_RING	(128 << 10)
 
+#define	VDEV_UBERBLOCK_SHIFT(sh)		\
+	MAX((sh), UBERBLOCK_SHIFT)
+#define	VDEV_UBERBLOCK_COUNT(sh)		\
+	(VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT(sh))
+#define	VDEV_UBERBLOCK_OFFSET(sh, n)	\
+	offsetof(vdev_label_t, vl_uberblock[(n) << VDEV_UBERBLOCK_SHIFT(sh)])
+#define	VDEV_UBERBLOCK_SIZE(sh)			\
+	(1ULL << VDEV_UBERBLOCK_SHIFT(sh))
+
 typedef struct vdev_phys {
 	char		vp_nvlist[VDEV_PHYS_SIZE - sizeof (zio_eck_t)];
 	zio_eck_t	vp_zbt;