Author: avg
Date: Fri Jun 29 10:18:36 2012
New Revision: 237765
URL: http://svn.freebsd.org/changeset/base/237765

Log:
  MFC r235329,235343,235361,235364: zfsboot/zfsloader: support accessing
  filesystems within a pool

Added:
  stable/8/sys/boot/zfs/devicename_stubs.c
     - copied unchanged from r235329, head/sys/boot/zfs/devicename_stubs.c
  stable/8/sys/boot/zfs/libzfs.h
     - copied unchanged from r235329, head/sys/boot/zfs/libzfs.h
Modified:
  stable/8/sys/boot/common/bootstrap.h
  stable/8/sys/boot/i386/libi386/Makefile
  stable/8/sys/boot/i386/libi386/devicename.c
  stable/8/sys/boot/i386/libi386/libi386.h
  stable/8/sys/boot/i386/loader/conf.c
  stable/8/sys/boot/i386/loader/main.c
  stable/8/sys/boot/i386/zfsboot/zfsboot.c
  stable/8/sys/boot/ofw/libofw/Makefile
  stable/8/sys/boot/ofw/libofw/devicename.c
  stable/8/sys/boot/ofw/libofw/libofw.h
  stable/8/sys/boot/sparc64/loader/Makefile
  stable/8/sys/boot/sparc64/loader/main.c
  stable/8/sys/boot/zfs/zfs.c
  stable/8/sys/boot/zfs/zfsimpl.c
  stable/8/sys/cddl/boot/zfs/zfsimpl.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/boot/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/e1000/   (props changed)

Modified: stable/8/sys/boot/common/bootstrap.h
==============================================================================
--- stable/8/sys/boot/common/bootstrap.h        Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/common/bootstrap.h        Fri Jun 29 10:18:36 2012        
(r237765)
@@ -301,6 +301,9 @@ struct arch_switch
     void       (*arch_isaoutb)(int port, int value);
     /* Pass in initial kernel memory size */
     void        (*arch_maphint)(vm_offset_t va, size_t len);   
+
+    /* Probe ZFS pool(s), if needed. */
+    void       (*arch_zfs_probe)(void);
 };
 extern struct arch_switch archsw;
 

Modified: stable/8/sys/boot/i386/libi386/Makefile
==============================================================================
--- stable/8/sys/boot/i386/libi386/Makefile     Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/i386/libi386/Makefile     Fri Jun 29 10:18:36 2012        
(r237765)
@@ -9,6 +9,8 @@ SRCS=   biosacpi.c bioscd.c biosdisk.c bio
        elf64_freebsd.c \
        i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
        smbios.c time.c vidconsole.c amd64_tramp.S
+.PATH: ${.CURDIR}/../../zfs
+SRCS+= devicename_stubs.c
 
 # Enable PXE TFTP or NFS support, not both.
 .if defined(LOADER_TFTP_SUPPORT)

Modified: stable/8/sys/boot/i386/libi386/devicename.c
==============================================================================
--- stable/8/sys/boot/i386/libi386/devicename.c Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/i386/libi386/devicename.c Fri Jun 29 10:18:36 2012        
(r237765)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/disklabel.h>
 #include "bootstrap.h"
 #include "libi386.h"
+#include "../zfs/libzfs.h"
 
 static int     i386_parsedev(struct i386_devdesc **dev, const char *devspec, 
const char **path);
 
@@ -171,7 +172,6 @@ i386_parsedev(struct i386_devdesc **dev,
 
     case DEVT_CD:
     case DEVT_NET:
-    case DEVT_ZFS:
        unit = 0;
 
        if (*np && (*np != ':')) {
@@ -192,7 +192,11 @@ i386_parsedev(struct i386_devdesc **dev,
        if (path != NULL)
            *path = (*cp == 0) ? cp : cp + 1;
        break;
-
+    case DEVT_ZFS:
+       err = zfs_parsedev((struct zfs_devdesc *)idev, np, path);
+       if (err != 0)
+           goto fail;
+       break;
     default:
        err = EINVAL;
        goto fail;
@@ -247,9 +251,10 @@ i386_fmtdev(void *vdev)
        break;
 
     case DEVT_NET:
-    case DEVT_ZFS:
        sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
        break;
+    case DEVT_ZFS:
+       return(zfs_fmtdev(vdev));
     }
     return(buf);
 }

Modified: stable/8/sys/boot/i386/libi386/libi386.h
==============================================================================
--- stable/8/sys/boot/i386/libi386/libi386.h    Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/i386/libi386/libi386.h    Fri Jun 29 10:18:36 2012        
(r237765)
@@ -30,7 +30,8 @@
 /*
  * i386 fully-qualified device descriptor.
  * Note, this must match the 'struct devdesc' declaration
- * in bootstrap.h.
+ * in bootstrap.h and also with struct zfs_devdesc for zfs
+ * support.
  */
 struct i386_devdesc
 {
@@ -49,6 +50,12 @@ struct i386_devdesc
        {
            void        *data;
        } bioscd;
+       struct
+       {
+           void        *data;
+           uint64_t    pool_guid;
+           uint64_t    root_guid;
+       } zfs;
     } d_kind;
 };
 

