Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Jan 2012 12:20:11 +0100
From:      Florian Wagner <florian@wagner-flo.net>
To:        Andriy Gapon <avg@FreeBSD.org>
Cc:        freebsd-fs@FreeBSD.org
Subject:   Re: Extending zfsboot.c to allow selecting filesystem from boot.config
Message-ID:  <20120109122011.0ae6ad70@naclador.mos32.de>
In-Reply-To: <4ED35326.80402@FreeBSD.org>
References:  <20111015214347.09f68e4e@naclador.mos32.de> <4E9ACA9F.5090308@FreeBSD.org> <20111019082139.1661868e@auedv3.syscomp.de> <4E9EEF45.9020404@FreeBSD.org> <20111019182130.27446750@naclador.mos32.de> <4EB98E05.4070900@FreeBSD.org> <20111119211921.7ffa9953@naclador.mos32.de> <4EC8CD14.4040600@FreeBSD.org> <20111120121248.5e9773c8@naclador.mos32.de> <4EC91B36.7060107@FreeBSD.org> <20111120191018.1aa4e882@naclador.mos32.de> <4ECA2DBD.5040701@FreeBSD.org> <20111121201332.03ecadf1@naclador.mos32.de> <4ECAC272.5080500@FreeBSD.org> <4ECEBD44.6090900@FreeBSD.org> <20111125224722.6cf3a299@naclador.mos32.de> <4ED0CFF9.4030503@FreeBSD.org> <20111126134927.60fe5097@naclador.mos32.de> <4ED35326.80402@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--Sig_/yZj6IQdWDsGiC2GeS=oaHxP
Content-Type: multipart/mixed; boundary="MP_/8h6raSy1Ymd8hSZ2Yhq+T1H"

--MP_/8h6raSy1Ymd8hSZ2Yhq+T1H
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

On Mon, 28 Nov 2011 11:23:50 +0200
Andriy Gapon <avg@FreeBSD.org> wrote:

> on 26/11/2011 14:49 Florian Wagner said the following:
> >=20
> > I'll try applying your patches to head instead of stable/8 in the
> > next days and test that. To make matters easier, can you tell me
> > which revision of head they are based on?
>=20
> I have finally updated my source repo and rebased the patches upon
> the recent CUURENT.  Please see
> https://gitorious.org/~avg/freebsd/avgbsd/commits/devel-20111127_1.
> The interesting commits are all near the HEAD.

I've built gptzfsboot and zfsloader from the code from your branch and
can report this as working perfectly over multiple reboots (including a
boot.config which specifies a root filesystem and vfs.root.mountfrom
being automatically set).

I've the looked at the diffs of the relevant stuff between my version
and your branch and as they were rather small decided to mix a bit by
copying from your branch:

 sys/boot/zfs/zfs.c
 sys/boot/zfs/zfsimpl.c
 sys/boot/i386/zfsboot/zfsboot.c

This also results in a working version according to the tests
mentioned above.

Attached are:

 - zfsboot-broken-to-working.patch which is the diff between the broken
   stable-8 we were discussing prior and the working one which results
   from copying over the mentioned files from your branch.

 - zfsboot-avgbsd-mix.patch which is the full patch (svn diff) above
   stable-8 revision 229801 that I've tested.


Do you currently have any plans to merge any of that into stable-9 or
stable-8?


Regards
Florian Wagner

--MP_/8h6raSy1Ymd8hSZ2Yhq+T1H
Content-Type: text/x-patch
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename=zfsboot-avgbsd-mix.patch

Index: sys/boot/common/boot.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/common/boot.c	(revision 229805)
+++ sys/boot/common/boot.c	(working copy)
@@ -311,12 +311,12 @@
     if (getenv("vfs.root.mountfrom") !=3D NULL)
 	return(0);
=20
+    error =3D 1;
     sprintf(lbuf, "%s/etc/fstab", rootdev);
     if ((fd =3D open(lbuf, O_RDONLY)) < 0)
-	return(1);
+	goto notfound;
=20
     /* loop reading lines from /etc/fstab    What was that about sscanf ag=
ain? */
-    error =3D 1;
     while (fgetstr(lbuf, sizeof(lbuf), fd) >=3D 0) {
 	if ((lbuf[0] =3D=3D 0) || (lbuf[0] =3D=3D '#'))
 	    continue;
@@ -377,6 +377,20 @@
 	break;
     }
     close(fd);
+
+notfound:
+    if (error) {
+	const char *currdev;
+
+	currdev =3D getenv("currdev");
+	if (currdev !=3D NULL && strncmp("zfs:", currdev, 4) =3D=3D 0) {
+	    cp =3D strdup(currdev);
+	    cp[strlen(cp) - 1] =3D '\0';
+	    setenv("vfs.root.mountfrom", cp, 0);
+	    error =3D 0;
+	}
+    }
+
     return(error);
 }
=20
Index: sys/boot/i386/libi386/devicename.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/i386/libi386/devicename.c	(revision 229805)
+++ sys/boot/i386/libi386/devicename.c	(working copy)
@@ -88,6 +88,8 @@
     int			i, unit, slice, partition, err;
     char		*cp;
     const char		*np;
+    const char		*sep;
+    const char		*end;
=20
     /* minimum length check */
     if (strlen(devspec) < 2)
@@ -171,7 +173,6 @@
=20
     case DEVT_CD:
     case DEVT_NET:
-    case DEVT_ZFS:
 	unit =3D 0;
