changeset 10056:9f478b0e65da

6770808 error 37 when encountering multiple pools w/same name but unique bootfs 6819150 add back label support in GRUB/zfs code 6837148 set_bootfs() returns garbage
author Eric Taylor <Eric.Taylor@Sun.COM>
date Wed, 08 Jul 2009 08:44:27 -0600
parents c14dc8a84103
children 6f1fb533f14e
files usr/src/grub/grub-0.97/stage2/builtins.c usr/src/grub/grub-0.97/stage2/disk_io.c usr/src/grub/grub-0.97/stage2/fsys_zfs.c usr/src/grub/grub-0.97/stage2/fsys_zfs.h
diffstat 4 files changed, 50 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/grub/grub-0.97/stage2/builtins.c	Wed Jul 08 04:04:58 2009 -0700
+++ b/usr/src/grub/grub-0.97/stage2/builtins.c	Wed Jul 08 08:44:27 2009 -0600
@@ -4226,10 +4226,7 @@
 		return 0;
 	}
 
-	if (set_bootfs(arg) == 0) {
-		errnum = ERR_BAD_ARGUMENT;
-		return 0;
-	}
+	grub_memmove(current_bootfs, arg, MAXNAMELEN);
 
 	return (1);
 }
--- a/usr/src/grub/grub-0.97/stage2/disk_io.c	Wed Jul 08 04:04:58 2009 -0700
+++ b/usr/src/grub/grub-0.97/stage2/disk_io.c	Wed Jul 08 08:44:27 2009 -0600
@@ -1013,12 +1013,6 @@
 part_choice;
 #endif /* ! STAGE1_5 */
 
-int
-set_bootfs(char *fsname)
-{
-	grub_memmove(current_bootfs, fsname, MAXNAMELEN);
-}
-
 char *
 set_device (char *device)
 {
--- a/usr/src/grub/grub-0.97/stage2/fsys_zfs.c	Wed Jul 08 04:04:58 2009 -0700
+++ b/usr/src/grub/grub-0.97/stage2/fsys_zfs.c	Wed Jul 08 08:44:27 2009 -0600
@@ -59,6 +59,7 @@
 static uint64_t dnode_start = 0;
 static uint64_t dnode_end = 0;
 
+static uint64_t pool_guid = 0;
 static uberblock_t current_uberblock;
 static char *stackbase;
 
@@ -175,30 +176,14 @@
 }
 
 /*
- * vdev_label_offset takes "offset" (the offset within a vdev_label) and
- * returns its physical disk offset (starting from the beginning of the vdev).
- *
- * Input:
- *	psize	: Physical size of this vdev
- *      l	: Label Number (0-3)
- *	offset	: The offset with a vdev_label in which we want the physical
- *		  address
- * Return:
- * 	Success : physical disk offset
- * 	Failure : errnum = ERR_BAD_ARGUMENT, return value is meaningless
+ * vdev_label_start returns the physical disk offset (in bytes) of
+ * label "l".
  */
 static uint64_t
-vdev_label_offset(uint64_t psize, int l, uint64_t offset)
+vdev_label_start(uint64_t psize, int l)
 {
-	/* XXX Need to add back label support! */
-	if (l >= VDEV_LABELS/2 || offset > sizeof (vdev_label_t)) {
-		errnum = ERR_BAD_ARGUMENT;
-		return (0);
-	}
-
-	return (offset + l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
+	return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
 	    0 : psize - VDEV_LABELS * sizeof (vdev_label_t)));
-
 }
 
 /*
@@ -239,7 +224,7 @@
  *    -1 - Failure
  */
 static int