Modified: stable/8/sys/boot/i386/loader/conf.c
==============================================================================
--- stable/8/sys/boot/i386/loader/conf.c        Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/i386/loader/conf.c        Fri Jun 29 10:18:36 2012        
(r237765)
@@ -30,6 +30,9 @@ __FBSDID("$FreeBSD$");
 #include <stand.h>
 #include <bootstrap.h>
 #include "libi386/libi386.h"
+#if defined(LOADER_ZFS_SUPPORT)
+#include "../zfs/libzfs.h"
+#endif
 
 /*
  * We could use linker sets for some or all of these, but
@@ -50,10 +53,6 @@ __FBSDID("$FreeBSD$");
 extern struct devsw fwohci;
 #endif
 
-#if defined(LOADER_ZFS_SUPPORT)
-extern struct devsw zfs_dev;
-#endif
-
 /* Exported for libstand */
 struct devsw *devsw[] = {
     &bioscd,
@@ -70,10 +69,6 @@ struct devsw *devsw[] = {
     NULL
 };
 
-#if defined(LOADER_ZFS_SUPPORT)
-extern struct fs_ops zfs_fsops;
-#endif
-
 struct fs_ops *file_system[] = {
     &ufs_fsops,
     &ext2fs_fsops,

Modified: stable/8/sys/boot/i386/loader/main.c
==============================================================================
--- stable/8/sys/boot/i386/loader/main.c        Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/i386/loader/main.c        Fri Jun 29 10:18:36 2012        
(r237765)
@@ -44,6 +44,10 @@ __FBSDID("$FreeBSD$");
 #include "libi386/libi386.h"
 #include "btxv86.h"
 
+#ifdef LOADER_ZFS_SUPPORT
+#include "../zfs/libzfs.h"
+#endif
+
 CTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE);
 CTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO);
 CTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS);
@@ -62,6 +66,9 @@ static void           extract_currdev(void);
 static int             isa_inb(int port);
 static void            isa_outb(int port, int value);
 void                   exit(int code);
+#ifdef LOADER_ZFS_SUPPORT
+static void            i386_zfs_probe(void);
+#endif
 
 /* from vers.c */
 extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
@@ -153,6 +160,9 @@ main(void)
     archsw.arch_readin = i386_readin;
     archsw.arch_isainb = isa_inb;
     archsw.arch_isaoutb = isa_outb;
+#ifdef LOADER_ZFS_SUPPORT
+    archsw.arch_zfs_probe = i386_zfs_probe;
+#endif
 
     /*
      * March through the device switch probing for things.
@@ -196,8 +206,11 @@ main(void)
 static void
 extract_currdev(void)
 {
-    struct i386_devdesc        new_currdev;
-    int                        biosdev = -1;
+    struct i386_devdesc                new_currdev;
+#ifdef LOADER_ZFS_SUPPORT
+    struct zfs_boot_args       *zargs;
+#endif
+    int                                biosdev = -1;
 
     /* Assume we are booting from a BIOS disk by default */
     new_currdev.d_dev = &biosdisk;
@@ -218,6 +231,24 @@ extract_currdev(void)
            new_currdev.d_kind.biosdisk.partition = 0;
            biosdev = -1;
        }