=20
 	if (*np && (*np !=3D ':')) {
@@ -193,6 +194,34 @@
 	    *path =3D (*cp =3D=3D 0) ? cp : cp + 1;
 	break;
=20
+    case DEVT_ZFS:
+	if (*np !=3D ':') {
+	    err =3D EINVAL;
+	    goto fail;
+	}
+	np++;
+	end =3D strchr(np, ':');
+	if (end =3D=3D NULL) {
+	    err =3D EINVAL;
+	    goto fail;
+	}
+	sep =3D strchr(np, '/');
+	if (sep =3D=3D NULL || sep >=3D end)
+	    sep =3D end;
+	memcpy(idev->d_kind.zfs.poolname, np, sep - np);
+	idev->d_kind.zfs.poolname[sep - np] =3D '\0';
+	if (sep < end) {
+	    sep++;
+	    memcpy(idev->d_kind.zfs.rootname, sep, end - sep);
+	    idev->d_kind.zfs.rootname[end - sep] =3D '\0';
+	}
+	else
+	    idev->d_kind.zfs.rootname[0] =3D '\0';
+
+	if (path !=3D NULL)
+	    *path =3D (*end =3D=3D '\0') ? end : end + 1;
+	break;
+
     default:
 	err =3D EINVAL;
 	goto fail;
@@ -216,7 +245,7 @@
 i386_fmtdev(void *vdev)
 {
     struct i386_devdesc	*dev =3D (struct i386_devdesc *)vdev;
-    static char		buf[128];	/* XXX device length constant? */
+    static char		buf[256];	/* XXX device length constant? */
     char		*cp;
    =20
     switch(dev->d_type) {
@@ -247,9 +276,14 @@
 	break;
=20
     case DEVT_NET:
-    case DEVT_ZFS:
 	sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
 	break;
+    case DEVT_ZFS:
+	if (dev->d_kind.zfs.rootname[0] =3D=3D '\0')
+	    sprintf(buf, "%s:%s:", dev->d_dev->dv_name, dev->d_kind.zfs.poolname);
+	else
+	    sprintf(buf, "%s:%s/%s:", dev->d_dev->dv_name, dev->d_kind.zfs.poolna=
me, dev->d_kind.zfs.rootname);
+	break;
     }
     return(buf);
 }
Index: sys/boot/i386/libi386/libi386.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/i386/libi386/libi386.h	(revision 229805)
+++ sys/boot/i386/libi386/libi386.h	(working copy)
@@ -49,6 +49,12 @@
 	{
 	    void	*data;
 	} bioscd;
+	struct
+	{
+	    void	*data;
+	    char	poolname[256];
+	    char	rootname[256];
+	} zfs;
     } d_kind;
 };
=20
Index: sys/boot/i386/zfsboot/zfsboot.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/i386/zfsboot/zfsboot.c	(revision 229805)
+++ sys/boot/i386/zfsboot/zfsboot.c	(working copy)
@@ -45,7 +45,8 @@
 /* Hint to loader that we came from ZFS */
 #define	KARGS_FLAGS_ZFS		0x4
=20
-#define PATH_CONFIG	"/boot.config"
+#define PATH_DOTCONFIG	"/boot.config"
+#define PATH_CONFIG	"/boot/config"
 #define PATH_BOOT3	"/boot/zfsloader"
 #define PATH_KERNEL	"/boot/kernel/kernel"
=20
@@ -53,7 +54,7 @@
 #define NOPT		14
 #define NDEV		3
=20
-#define BIOS_NUMDRIVES		0x475
+#define BIOS_NUMDRIVES	0x475
 #define DRV_HARD	0x80
 #define DRV_MASK	0x7f
=20
@@ -91,8 +92,10 @@
 static const char *const dev_nm[NDEV] =3D {"ad", "da", "fd"};
 static const unsigned char dev_maj[NDEV] =3D {30, 4, 2};
=20
+struct zfsmount zfsmount;
 static char cmd[512];
 static char kname[1024];
+static char rootname[256];
 static int comspeed =3D SIOSPD;
 static struct bootinfo bootinfo;
 static uint32_t bootdev;
@@ -495,7 +498,12 @@
      * will find any other available pools and it may fill in missing
      * vdevs for the boot pool.
      */
-    for (i =3D 0; i < *(unsigned char *)PTOV(BIOS_NUMDRIVES); i++) {
+#ifndef VIRTUALBOX
+    for (i =3D 0; i < *(unsigned char *)PTOV(BIOS_NUMDRIVES); i++)
+#else
+    for (i =3D 0; i < MAXBDDEV; i++)
+#endif
+    {
 	if ((i | DRV_HARD) =3D=3D *(uint8_t *)PTOV(ARGS))
 	    continue;
=20
@@ -526,18 +534,21 @@
 	}
     }
=20
-    zfs_mount_pool(spa);
-
-    if (zfs_lookup(spa, PATH_CONFIG, &dn) =3D=3D 0) {
+    if (zfs_spa_init(spa) !=3D 0 || zfs_mount(spa, 0, &zfsmount) !=3D 0) {
+	printf("%s: failed to mount default pool %s\n",
+	    BOOTPROG, spa->spa_name);
+	autoboot =3D 0;
+    } else if (zfs_lookup(&zfsmount, PATH_CONFIG, &dn) =3D=3D 0 ||
+        zfs_lookup(&zfsmount, PATH_DOTCONFIG, &dn) =3D=3D 0) {
 	off =3D 0;
 	zfs_read(spa, &dn, &off, cmd, sizeof(cmd));
     }
=20
     if (*cmd) {
+	if (!OPT_CHECK(RBX_QUIET))
+	    printf("%s: %s", PATH_CONFIG, cmd);
 	if (parse())
 	    autoboot =3D 0;
-	if (!OPT_CHECK(RBX_QUIET))
-	    printf("%s: %s", PATH_CONFIG, cmd);
 	/* Do not process this command twice */
 	*cmd =3D 0;
     }
@@ -558,11 +569,17 @@
     /* Present the user with the boot2 prompt. */
=20
     for (;;) {
-	if (!autoboot || !OPT_CHECK(RBX_QUIET))
-	    printf("\nFreeBSD/x86 boot\n"
-		   "Default: %s:%s\n"
-		   "boot: ",
-		   spa->spa_name, kname);
+	if (!autoboot || !OPT_CHECK(RBX_QUIET)) {
+	    printf("\nFreeBSD/x86 boot\n");
+	    if (zfs_rlookup(spa, zfsmount.rootobj, rootname) !=3D 0)
+		printf("Default: %s:<0x%llx>:%s\n"
+		       "boot: ",
+		       spa->spa_name, zfsmount.rootobj, kname);
+	    else
+		printf("Default: %s:%s:%s\n"
+		       "boot: ",
+		       spa->spa_name, rootname, kname);
+	}
 	if (ioctrl & IO_SERIAL)
 	    sio_flush();
 	if (!autoboot || keyhit(5))
@@ -598,7 +615,8 @@
     uint32_t addr, x;
     int fmt, i, j;
=20
-    if (zfs_lookup(spa, kname, &dn)) {
+    if (zfs_lookup(&zfsmount, kname, &dn)) {
+	printf("\nCan't find %s\n", kname);
 	return;
     }
     off =3D 0;
@@ -677,7 +695,9 @@
 	   KARGS_FLAGS_ZFS,
 	   (uint32_t) spa->spa_guid,
 	   (uint32_t) (spa->spa_guid >> 32),
-	   VTOP(&bootinfo));
+	   VTOP(&bootinfo),
+	   (uint32_t) zfsmount.rootobj,
+	   (uint32_t) (zfsmount.rootobj >> 32));
 }
