[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Port latest grub zfs boot code to pygrub



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1271242614 -3600
# Node ID ae08db793febf3a8da6cd74f38988d69d87d81a5
# Parent  07befd9cf6d3097c3b44d857c8498a6ed14772c7
Port latest grub zfs boot code to pygrub

Signed-off-by: Mark Johnson <mark.r.johnson@xxxxxxxxxx>

Add -Werror to CFLAGS and fix numerous warnings/errors.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/libfsimage/Rules.mk                         |    3 
 tools/libfsimage/common/fsimage_grub.h            |    1 
 tools/libfsimage/zfs/Makefile                     |    3 
 tools/libfsimage/zfs/filesys.h                    |   33 
 tools/libfsimage/zfs/fsi_zfs.c                    |  158 ++++
 tools/libfsimage/zfs/fsi_zfs.h                    |  103 ++
 tools/libfsimage/zfs/fsys_zfs.c                   |  792 ++++++++++++----------
 tools/libfsimage/zfs/fsys_zfs.h                   |  102 +-
 tools/libfsimage/zfs/shared.h                     |   33 
 tools/libfsimage/zfs/zfs-include/dmu.h            |   21 
 tools/libfsimage/zfs/zfs-include/dnode.h          |    7 
 tools/libfsimage/zfs/zfs-include/dsl_dataset.h    |    2 
 tools/libfsimage/zfs/zfs-include/dsl_dir.h        |    2 
 tools/libfsimage/zfs/zfs-include/sa_impl.h        |   35 
 tools/libfsimage/zfs/zfs-include/spa.h            |  103 +-
 tools/libfsimage/zfs/zfs-include/uberblock_impl.h |    2 
 tools/libfsimage/zfs/zfs-include/vdev_impl.h      |   27 
 tools/libfsimage/zfs/zfs-include/zap_impl.h       |    5 
 tools/libfsimage/zfs/zfs-include/zap_leaf.h       |    2 
 tools/libfsimage/zfs/zfs-include/zfs.h            |   12 
 tools/libfsimage/zfs/zfs-include/zfs_acl.h        |    7 
 tools/libfsimage/zfs/zfs-include/zfs_znode.h      |    5 
 tools/libfsimage/zfs/zfs-include/zil.h            |   10 
 tools/libfsimage/zfs/zfs-include/zio.h            |   22 
 tools/libfsimage/zfs/zfs-include/zio_checksum.h   |    4 
 tools/libfsimage/zfs/zfs_fletcher.c               |    2 
 tools/libfsimage/zfs/zfs_lzjb.c                   |   15 
 tools/libfsimage/zfs/zfs_sha256.c                 |    2 
 28 files changed, 1021 insertions(+), 492 deletions(-)

diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/Rules.mk
--- a/tools/libfsimage/Rules.mk Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/Rules.mk Wed Apr 14 11:56:54 2010 +0100
@@ -1,6 +1,7 @@ include $(XEN_ROOT)/tools/Rules.mk
 include $(XEN_ROOT)/tools/Rules.mk
 
-CFLAGS += -I$(XEN_ROOT)/tools/libfsimage/common/ -Werror
+CFLAGS += -Wno-unknown-pragmas -I$(XEN_ROOT)/tools/libfsimage/common/
+CFLAGS += -Werror -D_GNU_SOURCE
 LDFLAGS += -L../common/
 
 PIC_OBJS := $(patsubst %.c,%.opic,$(LIB_SRCS-y))
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/common/fsimage_grub.h
--- a/tools/libfsimage/common/fsimage_grub.h    Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/common/fsimage_grub.h    Wed Apr 14 11:56:54 2010 +0100
@@ -78,6 +78,7 @@ unsigned long fsig_log2(unsigned long);
 #define        ERR_DEV_VALUES 1
 #define        ERR_WONT_FIT 1
 #define        ERR_READ 1
+#define        ERR_NEWER_VERSION 1
 
 fsi_plugin_ops_t *fsig_init(fsi_plugin_t *, fsig_plugin_ops_t *);
 
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/Makefile
--- a/tools/libfsimage/zfs/Makefile     Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/Makefile     Wed Apr 14 11:56:54 2010 +0100
@@ -24,7 +24,8 @@
 
 XEN_ROOT = ../../..
 
-LIB_SRCS-y = fsys_zfs.c zfs_lzjb.c zfs_sha256.c zfs_fletcher.c
+CFLAGS += -DFSYS_ZFS -DFSIMAGE -I$(XEN_ROOT)/tools/libfsimage/zfs
+LIB_SRCS-y = zfs_lzjb.c zfs_sha256.c zfs_fletcher.c fsi_zfs.c fsys_zfs.c
 
 FS = zfs
 
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/filesys.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/zfs/filesys.h    Wed Apr 14 11:56:54 2010 +0100
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _FILESYS_H
+#define _FILESYS_H
+
+#ifdef  FSYS_ZFS
+
+/* THIS FILE IS INTENTIONALLY BLANK */
+
+#endif  /* FSI_ZFS */
+
+#endif /* !_FILESYS_H */
+
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/fsi_zfs.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/zfs/fsi_zfs.c    Wed Apr 14 11:56:54 2010 +0100
@@ -0,0 +1,158 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifdef FSYS_ZFS
+
+#include <fsimage_grub.h>
+#include <fsimage_priv.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include "mb_info.h"
+
+
+#undef filemax
+#undef filepos
+#undef errnum
+
+
+#define        MAXNAMELEN      256
+#define        MAXPATHLEN      1024
+
+/**** START FROM disk_io.c ****/
+char current_rootpool[MAXNAMELEN];
+char current_bootfs[MAXNAMELEN];
+uint64_t current_bootfs_obj;
+char current_bootpath[MAXPATHLEN];
+char current_devid[MAXPATHLEN];
+int is_zfs_mount;
+unsigned long best_drive;
+unsigned long best_part;
+int find_best_root;
+unsigned long part_length;
+/**** END FROM disk_io.c ****/
+
+uint64_t filemax;
+uint64_t filepos;
+
+struct multiboot_info mbi;
+fsi_file_t *zfs_ffi;
+int errnum;
+char *bootstring = NULL;
+
+extern int zfs_mount(void);
+extern int zfs_open(char *filename);
+extern int zfs_read(char *buf, int len);
+
+#define        ZFS_SCRATCH_SIZE        0x400000
+#define        FSI_MOS_SHIFT   10
+#define        FSI_MOS_MASK    ((1 << FSI_MOS_SHIFT) - 1)
+unsigned char fsi_mos_buf[ZFS_SCRATCH_SIZE + FSI_MOS_MASK + 1];
+
+#define        FSI_MOS_ALIGN(addr)     (((uintptr_t)addr + FSI_MOS_MASK) & \
+                               ~FSI_MOS_MASK)
+#define        FSI_MOS(buf)            ((FSI_MOS_ALIGN(buf) + \
+                               ZFS_SCRATCH_SIZE - 0x100000) >> FSI_MOS_SHIFT)
+
+static int
+fsi_zfs_mount(fsi_file_t *ffi, const char *options)
+{
+       zfs_ffi = ffi;
+       mbi.mem_upper = FSI_MOS(fsi_mos_buf);
+
+       /* If an boot filesystem is passed in, set it to current_bootfs */
+       if (options != NULL) {
+               if (strlen(options) < MAXNAMELEN) {
+                       strcpy(current_bootfs, options);
+               }
+       }
+
+       return (zfs_mount());
+}
+
+static int
+fsi_zfs_open(fsi_file_t *ffi, char *filename)
+{
+       char *fsi_bootstring;
+       uint64_t *fmax;
+       uint64_t *fpos;
+       int rc;
+
+       zfs_ffi = ffi;
+       fmax = fsig_filemax(ffi);
+       fpos = fsig_filepos(ffi);
+
+       rc = zfs_open(filename);
+       if (rc != 1) {
+               return (rc);
+       }
+
+       *fmax = filemax;
+       *fpos = filepos;
+
+       if (bootstring == NULL) {
+               rc = asprintf(&bootstring,
+                             "zfs-bootfs=%s/%"PRIu64",bootpath='%s'",
+                             current_rootpool, current_bootfs_obj,
+                             current_bootpath);
+               if (rc == -1) {
+                       return (rc);
+               }
+               fsi_bootstring = fsi_bootstring_alloc(ffi->ff_fsi,
+                   strlen(bootstring) + 1);
+               strcpy(fsi_bootstring, bootstring);
+       }
+
+       return (rc);
+}
+
+static int
+fsi_zfs_read(fsi_file_t *ffi, char *buf, int len)
+{
+       uint64_t *fpos;
+       int rc;
+
+       zfs_ffi = ffi;
+       fpos = fsig_filepos(ffi);
+       filepos = *fpos;
+       rc = zfs_read(buf, len);
+       *fpos = filepos;
+
+       return (rc);
+}
+
+
+fsi_plugin_ops_t *
+fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
+{
+       static fsig_plugin_ops_t ops = {
+               FSIMAGE_PLUGIN_VERSION,
+               .fpo_mount = fsi_zfs_mount,
+               .fpo_dir = fsi_zfs_open,
+               .fpo_read = fsi_zfs_read,
+       };
+
+       *name = "zfs";
+       return (fsig_init(fp, &ops));
+}
+
+#endif /* FSYS_ZFS */
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/fsi_zfs.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/zfs/fsi_zfs.h    Wed Apr 14 11:56:54 2010 +0100
@@ -0,0 +1,103 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _FSI_ZFS_H
+#define _FSI_ZFS_H
+
+#ifdef  FSYS_ZFS
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <fsimage_grub.h>
+
+
+/*** START FROM shared.h ****/
+#include "mb_info.h"
+
+/* Boot signature related defines for the findroot command */
+#define        BOOTSIGN_DIR    "/boot/grub/bootsign"
+#define        BOOTSIGN_BACKUP "/etc/bootsign"
+
+/* Maybe redirect memory requests through grub_scratch_mem. */
+#define        RAW_ADDR(x)     (x)
+#define        RAW_SEG(x)      (x)
+
+/* ZFS will use the top 4 Meg of physical memory (below 4Gig) for sratch */
+#define        ZFS_SCRATCH_SIZE        0x400000
+
+#define        MAXPATHLEN      1024
+#define        MAXNAMELEN      256
+#define        MIN(x, y)       ((x) < (y) ? (x) : (y))
+
+#define        MAXUINT         0xFFFFFFFF
+
+#undef NULL
+#define NULL         ((void *) 0)
+
+#define grub_printf printf
+#define grub_strcmp strcmp
+#define grub_strncmp strncmp
+#define grub_strstr strstr
+#define grub_strlen strlen
+#define grub_memmove memmove
+
+extern char current_bootpath[MAXPATHLEN];
+extern char current_rootpool[MAXNAMELEN];
+extern char current_bootfs[MAXNAMELEN];
+extern uint64_t current_bootfs_obj;
+extern char current_devid[MAXPATHLEN];
+extern int is_zfs_mount;
+extern unsigned long best_drive;
+extern unsigned long best_part;
+extern int find_best_root;
+
+extern unsigned long part_length;
+
+#undef filemax
+#undef filepos
+extern uint64_t filemax;
+extern uint64_t filepos;
+
+extern struct multiboot_info mbi;
+
+/*** END FROM shared.h ***/
+
+#ifdef __linux__
+typedef unsigned char  uchar_t;
+#endif
+
+typedef struct fsi_file *fsi_file_handle_t;
+extern fsi_file_handle_t zfs_ffi;
+extern int fsig_devread(fsi_file_handle_t, unsigned int, unsigned int,
+    unsigned int, char *);
+
+#undef devread
+#define devread(a, b, c, d)    fsig_devread(zfs_ffi, a, b, c, d)
+
+#undef errnum
+extern int errnum;
+
+#endif  /* FSI_ZFS */
+
+#endif /* !_FSI_ZFS_H */
+
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/fsys_zfs.c
--- a/tools/libfsimage/zfs/fsys_zfs.c   Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/fsys_zfs.c   Wed Apr 14 11:56:54 2010 +0100
@@ -17,14 +17,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
- */
-
-/*
- * All files in the zfs directory are derived from the OpenSolaris
- * zfs grub files.  All files in the zfs-include directory were
- * included without changes.
  */
 
 /*
@@ -48,59 +42,37 @@
  *         +--------------------------------------------+
  */
 
-#include <stdio.h>
-#include <strings.h>
-
-/* From "shared.h" */
-#include "mb_info.h"
-
-/* Boot signature related defines for the findroot command */
-#define        BOOTSIGN_DIR    "/boot/grub/bootsign"
-#define        BOOTSIGN_BACKUP "/etc/bootsign"
-
-/* Maybe redirect memory requests through grub_scratch_mem. */
-#define        RAW_ADDR(x) (x)
-#define        RAW_SEG(x) (x)
-
-/* ZFS will use the top 4 Meg of physical memory (below 4Gig) for sratch */
-#define        ZFS_SCRATCH_SIZE 0x400000
-
-#define        MIN(x, y) ((x) < (y) ? (x) : (y))
-/* End from shared.h */
-
+#ifdef FSYS_ZFS
+
+#include "shared.h"
+#include "filesys.h"
 #include "fsys_zfs.h"
 
 /* cache for a file block of the currently zfs_open()-ed file */