+#ifdef LOADER_ZFS_SUPPORT
+    } else if ((kargs->bootflags & KARGS_FLAGS_ZFS) != 0) {
+       zargs = NULL;
+       /* check for new style extended argument */
+       if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0)
+           zargs = (struct zfs_boot_args *)(kargs + 1);
+
+       if (zargs != NULL && zargs->size >= sizeof(*zargs)) {
+           /* sufficient data is provided */
+           new_currdev.d_kind.zfs.pool_guid = zargs->pool;
+           new_currdev.d_kind.zfs.root_guid = zargs->root;
+       } else {
+           /* old style zfsboot block */
+           new_currdev.d_kind.zfs.pool_guid = kargs->zfspool;
+           new_currdev.d_kind.zfs.root_guid = 0;
+       }
+       new_currdev.d_dev = &zfs_dev;
+#endif
     } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
        /* The passed-in boot device is bad */
        new_currdev.d_kind.biosdisk.slice = -1;
@@ -238,7 +269,7 @@ extract_currdev(void)
            biosdev = 0x80 + B_UNIT(initial_bootdev);           /* assume 
harddisk */
     }
     new_currdev.d_type = new_currdev.d_dev->dv_type;
-    
+
     /*
      * If we are booting off of a BIOS disk and we didn't succeed in 
determining
      * which one we booted off of, just use disk0: as a reasonable default.
@@ -249,33 +280,11 @@ extract_currdev(void)
               "Guessed BIOS device 0x%x not found by probes, defaulting to 
disk0:\n", biosdev);
        new_currdev.d_unit = 0;
     }
+
     env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
               i386_setcurrdev, env_nounset);
     env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset,
               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 = kargs->zfspool;
-       unit = zfs_guid_to_unit(guid);
-       if (unit >= 0) {
-           sprintf(devname, "zfs%d", unit);
-           setenv("currdev", devname, 1);
-       }
-    }
-#endif
 }
 
 COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
@@ -342,3 +351,30 @@ isa_outb(int port, int value)
     }
 }
 
+#ifdef LOADER_ZFS_SUPPORT
+static void
+i386_zfs_probe(void)
+{
+    char devname[32];
+    int unit, slice;
+
+    /*
+     * Open all the disks we can find and see if we can reconstruct
+     * ZFS pools from them. Bogusly assumes that the disks are named
+     * diskN, diskNpM or diskNsM.
+     */
+    for (unit = 0; unit < MAXBDDEV; unit++) {
+       sprintf(devname, "disk%d:", unit);
+       if (zfs_probe_dev(devname, NULL) == ENXIO)
+           continue;
+       for (slice = 1; slice <= 128; slice++) {
+           sprintf(devname, "disk%dp%d:", unit, slice);
+           zfs_probe_dev(devname, NULL);
+       }
+       for (slice = 1; slice <= 4; slice++) {
+           sprintf(devname, "disk%ds%d:", unit, slice);
+           zfs_probe_dev(devname, NULL);
+       }
+    }
+}
+#endif

Modified: stable/8/sys/boot/i386/zfsboot/zfsboot.c
==============================================================================
--- stable/8/sys/boot/i386/zfsboot/zfsboot.c    Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/i386/zfsboot/zfsboot.c    Fri Jun 29 10:18:36 2012        
(r237765)
@@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
 #include "cons.h"
 #include "bootargs.h"
 
+#include "libzfs.h"
+
 #define PATH_DOTCONFIG "/boot.config"
 #define PATH_CONFIG    "/boot/config"
 #define PATH_BOOT3     "/boot/zfsloader"
@@ -91,9 +93,12 @@ static const unsigned char dev_maj[NDEV]
 static char cmd[512];
 static char cmddup[512];
 static char kname[1024];
+static char rootname[256];
 static int comspeed = SIOSPD;
 static struct bootinfo bootinfo;
 static uint32_t bootdev;
+static struct zfs_boot_args zfsargs;
+static struct zfsmount zfsmount;
 
 vm_offset_t    high_heap_base;
 uint32_t       bios_basemem, bios_extmem, high_heap_size;
