gptzfsboot bug?

Matt Burke mattblists at icritical.com
Wed Jun 29 15:22:01 UTC 2011


When you have a log partition to a non-bootable zfs pool discovered before
a bootable zfs pool, the 2nd stage bootloader will break because the check
for ZPOOL_CONFIG_IS_LOG will never find it - at least on my system.

The problem is that ZFS uses nested nvlist structures, the 'is_log'
attribute is held below the root level, and nvlist_find doesn't recurse.

Attached is a diff against 8-STABLE as of a few minutes ago. C is not my
main language and I've been looking at zfs source for less than a day, so
please do check it for correctness although it works here. The xdr_int()
call is used to bump p to the beginning of the embedded list.


--- zfsimpl.c.orig	2011-06-29 14:29:49.460537991 +0100
+++ zfsimpl.c	2011-06-29 15:16:20.526890896 +0100
@@ -173,10 +173,20 @@
 					 (const unsigned char*) p;
 				return (0);
 			} else {
 				return (EIO);
 			}
+		} else if (!memcmp(ZPOOL_CONFIG_VDEV_TREE, pairname, namelen)
+			   && pairtype == DATA_TYPE_NVLIST) {
+			/*
+			 * If we find an nvlist, recurse into it
+			*/
+			xdr_int(&p, &elements);
+			if (0 == nvlist_find(p, name, type, elementsp, valuep))
+				return 0;
+			/* reset position in case find fails mid-way */
+			p = pair + encoded_size;
 		} else {
 			/*
 			 * Not the pair we are looking for, skip to the next one.
 			 */
 			p = pair + encoded_size;


As an aside, is it sensible for zfsboot.c to leave the prompt at
/boot/kernel/kernel, or even bother trying it given zfs is usually built as
a module and will need /boot/zfsloader to load everything first? Would it
be an idea to do something like this?

printf("First boot attempt failed.\n");
STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
	printf("Trying %s:%s\n", spa->spa_name, kname);
	zfs_mount_pool(spa);
	load();
	printf("Failed.\n");
}


Matt.

-- 


More information about the freebsd-fs mailing list