From owner-freebsd-fs@FreeBSD.ORG Mon Jan 9 11:36:00 2012 Return-Path: Delivered-To: freebsd-fs@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6E2D51065673 for ; Mon, 9 Jan 2012 11:36:00 +0000 (UTC) (envelope-from florian@wagner-flo.net) Received: from umbracor.wagner-flo.net (umbracor.wagner-flo.net [213.165.81.202]) by mx1.freebsd.org (Postfix) with ESMTP id BC5448FC16 for ; Mon, 9 Jan 2012 11:35:59 +0000 (UTC) Received: from naclador.mos32.de (ppp-88-217-80-44.dynamic.mnet-online.de [88.217.80.44]) by umbracor.wagner-flo.net (Postfix) with ESMTPSA id EC3AC3C058F6; Mon, 9 Jan 2012 12:20:13 +0100 (CET) Date: Mon, 9 Jan 2012 12:20:11 +0100 From: Florian Wagner To: Andriy Gapon 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> X-Mailer: Claws Mail 3.7.10 (GTK+ 2.24.8; x86_64-pc-linux-gnu) Mime-Version: 1.0 Content-Type: multipart/signed; micalg=PGP-SHA1; boundary="Sig_/yZj6IQdWDsGiC2GeS=oaHxP"; protocol="application/pgp-signature" Cc: freebsd-fs@FreeBSD.org Subject: Re: Extending zfsboot.c to allow selecting filesystem from boot.config X-BeenThere: freebsd-fs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Filesystems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Jan 2012 11:36:00 -0000 --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 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 #include #include +#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--