=20
 static int
@@ -729,7 +749,7 @@
 	} if (c =3D=3D '?') {
 	    dnode_phys_t dn;
=20
-	    if (zfs_lookup(spa, arg, &dn) =3D=3D 0) {
+	    if (zfs_lookup(&zfsmount, arg, &dn) =3D=3D 0) {
 		zap_list(spa, &dn);
 	    }
 	    return -1;
@@ -751,17 +771,32 @@
 	    q =3D (char *) strchr(arg, ':');
 	    if (q) {
 		spa_t *newspa;
+		uint64_t newroot;
=20
 		*q++ =3D 0;
 		newspa =3D spa_find_by_name(arg);
 		if (newspa) {
+		    arg =3D q;
 		    spa =3D newspa;
-		    zfs_mount_pool(spa);
+		    newroot =3D 0;
+		    q =3D (char *) strchr(arg, ':');
+		    if (q) {
+			*q++ =3D 0;
+			if (zfs_lookup_dataset(spa, arg, &newroot)) {
+			    printf("\nCan't find dataset %s in ZFS pool %s\n",
+			        arg, spa->spa_name);
+			    return -1;
+			}
+			arg =3D q;
+		    }
+		    if (zfs_mount(spa, newroot, &zfsmount)) {
+			printf("\nCan't mount ZFS dataset\n");
+			return -1;
+		    }
 		} else {
 		    printf("\nCan't find ZFS pool %s\n", arg);
 		    return -1;
 		}
-		arg =3D q;
 	    }
 	    if ((i =3D ep - arg)) {
 		if ((size_t)i >=3D sizeof(kname))
Index: sys/boot/i386/btx/btxldr/btxldr.S
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/i386/btx/btxldr/btxldr.S	(revision 229805)
+++ sys/boot/i386/btx/btxldr/btxldr.S	(working copy)
@@ -112,7 +112,7 @@
 		call hexout			#  relocation
 		call putstr			#  message
 #endif
-start_null_bi:	movl $0x18,%ecx 		# Allocate space
+start_null_bi:	movl $0x20,%ecx 		# Allocate space
 		subl %ecx,%ebp			#  for arguments
 		leal 0x4(%esp,1),%esi		# Source
 		movl %ebp,%edi			# Destination
Index: sys/boot/i386/btx/lib/btxcsu.s
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/i386/btx/lib/btxcsu.s	(revision 229805)
+++ sys/boot/i386/btx/lib/btxcsu.s	(working copy)
@@ -26,7 +26,7 @@
 #
 # Constants.
 #
-		.set ARGADJ,0xfa0		# Argument adjustment
+		.set ARGADJ,0xf98		# Argument adjustment
 #
 # Client entry point.
 #
Index: sys/boot/i386/loader/main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/i386/loader/main.c	(revision 229805)
+++ sys/boot/i386/loader/main.c	(working copy)
@@ -52,14 +52,21 @@
     u_int32_t	howto;
     u_int32_t	bootdev;
     u_int32_t	bootflags;
+#ifdef LOADER_ZFS_SUPPORT
     union {
+#endif
 	struct {
 	    u_int32_t	pxeinfo;
 	    u_int32_t	res2;
 	};
+#ifdef LOADER_ZFS_SUPPORT
 	uint64_t	zfspool;
     };
+#endif
     u_int32_t	bootinfo;
+#ifdef LOADER_ZFS_SUPPORT
+    uint64_t	zfsroot;
+#endif
 } *kargs;
=20
 static u_int32_t	initial_howto;
@@ -72,6 +79,9 @@
 static int		isa_inb(int port);
 static void		isa_outb(int port, int value);
 void			exit(int code);
+#ifdef LOADER_ZFS_SUPPORT
+extern int zfs_extract_currdev(uint64_t guid, uint64_t rootobj, struct i38=
6_devdesc *dev);
+#endif
=20
 /* from vers.c */
 extern	char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_mak=
er[];
@@ -259,33 +269,16 @@
 	       "Guessed BIOS device 0x%x not found by probes, defaulting to disk0=
:\n", biosdev);
 	new_currdev.d_unit =3D 0;
     }
+
+#ifdef LOADER_ZFS_SUPPORT
+    if ((kargs->bootflags & KARGS_FLAGS_ZFS) !=3D 0)
+	zfs_extract_currdev(kargs->zfspool, kargs->zfsroot, &new_currdev);
+#endif
+
     env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
 	       i386_setcurrdev, env_nounset);
     env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_nose=
t,
 	       env_nounset);
-
-#ifdef LOADER_ZFS_SUPPORT
-    /*
-     * If we were started from a ZFS-aware boot2, we can work out
-     * which ZFS pool we are booting from.
-     */
-    if (kargs->bootflags & KARGS_FLAGS_ZFS) {
-	/*
-	 * Dig out the pool guid and convert it to a 'unit number'
-	 */
-	uint64_t guid;
-	int unit;
-	char devname[32];
-	extern int zfs_guid_to_unit(uint64_t);
-
-	guid =3D kargs->zfspool;
-	unit =3D zfs_guid_to_unit(guid);
-	if (unit >=3D 0) {
-	    sprintf(devname, "zfs%d", unit);
-	    setenv("currdev", devname, 1);
-	}
-    }
-#endif
 }
=20
 COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
Index: sys/boot/zfs/zfs.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/zfs/zfs.c	(revision 229805)
+++ sys/boot/zfs/zfs.c	(working copy)
@@ -42,9 +42,12 @@
 #include <string.h>
 #include <stand.h>
 #include <bootstrap.h>
+#include <../i386/libi386/libi386.h>
=20
 #include "zfsimpl.c"
=20
+#define	MAXBDDEV	31
+
 static int	zfs_open(const char *path, struct open_file *f);
 static int	zfs_write(struct open_file *f, void *buf, size_t size, size_t *=
resid);
 static int	zfs_close(struct open_file *f);