-uberblock_verify(uberblock_phys_t *ub, int offset)
+uberblock_verify(uberblock_phys_t *ub, uint64_t offset)
 {
 
 	uberblock_t *uber = &ub->ubp_uberblock;
@@ -267,15 +252,15 @@
  *    Failure - NULL
  */
 static uberblock_phys_t *
-find_bestub(uberblock_phys_t *ub_array, int label)
+find_bestub(uberblock_phys_t *ub_array, uint64_t sector)
 {
 	uberblock_phys_t *ubbest = NULL;
-	int i, offset;
+	uint64_t offset;
+	int i;
 
 	for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++) {
-		offset = vdev_label_offset(0, label, VDEV_UBERBLOCK_OFFSET(i));
-		if (errnum == ERR_BAD_ARGUMENT)
-			return (NULL);
+		offset = (sector << SPA_MINBLOCKSHIFT) +
+		    VDEV_UBERBLOCK_OFFSET(i);
 		if (uberblock_verify(&ub_array[i], offset) == 0) {
 			if (ubbest == NULL) {
 				ubbest = &ub_array[i];
@@ -1220,16 +1205,16 @@
  *	ERR_* - failure
  */
 int
-check_pool_label(int label, char *stack, char *outdevid, char *outpath)
+check_pool_label(uint64_t sector, char *stack, char *outdevid,
+    char *outpath, uint64_t *outguid)
 {
 	vdev_phys_t *vdev;
-	uint64_t sector, pool_state, txg = 0;
+	uint64_t pool_state, txg = 0;
 	char *nvlist, *nv;
 	uint64_t diskguid;
 	uint64_t version;
 
-	sector = (label * sizeof (vdev_label_t) + VDEV_SKIP_SIZE)
-	    >> SPA_MINBLOCKSHIFT;
+	sector += (VDEV_SKIP_SIZE >> SPA_MINBLOCKSHIFT);
 
 	/* Read in the vdev name-value pair list (112K). */
 	if (devread(sector, 0, VDEV_PHYS_SIZE, stack) == 0)
@@ -1273,6 +1258,9 @@
 		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,
+	    DATA_TYPE_UINT64, NULL))
+		return (ERR_FSYS_CORRUPT);
 	return (0);
 }
 
@@ -1289,14 +1277,18 @@
 {
 	char *stack;
 	int label = 0;
-	uberblock_phys_t *ub_array, *ubbest = NULL;
+	uberblock_phys_t *ub_array, *ubbest;
 	objset_phys_t *osp;
 	char tmp_bootpath[MAXNAMELEN];
 	char tmp_devid[MAXNAMELEN];
+	uint64_t tmp_guid;
+	uint64_t adjpl = (uint64_t)part_length << SPA_MINBLOCKSHIFT;
 
 	/* if it's our first time here, zero the best uberblock out */
-	if (best_drive == 0 && best_part == 0 && find_best_root)
+	if (best_drive == 0 && best_part == 0 && find_best_root) {
 		grub_memset(&current_uberblock, 0, sizeof (uberblock_t));
+		pool_guid = 0;
+	}
 
 	stackbase = ZFS_SCRATCH;
 	stack = stackbase;
@@ -1305,30 +1297,34 @@
 
 	osp = (objset_phys_t *)stack;
 	stack += sizeof (objset_phys_t);
+	adjpl = P2ALIGN(adjpl, (uint64_t)sizeof (vdev_label_t));
 
-	/* XXX add back labels support? */
-	for (label = 0; ubbest == NULL && label < (VDEV_LABELS/2); label++) {
-		uint64_t sector = (label * sizeof (vdev_label_t) +
-		    VDEV_SKIP_SIZE + VDEV_PHYS_SIZE) >> SPA_MINBLOCKSHIFT;
+	for (label = 0; label < VDEV_LABELS; label++) {
+		uint64_t sector = vdev_label_start(adjpl,
+		    label) >> SPA_MINBLOCKSHIFT;
 
 		/* Read in the uberblock ring (128K). */
-		if (devread(sector, 0, VDEV_UBERBLOCK_RING,
+		if (devread(sector  +
+		    ((VDEV_SKIP_SIZE + VDEV_PHYS_SIZE) >>
+		    SPA_MINBLOCKSHIFT), 0, VDEV_UBERBLOCK_RING,
 		    (char *)ub_array) == 0)
 			continue;
 
-		if ((ubbest = find_bestub(ub_array, label)) != NULL &&
+		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 (check_pool_label(label, stack, tmp_devid,
-			    tmp_bootpath))
-				return (0);
+			if (check_pool_label(sector, stack, tmp_devid,
+			    tmp_bootpath, &tmp_guid))
+				continue;
+			if (pool_guid == 0)
+				pool_guid = tmp_guid;
 
-			if (find_best_root &&
+			if (find_best_root && ((pool_guid != tmp_guid) ||
 			    vdev_uberblock_compare(&ubbest->ubp_uberblock,
-			    &(current_uberblock)) <= 0)
+			    &(current_uberblock)) <= 0))
 				continue;
 
 			/* Got the MOS. Save it at the memory addr MOS. */
--- a/usr/src/grub/grub-0.97/stage2/fsys_zfs.h	Wed Jul 08 04:04:58 2009 -0700
+++ b/usr/src/grub/grub-0.97/stage2/fsys_zfs.h	Wed Jul 08 08:44:27 2009 -0600
@@ -17,14 +17,12 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #ifndef _FSYS_ZFS_H
 #define	_FSYS_ZFS_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #ifdef	FSYS_ZFS
 
 typedef unsigned long long uint64_t;
@@ -121,6 +119,15 @@
 	((offset + VDEV_LABEL_START_SIZE) >> SPA_MINBLOCKSHIFT)
 
 /*
+ * return x rounded down to an align boundary
+ * eg, P2ALIGN(1200, 1024) == 1024 (1*align)
+ * eg, P2ALIGN(1024, 1024) == 1024 (1*align)
+ * eg, P2ALIGN(0x1234, 0x100) == 0x1200 (0x12*align)
+ * eg, P2ALIGN(0x5600, 0x100) == 0x5600 (0x56*align)
+ */
+#define	P2ALIGN(x, align)		((x) & -(align))
+
+/*
  * For nvlist manipulation. (from nvpair.h)
  */
 #define	NV_ENCODE_NATIVE	0