-#define        file_buf zfs_ba->zfs_file_buf
-#define        file_start zfs_ba->zfs_file_start
-#define        file_end zfs_ba->zfs_file_end
+static void *file_buf = NULL;
+static uint64_t file_start = 0;
+static uint64_t file_end = 0;
 
 /* cache for a dnode block */
-#define        dnode_buf zfs_ba->zfs_dnode_buf
-#define        dnode_mdn zfs_ba->zfs_dnode_mdn
-#define        dnode_start zfs_ba->zfs_dnode_start
-#define        dnode_end zfs_ba->zfs_dnode_end
-
-#define        stackbase zfs_ba->zfs_stackbase
+static dnode_phys_t *dnode_buf = NULL;
+static dnode_phys_t *dnode_mdn = NULL;
+static uint64_t dnode_start = 0;
+static uint64_t dnode_end = 0;
+
+static uint64_t pool_guid = 0;
+static uberblock_t current_uberblock;
+static char *stackbase;
 
 decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] =
 {
-       {"noop", 0},
+       {"inherit", 0},                 /* ZIO_COMPRESS_INHERIT */
        {"on", lzjb_decompress},        /* ZIO_COMPRESS_ON */
-       {"off", 0},
-       {"lzjb", lzjb_decompress}       /* ZIO_COMPRESS_LZJB */
+       {"off", 0},                     /* ZIO_COMPRESS_OFF */
+       {"lzjb", lzjb_decompress},      /* ZIO_COMPRESS_LZJB */
+       {"empty", 0}                    /* ZIO_COMPRESS_EMPTY */
 };
 
-/* From disk_io.c */
-/* ZFS root filesystem for booting */
-#define        current_bootpath zfs_ba->zfs_current_bootpath
-#define        current_rootpool zfs_ba->zfs_current_rootpool
-#define        current_bootfs zfs_ba->zfs_current_bootfs
-#define        current_bootfs_obj zfs_ba->zfs_current_bootfs_obj
-#define        is_zfs_mount (*fsig_int1(ffi))
-/* End from disk_io.c */
-
-#define        is_zfs_open zfs_ba->zfs_open
+static int zio_read_data(blkptr_t *bp, void *buf, char *stack);
 
 /*
  * Our own version of bcmp().
@@ -108,8 +80,8 @@ static int
 static int
 zfs_bcmp(const void *s1, const void *s2, size_t n)
 {
-       const unsigned char *ps1 = s1;
-       const unsigned char *ps2 = s2;
+       const uchar_t *ps1 = s1;
+       const uchar_t *ps2 = s2;
 
        if (s1 != s2 && n != 0) {
                do {
@@ -146,15 +118,16 @@ zio_checksum_off(const void *buf, uint64
 
 /* Checksum Table and Values */
 zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = {
-       {{NULL,                 NULL},                  0, 0,   "inherit"},
-       {{NULL,                 NULL},                  0, 0,   "on"},
-       {{zio_checksum_off,     zio_checksum_off},      0, 0,   "off"},
-       {{zio_checksum_SHA256,  zio_checksum_SHA256},   1, 1,   "label"},
-       {{zio_checksum_SHA256,  zio_checksum_SHA256},   1, 1,   "gang_header"},
-       {{fletcher_2_native,    fletcher_2_byteswap},   0, 1,   "zilog"},
-       {{fletcher_2_native,    fletcher_2_byteswap},   0, 0,   "fletcher2"},
-       {{fletcher_4_native,    fletcher_4_byteswap},   1, 0,   "fletcher4"},
-       {{zio_checksum_SHA256,  zio_checksum_SHA256},   1, 0,   "SHA256"}
+       { { NULL, NULL }, 0, 0, "inherit" },
+       { { NULL, NULL }, 0, 0, "on" },
+       { { zio_checksum_off, zio_checksum_off }, 0, 0, "off" },
+       { { zio_checksum_SHA256, zio_checksum_SHA256 }, 1, 1, "label" },
+       { { zio_checksum_SHA256, zio_checksum_SHA256 }, 1, 1, "gang_header" },
+       { { NULL, NULL }, 0, 0, "zilog" },
+       { { fletcher_2_native, fletcher_2_byteswap }, 0, 0, "fletcher2" },
+       { { fletcher_4_native, fletcher_4_byteswap }, 1, 0, "fletcher4" },
+       { { zio_checksum_SHA256, zio_checksum_SHA256 }, 1, 0, "SHA256" },
+       { { NULL, NULL }, 0, 0, "zilog2" }
 };
 
 /*
@@ -170,10 +143,9 @@ zio_checksum_verify(blkptr_t *bp, char *
 zio_checksum_verify(blkptr_t *bp, char *data, int size)
 {
        zio_cksum_t zc = bp->blk_cksum;
-       uint32_t checksum = BP_IS_GANG(bp) ? ZIO_CHECKSUM_GANG_HEADER :
-           BP_GET_CHECKSUM(bp);
+       uint32_t checksum = BP_GET_CHECKSUM(bp);
        int byteswap = BP_SHOULD_BYTESWAP(bp);
-       zio_block_tail_t *zbt = (zio_block_tail_t *)(data + size) - 1;
+       zio_eck_t *zec = (zio_eck_t *)(data + size) - 1;
        zio_checksum_info_t *ci = &zio_checksum_table[checksum];
        zio_cksum_t actual_cksum, expected_cksum;
 
@@ -184,28 +156,14 @@ zio_checksum_verify(blkptr_t *bp, char *
        if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func[0] == NULL)
                return (-1);
 
-       if (ci->ci_zbt) {
-               if (checksum == ZIO_CHECKSUM_GANG_HEADER) {
-                       /*
-                        * 'gang blocks' is not supported.
-                        */
-                       return (-1);
-               }
-
-               if (zbt->zbt_magic == BSWAP_64(ZBT_MAGIC)) {
-                       /* byte swapping is not supported */
-                       return (-1);
-               } else {
-                       expected_cksum = zbt->zbt_cksum;
-                       zbt->zbt_cksum = zc;
-                       ci->ci_func[0](data, size, &actual_cksum);
-                       zbt->zbt_cksum = expected_cksum;
-               }
+       if (ci->ci_eck) {
+               expected_cksum = zec->zec_cksum;
+               zec->zec_cksum = zc;
+               ci->ci_func[0](data, size, &actual_cksum);
+               zec->zec_cksum = expected_cksum;
                zc = expected_cksum;
 
        } else {
-               if (BP_IS_GANG(bp))
-                       return (-1);
                ci->ci_func[byteswap](data, size, &actual_cksum);
        }
 
@@ -219,30 +177,14 @@ zio_checksum_verify(blkptr_t *bp, char *
 }
 
 /*
- * vdev_label_offset takes "offset" (the offset within a vdev_label) and
- * returns its physical disk offset (starting from the beginning of the vdev).
- *
- * Input:
- *     psize   : Physical size of this vdev
- *      l      : Label Number (0-3)
- *     offset  : The offset with a vdev_label in which we want the physical
- *               address
- * Return:
- *     Success : physical disk offset
- *     Failure : errnum = ERR_BAD_ARGUMENT, return value is meaningless
+ * vdev_label_start returns the physical disk offset (in bytes) of
+ * label "l".
  */
 static uint64_t