@@ -83,35 +86,20 @@
 static int
 zfs_open(const char *upath, struct open_file *f)
 {
-	spa_t *spa =3D (spa_t *) f->f_devdata;
+	struct zfsmount *mount =3D (struct zfsmount *)f->f_devdata;
 	struct file *fp;
 	int rc;
=20
 	if (f->f_dev !=3D &zfs_dev)
 		return (EINVAL);
=20
-	rc =3D zfs_mount_pool(spa);
-	if (rc)
-		return (rc);
-
 	/* allocate file system specific data structure */
 	fp =3D malloc(sizeof(struct file));
 	bzero(fp, sizeof(struct file));
 	f->f_fsdata =3D (void *)fp;
=20
-	if (spa->spa_root_objset.os_type !=3D DMU_OST_ZFS) {
-		printf("Unexpected object set type %llu\n",
-		    spa->spa_root_objset.os_type);
-		rc =3D EIO;
-		goto out;
-	}
-
-	rc =3D zfs_lookup(spa, upath, &fp->f_dnode);
-	if (rc)
-		goto out;
-
+	rc =3D zfs_lookup(mount, upath, &fp->f_dnode);
 	fp->f_seekp =3D 0;
-out:
 	if (rc) {
 		f->f_fsdata =3D NULL;
 		free(fp);
@@ -140,7 +128,7 @@
 static int
 zfs_read(struct open_file *f, void *start, size_t size, size_t *resid	/* o=
ut */)
 {
-	spa_t *spa =3D (spa_t *) f->f_devdata;
+	spa_t *spa =3D ((struct zfsmount *)f->f_devdata)->spa;
 	struct file *fp =3D (struct file *)f->f_fsdata;
 	struct stat sb;
 	size_t n;
@@ -214,16 +202,16 @@
 static int
 zfs_stat(struct open_file *f, struct stat *sb)
 {
-	spa_t *spa =3D (spa_t *) f->f_devdata;
+	struct zfsmount *mount =3D (struct zfsmount *)f->f_devdata;
 	struct file *fp =3D (struct file *)f->f_fsdata;
=20
-	return (zfs_dnode_stat(spa, &fp->f_dnode, sb));
+	return (zfs_dnode_stat(mount, &fp->f_dnode, sb));
 }
=20
 static int
 zfs_readdir(struct open_file *f, struct dirent *d)
 {
-	spa_t *spa =3D (spa_t *) f->f_devdata;
+	spa_t *spa =3D ((struct zfsmount *)f->f_devdata)->spa;
 	struct file *fp =3D (struct file *)f->f_fsdata;
 	mzap_ent_phys_t mze;
 	struct stat sb;
@@ -379,22 +367,31 @@
 	}
 }
=20
-/*
- * Convert a pool guid to a 'unit number' suitable for use with zfs_dev_op=
en.
- */
 int
-zfs_guid_to_unit(uint64_t guid)
+zfs_extract_currdev(uint64_t guid, uint64_t rootobj, struct i386_devdesc *=
dev)
 {
 	spa_t *spa;
-	int unit;
+	int rv;
=20
-	unit =3D 0;
-	STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
-		if (spa->spa_guid =3D=3D guid)
-			return unit;
-		unit++;
+	spa =3D spa_find_by_guid(guid);
+	if (spa =3D=3D NULL)
+		return (ENOENT);
+
+	rv =3D zfs_spa_init(spa);
+	if (rv !=3D 0)
+		return (rv);
+	strcpy(dev->d_kind.zfs.poolname, spa->spa_name);
+	if (rootobj =3D=3D 0 && zfs_get_root(spa, &rootobj)) {
+		printf("ZFS: can't find root filesystem\n");
+		return (EIO);
 	}
-	return (-1);
+	if (zfs_rlookup(spa, rootobj, dev->d_kind.zfs.rootname)) {
+		printf("ZFS: can't map root filesystem to its name\n");
+		return (ENOENT);
+	}
+	dev->d_dev =3D &zfs_dev;
+	dev->d_type =3D dev->d_dev->dv_type;
+	return (0);
 }
=20
 static int
@@ -410,7 +407,7 @@
 	 * diskN, diskNpM or diskNsM.
 	 */
 	zfs_init();
-	for (unit =3D 0; unit < 32 /* XXX */; unit++) {
+	for (unit =3D 0; unit < MAXBDDEV; unit++) {
 		sprintf(devname, "disk%d:", unit);
 		fd =3D open(devname, O_RDONLY);
 		if (fd =3D=3D -1)
@@ -448,17 +445,14 @@
 {
 	spa_t *spa;
 	char line[80];
-	int unit;
=20
 	if (verbose) {
 		spa_all_status();
 		return;
 	}
-	unit =3D 0;
 	STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
-		sprintf(line, "    zfs%d:   %s\n", unit, spa->spa_name);
+		sprintf(line, "    zfs:%s\n", spa->spa_name);
 		pager_output(line);
-		unit++;
 	}
 }
=20
@@ -469,33 +463,38 @@
 zfs_dev_open(struct open_file *f, ...)
 {
 	va_list		args;
-	struct devdesc	*dev;
-	int		unit, i;
+	struct i386_devdesc	*dev;
+	struct zfsmount	*mount;
 	spa_t		*spa;
+	uint64_t	rootobj;
+	int		rv;
=20
 	va_start(args, f);
-	dev =3D va_arg(args, struct devdesc*);
+	dev =3D va_arg(args, struct i386_devdesc *);
 	va_end(args);
=20
-	/*
-	 * We mostly ignore the stuff that devopen sends us. For now,
-	 * use the unit to find a pool - later we will override the
-	 * devname parsing so that we can name a pool and a fs within
-	 * the pool.
-	 */
-	unit =3D dev->d_unit;
-=09
-	i =3D 0;
-	STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
-		if (i =3D=3D unit)
-			break;
-		i++;
-	}
-	if (!spa) {
+	spa =3D spa_find_by_name(dev->d_kind.zfs.poolname);
+	if (!spa)
 		return (ENXIO);
+	rv =3D zfs_spa_init(spa);
+	if (rv !=3D 0)
+		return (rv);
+	mount =3D malloc(sizeof(*mount));
+	rootobj =3D 0;
+	if (dev->d_kind.zfs.rootname[0] !=3D '\0') {
+		rv =3D zfs_lookup_dataset(spa, dev->d_kind.zfs.rootname, &rootobj);
+		if (rv !=3D 0)
+			return (rv);
 	}
-
-	f->f_devdata =3D spa;
+	rv =3D zfs_mount(spa, rootobj, mount);
+	if (rv !=3D 0)
+		return (rv);
+	if (mount->objset.os_type !=3D DMU_OST_ZFS) {
+		printf("Unexpected object set type %llu\n",
+		    mount->objset.os_type);
+		return (EIO);
+	}
+	f->f_devdata =3D mount;
 	free(dev);
 	return (0);
 }
@@ -504,6 +503,7 @@
 zfs_dev_close(struct open_file *f)
 {
=20
+	free(f->f_devdata);
 	f->f_devdata =3D NULL;
 	return (0);
 }
Index: sys/boot/zfs/zfsimpl.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/boot/zfs/zfsimpl.c	(revision 229805)
+++ sys/boot/zfs/zfsimpl.c	(working copy)
@@ -36,6 +36,13 @@
 #include "zfsimpl.h"
 #include "zfssubr.c"
=20
+
+struct zfsmount {
+	spa_t		*spa;
+	objset_phys_t	objset;
+	uint64_t	rootobj;
+};
+
 /*
  * List of all vdevs, chained through v_alllink.
  */
@@ -458,6 +465,9 @@
=20
 	if (strcmp(type, VDEV_TYPE_MIRROR)
 	    && strcmp(type, VDEV_TYPE_DISK)
+#ifdef ZFS_TEST
+	    && strcmp(type, VDEV_TYPE_FILE)
+#endif
 	    && strcmp(type, VDEV_TYPE_RAIDZ)
 	    && strcmp(type, VDEV_TYPE_REPLACING)) {
 		printf("ZFS: can only boot from disk, mirror, raidz1, raidz2 and raidz3 =
vdevs\n");
@@ -623,8 +633,6 @@
 	return (0);
 }
=20
-#ifdef BOOT2
-
 static spa_t *
 spa_find_by_name(const char *name)
 {
@@ -637,8 +645,6 @@
 	return (0);
 }
=20
-#endif
-
 static spa_t *
 spa_create(uint64_t guid)
 {
@@ -968,7 +974,7 @@
 	int v;
=20
 	for (v =3D 0; v < 32; v++)
-		if (n =3D=3D (1 << v))
+		if (n =3D=3D (1 << v)) /* XXX n is expected to be a power of two? */
 			return v;
 	return -1;
 }
@@ -1449,6 +1455,259 @@
 		dnode, sizeof(dnode_phys_t));
 }
=20
+static int
+mzap_rlookup(spa_t *spa, const dnode_phys_t *dnode, char *name, uint64_t v=
alue)
+{
+	const mzap_phys_t *mz;
+	const mzap_ent_phys_t *mze;
+	size_t size;
+	int chunks, i;
+
+	/*
+	 * Microzap objects use exactly one block. Read the whole
+	 * thing.
+	 */
+	size =3D dnode->dn_datablkszsec * 512;
+
+	mz =3D (const mzap_phys_t *) zap_scratch;
+	chunks =3D size / MZAP_ENT_LEN - 1;
+
+	for (i =3D 0; i < chunks; i++) {
+		mze =3D &mz->mz_chunk[i];
+		if (value =3D=3D mze->mze_value) {
+			strcpy(name, mze->mze_name);
+			return (0);
+		}
+	}
+
+	return (ENOENT);
+}
+
+static void
+fzap_name_copy(const zap_leaf_t *zl, const zap_leaf_chunk_t *zc, char *nam=
e)
+{
+	size_t namelen;
+	const zap_leaf_chunk_t *nc;
+	char *p;
+
+	namelen =3D zc->l_entry.le_name_length;
+
+	nc =3D &ZAP_LEAF_CHUNK(zl, zc->l_entry.le_name_chunk);
+	p =3D name;
+	while (namelen > 0) {
+		size_t len;
+		len =3D namelen;
+		if (len > ZAP_LEAF_ARRAY_BYTES)
+			len =3D ZAP_LEAF_ARRAY_BYTES;
+		memcpy(p, nc->l_array.la_array, len);
+		p +=3D len;
+		namelen -=3D len;
+		nc =3D &ZAP_LEAF_CHUNK(zl, nc->l_array.la_next);
+	}
+
+	*p =3D '\0';
+}
+
+static int
+fzap_rlookup(spa_t *spa, const dnode_phys_t *dnode, char *name, uint64_t v=
alue)
+{
+	int bsize =3D dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
+	zap_phys_t zh =3D *(zap_phys_t *) zap_scratch;
+	fat_zap_t z;
+	uint64_t *ptrtbl;
+	uint64_t hash;
+	int rc;
+
+	if (zh.zap_magic !=3D ZAP_MAGIC)
+		return (EIO);
+
+	z.zap_block_shift =3D ilog2(bsize);
+	z.zap_phys =3D (zap_phys_t *) zap_scratch;
+
+	/*
+	 * Figure out where the pointer table is and read it in if necessary.
+	 */
+	if (zh.zap_ptrtbl.zt_blk) {
+		rc =3D dnode_read(spa, dnode, zh.zap_ptrtbl.zt_blk * bsize,
+			       zap_scratch, bsize);
+		if (rc)
+			return (rc);
+		ptrtbl =3D (uint64_t *) zap_scratch;
+	} else {
+		ptrtbl =3D &ZAP_EMBEDDED_PTRTBL_ENT(&z, 0);
+	}
+
+	hash =3D zap_hash(zh.zap_salt, name);
+
+	zap_leaf_t zl;
+	zl.l_bs =3D z.zap_block_shift;
+
+	off_t off =3D ptrtbl[hash >> (64 - zh.zap_ptrtbl.zt_shift)] << zl.l_bs;
+	zap_leaf_chunk_t *zc;
+
+	rc =3D dnode_read(spa, dnode, off, zap_scratch, bsize);
+	if (rc)
+		return (rc);
+
+	zl.l_phys =3D (zap_leaf_phys_t *) zap_scratch;
+
+	/*
+	 * Make sure this chunk matches our hash.
+	 */
+	if (zl.l_phys->l_hdr.lh_prefix_len > 0
+	    && zl.l_phys->l_hdr.lh_prefix
+	    !=3D hash >> (64 - zl.l_phys->l_hdr.lh_prefix_len))
+		return (ENOENT);
+
+	/*
+	 * Hash within the chunk to find our entry.
+	 */
+	int shift =3D (64 - ZAP_LEAF_HASH_SHIFT(&zl) - zl.l_phys->l_hdr.lh_prefix=
_len);
+	int h =3D (hash >> shift) & ((1 << ZAP_LEAF_HASH_SHIFT(&zl)) - 1);
+	h =3D zl.l_phys->l_hash[h];
+	if (h =3D=3D 0xffff)
+		return (ENOENT);
+	zc =3D &ZAP_LEAF_CHUNK(&zl, h);
+	while (zc->l_entry.le_hash !=3D hash) {
+		if (zc->l_entry.le_next =3D=3D 0xffff) {
+			zc =3D 0;
+			break;
+		}
+		zc =3D &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_next);
+	}
+	if (fzap_leaf_value(&zl, zc) =3D=3D value) {
+		fzap_name_copy(&zl, zc, name);
+		return (0);
+	}
+
+	return (ENOENT);
+}
+
+static int
+zap_rlookup(spa_t *spa, const dnode_phys_t *dnode, char *name, uint64_t va=
lue)
+{
+	int rc;
+	uint64_t zap_type;
+	size_t size =3D dnode->dn_datablkszsec * 512;
+
+	rc =3D dnode_read(spa, dnode, 0, zap_scratch, size);
+	if (rc)
+		return (rc);
+
+	zap_type =3D *(uint64_t *) zap_scratch;
+	if (zap_type =3D=3D ZBT_MICRO)
+		return mzap_rlookup(spa, dnode, name, value);
+	else
+		return fzap_rlookup(spa, dnode, name, value);
+}
+
+static int
+zfs_rlookup(spa_t *spa, uint64_t objnum, char *result)
+{
+	char name[256];
+	char component[256];
+	uint64_t dir_obj, parent_obj, child_dir_zapobj;
+	dnode_phys_t child_dir_zap, dataset, dir, parent;
+	dsl_dir_phys_t *dd;
+	dsl_dataset_phys_t *ds;
+	char *p;
+	int len;
+
+	p =3D &name[sizeof(name) - 1];
+	*p =3D '\0';
+
+	if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) {
+		printf("ZFS: can't find dataset %llu\n", objnum);
+		return (EIO);
+	}
+	ds =3D (dsl_dataset_phys_t *)&dataset.dn_bonus;
+	dir_obj =3D ds->ds_dir_obj;
+
+	for (;;) {
+		if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir) !=3D 0)
+			return (EIO);
+		dd =3D (dsl_dir_phys_t *)&dir.dn_bonus;
+
+		/* Actual loop condition. */
+		parent_obj  =3D dd->dd_parent_obj;
+		if (parent_obj =3D=3D 0)
+			break;
+
+		if (objset_get_dnode(spa, &spa->spa_mos, parent_obj, &parent) !=3D 0)
+			return (EIO);
+		dd =3D (dsl_dir_phys_t *)&parent.dn_bonus;
+		child_dir_zapobj =3D dd->dd_child_dir_zapobj;
+		if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj, &child_dir_za=
p) !=3D 0)
+			return (EIO);
+		if (zap_rlookup(spa, &child_dir_zap, component, dir_obj) !=3D 0)
+			return (EIO);
+
+		len =3D strlen(component);
+		p -=3D len;
+		memcpy(p, component, len);
+		--p;
+		*p =3D '/';
+
+		/* Actual loop iteration. */
+		dir_obj =3D parent_obj;
+	}
+
+	if (*p !=3D '\0')
+		++p;
+	strcpy(result, p);
+
+	return (0);
+}
+
+static int
+zfs_lookup_dataset(spa_t *spa, const char *name, uint64_t *objnum)
+{
+	char element[256];
+	uint64_t dir_obj, child_dir_zapobj;
+	dnode_phys_t child_dir_zap, dir;
+	dsl_dir_phys_t *dd;
+	const char *p, *q;
+
+	if (objset_get_dnode(spa, &spa->spa_mos, DMU_POOL_DIRECTORY_OBJECT, &dir))
+		return (EIO);
+	if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, &dir_obj))
+		return (EIO);
+
+	p =3D name;
+	for (;;) {
+		if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir))
+			return (EIO);
+		dd =3D (dsl_dir_phys_t *)&dir.dn_bonus;
+
+		while (*p =3D=3D '/')
+			p++;
+		/* Actual loop condition #1. */
+		if (*p =3D=3D '\0')
+			break;
+
+		q =3D strchr(p, '/');
+		if (q) {
+			memcpy(element, p, q - p);
+			element[q - p] =3D '\0';
+			p =3D q + 1;
+		} else {
+			strcpy(element, p);
+			p +=3D strlen(p);
+		}
+
+		child_dir_zapobj =3D dd->dd_child_dir_zapobj;
+		if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj, &child_dir_za=
p) !=3D 0)
+			return (EIO);
+
+		/* Actual loop condition #2. */
+		if (zap_lookup(spa, &child_dir_zap, element, &dir_obj) !=3D 0)
+			return (ENOENT);
+	}
+
+	*objnum =3D dd->dd_head_dataset_obj;
+	return (0);
+}
+
 /*
  * Find the object set given the object number of its dataset object
  * and return its details in *objset
@@ -1478,11 +1737,13 @@
  * dataset if there is none and return its details in *objset
  */
 static int