@@ -170,7 +175,7 @@ zfs_read(spa_t *spa, const dnode_phys_t 
 /*
  * Current ZFS pool
  */
-spa_t *spa;
+static spa_t *spa;
 
 /*
  * A wrapper for dskread that doesn't have to worry about whether the
@@ -209,7 +214,7 @@ static int
 xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte)
 {
     if ((size_t)zfs_read(spa, dnode, offp, buf, nbyte) != nbyte) {
-       printf("Invalid %s\n", "format");
+       printf("Invalid format\n");
        return -1;
     }
     return 0;
@@ -524,10 +529,12 @@ main(void)
        }
     }
 
-    zfs_mount_pool(spa);
-
-    if (zfs_lookup(spa, PATH_CONFIG, &dn) == 0 ||
-        zfs_lookup(spa, PATH_DOTCONFIG, &dn) == 0) {
+    if (zfs_spa_init(spa) != 0 || zfs_mount(spa, 0, &zfsmount) != 0) {
+       printf("%s: failed to mount default pool %s\n",
+           BOOTPROG, spa->spa_name);
+       autoboot = 0;
+    } else if (zfs_lookup(&zfsmount, PATH_CONFIG, &dn) == 0 ||
+        zfs_lookup(&zfsmount, PATH_DOTCONFIG, &dn) == 0) {
        off = 0;
        zfs_read(spa, &dn, &off, cmd, sizeof(cmd));
     }
@@ -562,11 +569,17 @@ main(void)
     /* Present the user with the boot2 prompt. */
 
     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) != 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))
@@ -602,7 +615,8 @@ load(void)
     uint32_t addr, x;
     int fmt, i, j;
 
-    if (zfs_lookup(spa, kname, &dn)) {
+    if (zfs_lookup(&zfsmount, kname, &dn)) {
+       printf("\nCan't find %s\n", kname);
        return;
     }
     off = 0;
@@ -676,12 +690,16 @@ load(void)
     }
     bootinfo.bi_esymtab = VTOP(p);
     bootinfo.bi_kernelname = VTOP(kname);
+    zfsargs.size = sizeof(zfsargs);
+    zfsargs.pool = zfsmount.spa->spa_guid;
+    zfsargs.root = zfsmount.rootobj;
     __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
           bootdev,
-          KARGS_FLAGS_ZFS,
+          KARGS_FLAGS_ZFS | KARGS_FLAGS_EXTARG,
           (uint32_t) spa->spa_guid,
           (uint32_t) (spa->spa_guid >> 32),
-          VTOP(&bootinfo));
+          VTOP(&bootinfo),
+          zfsargs);
 }
 
 static int