-vdev_label_offset(fsi_file_t *ffi, uint64_t psize, int l, uint64_t offset)
-{
-       /* XXX Need to add back label support! */
-       if (l >= VDEV_LABELS/2 || offset > sizeof (vdev_label_t)) {
-               errnum = ERR_BAD_ARGUMENT;
-               return (0);
-       }
-
-       return (offset + l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
+vdev_label_start(uint64_t psize, int l)
+{
+       return (l * sizeof (vdev_label_t) + (l < VDEV_LABELS / 2 ?
            0 : psize - VDEV_LABELS * sizeof (vdev_label_t)));
-
 }
 
 /*
@@ -283,7 +225,7 @@ vdev_uberblock_compare(uberblock_t *ub1,
  *    -1 - Failure
  */
 static int
-uberblock_verify(uberblock_phys_t *ub, int offset)
+uberblock_verify(uberblock_phys_t *ub, uint64_t offset)
 {
 
        uberblock_t *uber = &ub->ubp_uberblock;
@@ -297,7 +239,8 @@ uberblock_verify(uberblock_phys_t *ub, i
        if (zio_checksum_verify(&bp, (char *)ub, UBERBLOCK_SIZE) != 0)
                return (-1);
 
-       if (uber->ub_magic == UBERBLOCK_MAGIC && uber->ub_version > 0)
+       if (uber->ub_magic == UBERBLOCK_MAGIC &&
+           uber->ub_version > 0 && uber->ub_version <= SPA_VERSION)
                return (0);
 
        return (-1);
@@ -310,16 +253,15 @@ uberblock_verify(uberblock_phys_t *ub, i
  *    Failure - NULL
  */
 static uberblock_phys_t *
-find_bestub(fsi_file_t *ffi, uberblock_phys_t *ub_array, int label)
+find_bestub(uberblock_phys_t *ub_array, uint64_t sector)
 {
        uberblock_phys_t *ubbest = NULL;
-       int i, offset;
+       uint64_t offset;
+       int i;
 
        for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++) {
-               offset = vdev_label_offset(ffi, 0, label,
-                   VDEV_UBERBLOCK_OFFSET(i));
-               if (errnum == ERR_BAD_ARGUMENT)
-                       return (NULL);
+               offset = (sector << SPA_MINBLOCKSHIFT) +
+                   VDEV_UBERBLOCK_OFFSET(i);
                if (uberblock_verify(&ub_array[i], offset) == 0) {
                        if (ubbest == NULL) {
                                ubbest = &ub_array[i];
@@ -335,58 +277,142 @@ find_bestub(fsi_file_t *ffi, uberblock_p
 }
 
 /*
- * Read in a block and put its uncompressed data in buf.
+ * Read a block of data based on the gang block address dva,
+ * and put its data in buf.
  *
  * Return:
  *     0 - success
- *     errnum - failure
- */
-static int
-zio_read(fsi_file_t *ffi, blkptr_t *bp, void *buf, char *stack)
-{
+ *     1 - failure
+ */
+static int
+zio_read_gang(blkptr_t *bp, dva_t *dva, void *buf, char *stack)
+{
+       zio_gbh_phys_t *zio_gb;
        uint64_t offset, sector;
-       int psize, lsize;
-       int i, comp, cksum;
+       blkptr_t tmpbp;
+       int i;
+
+       zio_gb = (zio_gbh_phys_t *)stack;
+       stack += SPA_GANGBLOCKSIZE;
+       offset = DVA_GET_OFFSET(dva);
+       sector =  DVA_OFFSET_TO_PHYS_SECTOR(offset);
+
+       /* read in the gang block header */
+       if (devread(sector, 0, SPA_GANGBLOCKSIZE, (char *)zio_gb) == 0) {
+               grub_printf("failed to read in a gang block header\n");
+               return (1);
+       }
+
+       /* self checksuming the gang block header */
+       BP_ZERO(&tmpbp);
+       BP_SET_CHECKSUM(&tmpbp, ZIO_CHECKSUM_GANG_HEADER);
+       BP_SET_BYTEORDER(&tmpbp, ZFS_HOST_BYTEORDER);
+       ZIO_SET_CHECKSUM(&tmpbp.blk_cksum, DVA_GET_VDEV(dva),
+           DVA_GET_OFFSET(dva), bp->blk_birth, 0);
+       if (zio_checksum_verify(&tmpbp, (char *)zio_gb, SPA_GANGBLOCKSIZE)) {
+               grub_printf("failed to checksum a gang block header\n");
+               return (1);
+       }
+
+       for (i = 0; i < SPA_GBH_NBLKPTRS; i++) {
+               if (zio_gb->zg_blkptr[i].blk_birth == 0)
+                       continue;
+
+               if (zio_read_data(&zio_gb->zg_blkptr[i], buf, stack))
+                       return (1);
+               buf += BP_GET_PSIZE(&zio_gb->zg_blkptr[i]);
+       }
+
+       return (0);
+}
+
+/*
+ * Read in a block of raw data to buf.
+ *
+ * Return:
+ *     0 - success
+ *     1 - failure
+ */
+static int
+zio_read_data(blkptr_t *bp, void *buf, char *stack)
+{
+       int i, psize;
 
        psize = BP_GET_PSIZE(bp);
-       lsize = BP_GET_LSIZE(bp);
-       comp = BP_GET_COMPRESS(bp);
-       cksum = BP_GET_CHECKSUM(bp);
-
-       if ((unsigned int)comp >= ZIO_COMPRESS_FUNCTIONS ||
-           (comp != ZIO_COMPRESS_OFF &&
-           decomp_table[comp].decomp_func == NULL))
-               return (ERR_FSYS_CORRUPT);
 
        /* pick a good dva from the block pointer */
        for (i = 0; i < SPA_DVAS_PER_BP; i++) {
+               uint64_t offset, sector;
 
                if (bp->blk_dva[i].dva_word[0] == 0 &&
                    bp->blk_dva[i].dva_word[1] == 0)
                        continue;
 
-               /* read in a block */
-               offset = DVA_GET_OFFSET(&bp->blk_dva[i]);
-               sector =  DVA_OFFSET_TO_PHYS_SECTOR(offset);
-
-               if (comp != ZIO_COMPRESS_OFF) {
-
-                       if (devread(ffi, sector, 0, psize, stack) == 0)
-                               continue;
-                       if (zio_checksum_verify(bp, stack, psize) != 0)
-                               continue;
-                       decomp_table[comp].decomp_func(stack, buf, psize,
-                           lsize);
+               if (DVA_GET_GANG(&bp->blk_dva[i])) {
+                       if (zio_read_gang(bp, &bp->blk_dva[i], buf, stack) == 0)
+                               return (0);
                } else {
-                       if (devread(ffi, sector, 0, psize, buf) == 0)
-                               continue;
-                       if (zio_checksum_verify(bp, buf, psize) != 0)
-                               continue;
+                       /* read in a data block */
+                       offset = DVA_GET_OFFSET(&bp->blk_dva[i]);
+                       sector =  DVA_OFFSET_TO_PHYS_SECTOR(offset);
+                       if (devread(sector, 0, psize, buf))
+                               return (0);
                }
-               return (0);
-       }
-
-       return (ERR_FSYS_CORRUPT);
+       }
+
+       return (1);
+}
+
+/*
+ * Read in a block of data, verify its checksum, decompress if needed,
+ * and put the uncompressed data in buf.
+ *
+ * Return:
+ *     0 - success
+ *     errnum - failure
+ */
+static int
+zio_read(blkptr_t *bp, void *buf, char *stack)
+{
+       int lsize, psize, comp;
+       char *retbuf;
+
+       comp = BP_GET_COMPRESS(bp);
+       lsize = BP_GET_LSIZE(bp);
+       psize = BP_GET_PSIZE(bp);
+
+       if ((unsigned int)comp >= ZIO_COMPRESS_FUNCTIONS ||
+           (comp != ZIO_COMPRESS_OFF &&
+           decomp_table[comp].decomp_func == NULL)) {
+               grub_printf("compression algorithm not supported\n");
+               return (ERR_FSYS_CORRUPT);
+       }
+
+       if ((char *)buf < stack && ((char *)buf) + lsize > stack) {
+               grub_printf("not enough memory allocated\n");
+               return (ERR_WONT_FIT);
+       }
+
+       retbuf = buf;
+       if (comp != ZIO_COMPRESS_OFF) {
+               buf = stack;
+               stack += psize;
+       }
+
+       if (zio_read_data(bp, buf, stack)) {
+               grub_printf("zio_read_data failed\n");
+               return (ERR_FSYS_CORRUPT);
+       }
+
+       if (zio_checksum_verify(bp, buf, psize) != 0) {
+               grub_printf("checksum verification failed\n");
+               return (ERR_FSYS_CORRUPT);
+       }
+
+       if (comp != ZIO_COMPRESS_OFF)
+               decomp_table[comp].decomp_func(buf, retbuf, psize, lsize);
+
+       return (0);
 }
 
 /*
@@ -398,8 +424,7 @@ zio_read(fsi_file_t *ffi, blkptr_t *bp, 
  *     errnum - failure
  */
 static int
-dmu_read(fsi_file_t *ffi, dnode_phys_t *dn, uint64_t blkid, void *buf,
-    char *stack)
+dmu_read(dnode_phys_t *dn, uint64_t blkid, void *buf, char *stack)
 {
        int idx, level;
        blkptr_t *bp_array = dn->dn_blkptr;
@@ -421,9 +446,10 @@ dmu_read(fsi_file_t *ffi, dnode_phys_t *
                        grub_memset(buf, 0,
                            dn->dn_datablkszsec << SPA_MINBLOCKSHIFT);
                        break;
-               } else if ((errnum = zio_read(ffi, bp, tmpbuf, stack))) {
+               } else if ((errnum = zio_read(bp, tmpbuf, stack))) {
                        return (errnum);
                }
+
                bp_array = tmpbuf;
        }
 
@@ -447,7 +473,7 @@ mzap_lookup(mzap_phys_t *zapobj, int obj
 
        chunks = objsize/MZAP_ENT_LEN - 1;
        for (i = 0; i < chunks; i++) {
-               if (strcmp(mzap_ent[i].mze_name, name) == 0) {
+               if (grub_strcmp(mzap_ent[i].mze_name, name) == 0) {
                        *value = mzap_ent[i].mze_value;
                        return (0);
                }
@@ -457,7 +483,7 @@ mzap_lookup(mzap_phys_t *zapobj, int obj
 }
 
 static uint64_t
-zap_hash(fsi_file_t *ffi, uint64_t salt, const char *name)
+zap_hash(uint64_t salt, const char *name)
 {
        static uint64_t table[256];
        const uint8_t *cp;
@@ -488,7 +514,7 @@ zap_hash(fsi_file_t *ffi, uint64_t salt,
         * those are the onces that we first pay attention to when
         * chosing the bucket.
         */
-       crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1);
+       crc &= ~((1ULL << (64 - 28)) - 1);
 
        return (crc);
 }
@@ -590,7 +616,7 @@ zap_leaf_lookup(zap_leaf_phys_t *l, int 
  *     errnum - failure
  */
 static int
-fzap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, zap_phys_t *zap,
+fzap_lookup(dnode_phys_t *zap_dnode, zap_phys_t *zap,
     char *name, uint64_t *value, char *stack)
 {
        zap_leaf_phys_t *l;
@@ -598,10 +624,11 @@ fzap_lookup(fsi_file_t *ffi, dnode_phys_
        int blksft = zfs_log2(zap_dnode->dn_datablkszsec << DNODE_SHIFT);
 
        /* Verify if this is a fat zap header block */
-       if (zap->zap_magic != (uint64_t)ZAP_MAGIC)
-               return (ERR_FSYS_CORRUPT);
-
-       hash = zap_hash(ffi, zap->zap_salt, name);
+       if (zap->zap_magic != (uint64_t)ZAP_MAGIC ||
+           zap->zap_flags != 0)
+               return (ERR_FSYS_CORRUPT);
+
+       hash = zap_hash(zap->zap_salt, name);
        if (errnum)
                return (errnum);
 
@@ -616,7 +643,9 @@ fzap_lookup(fsi_file_t *ffi, dnode_phys_
        /* Get the leaf block */
        l = (zap_leaf_phys_t *)stack;
        stack += 1<<blksft;
-       if ((errnum = dmu_read(ffi, zap_dnode, blkid, l, stack)))
+       if ((1<<blksft) < sizeof (zap_leaf_phys_t))
+               return (ERR_FSYS_CORRUPT);
+       if ((errnum = dmu_read(zap_dnode, blkid, l, stack)))
                return (errnum);
 
        return (zap_leaf_lookup(l, blksft, hash, name, value));
@@ -631,8 +660,7 @@ fzap_lookup(fsi_file_t *ffi, dnode_phys_
  *     errnum - failure
  */
 static int
-zap_lookup(fsi_file_t *ffi, dnode_phys_t *zap_dnode, char *name,
-    uint64_t *val, char *stack)
+zap_lookup(dnode_phys_t *zap_dnode, char *name, uint64_t *val, char *stack)
 {
        uint64_t block_type;
        int size;
@@ -642,7 +670,8 @@ zap_lookup(fsi_file_t *ffi, dnode_phys_t
        zapbuf = stack;
        size = zap_dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
        stack += size;
-       if ((errnum = dmu_read(ffi, zap_dnode, 0, zapbuf, stack)))
+
+       if ((errnum = dmu_read(zap_dnode, 0, zapbuf, stack)))
                return (errnum);
 
        block_type = *((uint64_t *)zapbuf);
@@ -651,7 +680,7 @@ zap_lookup(fsi_file_t *ffi, dnode_phys_t
                return (mzap_lookup(zapbuf, size, name, val));
        } else if (block_type == ZBT_HEADER) {
                /* this is a fat zap */
-               return (fzap_lookup(ffi, zap_dnode, zapbuf, name,
+               return (fzap_lookup(zap_dnode, zapbuf, name,
                    val, stack));
        }
 
@@ -672,14 +701,13 @@ zap_lookup(fsi_file_t *ffi, dnode_phys_t
  *     errnum - failure
  */
 static int
-dnode_get(fsi_file_t *ffi, dnode_phys_t *mdn, uint64_t objnum,
-    uint8_t type, dnode_phys_t *buf, char *stack)
+dnode_get(dnode_phys_t *mdn, uint64_t objnum, uint8_t type, dnode_phys_t *buf,
+       char *stack)
 {
        uint64_t blkid, blksz; /* the block id this object dnode is in */
        int epbs; /* shift of number of dnodes in a block */
        int idx; /* index within a block */
        dnode_phys_t *dnbuf;
-       zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;
 
        blksz = mdn->dn_datablkszsec << SPA_MINBLOCKSHIFT;
        epbs = zfs_log2(blksz) - DNODE_SHIFT;
@@ -703,7 +731,7 @@ dnode_get(fsi_file_t *ffi, dnode_phys_t 
                stack += blksz;
        }
 
-       if ((errnum = dmu_read(ffi, mdn, blkid, (char *)dnbuf, stack)))
+       if ((errnum = dmu_read(mdn, blkid, (char *)dnbuf, stack)))
                return (errnum);
 
        grub_memmove(buf, &dnbuf[idx], DNODE_SIZE);
@@ -723,16 +751,16 @@ is_top_dataset_file(char *str)
 {
        char *tptr;
 
-       if (((tptr = strstr(str, "menu.lst"))) &&
+       if ((tptr = grub_strstr(str, "menu.lst")) &&
            (tptr[8] == '\0' || tptr[8] == ' ') &&
            *(tptr-1) == '/')
                return (1);
 
-       if (strncmp(str, BOOTSIGN_DIR"/",
-           strlen(BOOTSIGN_DIR) + 1) == 0)
+       if (grub_strncmp(str, BOOTSIGN_DIR"/",
+           grub_strlen(BOOTSIGN_DIR) + 1) == 0)
                return (1);
 
-       if (strcmp(str, BOOTSIGN_BACKUP) == 0)
+       if (grub_strcmp(str, BOOTSIGN_BACKUP) == 0)
                return (1);
 
        return (0);
@@ -748,23 +776,25 @@ is_top_dataset_file(char *str)
  *     errnum - failure
  */
 static int
-dnode_get_path(fsi_file_t *ffi, dnode_phys_t *mdn, char *path,
-    dnode_phys_t *dn, char *stack)
+dnode_get_path(dnode_phys_t *mdn, char *path, dnode_phys_t *dn,
+    char *stack)
 {
        uint64_t objnum, version;
        char *cname, ch;
 
-       if ((errnum = dnode_get(ffi, mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,
+       if ((errnum = dnode_get(mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,
            dn, stack)))
                return (errnum);
 
-       if ((errnum = zap_lookup(ffi, dn, ZPL_VERSION_STR, &version, stack)))
+       if ((errnum = zap_lookup(dn, ZPL_VERSION_STR, &version, stack)))
                return (errnum);
-
-       if ((errnum = zap_lookup(ffi, dn, ZFS_ROOT_OBJ, &objnum, stack)))
+       if (version > ZPL_VERSION)
+               return (-1);
+
+       if ((errnum = zap_lookup(dn, ZFS_ROOT_OBJ, &objnum, stack)))
                return (errnum);
 
-       if ((errnum = dnode_get(ffi, mdn, objnum, DMU_OT_DIRECTORY_CONTENTS,
+       if ((errnum = dnode_get(mdn, objnum, DMU_OT_DIRECTORY_CONTENTS,
            dn, stack)))
                return (errnum);
 
@@ -772,20 +802,20 @@ dnode_get_path(fsi_file_t *ffi, dnode_ph
        while (*path == '/')
                path++;
 
-       while (*path && !isspace((uint8_t)*path)) {
+       while (*path && !isspace(*path)) {
 
                /* get the next component name */
                cname = path;
-               while (*path && !isspace((uint8_t)*path) && *path != '/')
+               while (*path && !isspace(*path) && *path != '/')
                        path++;
                ch = *path;
                *path = 0;   /* ensure null termination */
 
-               if ((errnum = zap_lookup(ffi, dn, cname, &objnum, stack)))
+               if ((errnum = zap_lookup(dn, cname, &objnum, stack)))
                        return (errnum);
 
                objnum = ZFS_DIRENT_OBJ(objnum);
-               if ((errnum = dnode_get(ffi, mdn, objnum, 0, dn, stack)))
+               if ((errnum = dnode_get(mdn, objnum, 0, dn, stack)))
                        return (errnum);
 
                *path = ch;
@@ -807,14 +837,13 @@ dnode_get_path(fsi_file_t *ffi, dnode_ph
  *     errnum -failure
  */
 static int
-get_default_bootfsobj(fsi_file_t *ffi, dnode_phys_t *mosmdn,
-    uint64_t *obj, char *stack)
+get_default_bootfsobj(dnode_phys_t *mosmdn, uint64_t *obj, char *stack)
 {
        uint64_t objnum = 0;
        dnode_phys_t *dn = (dnode_phys_t *)stack;
        stack += DNODE_SIZE;
 
-       if ((errnum = dnode_get(ffi, mosmdn, DMU_POOL_DIRECTORY_OBJECT,
+       if ((errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
            DMU_OT_OBJECT_DIRECTORY, dn, stack)))
                return (errnum);
 
@@ -822,19 +851,17 @@ get_default_bootfsobj(fsi_file_t *ffi, d
         * find the object number for 'pool_props', and get the dnode
         * of the 'pool_props'.
         */
-       if (zap_lookup(ffi, dn, DMU_POOL_PROPS, &objnum, stack))
+       if (zap_lookup(dn, DMU_POOL_PROPS, &objnum, stack))
                return (ERR_FILESYSTEM_NOT_FOUND);
 
-       if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_POOL_PROPS, dn,
-           stack)))
+       if ((errnum = dnode_get(mosmdn, objnum, DMU_OT_POOL_PROPS, dn, stack)))
                return (errnum);
 
-       if (zap_lookup(ffi, dn, ZPOOL_PROP_BOOTFS, &objnum, stack))
+       if (zap_lookup(dn, ZPOOL_PROP_BOOTFS, &objnum, stack))
                return (ERR_FILESYSTEM_NOT_FOUND);
 
        if (!objnum)
                return (ERR_FILESYSTEM_NOT_FOUND);
-
 
        *obj = objnum;
        return (0);
@@ -854,29 +881,30 @@ get_default_bootfsobj(fsi_file_t *ffi, d
  *     errnum - failure
  */
 static int
-get_objset_mdn(fsi_file_t *ffi, dnode_phys_t *mosmdn, char *fsname,
-    uint64_t *obj, dnode_phys_t *mdn, char *stack)
+get_objset_mdn(dnode_phys_t *mosmdn, char *fsname, uint64_t *obj,
+    dnode_phys_t *mdn, char *stack)
 {
        uint64_t objnum, headobj;
        char *cname, ch;
        blkptr_t *bp;
        objset_phys_t *osp;
+       int issnapshot = 0;
+       char *snapname = NULL;
 
        if (fsname == NULL && obj) {
                headobj = *obj;
                goto skip;
        }
 
-       if ((errnum = dnode_get(ffi, mosmdn, DMU_POOL_DIRECTORY_OBJECT,
+       if ((errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
            DMU_OT_OBJECT_DIRECTORY, mdn, stack)))
                return (errnum);
 
-       if ((errnum = zap_lookup(ffi, mdn, DMU_POOL_ROOT_DATASET, &objnum,
+       if ((errnum = zap_lookup(mdn, DMU_POOL_ROOT_DATASET, &objnum,
            stack)))
                return (errnum);
 
-       if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_DSL_DIR, mdn,
-           stack)))
+       if ((errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR, mdn, stack)))
                return (errnum);
 
        if (fsname == NULL) {
@@ -886,51 +914,74 @@ get_objset_mdn(fsi_file_t *ffi, dnode_ph
        }
 
        /* take out the pool name */
-       while (*fsname && !isspace((uint8_t)*fsname) && *fsname != '/')
+       while (*fsname && !isspace(*fsname) && *fsname != '/')
                fsname++;
 
-       while (*fsname && !isspace((uint8_t)*fsname)) {
+       while (*fsname && !isspace(*fsname)) {
                uint64_t childobj;
 
                while (*fsname == '/')
                        fsname++;
 
                cname = fsname;
-               while (*fsname && !isspace((uint8_t)*fsname) && *fsname != '/')
+               while (*fsname && !isspace(*fsname) && *fsname != '/')
                        fsname++;
                ch = *fsname;
                *fsname = 0;
 
+               snapname = cname;
+               while (*snapname && !isspace(*snapname) && *snapname != '@')
+                       snapname++;
+               if (*snapname == '@') {
+                       issnapshot = 1;
+                       *snapname = 0;
+               }
                childobj =
                    ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_child_dir_zapobj;
-               if ((errnum = dnode_get(ffi, mosmdn, childobj,
+               if ((errnum = dnode_get(mosmdn, childobj,
                    DMU_OT_DSL_DIR_CHILD_MAP, mdn, stack)))
                        return (errnum);
 
-               if (zap_lookup(ffi, mdn, cname, &objnum, stack))
+               if (zap_lookup(mdn, cname, &objnum, stack))
                        return (ERR_FILESYSTEM_NOT_FOUND);
 
-               if ((errnum = dnode_get(ffi, mosmdn, objnum, DMU_OT_DSL_DIR,
+               if ((errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR,
                    mdn, stack)))
                        return (errnum);
 
                *fsname = ch;
+               if (issnapshot)
+                       *snapname = '@';
        }
        headobj = ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_head_dataset_obj;
        if (obj)
                *obj = headobj;
 
 skip:
-       if ((errnum = dnode_get(ffi, mosmdn, headobj, DMU_OT_DSL_DATASET, mdn,
-           stack)))
+       if ((errnum = dnode_get(mosmdn, headobj, DMU_OT_DSL_DATASET, mdn, 
stack)))
                return (errnum);
-
-       /* TODO: Add snapshot support here - for fsname=snapshot-name */
+       if (issnapshot) {
+               uint64_t snapobj;
+
+               snapobj = ((dsl_dataset_phys_t *)DN_BONUS(mdn))->
+                   ds_snapnames_zapobj;
+
+               if ((errnum = dnode_get(mosmdn, snapobj,
+                   DMU_OT_DSL_DS_SNAP_MAP, mdn, stack)))
+                       return (errnum);
+               if (zap_lookup(mdn, snapname + 1, &headobj, stack))
+                       return (ERR_FILESYSTEM_NOT_FOUND);
+               if ((errnum = dnode_get(mosmdn, headobj,
+                   DMU_OT_DSL_DATASET, mdn, stack)))
+                       return (errnum);
+               if (obj)
+                       *obj = headobj;
+       }
 
        bp = &((dsl_dataset_phys_t *)DN_BONUS(mdn))->ds_bp;
        osp = (objset_phys_t *)stack;
        stack += sizeof (objset_phys_t);
-       if ((errnum = zio_read(ffi, bp, osp, stack)))
+       if ((errnum = zio_read(bp, osp, stack)))
                return (errnum);
 
        grub_memmove((char *)mdn, (char *)&osp->os_meta_dnode, DNODE_SIZE);
@@ -1019,11 +1070,11 @@ nvlist_lookup_value(char *nvlist, char *
                type = BSWAP_32(*(uint32_t *)nvpair);
                nvpair += 4;
 
-               if (((strncmp(nvp_name, name, name_len) == 0) &&
-                   type == valtype)) {
+               if ((grub_strncmp(nvp_name, name, name_len) == 0) &&
+                   type == valtype) {
                        int nelm;
 
-                       if (((nelm = BSWAP_32(*(uint32_t *)nvpair)) < 1))
+                       if ((nelm = BSWAP_32(*(uint32_t *)nvpair)) < 1)
                                return (1);
                        nvpair += 4;
 
@@ -1069,8 +1120,6 @@ vdev_validate(char *nv)
            DATA_TYPE_UINT64, NULL) == 0 ||
            nvlist_lookup_value(nv, ZPOOL_CONFIG_FAULTED, &ival,
            DATA_TYPE_UINT64, NULL) == 0 ||
-           nvlist_lookup_value(nv, ZPOOL_CONFIG_DEGRADED, &ival,
-           DATA_TYPE_UINT64, NULL) == 0 ||
            nvlist_lookup_value(nv, ZPOOL_CONFIG_REMOVED, &ival,
            DATA_TYPE_UINT64, NULL) == 0)
                return (ERR_DEV_VALUES);
@@ -1079,26 +1128,58 @@ vdev_validate(char *nv)
 }
 
 /*
- * Get a list of valid vdev pathname from the boot device.
- * The caller should already allocate MAXNAMELEN memory for bootpath.
- */
-static int
-vdev_get_bootpath(char *nv, char *bootpath)
+ * Get a valid vdev pathname/devid from the boot device.
+ * The caller should already allocate MAXPATHLEN memory for bootpath and devid.
+ */
+static int
+vdev_get_bootpath(char *nv, uint64_t inguid, char *devid, char *bootpath,
+    int is_spare)
 {
        char type[16];
 
-       bootpath[0] = '\0';
        if (nvlist_lookup_value(nv, ZPOOL_CONFIG_TYPE, &type, DATA_TYPE_STRING,
            NULL))
                return (ERR_FSYS_CORRUPT);
 
        if (strcmp(type, VDEV_TYPE_DISK) == 0) {
-               if (vdev_validate(nv) != 0 ||
-                   nvlist_lookup_value(nv, ZPOOL_CONFIG_PHYS_PATH, bootpath,
-                   DATA_TYPE_STRING, NULL) != 0)
+               uint64_t guid;
+
+               if (vdev_validate(nv) != 0)
                        return (ERR_NO_BOOTPATH);
 
-       } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {
+               if (nvlist_lookup_value(nv, ZPOOL_CONFIG_GUID,
+                   &guid, DATA_TYPE_UINT64, NULL) != 0)
+                       return (ERR_NO_BOOTPATH);
+
+               if (guid != inguid)
+                       return (ERR_NO_BOOTPATH);
+
+               /* for a spare vdev, pick the disk labeled with "is_spare" */
+               if (is_spare) {
+                       uint64_t spare = 0;
+                       (void) nvlist_lookup_value(nv, ZPOOL_CONFIG_IS_SPARE,
+                           &spare, DATA_TYPE_UINT64, NULL);
+                       if (!spare)
+                               return (ERR_NO_BOOTPATH);
+               }
+
+               if (nvlist_lookup_value(nv, ZPOOL_CONFIG_PHYS_PATH,
+                   bootpath, DATA_TYPE_STRING, NULL) != 0)
+                       bootpath[0] = '\0';
+
+               if (nvlist_lookup_value(nv, ZPOOL_CONFIG_DEVID,
+                   devid, DATA_TYPE_STRING, NULL) != 0)
+                       devid[0] = '\0';
+
+               if (strlen(bootpath) >= MAXPATHLEN ||
+                   strlen(devid) >= MAXPATHLEN)
+                       return (ERR_WONT_FIT);
+
+               return (0);
+
+       } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
+           strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
+           (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
                int nelm, i;
                char *child;
 
@@ -1107,28 +1188,16 @@ vdev_get_bootpath(char *nv, char *bootpa
                        return (ERR_FSYS_CORRUPT);
 
                for (i = 0; i < nelm; i++) {
-                       char tmp_path[MAXNAMELEN];
                        char *child_i;
 
                        child_i = nvlist_array(child, i);
-                       if (vdev_validate(child_i) != 0)
-                               continue;
-
-                       if (nvlist_lookup_value(child_i, ZPOOL_CONFIG_PHYS_PATH,
-                           tmp_path, DATA_TYPE_STRING, NULL) != 0)
-                               return (ERR_NO_BOOTPATH);
-
-                       if ((strlen(bootpath) + strlen(tmp_path)) > MAXNAMELEN)
-                               return (ERR_WONT_FIT);
-
-                       if (strlen(bootpath) == 0)
-                               sprintf(bootpath, "%s", tmp_path);
-                       else
-                               sprintf(bootpath, "%s %s", bootpath, tmp_path);
+                       if (vdev_get_bootpath(child_i, inguid, devid,
+                           bootpath, is_spare) == 0)
+                               return (0);
                }
        }
 
-       return (strlen(bootpath) > 0 ? 0 : ERR_NO_BOOTPATH);
+       return (ERR_NO_BOOTPATH);
 }
 
 /*
@@ -1138,22 +1207,24 @@ vdev_get_bootpath(char *nv, char *bootpa
  *     0 - success
  *     ERR_* - failure
  */
-static int
-check_pool_label(fsi_file_t *ffi, int label, char *stack)
+int
+check_pool_label(uint64_t sector, char *stack, char *outdevid,
+    char *outpath, uint64_t *outguid)
 {
        vdev_phys_t *vdev;
-       uint64_t sector, pool_state, txg = 0;
+       uint64_t pool_state, txg = 0;
        char *nvlist, *nv;
-       zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;
-
-       sector = (label * sizeof (vdev_label_t) + VDEV_SKIP_SIZE +
-           VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT;
+       uint64_t diskguid;
+       uint64_t version;
+
+       sector += (VDEV_SKIP_SIZE >> SPA_MINBLOCKSHIFT);
 
        /* Read in the vdev name-value pair list (112K). */
-       if (devread(ffi, sector, 0, VDEV_PHYS_SIZE, stack) == 0)
+       if (devread(sector, 0, VDEV_PHYS_SIZE, stack) == 0)
                return (ERR_READ);
 
        vdev = (vdev_phys_t *)stack;
+       stack += sizeof (vdev_phys_t);
 
        if (nvlist_unpack(vdev->vp_nvlist, &nvlist))
                return (ERR_FSYS_CORRUPT);
@@ -1177,13 +1248,22 @@ check_pool_label(fsi_file_t *ffi, int la
        if (txg == 0)
                return (ERR_NO_BOOTPATH);
 
+       if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_VERSION, &version,
+           DATA_TYPE_UINT64, NULL))
+               return (ERR_FSYS_CORRUPT);
+       if (version > SPA_VERSION)
+               return (ERR_NEWER_VERSION);
        if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_VDEV_TREE, &nv,
            DATA_TYPE_NVLIST, NULL))
                return (ERR_FSYS_CORRUPT);
-
-       if (vdev_get_bootpath(nv, current_bootpath))
+       if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_GUID, &diskguid,
+           DATA_TYPE_UINT64, NULL))
+               return (ERR_FSYS_CORRUPT);
+       if (vdev_get_bootpath(nv, diskguid, outdevid, outpath, 0))
                return (ERR_NO_BOOTPATH);
-
+       if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_POOL_GUID, outguid,
+           DATA_TYPE_UINT64, NULL))
+               return (ERR_FSYS_CORRUPT);
        return (0);
 }
 
@@ -1195,34 +1275,23 @@ check_pool_label(fsi_file_t *ffi, int la
  *     1 - success
  *     0 - failure
  */
-static int
-zfs_mount(fsi_file_t *ffi, const char *options)
+int
+zfs_mount(void)
 {
        char *stack;
        int label = 0;
-       uberblock_phys_t *ub_array, *ubbest = NULL;
+       uberblock_phys_t *ub_array, *ubbest;
        objset_phys_t *osp;
-       zfs_bootarea_t *zfs_ba;
-
-       /* if zfs is already mounted, don't do it again */
-       if (is_zfs_mount == 1)
-               return (1);
-
-       /* get much bigger data block for zfs */
-       if (((zfs_ba = malloc(sizeof (zfs_bootarea_t))) == NULL)) {
-               return (1);
-       }
-       bzero(zfs_ba, sizeof (zfs_bootarea_t));
-
-       /* replace small data area in fsi with big one */
-       free(ffi->ff_fsi->f_data);
-       ffi->ff_fsi->f_data = (void *)zfs_ba;
-
-       /* If an boot filesystem is passed in, set it to current_bootfs */
-       if (options != NULL) {
-               if (strlen(options) < MAXNAMELEN) {
-                       strcpy(current_bootfs, options);
-               }
+       char tmp_bootpath[MAXNAMELEN];
+       char tmp_devid[MAXNAMELEN];
+       uint64_t tmp_guid;
+       uint64_t adjpl = (uint64_t)part_length << SPA_MINBLOCKSHIFT;
+       int err = errnum; /* preserve previous errnum state */
+
+       /* if it's our first time here, zero the best uberblock out */
+       if (best_drive == 0 && best_part == 0 && find_best_root) {
+               grub_memset(&current_uberblock, 0, sizeof (uberblock_t));
+               pool_guid = 0;
        }
 
        stackbase = ZFS_SCRATCH;
@@ -1232,43 +1301,71 @@ zfs_mount(fsi_file_t *ffi, const char *o
 
        osp = (objset_phys_t *)stack;
        stack += sizeof (objset_phys_t);
-
-       /* XXX add back labels support? */
-       for (label = 0; ubbest == NULL && label < (VDEV_LABELS/2); label++) {
-               uint64_t sector = (label * sizeof (vdev_label_t) +
-                   VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE +
-                   VDEV_PHYS_SIZE) >> SPA_MINBLOCKSHIFT;
-
+       adjpl = P2ALIGN(adjpl, (uint64_t)sizeof (vdev_label_t));
+
+       for (label = 0; label < VDEV_LABELS; label++) {
+
+               uint64_t sector;
+
+               /*
+                * some eltorito stacks don't give us a size and
+                * we end up setting the size to MAXUINT, further
+                * some of these devices stop working once a single
+                * read past the end has been issued. Checking
+                * for a maximum part_length and skipping the backup
+                * labels at the end of the slice/partition/device
+                * avoids breaking down on such devices.
+                */
+               if (part_length == MAXUINT && label == 2)
+                       break;
+
+               sector = vdev_label_start(adjpl,
+                   label) >> SPA_MINBLOCKSHIFT;
 
                /* Read in the uberblock ring (128K). */
-               if (devread(ffi, sector, 0, VDEV_UBERBLOCK_RING,
+               if (devread(sector  +
+                   ((VDEV_SKIP_SIZE + VDEV_PHYS_SIZE) >>
+                   SPA_MINBLOCKSHIFT), 0, VDEV_UBERBLOCK_RING,
                    (char *)ub_array) == 0)
                        continue;
 
-               if ((ubbest = find_bestub(ffi, ub_array, label)) != NULL &&
-                   zio_read(ffi, &ubbest->ubp_uberblock.ub_rootbp, osp, stack)
+               if ((ubbest = find_bestub(ub_array, sector)) != NULL &&
+                   zio_read(&ubbest->ubp_uberblock.ub_rootbp, osp, stack)
                    == 0) {
 
                        VERIFY_OS_TYPE(osp, DMU_OST_META);
+
+                       if (check_pool_label(sector, stack, tmp_devid,
+                           tmp_bootpath, &tmp_guid))
+                               continue;
+                       if (pool_guid == 0)
+                               pool_guid = tmp_guid;
+
+                       if (find_best_root && ((pool_guid != tmp_guid) ||
+                           vdev_uberblock_compare(&ubbest->ubp_uberblock,
+                           &(current_uberblock)) <= 0))
+                               continue;
 
                        /* Got the MOS. Save it at the memory addr MOS. */
                        grub_memmove(MOS, &osp->os_meta_dnode, DNODE_SIZE);
-
-                       if (check_pool_label(ffi, label, stack))
-                               return (0);
-
-                       /*
-                        * Copy fsi->f_data to ffi->ff_data since
-                        * fsig_mount copies from ff_data to f_data
-                        * overwriting fsi->f_data.
-                        */
-                       bcopy(zfs_ba, fsig_file_buf(ffi), FSYS_BUFLEN);
-
+                       grub_memmove(&current_uberblock,
+                           &ubbest->ubp_uberblock, sizeof (uberblock_t));
+                       grub_memmove(current_bootpath, tmp_bootpath,
+                           MAXNAMELEN);
+                       grub_memmove(current_devid, tmp_devid,
+                           grub_strlen(tmp_devid));
                        is_zfs_mount = 1;
                        return (1);
                }
        }
 
+       /*
+        * While some fs impls. (tftp) rely on setting and keeping
+        * global errnums set, others won't reset it and will break
+        * when issuing rawreads. The goal here is to simply not
+        * have zfs mount attempts impact the previous state.
+        */
+       errnum = err;
        return (0);
 }
 
@@ -1280,13 +1377,11 @@ zfs_mount(fsi_file_t *ffi, const char *o
  *     1 - success
  *     0 - failure
  */
-static int
-zfs_open(fsi_file_t *ffi, char *filename)
+int
+zfs_open(char *filename)
 {
        char *stack;
        dnode_phys_t *mdn;
-       char *bootstring;
-       zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;
 
        file_buf = NULL;
        stackbase = ZFS_SCRATCH;
@@ -1304,62 +1399,72 @@ zfs_open(fsi_file_t *ffi, char *filename
         * do not goto 'current_bootfs'.
         */
        if (is_top_dataset_file(filename)) {
-               if ((errnum = get_objset_mdn(ffi, MOS, NULL, NULL, mdn, stack)))
+               if ((errnum = get_objset_mdn(MOS, NULL, NULL, mdn, stack)))
                        return (0);
 
                current_bootfs_obj = 0;
        } else {
                if (current_bootfs[0] == '\0') {
                        /* Get the default root filesystem object number */
-                       if ((errnum = get_default_bootfsobj(ffi, MOS,
+                       if ((errnum = get_default_bootfsobj(MOS,
                            &current_bootfs_obj, stack)))
                                return (0);
-                       if ((errnum = get_objset_mdn(ffi, MOS, NULL,
+
+                       if ((errnum = get_objset_mdn(MOS, NULL,
                            &current_bootfs_obj, mdn, stack)))
                                return (0);
                } else {
-                       if ((errnum = get_objset_mdn(ffi, MOS,
-                           current_bootfs, &current_bootfs_obj, mdn, stack)))
+                       if ((errnum = get_objset_mdn(MOS, current_bootfs,
+                           &current_bootfs_obj, mdn, stack))) {
+                               grub_memset(current_bootfs, 0, MAXNAMELEN);
                                return (0);
-               }
-
-               /*
-                * Put zfs rootpool and boot obj number into bootstring.
-                */
-               if (is_zfs_open == 0) {
-                       char temp[25];          /* needs to hold long long */
-                       int alloc_size;
-                       char zfs_bootstr[] = "zfs-bootfs=";
-                       char zfs_bootpath[] = ",bootpath='";
-
-                       snprintf(temp, sizeof(temp), "%llu", (unsigned long 
long)
-                           current_bootfs_obj);
-                       alloc_size = strlen(zfs_bootstr) +
-                           strlen(current_rootpool) +
-                           strlen(temp) + strlen(zfs_bootpath) +
-                           strlen(current_bootpath) + 3;
-                       bootstring = fsi_bootstring_alloc(ffi->ff_fsi,
-                           alloc_size);
-                       if (bootstring != NULL) {
-                               strcpy(bootstring, zfs_bootstr);
-                               strcat(bootstring, current_rootpool);
-                               strcat(bootstring, "/");
-                               strcat(bootstring, temp);
-                               strcat(bootstring, zfs_bootpath);
-                               strcat(bootstring, current_bootpath);
-                               strcat(bootstring, "'");
-                               is_zfs_open = 1;
                        }
                }
        }
 
-       if (dnode_get_path(ffi, mdn, filename, DNODE, stack)) {
+       if (dnode_get_path(mdn, filename, DNODE, stack)) {
                errnum = ERR_FILE_NOT_FOUND;
                return (0);
        }
 
        /* get the file size and set the file position to 0 */
-       filemax = ((znode_phys_t *)DN_BONUS(DNODE))->zp_size;
+
+       /*
+        * For DMU_OT_SA we will need to locate the SIZE attribute
+        * attribute, which could be either in the bonus buffer
+        * or the "spill" block.
+        */
+       if (DNODE->dn_bonustype == DMU_OT_SA) {
+               sa_hdr_phys_t *sahdrp;
+               int hdrsize;
+
+               if (DNODE->dn_bonuslen != 0) {
+                       sahdrp = (sa_hdr_phys_t *)DN_BONUS(DNODE);
+               } else {
+                       if (DNODE->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
+                               blkptr_t *bp = &DNODE->dn_spill;
+                               void *buf;
+
+                               buf = (void *)stack;
+                               stack += BP_GET_LSIZE(bp);
+
+                               /* reset errnum to rawread() failure */
+                               errnum = 0;
+                               if (zio_read(bp, buf, stack) != 0) {
+                                       return (0);
+                               }
+                               sahdrp = buf;
+                       } else {
+                               errnum = ERR_FSYS_CORRUPT;
+                               return (0);
+                       }
+               }
+               hdrsize = SA_HDR_SIZE(sahdrp);
+               filemax = *(uint64_t *)((char *)sahdrp + hdrsize +
+                   SA_SIZE_OFFSET);
+       } else {
+               filemax = ((znode_phys_t *)DN_BONUS(DNODE))->zp_size;
+       }
        filepos = 0;
 
        dnode_buf = NULL;
@@ -1373,12 +1478,11 @@ zfs_open(fsi_file_t *ffi, char *filename
  *     len - the length successfully read in to the buffer
  *     0   - failure
  */
-static int
-zfs_read(fsi_file_t *ffi, char *buf, int len)
+int
+zfs_read(char *buf, int len)
 {
        char *stack;
        int blksz, length, movesize;
-       zfs_bootarea_t *zfs_ba = (zfs_bootarea_t *)ffi->ff_fsi->f_data;
 
        if (file_buf == NULL) {
                file_buf = stackbase;
@@ -1411,7 +1515,7 @@ zfs_read(fsi_file_t *ffi, char *buf, int
                 */
                uint64_t blkid = filepos / blksz;
 
-               if ((errnum = dmu_read(ffi, DNODE, blkid, file_buf, stack)))
+               if ((errnum = dmu_read(DNODE, blkid, file_buf, stack)))
                        return (0);
 
                file_start = blkid * blksz;
@@ -1438,16 +1542,4 @@ zfs_embed(int *start_sector, int needed_
        return (1);
 }
 
-fsi_plugin_ops_t *
-fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
-{
-       static fsig_plugin_ops_t ops = {
-               FSIMAGE_PLUGIN_VERSION,
-               .fpo_mount = zfs_mount,
-               .fpo_dir = zfs_open,
-               .fpo_read = zfs_read
-       };
-
-       *name = "zfs";
-       return (fsig_init(fp, &ops));
-}
+#endif /* FSYS_ZFS */
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/fsys_zfs.h
--- a/tools/libfsimage/zfs/fsys_zfs.h   Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/fsys_zfs.h   Wed Apr 14 11:56:54 2010 +0100
@@ -17,63 +17,55 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #ifndef _FSYS_ZFS_H
 #define        _FSYS_ZFS_H
 
-#include <fsimage_grub.h>
-#include <fsimage_priv.h>
-
-#include "zfs-include/zfs.h"
-#include "zfs-include/dmu.h"
-#include "zfs-include/spa.h"
-#include "zfs-include/zio.h"
-#include "zfs-include/zio_checksum.h"
-#include "zfs-include/vdev_impl.h"
-#include "zfs-include/zap_impl.h"
-#include "zfs-include/zap_leaf.h"
-#include "zfs-include/uberblock_impl.h"
-#include "zfs-include/dnode.h"
-#include "zfs-include/dsl_dir.h"
-#include "zfs-include/zfs_acl.h"
-#include "zfs-include/zfs_znode.h"
-#include "zfs-include/dsl_dataset.h"
-#include "zfs-include/zil.h"
-#include "zfs-include/dmu_objset.h"
+#ifdef FSYS_ZFS
+
+#ifndef        FSIMAGE
+typedef unsigned long long uint64_t;
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+typedef unsigned char uchar_t;
+
+#if defined(_LP64) || defined(_I32LPx)
+typedef        unsigned long size_t;
+#else
+typedef        unsigned int size_t;
+#endif
+#else
+#include "fsi_zfs.h"
+#endif /* !FSIMAGE */
+
+#include <zfs-include/zfs.h>
+#include <zfs-include/dmu.h>
+#include <zfs-include/spa.h>
+#include <zfs-include/zio.h>
+#include <zfs-include/zio_checksum.h>
+#include <zfs-include/vdev_impl.h>
+#include <zfs-include/zap_impl.h>
+#include <zfs-include/zap_leaf.h>
+#include <zfs-include/uberblock_impl.h>
+#include <zfs-include/dnode.h>
+#include <zfs-include/dsl_dir.h>
+#include <zfs-include/zfs_acl.h>
+#include <zfs-include/zfs_znode.h>
+#include <zfs-include/dsl_dataset.h>
+#include <zfs-include/zil.h>
+#include <zfs-include/dmu_objset.h>
+#include <zfs-include/sa_impl.h>
 
 /*
  * Global Memory addresses to store MOS and DNODE data
  */
-#define        MOS             ((dnode_phys_t *)(((zfs_bootarea_t *) \
-                           (ffi->ff_fsi->f_data))->zfs_data))
+#define        MOS             ((dnode_phys_t *)\
+       (RAW_ADDR((mbi.mem_upper << 10) + 0x100000) - ZFS_SCRATCH_SIZE))
 #define        DNODE           (MOS+1) /* move sizeof(dnode_phys_t) bytes */
 #define        ZFS_SCRATCH     ((char *)(DNODE+1))
-
-#define        MAXNAMELEN      256
-
-typedef struct zfs_bootarea {
-       char zfs_current_bootpath[MAXNAMELEN];
-       char zfs_current_rootpool[MAXNAMELEN];
-       char zfs_current_bootfs[MAXNAMELEN];
-       uint64_t zfs_current_bootfs_obj;
-       int zfs_open;
-
-       /* cache for a file block of the currently zfs_open()-ed file */
-       void *zfs_file_buf;
-       uint64_t zfs_file_start;
-       uint64_t zfs_file_end;
-
-       /* cache for a dnode block */
-       dnode_phys_t *zfs_dnode_buf;
-       dnode_phys_t *zfs_dnode_mdn;
-       uint64_t zfs_dnode_start;
-       uint64_t zfs_dnode_end;
-
-       char *zfs_stackbase;
-       char zfs_data[0x400000];
-} zfs_bootarea_t;
 
 /*
  * Verify dnode type.
@@ -108,9 +100,8 @@ typedef struct zfs_bootarea {
  * can support large sector disks.
  */
 #define        UBERBLOCK_SIZE          (1ULL << UBERBLOCK_SHIFT)
-#undef offsetof
-#define        offsetof(t, m)   (size_t)(&(((t *)0)->m))
 #define        VDEV_UBERBLOCK_SHIFT    UBERBLOCK_SHIFT
+#include <stddef.h>
 #define        VDEV_UBERBLOCK_OFFSET(n) \
 offsetof(vdev_label_t, vl_uberblock[(n) << VDEV_UBERBLOCK_SHIFT])
 
@@ -120,8 +111,8 @@ typedef struct uberblock_phys {
 typedef struct uberblock_phys {
        uberblock_t     ubp_uberblock;
        char            ubp_pad[UBERBLOCK_SIZE - sizeof (uberblock_t) -
-                               sizeof (zio_block_tail_t)];
-       zio_block_tail_t ubp_zbt;
+                               sizeof (zio_eck_t)];
+       zio_eck_t       ubp_zec;
 } uberblock_phys_t;
 
 /*
@@ -130,6 +121,15 @@ typedef struct uberblock_phys {
 #define        P2PHASE(x, align)               ((x) & ((align) - 1))
 #define        DVA_OFFSET_TO_PHYS_SECTOR(offset) \
        ((offset + VDEV_LABEL_START_SIZE) >> SPA_MINBLOCKSHIFT)
+
+/*
+ * return x rounded down to an align boundary
+ * eg, P2ALIGN(1200, 1024) == 1024 (1*align)
+ * eg, P2ALIGN(1024, 1024) == 1024 (1*align)
+ * eg, P2ALIGN(0x1234, 0x100) == 0x1200 (0x12*align)
+ * eg, P2ALIGN(0x5600, 0x100) == 0x5600 (0x56*align)
+ */
+#define        P2ALIGN(x, align)               ((x) & -(align))
 
 /*
  * For nvlist manipulation. (from nvpair.h)
@@ -200,4 +200,6 @@ extern void zio_checksum_SHA256(const vo
 extern void zio_checksum_SHA256(const void *, uint64_t, zio_cksum_t *);
 extern int lzjb_decompress(void *, void *, size_t, size_t);
 
+#endif /* FSYS_ZFS */
+
 #endif /* !_FSYS_ZFS_H */
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/shared.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/zfs/shared.h     Wed Apr 14 11:56:54 2010 +0100
@@ -0,0 +1,33 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _SHARED_H
+#define _SHARED_H
+
+#ifdef  FSYS_ZFS
+
+/* THIS FILE IS INTENTIONALLY BLANK */
+
+#endif  /* FSI_ZFS */
+
+#endif /* !_SHARED_H */
+
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/dmu.h
--- a/tools/libfsimage/zfs/zfs-include/dmu.h    Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/dmu.h    Wed Apr 14 11:56:54 2010 +0100
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -56,7 +56,7 @@ typedef enum dmu_object_type {
        DMU_OT_DSL_DATASET,             /* UINT64 */
        /* zpl: */
        DMU_OT_ZNODE,                   /* ZNODE */
-       DMU_OT_ACL,                     /* ACL */
+       DMU_OT_OLDACL,                  /* OLD ACL */
        DMU_OT_PLAIN_FILE_CONTENTS,     /* UINT8 */
        DMU_OT_DIRECTORY_CONTENTS,      /* ZAP */
        DMU_OT_MASTER_NODE,             /* ZAP */
@@ -73,7 +73,22 @@ typedef enum dmu_object_type {
        DMU_OT_SPA_HISTORY,             /* UINT8 */
        DMU_OT_SPA_HISTORY_OFFSETS,     /* spa_his_phys_t */
        DMU_OT_POOL_PROPS,              /* ZAP */
-
+       DMU_OT_DSL_PERMS,               /* ZAP */
+       DMU_OT_ACL,                     /* ACL */
+       DMU_OT_SYSACL,                  /* SYSACL */
+       DMU_OT_FUID,                    /* FUID table (Packed NVLIST UINT8) */
+       DMU_OT_FUID_SIZE,               /* FUID table size UINT64 */
+       DMU_OT_NEXT_CLONES,             /* ZAP */
+       DMU_OT_SCRUB_QUEUE,             /* ZAP */
+       DMU_OT_USERGROUP_USED,          /* ZAP */
+       DMU_OT_USERGROUP_QUOTA,         /* ZAP */
+       DMU_OT_USERREFS,                /* ZAP */
+       DMU_OT_DDT_ZAP,                 /* ZAP */
+       DMU_OT_DDT_STATS,               /* ZAP */
+       DMU_OT_SA,                      /* System attr */
+       DMU_OT_SA_MASTER_NODE,          /* ZAP */
+       DMU_OT_SA_ATTR_REGISTRATION,    /* ZAP */
+       DMU_OT_SA_ATTR_LAYOUTS,         /* ZAP */
        DMU_OT_NUMTYPES
 } dmu_object_type_t;
 
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/dnode.h
--- a/tools/libfsimage/zfs/zfs-include/dnode.h  Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/dnode.h  Wed Apr 14 11:56:54 2010 +0100
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -47,6 +47,8 @@
 #define        DNODES_PER_BLOCK        (1ULL << DNODES_PER_BLOCK_SHIFT)
 #define        DNODES_PER_LEVEL_SHIFT  (DN_MAX_INDBLKSHIFT - SPA_BLKPTRSHIFT)
 
+#define        DNODE_FLAG_SPILL_BLKPTR (1<<2)
+
 #define        DN_BONUS(dnp)   ((void*)((dnp)->dn_bonus + \
        (((dnp)->dn_nblkptr - 1) * sizeof (blkptr_t))))
 
@@ -70,7 +72,8 @@ typedef struct dnode_phys {
        uint64_t dn_pad3[4];
 
        blkptr_t dn_blkptr[1];
-       uint8_t dn_bonus[DN_MAX_BONUSLEN];
+       uint8_t dn_bonus[DN_MAX_BONUSLEN - sizeof (blkptr_t)];
+       blkptr_t dn_spill;
 } dnode_phys_t;
 
 #endif /* _SYS_DNODE_H */
diff -r 07befd9cf6d3 -r ae08db793feb 
tools/libfsimage/zfs/zfs-include/dsl_dataset.h
--- a/tools/libfsimage/zfs/zfs-include/dsl_dataset.h    Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/dsl_dataset.h    Wed Apr 14 11:56:54 
2010 +0100
@@ -23,6 +23,8 @@
 
 #ifndef        _SYS_DSL_DATASET_H
 #define        _SYS_DSL_DATASET_H
+
+#pragma ident  "%Z%%M% %I%     %E% SMI"
 
 typedef struct dsl_dataset_phys {
        uint64_t ds_dir_obj;
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/dsl_dir.h
--- a/tools/libfsimage/zfs/zfs-include/dsl_dir.h        Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/dsl_dir.h        Wed Apr 14 11:56:54 
2010 +0100
@@ -24,6 +24,8 @@
 #ifndef        _SYS_DSL_DIR_H
 #define        _SYS_DSL_DIR_H
 
+#pragma ident  "%Z%%M% %I%     %E% SMI"
+
 typedef struct dsl_dir_phys {
        uint64_t dd_creation_time; /* not actually used */
        uint64_t dd_head_dataset_obj;
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/sa_impl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/zfs/zfs-include/sa_impl.h        Wed Apr 14 11:56:54 
2010 +0100
@@ -0,0 +1,35 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef        _SYS_SA_IMPL_H
+#define        _SYS_SA_IMPL_H
+
+typedef struct sa_hdr_phys {
+       uint32_t sa_magic;
+       uint16_t sa_layout_info;
+       uint16_t sa_lengths[1];
+} sa_hdr_phys_t;
+
+#define        SA_HDR_SIZE(hdr)        BF32_GET_SB(hdr->sa_layout_info, 10, 
16, 3, 0)
+#define        SA_SIZE_OFFSET  0x8
+
+#endif /* _SYS_SA_IMPL_H */
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/spa.h
--- a/tools/libfsimage/zfs/zfs-include/spa.h    Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/spa.h    Wed Apr 14 11:56:54 2010 +0100
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -61,6 +61,11 @@
 #define        SPA_MAXBLOCKSIZE        (1ULL << SPA_MAXBLOCKSHIFT)
 
 #define        SPA_BLOCKSIZES          (SPA_MAXBLOCKSHIFT - SPA_MINBLOCKSHIFT 
+ 1)
+
+/*
+ * Size of block to hold the configuration data (a packed nvlist)
+ */
+#define        SPA_CONFIG_BLOCKSIZE    (1 << 14)
 
 /*
  * The DVA size encodings for LSIZE and PSIZE support blocks up to 32MB.
@@ -106,15 +111,15 @@ typedef struct zio_cksum {
  *     +-------+-------+-------+-------+-------+-------+-------+-------+
  * 5   |G|                      offset3                                |
  *     +-------+-------+-------+-------+-------+-------+-------+-------+
- * 6   |E| lvl | type  | cksum | comp  |     PSIZE     |     LSIZE     |
+ * 6   |BDX|lvl| type  | cksum | comp  |     PSIZE     |     LSIZE     |
  *     +-------+-------+-------+-------+-------+-------+-------+-------+
  * 7   |                       padding                                 |
  *     +-------+-------+-------+-------+-------+-------+-------+-------+
  * 8   |                       padding                                 |
  *     +-------+-------+-------+-------+-------+-------+-------+-------+
- * 9   |                       padding                                 |
- *     +-------+-------+-------+-------+-------+-------+-------+-------+
- * a   |                       birth txg                               |
+ * 9   |                       physical birth txg                      |
+ *     +-------+-------+-------+-------+-------+-------+-------+-------+
+ * a   |                       logical birth txg                       |
  *     +-------+-------+-------+-------+-------+-------+-------+-------+
  * b   |                       fill count                              |
  *     +-------+-------+-------+-------+-------+-------+-------+-------+
@@ -138,24 +143,28 @@ typedef struct zio_cksum {
  * cksum       checksum function
  * comp                compression function
  * G           gang block indicator
- * E           endianness
+ * B           byteorder (endianness)
+ * D           dedup
+ * X           unused
+ * lvl         level of indirection
  * type                DMU object type
- * lvl         level of indirection
- * birth txg   transaction group in which the block was born
+ * phys birth  txg of block allocation; zero if same as logical birth txg
+ * log. birth  transaction group in which the block was logically born
  * fill count  number of non-zero blocks under this bp
  * checksum[4] 256-bit checksum of the data this bp describes
  */
-typedef struct blkptr {
-       dva_t           blk_dva[3];     /* 128-bit Data Virtual Address */
-       uint64_t        blk_prop;       /* size, compression, type, etc */
-       uint64_t        blk_pad[3];     /* Extra space for the future   */
-       uint64_t        blk_birth;      /* transaction group at birth   */
-       uint64_t        blk_fill;       /* fill count                   */
-       zio_cksum_t     blk_cksum;      /* 256-bit checksum             */
-} blkptr_t;
-
 #define        SPA_BLKPTRSHIFT 7               /* blkptr_t is 128 bytes        
*/
 #define        SPA_DVAS_PER_BP 3               /* Number of DVAs in a bp       
*/
+
+typedef struct blkptr {
+       dva_t           blk_dva[SPA_DVAS_PER_BP]; /* Data Virtual Addresses */
+       uint64_t        blk_prop;       /* size, compression, type, etc     */
+       uint64_t        blk_pad[2];     /* Extra space for the future       */
+       uint64_t        blk_phys_birth; /* txg when block was allocated     */
+       uint64_t        blk_birth;      /* transaction group at birth       */
+       uint64_t        blk_fill;       /* fill count                       */
+       zio_cksum_t     blk_cksum;      /* 256-bit checksum                 */
+} blkptr_t;
 
 /*
  * Macros to get and set fields in a bp or DVA.
@@ -180,8 +189,7 @@ typedef struct blkptr {
 #define        DVA_SET_GANG(dva, x)    BF64_SET((dva)->dva_word[1], 63, 1, x)
 
 #define        BP_GET_LSIZE(bp)        \
-       (BP_IS_HOLE(bp) ? 0 : \
-       BF64_GET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1))
+       BF64_GET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1)
 #define        BP_SET_LSIZE(bp, x)     \
        BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x)
 
@@ -190,20 +198,35 @@ typedef struct blkptr {
 #define        BP_SET_PSIZE(bp, x)     \
        BF64_SET_SB((bp)->blk_prop, 16, 16, SPA_MINBLOCKSHIFT, 1, x)
 
-#define        BP_GET_COMPRESS(bp)     BF64_GET((bp)->blk_prop, 32, 8)
-#define        BP_SET_COMPRESS(bp, x)  BF64_SET((bp)->blk_prop, 32, 8, x)
-
-#define        BP_GET_CHECKSUM(bp)     BF64_GET((bp)->blk_prop, 40, 8)
-#define        BP_SET_CHECKSUM(bp, x)  BF64_SET((bp)->blk_prop, 40, 8, x)
-
-#define        BP_GET_TYPE(bp)         BF64_GET((bp)->blk_prop, 48, 8)
-#define        BP_SET_TYPE(bp, x)      BF64_SET((bp)->blk_prop, 48, 8, x)
-
-#define        BP_GET_LEVEL(bp)        BF64_GET((bp)->blk_prop, 56, 5)
-#define        BP_SET_LEVEL(bp, x)     BF64_SET((bp)->blk_prop, 56, 5, x)
-
-#define        BP_GET_BYTEORDER(bp)    (0 - BF64_GET((bp)->blk_prop, 63, 1))
-#define        BP_SET_BYTEORDER(bp, x) BF64_SET((bp)->blk_prop, 63, 1, x)
+#define        BP_GET_COMPRESS(bp)             BF64_GET((bp)->blk_prop, 32, 8)
+#define        BP_SET_COMPRESS(bp, x)          BF64_SET((bp)->blk_prop, 32, 8, 
x)
+
+#define        BP_GET_CHECKSUM(bp)             BF64_GET((bp)->blk_prop, 40, 8)
+#define        BP_SET_CHECKSUM(bp, x)          BF64_SET((bp)->blk_prop, 40, 8, 
x)
+
+#define        BP_GET_TYPE(bp)                 BF64_GET((bp)->blk_prop, 48, 8)
+#define        BP_SET_TYPE(bp, x)              BF64_SET((bp)->blk_prop, 48, 8, 
x)
+
+#define        BP_GET_LEVEL(bp)                BF64_GET((bp)->blk_prop, 56, 5)
+#define        BP_SET_LEVEL(bp, x)             BF64_SET((bp)->blk_prop, 56, 5, 
x)
+
+#define        BP_GET_PROP_BIT_61(bp)          BF64_GET((bp)->blk_prop, 61, 1)
+#define        BP_SET_PROP_BIT_61(bp, x)       BF64_SET((bp)->blk_prop, 61, 1, 
x)
+
+#define        BP_GET_DEDUP(bp)                BF64_GET((bp)->blk_prop, 62, 1)
+#define        BP_SET_DEDUP(bp, x)             BF64_SET((bp)->blk_prop, 62, 1, 
x)
+
+#define        BP_GET_BYTEORDER(bp)            (0 - BF64_GET((bp)->blk_prop, 
63, 1))
+#define        BP_SET_BYTEORDER(bp, x)         BF64_SET((bp)->blk_prop, 63, 1, 
x)
+
+#define        BP_PHYSICAL_BIRTH(bp)           \
+       ((bp)->blk_phys_birth ? (bp)->blk_phys_birth : (bp)->blk_birth)
+
+#define        BP_SET_BIRTH(bp, logical, physical)     \
+{                                              \
+       (bp)->blk_birth = (logical);            \
+       (bp)->blk_phys_birth = ((logical) == (physical) ? 0 : (physical)); \
+}
 
 #define        BP_GET_ASIZE(bp)        \
        (DVA_GET_ASIZE(&(bp)->blk_dva[0]) + DVA_GET_ASIZE(&(bp)->blk_dva[1]) + \
@@ -226,13 +249,18 @@ typedef struct blkptr {
 #define        DVA_EQUAL(dva1, dva2)   \
        ((dva1)->dva_word[1] == (dva2)->dva_word[1] && \
        (dva1)->dva_word[0] == (dva2)->dva_word[0])
+
+#define        BP_EQUAL(bp1, bp2)      \
+       (BP_PHYSICAL_BIRTH(bp1) == BP_PHYSICAL_BIRTH(bp2) &&    \
+       DVA_EQUAL(&(bp1)->blk_dva[0], &(bp2)->blk_dva[0]) &&    \
+       DVA_EQUAL(&(bp1)->blk_dva[1], &(bp2)->blk_dva[1]) &&    \
+       DVA_EQUAL(&(bp1)->blk_dva[2], &(bp2)->blk_dva[2]))
 
 #define        ZIO_CHECKSUM_EQUAL(zc1, zc2) \
        (0 == (((zc1).zc_word[0] - (zc2).zc_word[0]) | \
        ((zc1).zc_word[1] - (zc2).zc_word[1]) | \
        ((zc1).zc_word[2] - (zc2).zc_word[2]) | \
        ((zc1).zc_word[3] - (zc2).zc_word[3])))
-
 
 #define        DVA_IS_VALID(dva)       (DVA_GET_ASIZE(dva) != 0)
 
@@ -247,7 +275,10 @@ typedef struct blkptr {
 #define        BP_IDENTITY(bp)         (&(bp)->blk_dva[0])
 #define        BP_IS_GANG(bp)          DVA_GET_GANG(BP_IDENTITY(bp))
 #define        BP_IS_HOLE(bp)          ((bp)->blk_birth == 0)
-#define        BP_IS_OLDER(bp, txg)    (!BP_IS_HOLE(bp) && (bp)->blk_birth < 
(txg))
+
+/* BP_IS_RAIDZ(bp) assumes no block compression */
+#define        BP_IS_RAIDZ(bp)         (DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \
+                               BP_GET_PSIZE(bp))
 
 #define        BP_ZERO(bp)                             \
 {                                              \
@@ -260,7 +291,7 @@ typedef struct blkptr {
        (bp)->blk_prop = 0;                     \
        (bp)->blk_pad[0] = 0;                   \
        (bp)->blk_pad[1] = 0;                   \
-       (bp)->blk_pad[2] = 0;                   \
+       (bp)->blk_phys_birth = 0;               \
        (bp)->blk_birth = 0;                    \
        (bp)->blk_fill = 0;                     \
        ZIO_SET_CHECKSUM(&(bp)->blk_cksum, 0, 0, 0, 0); \
diff -r 07befd9cf6d3 -r ae08db793feb 
tools/libfsimage/zfs/zfs-include/uberblock_impl.h
--- a/tools/libfsimage/zfs/zfs-include/uberblock_impl.h Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/uberblock_impl.h Wed Apr 14 11:56:54 
2010 +0100
@@ -24,6 +24,8 @@
 #ifndef _SYS_UBERBLOCK_IMPL_H
 #define        _SYS_UBERBLOCK_IMPL_H
 
+#pragma ident  "%Z%%M% %I%     %E% SMI"
+
 /*
  * The uberblock version is incremented whenever an incompatible on-disk
  * format change is made to the SPA, DMU, or ZAP.
diff -r 07befd9cf6d3 -r ae08db793feb 
tools/libfsimage/zfs/zfs-include/vdev_impl.h
--- a/tools/libfsimage/zfs/zfs-include/vdev_impl.h      Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/vdev_impl.h      Wed Apr 14 11:56:54 
2010 +0100
@@ -17,38 +17,27 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef _SYS_VDEV_IMPL_H
 #define        _SYS_VDEV_IMPL_H
 
-#define        VDEV_SKIP_SIZE          (8 << 10)
-#define        VDEV_BOOT_HEADER_SIZE   (8 << 10)
+#define        VDEV_PAD_SIZE           (8 << 10)
+/* 2 padding areas (vl_pad1 and vl_pad2) to skip */
+#define        VDEV_SKIP_SIZE          VDEV_PAD_SIZE * 2
 #define        VDEV_PHYS_SIZE          (112 << 10)
 #define        VDEV_UBERBLOCK_RING     (128 << 10)
 
-/* ZFS boot block */
-#define        VDEV_BOOT_MAGIC         0x2f5b007b10cULL
-#define        VDEV_BOOT_VERSION       1               /* version number       
*/
-
-typedef struct vdev_boot_header {
-       uint64_t        vb_magic;               /* VDEV_BOOT_MAGIC      */
-       uint64_t        vb_version;             /* VDEV_BOOT_VERSION    */
-       uint64_t        vb_offset;              /* start offset (bytes) */
-       uint64_t        vb_size;                /* size (bytes)         */
-       char            vb_pad[VDEV_BOOT_HEADER_SIZE - 4 * sizeof (uint64_t)];
-} vdev_boot_header_t;
-
 typedef struct vdev_phys {
-       char            vp_nvlist[VDEV_PHYS_SIZE - sizeof (zio_block_tail_t)];
-       zio_block_tail_t vp_zbt;
+       char            vp_nvlist[VDEV_PHYS_SIZE - sizeof (zio_eck_t)];
+       zio_eck_t       vp_zbt;
 } vdev_phys_t;
 
 typedef struct vdev_label {
-       char            vl_pad[VDEV_SKIP_SIZE];                 /*   8K */
-       vdev_boot_header_t vl_boot_header;                      /*   8K */
+       char            vl_pad1[VDEV_PAD_SIZE];                 /*  8K  */
+       char            vl_pad2[VDEV_PAD_SIZE];                 /*  8K  */
        vdev_phys_t     vl_vdev_phys;                           /* 112K */
        char            vl_uberblock[VDEV_UBERBLOCK_RING];      /* 128K */
 } vdev_label_t;                                                        /* 256K 
total */
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/zap_impl.h
--- a/tools/libfsimage/zfs/zfs-include/zap_impl.h       Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/zap_impl.h       Wed Apr 14 11:56:54 
2010 +0100
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -26,7 +26,6 @@
 
 #define        ZAP_MAGIC 0x2F52AB2ABULL
 
-#define        ZAP_HASHBITS            28
 #define        MZAP_ENT_LEN            64
 #define        MZAP_NAME_LEN           (MZAP_ENT_LEN - 8 - 4 - 2)
 #define        MZAP_MAX_BLKSHIFT       SPA_MAXBLOCKSHIFT
@@ -99,6 +98,8 @@ typedef struct zap_phys {
        uint64_t zap_num_leafs;         /* number of leafs */
        uint64_t zap_num_entries;       /* number of entries */
        uint64_t zap_salt;              /* salt to stir into hash function */
+       uint64_t zap_normflags;         /* flags for u8_textprep_str() */
+       uint64_t zap_flags;             /* zap_flag_t */
        /*
         * This structure is followed by padding, and then the embedded
         * pointer table.  The embedded pointer table takes up second
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/zap_leaf.h
--- a/tools/libfsimage/zfs/zfs-include/zap_leaf.h       Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/zap_leaf.h       Wed Apr 14 11:56:54 
2010 +0100
@@ -23,6 +23,8 @@
 
 #ifndef        _SYS_ZAP_LEAF_H
 #define        _SYS_ZAP_LEAF_H
+
+#pragma ident  "%Z%%M% %I%     %E% SMI"
 
 #define        ZAP_LEAF_MAGIC 0x2AB1EAF
 
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/zfs.h
--- a/tools/libfsimage/zfs/zfs-include/zfs.h    Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/zfs.h    Wed Apr 14 11:56:54 2010 +0100
@@ -17,18 +17,17 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef        _SYS_FS_ZFS_H
 #define        _SYS_FS_ZFS_H
 
-
 /*
  * On-disk version number.
  */
-#define        SPA_VERSION                     16ULL
+#define        SPA_VERSION                     24ULL
 
 /*
  * The following are configuration names used in the nvlist describing a pool's
@@ -62,6 +61,12 @@
 #define        ZPOOL_CONFIG_NPARITY            "nparity"
 #define        ZPOOL_CONFIG_PHYS_PATH          "phys_path"
 #define        ZPOOL_CONFIG_L2CACHE            "l2cache"
+#define        ZPOOL_CONFIG_HOLE_ARRAY         "hole_array"
+#define        ZPOOL_CONFIG_VDEV_CHILDREN      "vdev_children"
+#define        ZPOOL_CONFIG_IS_HOLE            "is_hole"
+#define        ZPOOL_CONFIG_DDT_HISTOGRAM      "ddt_histogram"
+#define        ZPOOL_CONFIG_DDT_OBJ_STATS      "ddt_object_stats"
+#define        ZPOOL_CONFIG_DDT_STATS          "ddt_stats"
 /*
  * The persistent vdev state is stored as separate values rather than a single
  * 'vdev_state' entry.  This is because a device can be in multiple states, 
such
@@ -79,6 +84,7 @@
 #define        VDEV_TYPE_DISK                  "disk"
 #define        VDEV_TYPE_FILE                  "file"
 #define        VDEV_TYPE_MISSING               "missing"
+#define        VDEV_TYPE_HOLE                  "hole"
 #define        VDEV_TYPE_SPARE                 "spare"
 #define        VDEV_TYPE_L2CACHE               "l2cache"
 
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/zfs_acl.h
--- a/tools/libfsimage/zfs/zfs-include/zfs_acl.h        Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/zfs_acl.h        Wed Apr 14 11:56:54 
2010 +0100
@@ -23,6 +23,13 @@
 
 #ifndef        _SYS_FS_ZFS_ACL_H
 #define        _SYS_FS_ZFS_ACL_H
+
+#pragma ident  "%Z%%M% %I%     %E% SMI"
+
+#ifndef _UID_T
+#define        _UID_T
+typedef        unsigned int uid_t;                     /* UID type */
+#endif /* _UID_T */
 
 typedef struct zfs_oldace {
        uint32_t        z_fuid;         /* "who" */
diff -r 07befd9cf6d3 -r ae08db793feb 
tools/libfsimage/zfs/zfs-include/zfs_znode.h
--- a/tools/libfsimage/zfs/zfs-include/zfs_znode.h      Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/zfs_znode.h      Wed Apr 14 11:56:54 
2010 +0100
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -27,8 +27,9 @@
 #define        MASTER_NODE_OBJ 1
 #define        ZFS_ROOT_OBJ            "ROOT"
 #define        ZPL_VERSION_STR         "VERSION"
+#define        ZFS_SA_ATTRS            "SA_ATTRS"
 
-#define        ZPL_VERSION             4ULL
+#define        ZPL_VERSION             5ULL
 
 #define        ZFS_DIRENT_OBJ(de) BF64_GET(de, 0, 48)
 
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/zil.h
--- a/tools/libfsimage/zfs/zfs-include/zil.h    Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/zil.h    Wed Apr 14 11:56:54 2010 +0100
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -45,7 +45,13 @@ typedef struct zil_header {
        uint64_t zh_replay_seq; /* highest replayed sequence number */
        blkptr_t zh_log;        /* log chain */
        uint64_t zh_claim_seq;  /* highest claimed sequence number */
-       uint64_t zh_pad[5];
+       uint64_t zh_flags;      /* header flags */
+       uint64_t zh_pad[4];
 } zil_header_t;
 
+/*
+ * zh_flags bit settings
+ */
+#define        ZIL_REPLAY_NEEDED 0x1   /* replay needed - internal only */
+
 #endif /* _SYS_ZIL_H */
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs-include/zio.h
--- a/tools/libfsimage/zfs/zfs-include/zio.h    Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/zio.h    Wed Apr 14 11:56:54 2010 +0100
@@ -17,19 +17,19 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #ifndef _ZIO_H
 #define        _ZIO_H
 
-#define        ZBT_MAGIC       0x210da7ab10c7a11ULL    /* zio data bloc tail */
+#define        ZEC_MAGIC       0x210da7ab10c7a11ULL    /* zio data bloc tail */
 
-typedef struct zio_block_tail {
-       uint64_t        zbt_magic;      /* for validation, endianness   */
-       zio_cksum_t     zbt_cksum;      /* 256-bit checksum             */
-} zio_block_tail_t;
+typedef struct zio_eck {
+       uint64_t        zec_magic;      /* for validation, endianness   */
+       zio_cksum_t     zec_cksum;      /* 256-bit checksum             */
+} zio_eck_t;
 
 /*
  * Gang block headers are self-checksumming and contain an array
@@ -37,9 +37,9 @@ typedef struct zio_block_tail {
  */
 #define        SPA_GANGBLOCKSIZE       SPA_MINBLOCKSIZE
 #define        SPA_GBH_NBLKPTRS        ((SPA_GANGBLOCKSIZE - \
-       sizeof (zio_block_tail_t)) / sizeof (blkptr_t))
+       sizeof (zio_eck_t)) / sizeof (blkptr_t))
 #define        SPA_GBH_FILLER          ((SPA_GANGBLOCKSIZE - \
-       sizeof (zio_block_tail_t) - \
+       sizeof (zio_eck_t) - \
        (SPA_GBH_NBLKPTRS * sizeof (blkptr_t))) /\
        sizeof (uint64_t))
 
@@ -50,7 +50,7 @@ typedef struct zio_gbh {
 typedef struct zio_gbh {
        blkptr_t                zg_blkptr[SPA_GBH_NBLKPTRS];
        uint64_t                zg_filler[SPA_GBH_FILLER];
-       zio_block_tail_t        zg_tail;
+       zio_eck_t               zg_tail;
 } zio_gbh_phys_t;
 
 enum zio_checksum {
@@ -63,11 +63,9 @@ enum zio_checksum {
        ZIO_CHECKSUM_FLETCHER_2,
        ZIO_CHECKSUM_FLETCHER_4,
        ZIO_CHECKSUM_SHA256,
+       ZIO_CHECKSUM_ZILOG2,
        ZIO_CHECKSUM_FUNCTIONS
 };
-
-#define        ZIO_CHECKSUM_ON_VALUE   ZIO_CHECKSUM_FLETCHER_2
-#define        ZIO_CHECKSUM_DEFAULT    ZIO_CHECKSUM_ON
 
 enum zio_compress {
        ZIO_COMPRESS_INHERIT = 0,
diff -r 07befd9cf6d3 -r ae08db793feb 
tools/libfsimage/zfs/zfs-include/zio_checksum.h
--- a/tools/libfsimage/zfs/zfs-include/zio_checksum.h   Wed Apr 14 11:29:05 
2010 +0100
+++ b/tools/libfsimage/zfs/zfs-include/zio_checksum.h   Wed Apr 14 11:56:54 
2010 +0100
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,7 +35,7 @@ typedef struct zio_checksum_info {
 typedef struct zio_checksum_info {
        zio_checksum_t  *ci_func[2]; /* checksum function for each byteorder */
        int             ci_correctable; /* number of correctable bits   */
-       int             ci_zbt;         /* uses zio block tail? */
+       int             ci_eck;         /* uses zio embedded checksum? */
        char            *ci_name;       /* descriptive name */
 } zio_checksum_info_t;
 
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs_fletcher.c
--- a/tools/libfsimage/zfs/zfs_fletcher.c       Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs_fletcher.c       Wed Apr 14 11:56:54 2010 +0100
@@ -20,6 +20,8 @@
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+
+#pragma ident  "%Z%%M% %I%     %E% SMI"
 
 #include "fsys_zfs.h"
 
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs_lzjb.c
--- a/tools/libfsimage/zfs/zfs_lzjb.c   Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs_lzjb.c   Wed Apr 14 11:56:54 2010 +0100
@@ -21,6 +21,8 @@
  * Use is subject to license terms.
  */
 
+#pragma ident  "%Z%%M% %I%     %E% SMI"
+
 #include "fsys_zfs.h"
 
 #define        MATCH_BITS      6
@@ -32,11 +34,10 @@ int
 int
 lzjb_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len)
 {
-       unsigned char *src = s_start;
-       unsigned char *dst = d_start;
-       unsigned char *d_end = (unsigned char *)d_start + d_len;
-       unsigned char *cpy;
-       unsigned char copymap = '\0';
+       uchar_t *src = s_start;
+       uchar_t *dst = d_start;
+       uchar_t *d_end = (uchar_t *)d_start + d_len;
+       uchar_t *cpy, copymap = '\0';
        int copymask = 1 << (NBBY - 1);
 
        while (dst < d_end) {
@@ -44,11 +45,11 @@ lzjb_decompress(void *s_start, void *d_s
                        copymask = 1;
                        copymap = *src++;
                }
-               if (copymap & (unsigned char)copymask) {
+               if (copymap & copymask) {
                        int mlen = (src[0] >> (NBBY - MATCH_BITS)) + MATCH_MIN;
                        int offset = ((src[0] << NBBY) | src[1]) & OFFSET_MASK;
                        src += 2;
-                       if ((cpy = dst - offset) < (unsigned char *)d_start)
+                       if ((cpy = dst - offset) < (uchar_t *)d_start)
                                return (-1);
                        while (--mlen >= 0 && dst < d_end)
                                *dst++ = *cpy++;
diff -r 07befd9cf6d3 -r ae08db793feb tools/libfsimage/zfs/zfs_sha256.c
--- a/tools/libfsimage/zfs/zfs_sha256.c Wed Apr 14 11:29:05 2010 +0100
+++ b/tools/libfsimage/zfs/zfs_sha256.c Wed Apr 14 11:56:54 2010 +0100
@@ -20,6 +20,8 @@
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+
+#pragma ident  "%Z%%M% %I%     %E% SMI"
 
 #include "fsys_zfs.h"
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.