-zfs_mount_root(spa_t *spa, objset_phys_t *objset)
+zfs_get_root(spa_t *spa, uint64_t *objid)
 {
 	dnode_phys_t dir, propdir;
 	uint64_t props, bootfs, root;
=20
+	*objid =3D 0;
+
 	/*
 	 * Start with the MOS directory object.
 	 */
@@ -1498,8 +1759,10 @@
 	     && objset_get_dnode(spa, &spa->spa_mos, props, &propdir) =3D=3D 0
 	     && zap_lookup(spa, &propdir, "bootfs", &bootfs) =3D=3D 0
 	     && bootfs !=3D 0)
-		return zfs_mount_dataset(spa, bootfs, objset);
-
+	{
+		*objid =3D bootfs;
+		return (0);
+	}
 	/*
 	 * Lookup the root dataset directory
 	 */
@@ -1514,36 +1777,52 @@
 	 * to find the dataset object and from that the object set itself.
 	 */
 	dsl_dir_phys_t *dd =3D (dsl_dir_phys_t *) &dir.dn_bonus;
-	return zfs_mount_dataset(spa, dd->dd_head_dataset_obj, objset);
+	*objid =3D dd->dd_head_dataset_obj;
+	return (0);
 }
=20
 static int
-zfs_mount_pool(spa_t *spa)
+zfs_mount(spa_t *spa, uint64_t rootobj, struct zfsmount *mount)
 {
=20
+	mount->spa =3D spa;
+
 	/*
-	 * Find the MOS and work our way in from there.
+	 * Find the root object set if not explicitly provided
 	 */
-	if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) {
-		printf("ZFS: can't read MOS\n");
+	if (rootobj =3D=3D 0 && zfs_get_root(spa, &rootobj)) {
+		printf("ZFS: can't find root filesystem\n");
 		return (EIO);
 	}
=20
-	/*
-	 * Find the root object set
-	 */
-	if (zfs_mount_root(spa, &spa->spa_root_objset)) {
-		printf("Can't find root filesystem - giving up\n");
+	if (zfs_mount_dataset(spa, rootobj, &mount->objset)) {
+		printf("ZFS: can't open root filesystem\n");
 		return (EIO);
 	}
=20
+	mount->rootobj =3D rootobj;
+
 	return (0);
 }
=20
 static int
-zfs_dnode_stat(spa_t *spa, dnode_phys_t *dn, struct stat *sb)
+zfs_spa_init(spa_t *spa)
 {
=20
+	if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) {
+		printf("ZFS: can't read MOS of pool %s\n", spa->spa_name);
+		return (EIO);
+	}
+	return (0);
+}
+
+static int
+zfs_dnode_stat(const struct zfsmount *mount, dnode_phys_t *dn, struct stat=
 *sb)