@@ -733,7 +751,7 @@ parse(void)
        } if (c == '?') {
            dnode_phys_t dn;
 
-           if (zfs_lookup(spa, arg, &dn) == 0) {
+           if (zfs_lookup(&zfsmount, arg, &dn) == 0) {
                zap_list(spa, &dn);
            }
            return -1;
@@ -755,17 +773,32 @@ parse(void)
            q = (char *) strchr(arg, ':');
            if (q) {
                spa_t *newspa;
+               uint64_t newroot;
 
                *q++ = 0;
                newspa = spa_find_by_name(arg);
                if (newspa) {
+                   arg = q;
                    spa = newspa;
-                   zfs_mount_pool(spa);
+                   newroot = 0;
+                   q = (char *) strchr(arg, ':');
+                   if (q) {
+                       *q++ = 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 = 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 = q;
            }
            if ((i = ep - arg)) {
                if ((size_t)i >= sizeof(kname))

Modified: stable/8/sys/boot/ofw/libofw/Makefile
==============================================================================
--- stable/8/sys/boot/ofw/libofw/Makefile       Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/ofw/libofw/Makefile       Fri Jun 29 10:18:36 2012        
(r237765)
@@ -6,6 +6,8 @@ INTERNALLIB=
 SRCS=  devicename.c elf_freebsd.c ofw_console.c ofw_copy.c ofw_disk.c \
        ofw_memory.c ofw_module.c ofw_net.c ofw_reboot.c \
        ofw_time.c openfirm.c
+.PATH: ${.CURDIR}/../../zfs
+SRCS+=  devicename_stubs.c
 
 CFLAGS+=       -I${.CURDIR}/../../../../lib/libstand/
 

Modified: stable/8/sys/boot/ofw/libofw/devicename.c
==============================================================================
--- stable/8/sys/boot/ofw/libofw/devicename.c   Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/ofw/libofw/devicename.c   Fri Jun 29 10:18:36 2012        
(r237765)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 
 #include "bootstrap.h"
 #include "libofw.h"
+#include "../zfs/libzfs.h"
 
 static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **);
 
@@ -81,6 +82,7 @@ ofw_parsedev(struct ofw_devdesc **dev, c
     char               *ep;
     char               name[256];
     char               type[64];
+    int                        err;
     int                        len;
     int                        i;
 
@@ -114,14 +116,11 @@ found:
     idev->d_dev = dv;
     idev->d_type = dv->dv_type;
     if (idev->d_type == DEVT_ZFS) {
-       idev->d_unit = 0;
-       p = name + strlen(dv->dv_name);
-       if (*p && (*p != ':')) {
-           idev->d_unit = strtol(p, &ep, 0);
-           if (ep == p) {
-               free(idev);
-               return (EUNIT);
-           }
+       p = devspec + strlen(dv->dv_name);
+       err = zfs_parsedev((struct zfs_devdesc *)idev, p, path);
+       if (err != 0) {
+           free(idev);
+           return (err);
        }
     }
 

Modified: stable/8/sys/boot/ofw/libofw/libofw.h
==============================================================================
--- stable/8/sys/boot/ofw/libofw/libofw.h       Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/ofw/libofw/libofw.h       Fri Jun 29 10:18:36 2012        
(r237765)
@@ -33,7 +33,13 @@ struct ofw_devdesc {
        int             d_type;
        int             d_unit;
        ihandle_t       d_handle;
-       char            d_path[256];
+       union {
+               char                    d_path[256];
+               struct {
+                       uint64_t        pool_guid;
+                       uint64_t        root_guid;
+               };
+       };
 };
 
 extern int     ofw_getdev(void **vdev, const char *devspec, const char **path);

Modified: stable/8/sys/boot/sparc64/loader/Makefile
==============================================================================
--- stable/8/sys/boot/sparc64/loader/Makefile   Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/sparc64/loader/Makefile   Fri Jun 29 10:18:36 2012        
(r237765)
@@ -37,6 +37,7 @@ CFLAGS+=      -DLOADER_CD9660_SUPPORT
 CFLAGS+=       -DLOADER_ZFS_SUPPORT
 CFLAGS+=       -I${.CURDIR}/../../zfs
 CFLAGS+=       -I${.CURDIR}/../../../cddl/boot/zfs
+LIBZFSBOOT=    ${.OBJDIR}/../../zfs/libzfsboot.a
 .endif
 .if ${LOADER_GZIP_SUPPORT} == "yes"
 CFLAGS+=       -DLOADER_GZIP_SUPPORT
@@ -83,8 +84,8 @@ CFLAGS+=      -I${.CURDIR}/../../ofw/libofw/
 # where to get libstand from
 CFLAGS+=       -I${.CURDIR}/../../../../lib/libstand/
 
-DPADD=         ${LIBFICL} ${LIBOFW} ${LIBSTAND}
-LDADD=         ${LIBFICL} ${LIBOFW} -lstand
+DPADD=         ${LIBFICL} ${LIBZFSBOOT} ${LIBOFW} ${LIBSTAND}
+LDADD=         ${LIBFICL} ${LIBZFSBOOT} ${LIBOFW} -lstand
 
 vers.c:        ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version
        sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/../loader/version \

Modified: stable/8/sys/boot/sparc64/loader/main.c
==============================================================================
--- stable/8/sys/boot/sparc64/loader/main.c     Fri Jun 29 10:12:27 2012        
(r237764)
+++ stable/8/sys/boot/sparc64/loader/main.c     Fri Jun 29 10:18:36 2012        
(r237765)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/types.h>
 #ifdef LOADER_ZFS_SUPPORT
 #include <sys/vtoc.h>
+#include "../zfs/libzfs.h"
 #endif
 
 #include <vm/vm.h>
@@ -74,6 +75,8 @@ __FBSDID("$FreeBSD$");
 #include "libofw.h"
 #include "dev_net.h"
 
+#define        MAXDEV  31
+
 extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
 
 enum {
@@ -154,11 +157,6 @@ static vm_offset_t heapva;
 
 static phandle_t root;
 
-#ifdef LOADER_ZFS_SUPPORT
-static int zfs_dev_init(void);
-#include "zfs.c"
-#endif
-
 /*
  * Machine dependent structures that the machine independent
  * loader part uses.
@@ -838,39 +836,20 @@ tlb_init_sun4v(void)
 }
 
 #ifdef LOADER_ZFS_SUPPORT
-
-static int
-zfs_dev_init(void)
+static void
+sparc64_zfs_probe(void)
 {
        struct vtoc8 vtoc;
-       char devname[512];
-       spa_t *spa;
-       vdev_t *vdev;
+       struct zfs_devdesc zfs_currdev;
+       char devname[32];
        uint64_t guid;
        int fd, part, unit;
 
-       zfs_init();
-
-       guid = 0;
        /* Get the GUID of the ZFS pool on the boot device. */
-       fd = open(getenv("currdev"), O_RDONLY);
-       if (fd != -1) {
-               if (vdev_probe(vdev_read, (void *)(uintptr_t) fd, &spa) == 0)
-                       guid = spa->spa_guid;
-               close(fd);
-       }
-
-       /* Clean up the environment to let ZFS work. */
-       while ((vdev = STAILQ_FIRST(&zfs_vdevs)) != NULL) {
-               STAILQ_REMOVE_HEAD(&zfs_vdevs, v_alllink);
-               free(vdev);
-       }
-       while ((spa = STAILQ_FIRST(&zfs_pools)) != NULL) {
-               STAILQ_REMOVE_HEAD(&zfs_pools, spa_link);
-               free(spa);
-       }
+       guid = 0;
+       zfs_probe_dev(getenv("currdev"), &guid);
 
-       for (unit = 0; unit < MAXBDDEV; unit++) {
+       for (unit = 0; unit < MAXDEV; unit++) {
                /* Find freebsd-zfs slices in the VTOC. */
                sprintf(devname, "disk%d:", unit);
                fd = open(devname, O_RDONLY);
@@ -888,29 +867,23 @@ zfs_dev_init(void)
                             VTOC_TAG_FREEBSD_ZFS)
                                continue;
                        sprintf(devname, "disk%d:%c", unit, part + 'a');
-                       fd = open(devname, O_RDONLY);
-                       if (fd == -1)
+                       if (zfs_probe_dev(devname, NULL) == ENXIO)
                                break;
-
-                       if (vdev_probe(vdev_read, (void*)(uintptr_t) fd, 0))
-                               close(fd);
                }
        }
 
        if (guid != 0) {
-               unit = zfs_guid_to_unit(guid);
-               if (unit >= 0) {
-                       /* Update the environment for ZFS. */
-                       sprintf(devname, "zfs%d", unit);
-                       env_setenv("currdev", EV_VOLATILE, devname,
-                          ofw_setcurrdev, env_nounset);
-                       env_setenv("loaddev", EV_VOLATILE, devname,
-                          env_noset, env_nounset);
-               }
+               zfs_currdev.pool_guid = guid;
+               zfs_currdev.root_guid = 0;
+               zfs_currdev.d_dev = &zfs_dev;
+               zfs_currdev.d_type = zfs_currdev.d_dev->dv_type;
+               /* Update the environment for ZFS. */
+               env_setenv("currdev", EV_VOLATILE, zfs_fmtdev(&zfs_currdev),
+                   ofw_setcurrdev, env_nounset);
+               env_setenv("loaddev", EV_VOLATILE, zfs_fmtdev(&zfs_currdev),
+                   env_noset, env_nounset);
        }
-       return (0);
 }
-
 #endif /* LOADER_ZFS_SUPPORT */
 
 int
@@ -931,6 +904,9 @@ main(int (*openfirm)(void *))
        archsw.arch_readin = sparc64_readin;
        archsw.arch_autoload = sparc64_autoload;
        archsw.arch_maphint = sparc64_maphint;
+#ifdef LOADER_ZFS_SUPPORT
+       archsw.arch_zfs_probe = sparc64_zfs_probe;
+#endif
 
        if (init_heap() == (vm_offset_t)-1)
                OF_exit();

Copied: stable/8/sys/boot/zfs/devicename_stubs.c (from r235329, 
head/sys/boot/zfs/devicename_stubs.c)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/8/sys/boot/zfs/devicename_stubs.c    Fri Jun 29 10:18:36 2012        
(r237765, copy of r235329, head/sys/boot/zfs/devicename_stubs.c)
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2012 Andriy Gapon <a...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include "libzfs.h"
+
+__attribute__((weak))
+int
+zfs_parsedev(struct zfs_devdesc *dev, const char *devspec, const char **path)
+{
+       return (EINVAL);
+}
+
+__attribute__((weak))
+char *
+zfs_fmtdev(void *vdev)
+{
+    static char        buf[128];
+
+    return (buf);
+}

Copied: stable/8/sys/boot/zfs/libzfs.h (from r235329, 
head/sys/boot/zfs/libzfs.h)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/8/sys/boot/zfs/libzfs.h      Fri Jun 29 10:18:36 2012        
(r237765, copy of r235329, head/sys/boot/zfs/libzfs.h)
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2012 Andriy Gapon <a...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BOOT_LIBZFS_H_
+#define _BOOT_LIBZFS_H_
+
+#define        ZFS_MAXNAMELEN  256
+
+/*
+ * ZFS fully-qualified device descriptor.
+ * Note, this must match the 'struct devdesc' declaration in bootstrap.h.
+ * Arch-specific device descriptors should be binary compatible with this
+ * structure if they are to support ZFS.
+ */
+struct zfs_devdesc
+{
+    struct devsw       *d_dev;
+    int                        d_type;
+    int                        d_unit;
+    void               *d_opendata;
+    uint64_t           pool_guid;
+    uint64_t           root_guid;
+};
+
+struct zfs_boot_args
+{
+    uint32_t           size;
+    uint32_t           reserved;
+    uint64_t           pool;
+    uint64_t           root;
+};
+
+int    zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
+                    const char **path);
+char   *zfs_fmtdev(void *vdev);
+int    zfs_probe_dev(const char *devname, uint64_t *pool_guid);
+
+extern struct devsw zfs_dev;
+extern struct fs_ops zfs_fsops;
+
+#endif /*_BOOT_LIBZFS_H_*/

Modified: stable/8/sys/boot/zfs/zfs.c
==============================================================================
--- stable/8/sys/boot/zfs/zfs.c Fri Jun 29 10:12:27 2012        (r237764)
+++ stable/8/sys/boot/zfs/zfs.c Fri Jun 29 10:18:36 2012        (r237765)
@@ -43,9 +43,9 @@ __FBSDID("$FreeBSD$");
 #include <stand.h>
 #include <bootstrap.h>
 
-#include "zfsimpl.c"
+#include "libzfs.h"
 
-#define        MAXBDDEV        31
+#include "zfsimpl.c"
 
 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);
@@ -56,6 +56,7 @@ static int    zfs_stat(struct open_file *f,
 static int     zfs_readdir(struct open_file *f, struct dirent *d);
 
 struct devsw zfs_dev;
+struct devsw zfs_dev_compat;
 
 struct fs_ops zfs_fsops = {
        "zfs",
@@ -85,35 +86,20 @@ struct file {
 static int
 zfs_open(const char *upath, struct open_file *f)
 {
-       spa_t *spa = (spa_t *) f->f_devdata;
+       struct zfsmount *mount = (struct zfsmount *)f->f_devdata;
        struct file *fp;
        int rc;
 
-       if (f->f_dev != &zfs_dev)
+       if (f->f_dev != &zfs_dev && f->f_dev != &zfs_dev_compat)
                return (EINVAL);
 
-       rc = zfs_mount_pool(spa);
-       if (rc)
-               return (rc);
-
        /* allocate file system specific data structure */
        fp = malloc(sizeof(struct file));
        bzero(fp, sizeof(struct file));
        f->f_fsdata = (void *)fp;
 
-       if (spa->spa_root_objset.os_type != DMU_OST_ZFS) {
-               printf("Unexpected object set type %llu\n",
-                   spa->spa_root_objset.os_type);
-               rc = EIO;
-               goto out;
-       }
-
-       rc = zfs_lookup(spa, upath, &fp->f_dnode);
-       if (rc)
-               goto out;
-
+       rc = zfs_lookup(mount, upath, &fp->f_dnode);
        fp->f_seekp = 0;
-out:
        if (rc) {
                f->f_fsdata = NULL;
                free(fp);
@@ -142,7 +128,7 @@ zfs_close(struct open_file *f)
 static int
 zfs_read(struct open_file *f, void *start, size_t size, size_t *resid  /* out 
*/)
 {
-       spa_t *spa = (spa_t *) f->f_devdata;
+       spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
        struct file *fp = (struct file *)f->f_fsdata;
        struct stat sb;
        size_t n;
@@ -216,7 +202,7 @@ zfs_seek(struct open_file *f, off_t offs
 static int
 zfs_stat(struct open_file *f, struct stat *sb)
 {
-       spa_t *spa = (spa_t *) f->f_devdata;
+       spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
        struct file *fp = (struct file *)f->f_fsdata;
 
        return (zfs_dnode_stat(spa, &fp->f_dnode, sb));
@@ -225,7 +211,7 @@ zfs_stat(struct open_file *f, struct sta
 static int
 zfs_readdir(struct open_file *f, struct dirent *d)
 {
-       spa_t *spa = (spa_t *) f->f_devdata;
+       spa_t *spa = ((struct zfsmount *)f->f_devdata)->spa;
        struct file *fp = (struct file *)f->f_fsdata;
        mzap_ent_phys_t mze;
        struct stat sb;
@@ -381,68 +367,33 @@ vdev_read(vdev_t *vdev, void *priv, off_
        }
 }
 
-/*
- * Convert a pool guid to a 'unit number' suitable for use with zfs_dev_open.
- */
-int
-zfs_guid_to_unit(uint64_t guid)
+static int
+zfs_dev_init(void)
 {
-       spa_t *spa;
-       int unit;
-
-       unit = 0;
-       STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
-               if (spa->spa_guid == guid)
-                       return unit;
-               unit++;
-       }
-       return (-1);
+       zfs_init();
+       if (archsw.arch_zfs_probe == NULL)
+               return (ENXIO);
+       archsw.arch_zfs_probe();
+       return (0);
 }
 
-#if defined(__amd64__) || defined(__i386__)
-static int
-zfs_dev_init(void) 
+int
+zfs_probe_dev(const char *devname, uint64_t *pool_guid)
 {
-       char devname[512];
-       int unit, slice;
+       spa_t *spa;
        int fd;
+       int ret;
 
-       /*
-        * Open all the disks we can find and see if we can reconstruct
-        * ZFS pools from them. Bogusly assumes that the disks are named
-        * diskN, diskNpM or diskNsM.
-        */
-       zfs_init();
-       for (unit = 0; unit < MAXBDDEV; unit++) {
-               sprintf(devname, "disk%d:", unit);
-               fd = open(devname, O_RDONLY);
-               if (fd == -1)
-                       continue;
-
-               /*
-                * If we find a vdev, the zfs code will eat the fd, otherwise
-                * we close it.
-                */
-               if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
-                       close(fd);
-
-               for (slice = 1; slice <= 128; slice++) {
-                       sprintf(devname, "disk%dp%d:", unit, slice);
-                       fd = open(devname, O_RDONLY);
-                       if (fd == -1) {
-                               sprintf(devname, "disk%ds%d:", unit, slice);
-                               fd = open(devname, O_RDONLY);
-                               if (fd == -1)
-                                       continue;
-                       }
-                       if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
-                               close(fd);
-               }
-       }
-
+       fd = open(devname, O_RDONLY);
+       if (fd == -1)
+               return (ENXIO);
+       ret = vdev_probe(vdev_read, (void *)(uintptr_t)fd, &spa);
+       if (ret != 0)
+               close(fd);
+       else if (pool_guid != NULL)
+               *pool_guid = spa->spa_guid;
        return (0);
 }
-#endif
 
 /*
  * Print information about ZFS pools
@@ -452,54 +403,52 @@ zfs_dev_print(int verbose)
 {
        spa_t *spa;
        char line[80];
-       int unit;
 
        if (verbose) {
                spa_all_status();
                return;
        }
-       unit = 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++;
        }
 }
 
 /*
  * Attempt to open the pool described by (dev) for use by (f).
  */
-static int 
+static int
 zfs_dev_open(struct open_file *f, ...)
 {
        va_list         args;
-       struct devdesc  *dev;
-       int             unit, i;
+       struct zfs_devdesc      *dev;
+       struct zfsmount *mount;
        spa_t           *spa;
+       int             rv;
 
        va_start(args, f);
-       dev = va_arg(args, struct devdesc*);
+       dev = va_arg(args, struct zfs_devdesc *);
        va_end(args);
 
-       /*
-        * 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 = dev->d_unit;
-       
-       i = 0;
-       STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
-               if (i == unit)
-                       break;
-               i++;
-       }
-       if (!spa) {
+       spa = spa_find_by_guid(dev->pool_guid);
+       if (!spa)
                return (ENXIO);
+       rv = zfs_spa_init(spa);
+       if (rv != 0)
+               return (rv);
+       mount = malloc(sizeof(*mount));
+       rv = zfs_mount(spa, dev->root_guid, mount);
+       if (rv != 0) {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to