+{
+	spa_t *spa;
+
+	spa =3D mount->spa;
+
 	if (dn->dn_bonustype !=3D DMU_OT_SA) {
 		znode_phys_t *zp =3D (znode_phys_t *)dn->dn_bonus;
=20
@@ -1596,10 +1875,11 @@
  * Lookup a file and return its dnode.
  */
 static int
-zfs_lookup(spa_t *spa, const char *upath, dnode_phys_t *dnode)
+zfs_lookup(const struct zfsmount *mount, const char *upath, dnode_phys_t *=
dnode)
 {
 	int rc;
 	uint64_t objnum, rootnum, parentnum;
+	spa_t *spa;
 	dnode_phys_t dn;
 	const char *p, *q;
 	char element[256];
@@ -1607,16 +1887,17 @@
 	int symlinks_followed =3D 0;
 	struct stat sb;
=20
-	if (spa->spa_root_objset.os_type !=3D DMU_OST_ZFS) {
+	spa =3D mount->spa;
+	if (mount->objset.os_type !=3D DMU_OST_ZFS) {
 		printf("ZFS: unexpected object set type %llu\n",
-		       spa->spa_root_objset.os_type);
+		       mount->objset.os_type);
 		return (EIO);
 	}
=20
 	/*
 	 * Get the root directory dnode.
 	 */
-	rc =3D objset_get_dnode(spa, &spa->spa_root_objset, MASTER_NODE_OBJ, &dn);
+	rc =3D objset_get_dnode(spa, &mount->objset, MASTER_NODE_OBJ, &dn);
 	if (rc)
 		return (rc);
=20
@@ -1624,7 +1905,7 @@
 	if (rc)
 		return (rc);
=20
-	rc =3D objset_get_dnode(spa, &spa->spa_root_objset, rootnum, &dn);
+	rc =3D objset_get_dnode(spa, &mount->objset, rootnum, &dn);
 	if (rc)
 		return (rc);
=20
@@ -1645,7 +1926,7 @@
 			p =3D 0;
 		}
=20
-		rc =3D zfs_dnode_stat(spa, &dn, &sb);
+		rc =3D zfs_dnode_stat(mount, &dn, &sb);
 		if (rc)
 			return (rc);
 		if (!S_ISDIR(sb.st_mode))
@@ -1657,14 +1938,14 @@
 			return (rc);
 		objnum =3D ZFS_DIRENT_OBJ(objnum);
=20
-		rc =3D objset_get_dnode(spa, &spa->spa_root_objset, objnum, &dn);
+		rc =3D objset_get_dnode(spa, &mount->objset, objnum, &dn);
 		if (rc)
 			return (rc);
=20
 		/*
 		 * Check for symlink.
 		 */
-		rc =3D zfs_dnode_stat(spa, &dn, &sb);
+		rc =3D zfs_dnode_stat(mount, &dn, &sb);
 		if (rc)
 			return (rc);
 		if (S_ISLNK(sb.st_mode)) {
@@ -1699,7 +1980,7 @@
 				objnum =3D rootnum;
 			else
 				objnum =3D parentnum;
-			objset_get_dnode(spa, &spa->spa_root_objset, objnum, &dn);
+			objset_get_dnode(spa, &mount->objset, objnum, &dn);
 		}
 	}
=20
Index: sys/cddl/boot/zfs/zfsimpl.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/cddl/boot/zfs/zfsimpl.h	(revision 229805)
+++ sys/cddl/boot/zfs/zfsimpl.h	(working copy)
@@ -1327,5 +1327,4 @@
 	struct uberblock spa_uberblock;	/* best uberblock so far */
 	vdev_list_t	spa_vdevs;	/* list of all toplevel vdevs */
 	objset_phys_t	spa_mos;	/* MOS for this pool */
-	objset_phys_t	spa_root_objset; /* current mounted ZPL objset */
 } spa_t;

--MP_/8h6raSy1Ymd8hSZ2Yhq+T1H
Content-Type: text/x-patch
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename=zfsboot-broken-to-working.patch

diff --exclude=3D.svn -Nur boot-stable-8/i386/zfsboot/zfsboot.c stable-8/sy=
s/boot/i386/zfsboot/zfsboot.c
--- boot-stable-8/i386/zfsboot/zfsboot.c	2012-01-08 19:01:50.409526858 +0000
+++ stable-8/sys/boot/i386/zfsboot/zfsboot.c	2012-01-08 19:06:06.021632256 =
+0000
@@ -45,7 +45,8 @@
 /* Hint to loader that we came from ZFS */
 #define	KARGS_FLAGS_ZFS		0x4
=20
-#define PATH_CONFIG	"/boot.config"
+#define PATH_DOTCONFIG	"/boot.config"
+#define PATH_CONFIG	"/boot/config"
 #define PATH_BOOT3	"/boot/zfsloader"
 #define PATH_KERNEL	"/boot/kernel/kernel"
=20
@@ -53,7 +54,7 @@
 #define NOPT		14
 #define NDEV		3
=20
-#define BIOS_NUMDRIVES		0x475
+#define BIOS_NUMDRIVES	0x475
 #define DRV_HARD	0x80
 #define DRV_MASK	0x7f
=20
@@ -497,7 +498,12 @@
      * will find any other available pools and it may fill in missing
      * vdevs for the boot pool.
      */
-    for (i =3D 0; i < *(unsigned char *)PTOV(BIOS_NUMDRIVES); i++) {
+#ifndef VIRTUALBOX
+    for (i =3D 0; i < *(unsigned char *)PTOV(BIOS_NUMDRIVES); i++)
+#else
+    for (i =3D 0; i < MAXBDDEV; i++)
+#endif
+    {
 	if ((i | DRV_HARD) =3D=3D *(uint8_t *)PTOV(ARGS))
 	    continue;
=20
@@ -528,9 +534,12 @@
 	}
     }
=20
-    zfs_mount(spa, 0, &zfsmount);
-
-    if (zfs_lookup(&zfsmount, PATH_CONFIG, &dn) =3D=3D 0) {
+    if (zfs_spa_init(spa) !=3D 0 || zfs_mount(spa, 0, &zfsmount) !=3D 0) {
+	printf("%s: failed to mount default pool %s\n",
+	    BOOTPROG, spa->spa_name);
+	autoboot =3D 0;
+    } else if (zfs_lookup(&zfsmount, PATH_CONFIG, &dn) =3D=3D 0 ||
+        zfs_lookup(&zfsmount, PATH_DOTCONFIG, &dn) =3D=3D 0) {
 	off =3D 0;
 	zfs_read(spa, &dn, &off, cmd, sizeof(cmd));
     }
@@ -565,7 +574,7 @@
 	    if (zfs_rlookup(spa, zfsmount.rootobj, rootname) !=3D 0)
 		printf("Default: %s:<0x%llx>:%s\n"
 		       "boot: ",
-		       spa->spa_name, rootname, kname);
+		       spa->spa_name, zfsmount.rootobj, kname);
 	    else
 		printf("Default: %s:%s:%s\n"
 		       "boot: ",
diff --exclude=3D.svn -Nur boot-stable-8/zfs/zfs.c stable-8/sys/boot/zfs/zf=
s.c
--- boot-stable-8/zfs/zfs.c	2012-01-08 19:01:50.409526858 +0000
+++ stable-8/sys/boot/zfs/zfs.c	2012-01-08 19:04:04.050596447 +0000
@@ -46,6 +46,8 @@
=20
 #include "zfsimpl.c"
=20
+#define	MAXBDDEV	31
+
 static int	zfs_open(const char *path, struct open_file *f);
 static int	zfs_write(struct open_file *f, void *buf, size_t size, size_t *=
resid);
 static int	zfs_close(struct open_file *f);
@@ -369,15 +371,16 @@
 zfs_extract_currdev(uint64_t guid, uint64_t rootobj, struct i386_devdesc *=
dev)
 {
 	spa_t *spa;
+	int rv;
=20
-	STAILQ_FOREACH(spa, &zfs_pools, spa_link)
-		if (spa->spa_guid =3D=3D guid) {
-			strcpy(dev->d_kind.zfs.poolname, spa->spa_name);
-			break;
-		}
-
+	spa =3D spa_find_by_guid(guid);
 	if (spa =3D=3D NULL)
 		return (ENOENT);
+
+	rv =3D zfs_spa_init(spa);
+	if (rv !=3D 0)
+		return (rv);
+	strcpy(dev->d_kind.zfs.poolname, spa->spa_name);
 	if (rootobj =3D=3D 0 && zfs_get_root(spa, &rootobj)) {
 		printf("ZFS: can't find root filesystem\n");
 		return (EIO);
@@ -404,7 +407,7 @@
 	 * diskN, diskNpM or diskNsM.
 	 */
 	zfs_init();
-	for (unit =3D 0; unit < 32 /* XXX */; unit++) {
+	for (unit =3D 0; unit < MAXBDDEV; unit++) {
 		sprintf(devname, "disk%d:", unit);
 		fd =3D open(devname, O_RDONLY);
 		if (fd =3D=3D -1)
@@ -470,11 +473,12 @@
 	dev =3D va_arg(args, struct i386_devdesc *);
 	va_end(args);
=20
-	STAILQ_FOREACH(spa, &zfs_pools, spa_link)
-		if (strcmp(spa->spa_name, dev->d_kind.zfs.poolname) =3D=3D 0)
-			break;
+	spa =3D spa_find_by_name(dev->d_kind.zfs.poolname);
 	if (!spa)
 		return (ENXIO);
+	rv =3D zfs_spa_init(spa);
+	if (rv !=3D 0)
+		return (rv);
 	mount =3D malloc(sizeof(*mount));
 	rootobj =3D 0;
 	if (dev->d_kind.zfs.rootname[0] !=3D '\0') {
diff --exclude=3D.svn -Nur boot-stable-8/zfs/zfsimpl.c stable-8/sys/boot/zf=
s/zfsimpl.c
--- boot-stable-8/zfs/zfsimpl.c	2012-01-08 19:01:50.409526858 +0000
+++ stable-8/sys/boot/zfs/zfsimpl.c	2012-01-08 19:04:04.070575607 +0000
@@ -633,8 +633,6 @@
 	return (0);
 }
=20
-#ifdef BOOT2
-
 static spa_t *
 spa_find_by_name(const char *name)
 {
@@ -647,8 +645,6 @@
 	return (0);
 }
=20
-#endif
-
 static spa_t *
 spa_create(uint64_t guid)
 {
@@ -967,15 +963,6 @@
 	}
 	zfs_free(upbuf, VDEV_UBERBLOCK_SIZE(vdev));
=20
-	STAILQ_FOREACH(top_vdev, &spa->spa_vdevs, v_childlink)
-		if (top_vdev->v_state < VDEV_STATE_DEGRADED)
-			break;
-	if (top_vdev =3D=3D NULL) { /* all top vdevs are sufficiently healthy to =
try */
-		if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) {
-			printf("ZFS: can't read MOS\n");
-		}
-	}
-
 	if (spap)
 		*spap =3D spa;
 	return (0);
@@ -987,7 +974,7 @@
 	int v;
=20
 	for (v =3D 0; v < 32; v++)
-		if (n =3D=3D (1 << v))
+		if (n =3D=3D (1 << v)) /* XXX n is expected to be a power of two? */
 			return v;
 	return -1;
 }
@@ -1819,6 +1806,17 @@
 }
=20
 static int
+zfs_spa_init(spa_t *spa)
+{
+
+	if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) {
+		printf("ZFS: can't read MOS of pool %s\n", spa->spa_name);
+		return (EIO);
+	}
+	return (0);
+}
+
+static int
 zfs_dnode_stat(const struct zfsmount *mount, dnode_phys_t *dn, struct stat=
 *sb)
 {
 	spa_t *spa;

--MP_/8h6raSy1Ymd8hSZ2Yhq+T1H--

--Sig_/yZj6IQdWDsGiC2GeS=oaHxP
Content-Type: application/pgp-signature; name=signature.asc
Content-Disposition: attachment; filename=signature.asc

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (GNU/Linux)

iEYEARECAAYFAk8KzWwACgkQLvW/2gp2pPzBFQCgn5Mnw1bCmcc20VvQh+kQ04Sx
nFUAnjEc48w9QGXeY6o+iAXv+kalnsuP
=DjNq
-----END PGP SIGNATURE-----

--Sig_/yZj6IQdWDsGiC2GeS=oaHxP--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120109122011.0ae6ad70>