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

Re: [Xen-devel] [PATCH] 1. changes for vdiskadm on illumos based platform



On Sat, Oct 26, 2013 at 08:09:04PM +0400, Igor Kozhkuhov wrote:
> 2. update ZFS in libfsimage from illumos for pygrub
> 

Wow, this is such a hugh diff. TBH this is not a proper patch.
Please have a look at

  http://wiki.xen.org/wiki/Submitting_Xen_Patches

And don't forget to CC respective maintainers. In your case you should
CC Ian Campbell and Ian Jackson as they are toolstack maintainers.

Wei.

> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/Rules.mk
> --- a/tools/libfsimage/Rules.mk       Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/Rules.mk       Sat Oct 26 20:03:06 2013 +0400
> @@ -2,11 +2,19 @@ include $(XEN_ROOT)/tools/Rules.mk
>  
>  CFLAGS += -Wno-unknown-pragmas -I$(XEN_ROOT)/tools/libfsimage/common/ 
> -DFSIMAGE_FSDIR=\"$(FSDIR)\"
>  CFLAGS += -Werror -D_GNU_SOURCE
> +# need for build illumos ZFS
> +CFLAGS += -Wno-parentheses
> +CFLAGS += -Wno-unused
> +# end
>  LDFLAGS += -L../common/
>  
>  PIC_OBJS := $(patsubst %.c,%.opic,$(LIB_SRCS-y))
>  
> -FSDIR = $(LIBDIR)/fs
> +FSDIR-y = $(LIBDIR)/fs/$(FS)
> +FSDIR-$(CONFIG_SunOS)-x86_64 = $(PREFIX)/lib/fs/$(FS)/64
> +FSDIR-$(CONFIG_SunOS)-x86_32 = $(PREFIX)/lib/fs/$(FS)/
> +FSDIR-$(CONFIG_SunOS) = $(FSDIR-$(CONFIG_SunOS)-$(XEN_TARGET_ARCH))
> +FSDIR = $(FSDIR-y)
>  
>  FSLIB = fsimage.so
>  
> @@ -15,11 +23,14 @@ fs-all: $(FSLIB)
>  
>  .PHONY: fs-install
>  fs-install: fs-all
> -     $(INSTALL_DIR) $(DESTDIR)$(FSDIR)/$(FS)
> -     $(INSTALL_PROG) $(FSLIB) $(DESTDIR)$(FSDIR)/$(FS)
> +     $(INSTALL_DIR) $(DESTDIR)$(FSDIR)
> +     $(INSTALL_PROG) $(FSLIB) $(DESTDIR)$(FSDIR)
> +
> +BUILD_LINE-y = $(CC) $(LDFLAGS) $(SHLIB_LDFLAGS) -o $@ $^ -lfsimage 
> $(FS_LIBDEPS) $(APPEND_LDFLAGS)
> +BUILD_LINE-$(CONFIG_SunOS) = $(CC) $(CFLAGS) $(LDFLAGS) $(SHLIB_LDFLAGS) -o 
> $@ $^ -lfsimage $(FS_LIBDEPS)
>  
>  $(FSLIB): $(PIC_OBJS)
> -     $(CC) $(LDFLAGS) $(SHLIB_LDFLAGS) -o $@ $^ -lfsimage $(FS_LIBDEPS) 
> $(APPEND_LDFLAGS)
> +     $(BUILD_LINE-y)
>  
>  clean distclean::
>       rm -f $(PIC_OBJS) $(FSLIB) $(DEPS)
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/common/Makefile
> --- a/tools/libfsimage/common/Makefile        Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/common/Makefile        Sat Oct 26 20:03:06 2013 +0400
> @@ -4,11 +4,16 @@ include $(XEN_ROOT)/tools/libfsimage/Rul
>  MAJOR = 1.0
>  MINOR = 0
>  
> -LDFLAGS-$(CONFIG_SunOS) = -Wl,-M -Wl,mapfile-SunOS
> +CFLAGS-ADDS-$(CONFIG_SunOS) += -Werror -Wp,-MD,.$(@F).d $(ADD_INCLUDES)
> +CFLAGS-ADDS-$(CONFIG_SunOS) += -I/usr/include/libxml2
> +CFLAGS-ADDS-$(CONFIG_Linux)=
> +
> +LDFLAGS-$(CONFIG_SunOS) = -Wl,-M -Wl,mapfile-SunOS $(ADD_PATH_LIBS)
>  LDFLAGS-$(CONFIG_Linux) = -Wl,mapfile-GNU
>  LDFLAGS = $(LDFLAGS-y)
>  
>  CFLAGS += $(PTHREAD_CFLAGS)
> +CFLAGS += $(CFLAGS-ADDS-y)
>  LDFLAGS += $(PTHREAD_LDFLAGS)
>  
>  LIB_SRCS-y = fsimage.c fsimage_plugin.c fsimage_grub.c
> @@ -32,15 +37,18 @@ install: all
>       $(INSTALL_DATA) fsimage_grub.h $(DESTDIR)$(INCLUDEDIR)
>  
>  clean distclean::
> -     rm -f $(LIB)
> +     rm -f $(PIC_OBJS) $(LIB) $(DEPS)
>  
>  libfsimage.so: libfsimage.so.$(MAJOR)
>       ln -sf $< $@
>  libfsimage.so.$(MAJOR): libfsimage.so.$(MAJOR).$(MINOR)
>       ln -sf $< $@
>  
> +BUILD_LINE-y = $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) 
> -Wl,libfsimage.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(PTHREAD_LIBS)
> +BUILD_LINE-$(CONFIG_SunOS) = $(CC) $(CFLAGS $(LDFLAGS) -Wl,$(SONAME_LDFLAG) 
> -Wl,libfsimage.so.$(MAJOR) $(SHLIB_LDFLAGS) -o $@ $^ $(PTHREAD_LIBS) -lvdisk 
> -lvboxdisk -lxml2 -lgen -lc
> +
>  libfsimage.so.$(MAJOR).$(MINOR): $(PIC_OBJS)
> -     $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libfsimage.so.$(MAJOR) 
> $(SHLIB_LDFLAGS) -o $@ $^ $(PTHREAD_LIBS)
> +     $(BUILD_LINE-y)
>  
>  -include $(DEPS)
>  
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/common/fsimage.c
> --- a/tools/libfsimage/common/fsimage.c       Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/common/fsimage.c       Sat Oct 26 20:03:06 2013 +0400
> @@ -36,22 +36,43 @@
>  
>  static pthread_mutex_t fsi_lock = PTHREAD_MUTEX_INITIALIZER;
>  
> +#ifdef _VDISK_
> +#include "vdisk.h"
> +#endif
> +
>  fsi_t *fsi_open_fsimage(const char *path, uint64_t off, const char *options)
>  {
>       fsi_t *fsi = NULL;
> -     int fd;
> +     int fd = -1;
>       int err;
> +     void *pvd = NULL;
>  
> +#ifdef _VDISK_
> +     if (vdisk_check_vdisk(path)) {
> +             if ((pvd = vdisk_open(path)) == NULL)
> +                     goto fail;
> +     } else {
> +             if ((fd = open(path, O_RDONLY)) == -1)
> +                     goto fail;
> +     }
> +#else
>       if ((fd = open(path, O_RDONLY)) == -1)
>               goto fail;
> +#endif
>  
>       if ((fsi = malloc(sizeof(*fsi))) == NULL)
>               goto fail;
>  
> -     fsi->f_fd = fd;
>       fsi->f_off = off;
>       fsi->f_data = NULL;
>       fsi->f_bootstring = NULL;
> +     if (pvd) {
> +             fsi->f_fd = NULL;
> +             fsi->f_pvdisk = pvd;
> +     } else {
> +             fsi->f_fd = fd;
> +             fsi->f_pvdisk = NULL;
> +     }
>  
>       pthread_mutex_lock(&fsi_lock);
>       err = find_plugin(fsi, path, options);
> @@ -73,8 +94,16 @@ fail:
>  void fsi_close_fsimage(fsi_t *fsi)
>  {
>       pthread_mutex_lock(&fsi_lock);
> -        fsi->f_plugin->fp_ops->fpo_umount(fsi);
> -        (void) close(fsi->f_fd);
> +     fsi->f_plugin->fp_ops->fpo_umount(fsi);
> +#ifdef _VDISK_
> +     if (fsi->f_pvdisk) {
> +             vdisk_close(fsi->f_pvdisk);
> +     } else {
> +             (void) close(fsi->f_fd);
> +     }
> +#else
> +     (void) close(fsi->f_fd);
> +#endif
>       free(fsi);
>       pthread_mutex_unlock(&fsi_lock);
>  }
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/common/fsimage_grub.c
> --- a/tools/libfsimage/common/fsimage_grub.c  Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/common/fsimage_grub.c  Sat Oct 26 20:03:06 2013 +0400
> @@ -31,6 +31,10 @@
>  #include "fsimage_grub.h"
>  #include "fsimage_priv.h"
>  
> +#ifdef _VDISK_
> +#include "vdisk.h"
> +#endif
> +
>  static char *disk_read_junk;
>  
>  typedef struct fsig_data {
> @@ -176,7 +180,17 @@ fsig_devread(fsi_file_t *ffi, unsigned i
>               r = SECTOR_SIZE - n;
>               if (r > bufsize)
>                       r = bufsize;
> +#ifdef _VDISK_
> +             if (ffi->ff_fsi->f_pvdisk) {
> +                     ret = vdisk_read(ffi->ff_fsi->f_pvdisk,
> +                         (off_t)(off - n), tmp, SECTOR_SIZE);
> +             } else {
> +                     ret = pread(ffi->ff_fsi->f_fd, tmp, SECTOR_SIZE,
> +                         off - n);
> +             }
> +#else
>               ret = pread(ffi->ff_fsi->f_fd, tmp, SECTOR_SIZE, off - n);
> +#endif
>               if (ret < n + r)
>                       return (0);
>               memcpy(buf, tmp + n, r);
> @@ -187,7 +201,16 @@ fsig_devread(fsi_file_t *ffi, unsigned i
>  
>       n = (bufsize & ~(SECTOR_SIZE - 1));
>       if (n > 0) {
> +#ifdef _VDISK_
> +             if (ffi->ff_fsi->f_pvdisk) {
> +                     ret = vdisk_read(ffi->ff_fsi->f_pvdisk, (off_t)off,
> +                         buf, n);
> +             } else {
> +                     ret = pread(ffi->ff_fsi->f_fd, buf, n, off);
> +             }
> +#else
>               ret = pread(ffi->ff_fsi->f_fd, buf, n, off);
> +#endif
>               if (ret < n)
>                       return (0);
>               buf += n;
> @@ -195,7 +218,16 @@ fsig_devread(fsi_file_t *ffi, unsigned i
>               off += n;
>       }
>       if (bufsize > 0) {
> +#ifdef _VDISK_
> +             if (ffi->ff_fsi->f_pvdisk) {
> +                     ret = vdisk_read(ffi->ff_fsi->f_pvdisk, (off_t)off,
> +                         tmp, SECTOR_SIZE);
> +             } else {
> +                     ret = pread(ffi->ff_fsi->f_fd, tmp, SECTOR_SIZE, off);
> +             }
> +#else
>               ret = pread(ffi->ff_fsi->f_fd, tmp, SECTOR_SIZE, off);
> +#endif
>               if (ret < bufsize)
>                       return (0);
>               memcpy(buf, tmp, bufsize);
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/common/fsimage_plugin.c
> --- a/tools/libfsimage/common/fsimage_plugin.c        Thu Oct 24 22:46:20 
> 2013 +0100
> +++ b/tools/libfsimage/common/fsimage_plugin.c        Sat Oct 26 20:03:06 
> 2013 +0400
> @@ -122,6 +122,7 @@ fail:
>  static int load_plugins(void)
>  {
>       const char *fsdir = getenv("FSIMAGE_FSDIR");
> +     const char *isadir = "";
>       struct dirent *dp = NULL;
>       struct dirent *dpp;
>       DIR *dir = NULL;
> @@ -130,8 +131,26 @@ static int load_plugins(void)
>       int err;
>       int ret = -1;
>  
> +#if defined(FSIMAGE_FSDIR)
>       if (fsdir == NULL)
>               fsdir = FSIMAGE_FSDIR;
> +#elif defined(__sun__)
> +     if (fsdir == NULL)
> +             fsdir = "/usr/lib/fs";
> +
> +     if (sizeof(void *) == 8)
> +             isadir = "64/";
> +#elif defined(__ia64__)
> +     if (fsdir == NULL)
> +             fsdir = "/usr/lib/fs";
> +#else
> +     if (fsdir == NULL) {
> +             if (sizeof(void *) == 8)
> +                     fsdir = "/usr/lib64/fs";
> +             else
> +                     fsdir = "/usr/lib/fs";
> +     }
> +#endif
>  
>       if ((name_max = pathconf(fsdir, _PC_NAME_MAX)) == -1)
>               goto fail;
> @@ -153,8 +172,8 @@ static int load_plugins(void)
>               if (strcmp(dpp->d_name, "..") == 0)
>                       continue;
>  
> -             (void) snprintf(tmp, name_max, "%s/%s/fsimage.so", fsdir,
> -                     dpp->d_name);
> +             (void) snprintf(tmp, name_max, "%s/%s/%sfsimage.so", fsdir,
> +                 dpp->d_name, isadir);
>  
>               if (init_plugin(tmp) != 0)
>                       goto fail;
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/common/fsimage_priv.h
> --- a/tools/libfsimage/common/fsimage_priv.h  Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/common/fsimage_priv.h  Sat Oct 26 20:03:06 2013 +0400
> @@ -47,6 +47,7 @@ struct fsi {
>       void *f_data;
>       fsi_plugin_t *f_plugin;
>       char *f_bootstring;
> +     void *f_pvdisk;
>  };
>  
>  struct fsi_file {
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/Makefile
> --- a/tools/libfsimage/zfs/Makefile   Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/Makefile   Sat Oct 26 20:03:06 2013 +0400
> @@ -25,7 +25,7 @@
>  XEN_ROOT = $(CURDIR)/../../..
>  
>  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
> +LIB_SRCS-y = zfs_lzjb.c zfs_sha256.c zfs_fletcher.c fsi_zfs.c fsys_zfs.c 
> zfs_lz4.c
>  
>  FS = zfs
>  
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/fsi_zfs.h
> --- a/tools/libfsimage/zfs/fsi_zfs.h  Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/fsi_zfs.h  Sat Oct 26 20:03:06 2013 +0400
> @@ -36,6 +36,8 @@
>  
>  /* Boot signature related defines for the findroot command */
>  #define      BOOTSIGN_DIR    "/boot/grub/bootsign"
> +#define      BOOTSIGN_ARGLEN (MAXNAMELEN + 10)       /* (<sign>,0,d) */
> +#define      BOOTSIGN_LEN    (sizeof (BOOTSIGN_DIR) + 1 + BOOTSIGN_ARGLEN)
>  #define      BOOTSIGN_BACKUP "/etc/bootsign"
>  
>  /* Maybe redirect memory requests through grub_scratch_mem. */
> @@ -60,6 +62,7 @@
>  #define grub_strstr strstr
>  #define grub_strlen strlen
>  #define grub_memmove memmove
> +#define grub_isspace isspace
>  
>  extern char current_bootpath[MAXPATHLEN];
>  extern char current_rootpool[MAXNAMELEN];
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/fsys_zfs.c
> --- a/tools/libfsimage/zfs/fsys_zfs.c Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/fsys_zfs.c Sat Oct 26 20:03:06 2013 +0400
> @@ -16,12 +16,18 @@
>   *  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.
>   */
>  
>  /*
> + * Copyright (c) 2012 by Delphix. All rights reserved.
> + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
> + */
> +
> +/*
>   * The zfs plug-in routines for GRUB are:
>   *
>   * zfs_mount() - locates a valid uberblock of the root pool and reads
> @@ -69,7 +75,18 @@ decomp_entry_t decomp_table[ZIO_COMPRESS
>       {"on", lzjb_decompress},        /* ZIO_COMPRESS_ON */
>       {"off", 0},                     /* ZIO_COMPRESS_OFF */
>       {"lzjb", lzjb_decompress},      /* ZIO_COMPRESS_LZJB */
> -     {"empty", 0}                    /* ZIO_COMPRESS_EMPTY */
> +     {"empty", 0},                   /* ZIO_COMPRESS_EMPTY */
> +     {"gzip-1", 0},                  /* ZIO_COMPRESS_GZIP_1 */
> +     {"gzip-2", 0},                  /* ZIO_COMPRESS_GZIP_2 */
> +     {"gzip-3", 0},                  /* ZIO_COMPRESS_GZIP_3 */
> +     {"gzip-4", 0},                  /* ZIO_COMPRESS_GZIP_4 */
> +     {"gzip-5", 0},                  /* ZIO_COMPRESS_GZIP_5 */
> +     {"gzip-6", 0},                  /* ZIO_COMPRESS_GZIP_6 */
> +     {"gzip-7", 0},                  /* ZIO_COMPRESS_GZIP_7 */
> +     {"gzip-8", 0},                  /* ZIO_COMPRESS_GZIP_8 */
> +     {"gzip-9", 0},                  /* ZIO_COMPRESS_GZIP_9 */
> +     {"zle", 0},                     /* ZIO_COMPRESS_ZLE */
> +     {"lz4", lz4_decompress}         /* ZIO_COMPRESS_LZ4 */
>  };
>  
>  static int zio_read_data(blkptr_t *bp, void *buf, char *stack);
> @@ -80,8 +97,8 @@ static int zio_read_data(blkptr_t *bp, v
>  static int
>  zfs_bcmp(const void *s1, const void *s2, size_t n)
>  {
> -     const uint8_t *ps1 = s1;
> -     const uint8_t *ps2 = s2;
> +     const uchar_t *ps1 = s1;
> +     const uchar_t *ps2 = s2;
>  
>       if (s1 != s2 && n != 0) {
>               do {
> @@ -118,16 +135,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" },
> -     { { 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" }
> +     {{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"},
>  };
>  
>  /*
> @@ -217,18 +234,13 @@ vdev_uberblock_compare(uberblock_t *ub1,
>   * Three pieces of information are needed to verify an uberblock: the magic
>   * number, the version number, and the checksum.
>   *
> - * Currently Implemented: version number, magic number
> - * Need to Implement: checksum
> - *
>   * Return:
>   *     0 - Success
>   *    -1 - Failure
>   */
>  static int
> -uberblock_verify(uberblock_phys_t *ub, uint64_t offset)
> +uberblock_verify(uberblock_t *uber, uint64_t ub_size, uint64_t offset)
>  {
> -
> -     uberblock_t *uber = &ub->ubp_uberblock;
>       blkptr_t bp;
>  
>       BP_ZERO(&bp);
> @@ -236,11 +248,11 @@ uberblock_verify(uberblock_phys_t *ub, u
>       BP_SET_BYTEORDER(&bp, ZFS_HOST_BYTEORDER);
>       ZIO_SET_CHECKSUM(&bp.blk_cksum, offset, 0, 0, 0);
>  
> -     if (zio_checksum_verify(&bp, (char *)ub, UBERBLOCK_SIZE) != 0)
> +     if (zio_checksum_verify(&bp, (char *)uber, ub_size) != 0)
>               return (-1);
>  
>       if (uber->ub_magic == UBERBLOCK_MAGIC &&
> -         uber->ub_version > 0 && uber->ub_version <= SPA_VERSION)
> +         SPA_VERSION_IS_SUPPORTED(uber->ub_version))
>               return (0);
>  
>       return (-1);
> @@ -252,25 +264,28 @@ uberblock_verify(uberblock_phys_t *ub, u
>   *    Success - Pointer to the best uberblock.
>   *    Failure - NULL
>   */
> -static uberblock_phys_t *
> -find_bestub(uberblock_phys_t *ub_array, uint64_t sector)
> +static uberblock_t *
> +find_bestub(char *ub_array, uint64_t ashift, uint64_t sector)
>  {
> -     uberblock_phys_t *ubbest = NULL;
> -     uint64_t offset;
> +     uberblock_t *ubbest = NULL;
> +     uberblock_t *ubnext;
> +     uint64_t offset, ub_size;
>       int i;
>  
> -     for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++) {
> +     ub_size = VDEV_UBERBLOCK_SIZE(ashift);
> +
> +     for (i = 0; i < VDEV_UBERBLOCK_COUNT(ashift); i++) {
> +             ubnext = (uberblock_t *)ub_array;
> +             ub_array += ub_size;
>               offset = (sector << SPA_MINBLOCKSHIFT) +
> -                 VDEV_UBERBLOCK_OFFSET(i);
> -             if (uberblock_verify(&ub_array[i], offset) == 0) {
> -                     if (ubbest == NULL) {
> -                             ubbest = &ub_array[i];
> -                     } else if (vdev_uberblock_compare(
> -                         &(ub_array[i].ubp_uberblock),
> -                         &(ubbest->ubp_uberblock)) > 0) {
> -                             ubbest = &ub_array[i];
> -                     }
> -             }
> +                 VDEV_UBERBLOCK_OFFSET(ashift, i);
> +
> +             if (uberblock_verify(ubnext, ub_size, offset) != 0)
> +                     continue;
> +
> +             if (ubbest == NULL ||
> +                 vdev_uberblock_compare(ubnext, ubbest) > 0)
> +                     ubbest = ubnext;
>       }
>  
>       return (ubbest);
> @@ -295,7 +310,7 @@ zio_read_gang(blkptr_t *bp, dva_t *dva, 
>       zio_gb = (zio_gbh_phys_t *)stack;
>       stack += SPA_GANGBLOCKSIZE;
>       offset = DVA_GET_OFFSET(dva);
> -     sector =  DVA_OFFSET_TO_PHYS_SECTOR(offset);
> +     sector = DVA_OFFSET_TO_PHYS_SECTOR(offset);
>  
>       /* read in the gang block header */
>       if (devread(sector, 0, SPA_GANGBLOCKSIZE, (char *)zio_gb) == 0) {
> @@ -354,8 +369,8 @@ zio_read_data(blkptr_t *bp, void *buf, c
>               } else {
>                       /* 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))
> +                     sector = DVA_OFFSET_TO_PHYS_SECTOR(offset);
> +                     if (devread(sector, 0, psize, buf) != 0)
>                               return (0);
>               }
>       }
> @@ -399,7 +414,7 @@ zio_read(blkptr_t *bp, void *buf, char *
>               stack += psize;
>       }
>  
> -     if (zio_read_data(bp, buf, stack)) {
> +     if (zio_read_data(bp, buf, stack) != 0) {
>               grub_printf("zio_read_data failed\n");
>               return (ERR_FSYS_CORRUPT);
>       }
> @@ -409,8 +424,13 @@ zio_read(blkptr_t *bp, void *buf, char *
>               return (ERR_FSYS_CORRUPT);
>       }
>  
> -     if (comp != ZIO_COMPRESS_OFF)
> -             decomp_table[comp].decomp_func(buf, retbuf, psize, lsize);
> +     if (comp != ZIO_COMPRESS_OFF) {
> +             if (decomp_table[comp].decomp_func(buf, retbuf, psize,
> +                 lsize) != 0) {
> +                     grub_printf("zio_read decompression failed\n");
> +                     return (ERR_FSYS_CORRUPT);
> +             }
> +     }
>  
>       return (0);
>  }
> @@ -446,7 +466,7 @@ dmu_read(dnode_phys_t *dn, uint64_t blki
>                       grub_memset(buf, 0,
>                           dn->dn_datablkszsec << SPA_MINBLOCKSHIFT);
>                       break;
> -             } else if ((errnum = zio_read(bp, tmpbuf, stack))) {
> +             } else if (errnum = zio_read(bp, tmpbuf, stack)) {
>                       return (errnum);
>               }
>  
> @@ -465,13 +485,13 @@ dmu_read(dnode_phys_t *dn, uint64_t blki
>   *   errnum - failure
>   */
>  static int
> -mzap_lookup(mzap_phys_t *zapobj, int objsize, char *name,
> +mzap_lookup(mzap_phys_t *zapobj, int objsize, const char *name,
>       uint64_t *value)
>  {
>       int i, chunks;
>       mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk;
>  
> -     chunks = objsize/MZAP_ENT_LEN - 1;
> +     chunks = objsize / MZAP_ENT_LEN - 1;
>       for (i = 0; i < chunks; i++) {
>               if (grub_strcmp(mzap_ent[i].mze_name, name) == 0) {
>                       *value = mzap_ent[i].mze_value;
> @@ -511,8 +531,8 @@ zap_hash(uint64_t salt, const char *name
>       /*
>        * Only use 28 bits, since we need 4 bits in the cookie for the
>        * collision differentiator.  We MUST use the high bits, since
> -      * those are the onces that we first pay attention to when
> -      * chosing the bucket.
> +      * those are the ones that we first pay attention to when
> +      * choosing the bucket.
>        */
>       crc &= ~((1ULL << (64 - 28)) - 1);
>  
> @@ -617,7 +637,7 @@ zap_leaf_lookup(zap_leaf_phys_t *l, int 
>   */
>  static int
>  fzap_lookup(dnode_phys_t *zap_dnode, zap_phys_t *zap,
> -    char *name, uint64_t *value, char *stack)
> +    const char *name, uint64_t *value, char *stack)
>  {
>       zap_leaf_phys_t *l;
>       uint64_t hash, idx, blkid;
> @@ -645,7 +665,7 @@ fzap_lookup(dnode_phys_t *zap_dnode, zap
>       stack += 1<<blksft;
>       if ((1<<blksft) < sizeof (zap_leaf_phys_t))
>               return (ERR_FSYS_CORRUPT);
> -     if ((errnum = dmu_read(zap_dnode, blkid, l, stack)))
> +     if (errnum = dmu_read(zap_dnode, blkid, l, stack))
>               return (errnum);
>  
>       return (zap_leaf_lookup(l, blksft, hash, name, value));
> @@ -660,7 +680,8 @@ fzap_lookup(dnode_phys_t *zap_dnode, zap
>   *   errnum - failure
>   */
>  static int
> -zap_lookup(dnode_phys_t *zap_dnode, char *name, uint64_t *val, char *stack)
> +zap_lookup(dnode_phys_t *zap_dnode, const char *name, uint64_t *val,
> +    char *stack)
>  {
>       uint64_t block_type;
>       int size;
> @@ -671,7 +692,7 @@ zap_lookup(dnode_phys_t *zap_dnode, char
>       size = zap_dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
>       stack += size;
>  
> -     if ((errnum = dmu_read(zap_dnode, 0, zapbuf, stack)))
> +     if ((errnum = dmu_read(zap_dnode, 0, zapbuf, stack)) != 0)
>               return (errnum);
>  
>       block_type = *((uint64_t *)zapbuf);
> @@ -687,6 +708,56 @@ zap_lookup(dnode_phys_t *zap_dnode, char
>       return (ERR_FSYS_CORRUPT);
>  }
>  
> +typedef struct zap_attribute {
> +     int za_integer_length;
> +     uint64_t za_num_integers;
> +     uint64_t za_first_integer;
> +     char *za_name;
> +} zap_attribute_t;
> +
> +typedef int (zap_cb_t)(zap_attribute_t *za, void *arg, char *stack);
> +
> +static int
> +zap_iterate(dnode_phys_t *zap_dnode, zap_cb_t *cb, void *arg, char *stack)
> +{
> +     uint32_t size = zap_dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
> +     zap_attribute_t za;
> +     int i;
> +     mzap_phys_t *mzp = (mzap_phys_t *)stack;
> +     stack += size;
> +
> +     if ((errnum = dmu_read(zap_dnode, 0, mzp, stack)) != 0)
> +             return (errnum);
> +
> +     /*
> +      * Iteration over fatzap objects has not yet been implemented.
> +      * If we encounter a pool in which there are more features for
> +      * read than can fit inside a microzap (i.e., more than 2048
> +      * features for read), we can add support for fatzap iteration.
> +      * For now, fail.
> +      */
> +     if (mzp->mz_block_type != ZBT_MICRO) {
> +             grub_printf("feature information stored in fatzap, pool "
> +                 "version not supported\n");
> +             return (1);
> +     }
> +
> +     za.za_integer_length = 8;
> +     za.za_num_integers = 1;
> +     for (i = 0; i < size / MZAP_ENT_LEN - 1; i++) {
> +             mzap_ent_phys_t *mzep = &mzp->mz_chunk[i];
> +             int err;
> +
> +             za.za_first_integer = mzep->mze_value;
> +             za.za_name = mzep->mze_name;
> +             err = cb(&za, arg, stack);
> +             if (err != 0)
> +                     return (err);
> +     }
> +
> +     return (0);
> +}
> +
>  /*
>   * Get the dnode of an object number from the metadnode of an object set.
>   *
> @@ -731,7 +802,7 @@ dnode_get(dnode_phys_t *mdn, uint64_t ob
>               stack += blksz;
>       }
>  
> -     if ((errnum = dmu_read(mdn, blkid, (char *)dnbuf, stack)))
> +     if (errnum = dmu_read(mdn, blkid, (char *)dnbuf, stack))
>               return (errnum);
>  
>       grub_memmove(buf, &dnbuf[idx], DNODE_SIZE);
> @@ -766,6 +837,24 @@ is_top_dataset_file(char *str)
>       return (0);
>  }
>  
> +static int
> +check_feature(zap_attribute_t *za, void *arg, char *stack)
> +{
> +     const char **names = arg;
> +     int i;
> +
> +     if (za->za_first_integer == 0)
> +             return (0);
> +
> +     for (i = 0; names[i] != NULL; i++) {
> +             if (grub_strcmp(za->za_name, names[i]) == 0) {
> +                     return (0);
> +             }
> +     }
> +     grub_printf("missing feature for read '%s'\n", za->za_name);
> +     return (ERR_NEWER_VERSION);
> +}
> +
>  /*
>   * Get the file dnode for a given file name where mdn is the meta dnode
>   * for this ZFS object set. When found, place the file dnode in dn.
> @@ -782,40 +871,40 @@ dnode_get_path(dnode_phys_t *mdn, char *
>       uint64_t objnum, version;
>       char *cname, ch;
>  
> -     if ((errnum = dnode_get(mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,
> -         dn, stack)))
> +     if (errnum = dnode_get(mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE,
> +         dn, stack))
>               return (errnum);
>  
> -     if ((errnum = zap_lookup(dn, ZPL_VERSION_STR, &version, stack)))
> +     if (errnum = zap_lookup(dn, ZPL_VERSION_STR, &version, stack))
>               return (errnum);
>       if (version > ZPL_VERSION)
>               return (-1);
>  
> -     if ((errnum = zap_lookup(dn, ZFS_ROOT_OBJ, &objnum, stack)))
> +     if (errnum = zap_lookup(dn, ZFS_ROOT_OBJ, &objnum, stack))
>               return (errnum);
>  
> -     if ((errnum = dnode_get(mdn, objnum, DMU_OT_DIRECTORY_CONTENTS,
> -         dn, stack)))
> +     if (errnum = dnode_get(mdn, objnum, DMU_OT_DIRECTORY_CONTENTS,
> +         dn, stack))
>               return (errnum);
>  
>       /* skip leading slashes */
>       while (*path == '/')
>               path++;
>  
> -     while (*path && !isspace((uint8_t)*path)) {
> +     while (*path && !grub_isspace(*path)) {
>  
>               /* get the next component name */
>               cname = path;
> -             while (*path && !isspace((uint8_t)*path) && *path != '/')
> +             while (*path && !grub_isspace(*path) && *path != '/')
>                       path++;
>               ch = *path;
>               *path = 0;   /* ensure null termination */
>  
> -             if ((errnum = zap_lookup(dn, cname, &objnum, stack)))
> +             if (errnum = zap_lookup(dn, cname, &objnum, stack))
>                       return (errnum);
>  
>               objnum = ZFS_DIRENT_OBJ(objnum);
> -             if ((errnum = dnode_get(mdn, objnum, 0, dn, stack)))
> +             if (errnum = dnode_get(mdn, objnum, 0, dn, stack))
>                       return (errnum);
>  
>               *path = ch;
> @@ -843,8 +932,8 @@ get_default_bootfsobj(dnode_phys_t *mosm
>       dnode_phys_t *dn = (dnode_phys_t *)stack;
>       stack += DNODE_SIZE;
>  
> -     if ((errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
> -         DMU_OT_OBJECT_DIRECTORY, dn, stack)))
> +     if (errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
> +         DMU_OT_OBJECT_DIRECTORY, dn, stack))
>               return (errnum);
>  
>       /*
> @@ -854,7 +943,7 @@ get_default_bootfsobj(dnode_phys_t *mosm
>       if (zap_lookup(dn, DMU_POOL_PROPS, &objnum, stack))
>               return (ERR_FILESYSTEM_NOT_FOUND);
>  
> -     if ((errnum = dnode_get(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(dn, ZPOOL_PROP_BOOTFS, &objnum, stack))
> @@ -868,6 +957,57 @@ get_default_bootfsobj(dnode_phys_t *mosm
>  }
>  
>  /*
> + * List of pool features that the grub implementation of ZFS supports for
> + * read. Note that features that are only required for write do not need
> + * to be listed here since grub opens pools in read-only mode.
> + *
> + * When this list is updated the version number in usr/src/grub/capability
> + * must be incremented to ensure the new grub gets installed.
> + */
> +static const char *spa_feature_names[] = {
> +     "org.illumos:lz4_compress",
> +     NULL
> +};
> +
> +/*
> + * Checks whether the MOS features that are active are supported by this
> + * (GRUB's) implementation of ZFS.
> + *
> + * Return:
> + *   0: Success.
> + *   errnum: Failure.
> + */
> +static int
> +check_mos_features(dnode_phys_t *mosmdn, char *stack)
> +{
> +     uint64_t objnum;
> +     dnode_phys_t *dn;
> +     uint8_t error = 0;
> +
> +     dn = (dnode_phys_t *)stack;
> +     stack += DNODE_SIZE;
> +
> +     if ((errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
> +         DMU_OT_OBJECT_DIRECTORY, dn, stack)) != 0)
> +             return (errnum);
> +
> +     /*
> +      * Find the object number for 'features_for_read' and retrieve its
> +      * corresponding dnode. Note that we don't check features_for_write
> +      * because GRUB is not opening the pool for write.
> +      */
> +     if ((errnum = zap_lookup(dn, DMU_POOL_FEATURES_FOR_READ, &objnum,
> +         stack)) != 0)
> +             return (errnum);
> +
> +     if ((errnum = dnode_get(mosmdn, objnum, DMU_OTN_ZAP_METADATA,
> +         dn, stack)) != 0)
> +             return (errnum);
> +
> +     return (zap_iterate(dn, check_feature, spa_feature_names, stack));
> +}
> +
> +/*
>   * Given a MOS metadnode, get the metadnode of a given filesystem name 
> (fsname),
>   * e.g. pool/rootfs, or a given object number (obj), e.g. the object number
>   * of pool/rootfs.
> @@ -896,15 +1036,15 @@ get_objset_mdn(dnode_phys_t *mosmdn, cha
>               goto skip;
>       }
>  
> -     if ((errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
> -         DMU_OT_OBJECT_DIRECTORY, mdn, stack)))
> +     if (errnum = dnode_get(mosmdn, DMU_POOL_DIRECTORY_OBJECT,
> +         DMU_OT_OBJECT_DIRECTORY, mdn, stack))
>               return (errnum);
>  
> -     if ((errnum = zap_lookup(mdn, DMU_POOL_ROOT_DATASET, &objnum,
> -         stack)))
> +     if (errnum = zap_lookup(mdn, DMU_POOL_ROOT_DATASET, &objnum,
> +         stack))
>               return (errnum);
>  
> -     if ((errnum = dnode_get(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) {
> @@ -914,23 +1054,24 @@ get_objset_mdn(dnode_phys_t *mosmdn, cha
>       }
>  
>       /* take out the pool name */
> -     while (*fsname && !isspace((uint8_t)*fsname) && *fsname != '/')
> +     while (*fsname && !grub_isspace(*fsname) && *fsname != '/')
>               fsname++;
>  
> -     while (*fsname && !isspace((uint8_t)*fsname)) {
> +     while (*fsname && !grub_isspace(*fsname)) {
>               uint64_t childobj;
>  
>               while (*fsname == '/')
>                       fsname++;
>  
>               cname = fsname;
> -             while (*fsname && !isspace((uint8_t)*fsname) && *fsname != '/')
> +             while (*fsname && !grub_isspace(*fsname) && *fsname != '/')
>                       fsname++;
>               ch = *fsname;
>               *fsname = 0;
>  
>               snapname = cname;
> -             while (*snapname && !isspace((uint8_t)*snapname) && *snapname 
> != '@')
> +             while (*snapname && !grub_isspace(*snapname) && *snapname !=
> +                 '@')
>                       snapname++;
>               if (*snapname == '@') {
>                       issnapshot = 1;
> @@ -938,15 +1079,15 @@ get_objset_mdn(dnode_phys_t *mosmdn, cha
>               }
>               childobj =
>                   ((dsl_dir_phys_t *)DN_BONUS(mdn))->dd_child_dir_zapobj;
> -             if ((errnum = dnode_get(mosmdn, childobj,
> -                 DMU_OT_DSL_DIR_CHILD_MAP, mdn, stack)))
> +             if (errnum = dnode_get(mosmdn, childobj,
> +                 DMU_OT_DSL_DIR_CHILD_MAP, mdn, stack))
>                       return (errnum);
>  
>               if (zap_lookup(mdn, cname, &objnum, stack))
>                       return (ERR_FILESYSTEM_NOT_FOUND);
>  
> -             if ((errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR,
> -                 mdn, stack)))
> +             if (errnum = dnode_get(mosmdn, objnum, DMU_OT_DSL_DIR,
> +                 mdn, stack))
>                       return (errnum);
>  
>               *fsname = ch;
> @@ -958,7 +1099,7 @@ get_objset_mdn(dnode_phys_t *mosmdn, cha
>               *obj = headobj;
>  
>  skip:
> -     if ((errnum = dnode_get(mosmdn, headobj, DMU_OT_DSL_DATASET, mdn, 
> stack)))
> +     if (errnum = dnode_get(mosmdn, headobj, DMU_OT_DSL_DATASET, mdn, stack))
>               return (errnum);
>       if (issnapshot) {
>               uint64_t snapobj;
> @@ -966,13 +1107,13 @@ skip:
>               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)))
> +             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)))
> +             if (errnum = dnode_get(mosmdn, headobj,
> +                 DMU_OT_DSL_DATASET, mdn, stack))
>                       return (errnum);
>               if (obj)
>                       *obj = headobj;
> @@ -981,7 +1122,7 @@ skip:
>       bp = &((dsl_dataset_phys_t *)DN_BONUS(mdn))->ds_bp;
>       osp = (objset_phys_t *)stack;
>       stack += sizeof (objset_phys_t);
> -     if ((errnum = zio_read(bp, osp, stack)))
> +     if (errnum = zio_read(bp, osp, stack))
>               return (errnum);
>  
>       grub_memmove((char *)mdn, (char *)&osp->os_meta_dnode, DNODE_SIZE);
> @@ -1019,8 +1160,7 @@ nvlist_unpack(char *nvlist, char **out)
>       if (nvlist[0] != NV_ENCODE_XDR || nvlist[1] != HOST_ENDIAN)
>               return (1);
>  
> -     nvlist += 4;
> -     *out = nvlist;
> +     *out = nvlist + 4;
>       return (0);
>  }
>  
> @@ -1033,7 +1173,7 @@ nvlist_array(char *nvlist, int index)
>               /* skip the header, nvl_version, and nvl_nvflag */
>               nvlist = nvlist + 4 * 2;
>  
> -             while ((encode_size = BSWAP_32(*(uint32_t *)nvlist)))
> +             while (encode_size = BSWAP_32(*(uint32_t *)nvlist))
>                       nvlist += encode_size; /* goto the next nvpair */
>  
>               nvlist = nvlist + 4 * 2; /* skip the ending 2 zeros - 8 bytes */
> @@ -1042,69 +1182,159 @@ nvlist_array(char *nvlist, int index)
>       return (nvlist);
>  }
>  
> +/*
> + * The nvlist_next_nvpair() function returns a handle to the next nvpair in 
> the
> + * list following nvpair. If nvpair is NULL, the first pair is returned. If
> + * nvpair is the last pair in the nvlist, NULL is returned.
> + */
> +static char *
> +nvlist_next_nvpair(char *nvl, char *nvpair)
> +{
> +     char *cur, *prev;
> +     int encode_size;
> +
> +     if (nvl == NULL)
> +             return (NULL);
> +
> +     if (nvpair == NULL) {
> +             /* skip over nvl_version and nvl_nvflag */
> +             nvpair = nvl + 4 * 2;
> +     } else {
> +             /* skip to the next nvpair */
> +             encode_size = BSWAP_32(*(uint32_t *)nvpair);
> +             nvpair += encode_size;
> +     }
> +
> +     /* 8 bytes of 0 marks the end of the list */
> +     if (*(uint64_t *)nvpair == 0)
> +             return (NULL);
> +
> +     return (nvpair);
> +}
> +
> +/*
> + * This function returns 0 on success and 1 on failure. On success, a string
> + * containing the name of nvpair is saved in buf.
> + */
> +static int
> +nvpair_name(char *nvp, char *buf, int buflen)
> +{
> +     int len;
> +
> +     /* skip over encode/decode size */
> +     nvp += 4 * 2;
> +
> +     len = BSWAP_32(*(uint32_t *)nvp);
> +     if (buflen < len + 1)
> +             return (1);
> +
> +     grub_memmove(buf, nvp + 4, len);
> +     buf[len] = '\0';
> +
> +     return (0);
> +}
> +
> +/*
> + * This function retrieves the value of the nvpair in the form of enumerated
> + * type data_type_t. This is used to determine the appropriate type to pass 
> to
> + * nvpair_value().
> + */
> +static int
> +nvpair_type(char *nvp)
> +{
> +     int name_len, type;
> +
> +     /* skip over encode/decode size */
> +     nvp += 4 * 2;
> +
> +     /* skip over name_len */
> +     name_len = BSWAP_32(*(uint32_t *)nvp);
> +     nvp += 4;
> +
> +     /* skip over name */
> +     nvp = nvp + ((name_len + 3) & ~3); /* align */
> +
> +     type = BSWAP_32(*(uint32_t *)nvp);
> +
> +     return (type);
> +}
> +
> +static int
> +nvpair_value(char *nvp, void *val, int valtype, int *nelmp)
> +{
> +     int name_len, type, slen;
> +     char *strval = val;
> +     uint64_t *intval = val;
> +
> +     /* skip over encode/decode size */
> +     nvp += 4 * 2;
> +
> +     /* skip over name_len */
> +     name_len = BSWAP_32(*(uint32_t *)nvp);
> +     nvp += 4;
> +
> +     /* skip over name */
> +     nvp = nvp + ((name_len + 3) & ~3); /* align */
> +
> +     /* skip over type */
> +     type = BSWAP_32(*(uint32_t *)nvp);
> +     nvp += 4;
> +
> +     if (type == valtype) {
> +             int nelm;
> +
> +             nelm = BSWAP_32(*(uint32_t *)nvp);
> +             if (valtype != DATA_TYPE_BOOLEAN && nelm < 1)
> +                     return (1);
> +             nvp += 4;
> +
> +             switch (valtype) {
> +             case DATA_TYPE_BOOLEAN:
> +                     return (0);
> +
> +             case DATA_TYPE_STRING:
> +                     slen = BSWAP_32(*(uint32_t *)nvp);
> +                     nvp += 4;
> +                     grub_memmove(strval, nvp, slen);
> +                     strval[slen] = '\0';
> +                     return (0);
> +
> +             case DATA_TYPE_UINT64:
> +                     *intval = BSWAP_64(*(uint64_t *)nvp);
> +                     return (0);
> +
> +             case DATA_TYPE_NVLIST:
> +                     *(void **)val = (void *)nvp;
> +                     return (0);
> +
> +             case DATA_TYPE_NVLIST_ARRAY:
> +                     *(void **)val = (void *)nvp;
> +                     if (nelmp)
> +                             *nelmp = nelm;
> +                     return (0);
> +             }
> +     }
> +
> +     return (1);
> +}
> +
>  static int
>  nvlist_lookup_value(char *nvlist, char *name, void *val, int valtype,
>      int *nelmp)
>  {
> -     int name_len, type, slen, encode_size;
> -     char *nvpair, *nvp_name, *strval = val;
> -     uint64_t *intval = val;
> +     char *nvpair;
>  
> -     /* skip the header, nvl_version, and nvl_nvflag */
> -     nvlist = nvlist + 4 * 2;
> -
> -     /*
> -      * Loop thru the nvpair list
> -      * The XDR representation of an integer is in big-endian byte order.
> -      */
> -     while ((encode_size = BSWAP_32(*(uint32_t *)nvlist)))  {
> -
> -             nvpair = nvlist + 4 * 2; /* skip the encode/decode size */
> -
> -             name_len = BSWAP_32(*(uint32_t *)nvpair);
> -             nvpair += 4;
> -
> -             nvp_name = nvpair;
> -             nvpair = nvpair + ((name_len + 3) & ~3); /* align */
> -
> -             type = BSWAP_32(*(uint32_t *)nvpair);
> -             nvpair += 4;
> +     for (nvpair = nvlist_next_nvpair(nvlist, NULL);
> +         nvpair != NULL;
> +         nvpair = nvlist_next_nvpair(nvlist, nvpair)) {
> +             int name_len = BSWAP_32(*(uint32_t *)(nvpair + 4 * 2));
> +             char *nvp_name = nvpair + 4 * 3;
>  
>               if ((grub_strncmp(nvp_name, name, name_len) == 0) &&
> -                 type == valtype) {
> -                     int nelm;
> -
> -                     if ((nelm = BSWAP_32(*(uint32_t *)nvpair)) < 1)
> -                             return (1);
> -                     nvpair += 4;
> -
> -                     switch (valtype) {
> -                     case DATA_TYPE_STRING:
> -                             slen = BSWAP_32(*(uint32_t *)nvpair);
> -                             nvpair += 4;
> -                             grub_memmove(strval, nvpair, slen);
> -                             strval[slen] = '\0';
> -                             return (0);
> -
> -                     case DATA_TYPE_UINT64:
> -                             *intval = BSWAP_64(*(uint64_t *)nvpair);
> -                             return (0);
> -
> -                     case DATA_TYPE_NVLIST:
> -                             *(void **)val = (void *)nvpair;
> -                             return (0);
> -
> -                     case DATA_TYPE_NVLIST_ARRAY:
> -                             *(void **)val = (void *)nvpair;
> -                             if (nelmp)
> -                                     *nelmp = nelm;
> -                             return (0);
> -                     }
> +                 nvpair_type(nvpair) == valtype) {
> +                     return (nvpair_value(nvpair, val, valtype, nelmp));
>               }
> -
> -             nvlist += encode_size; /* goto the next nvpair */
>       }
> -
>       return (1);
>  }
>  
> @@ -1141,7 +1371,7 @@ vdev_get_bootpath(char *nv, uint64_t ing
>           NULL))
>               return (ERR_FSYS_CORRUPT);
>  
> -     if (strcmp(type, VDEV_TYPE_DISK) == 0) {
> +     if (grub_strcmp(type, VDEV_TYPE_DISK) == 0) {
>               uint64_t guid;
>  
>               if (vdev_validate(nv) != 0)
> @@ -1171,15 +1401,15 @@ vdev_get_bootpath(char *nv, uint64_t ing
>                   devid, DATA_TYPE_STRING, NULL) != 0)
>                       devid[0] = '\0';
>  
> -             if (strlen(bootpath) >= MAXPATHLEN ||
> -                 strlen(devid) >= MAXPATHLEN)
> +             if (grub_strlen(bootpath) >= MAXPATHLEN ||
> +                 grub_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))) {
> +     } else if (grub_strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
> +         grub_strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
> +         (is_spare = (grub_strcmp(type, VDEV_TYPE_SPARE) == 0))) {
>               int nelm, i;
>               char *child;
>  
> @@ -1207,15 +1437,14 @@ vdev_get_bootpath(char *nv, uint64_t ing
>   *   0 - success
>   *   ERR_* - failure
>   */
> -int
> +static int
>  check_pool_label(uint64_t sector, char *stack, char *outdevid,
> -    char *outpath, uint64_t *outguid)
> +    char *outpath, uint64_t *outguid, uint64_t *outashift, uint64_t 
> *outversion)
>  {
>       vdev_phys_t *vdev;
>       uint64_t pool_state, txg = 0;
> -     char *nvlist, *nv;
> +     char *nvlist, *nv, *features;
>       uint64_t diskguid;
> -     uint64_t version;
>  
>       sector += (VDEV_SKIP_SIZE >> SPA_MINBLOCKSHIFT);
>  
> @@ -1248,10 +1477,10 @@ check_pool_label(uint64_t sector, char *
>       if (txg == 0)
>               return (ERR_NO_BOOTPATH);
>  
> -     if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_VERSION, &version,
> +     if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_VERSION, outversion,
>           DATA_TYPE_UINT64, NULL))
>               return (ERR_FSYS_CORRUPT);
> -     if (version > SPA_VERSION)
> +     if (!SPA_VERSION_IS_SUPPORTED(*outversion))
>               return (ERR_NEWER_VERSION);
>       if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_VDEV_TREE, &nv,
>           DATA_TYPE_NVLIST, NULL))
> @@ -1259,11 +1488,38 @@ check_pool_label(uint64_t sector, char *
>       if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_GUID, &diskguid,
>           DATA_TYPE_UINT64, NULL))
>               return (ERR_FSYS_CORRUPT);
> +     if (nvlist_lookup_value(nv, ZPOOL_CONFIG_ASHIFT, outashift,
> +         DATA_TYPE_UINT64, NULL) != 0)
> +             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);
> +
> +     if (nvlist_lookup_value(nvlist, ZPOOL_CONFIG_FEATURES_FOR_READ,
> +         &features, DATA_TYPE_NVLIST, NULL) == 0) {
> +             char *nvp;
> +             char *name = stack;
> +             stack += MAXNAMELEN;
> +
> +             for (nvp = nvlist_next_nvpair(features, NULL);
> +                 nvp != NULL;
> +                 nvp = nvlist_next_nvpair(features, nvp)) {
> +                     zap_attribute_t za;
> +
> +                     if (nvpair_name(nvp, name, MAXNAMELEN) != 0)
> +                             return (ERR_FSYS_CORRUPT);
> +
> +                     za.za_integer_length = 8;
> +                     za.za_num_integers = 1;
> +                     za.za_first_integer = 1;
> +                     za.za_name = name;
> +                     if (check_feature(&za, spa_feature_names, stack) != 0)
> +                             return (ERR_NEWER_VERSION);
> +             }
> +     }
> +
>       return (0);
>  }
>  
> @@ -1278,15 +1534,16 @@ check_pool_label(uint64_t sector, char *
>  int
>  zfs_mount(void)
>  {
> -     char *stack;
> +     char *stack, *ub_array;
>       int label = 0;
> -     uberblock_phys_t *ub_array, *ubbest;
> +     uberblock_t *ubbest;
>       objset_phys_t *osp;
>       char tmp_bootpath[MAXNAMELEN];
>       char tmp_devid[MAXNAMELEN];
> -     uint64_t tmp_guid;
> +     uint64_t tmp_guid, ashift, version;
>       uint64_t adjpl = (uint64_t)part_length << SPA_MINBLOCKSHIFT;
>       int err = errnum; /* preserve previous errnum state */
> +     uint64_t sector;
>  
>       /* if it's our first time here, zero the best uberblock out */
>       if (best_drive == 0 && best_part == 0 && find_best_root) {
> @@ -1296,7 +1553,7 @@ zfs_mount(void)
>  
>       stackbase = ZFS_SCRATCH;
>       stack = stackbase;
> -     ub_array = (uberblock_phys_t *)stack;
> +     ub_array = stack;
>       stack += VDEV_UBERBLOCK_RING;
>  
>       osp = (objset_phys_t *)stack;
> @@ -1305,8 +1562,6 @@ zfs_mount(void)
>  
>       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
> @@ -1324,39 +1579,38 @@ zfs_mount(void)
>  
>               /* Read in the uberblock ring (128K). */
>               if (devread(sector  +
> -                 ((VDEV_SKIP_SIZE + VDEV_PHYS_SIZE) >>
> -                 SPA_MINBLOCKSHIFT), 0, VDEV_UBERBLOCK_RING,
> -                 (char *)ub_array) == 0)
> +                 ((VDEV_SKIP_SIZE + VDEV_PHYS_SIZE) >> SPA_MINBLOCKSHIFT),
> +                 0, VDEV_UBERBLOCK_RING, ub_array) == 0)
>                       continue;
>  
> -             if ((ubbest = find_bestub(ub_array, sector)) != NULL &&
> -                 zio_read(&ubbest->ubp_uberblock.ub_rootbp, osp, stack)
> -                 == 0) {
> +             if (check_pool_label(sector, stack, tmp_devid,
> +                 tmp_bootpath, &tmp_guid, &ashift, &version))
> +                     continue;
>  
> -                     VERIFY_OS_TYPE(osp, DMU_OST_META);
> +             if (pool_guid == 0)
> +                     pool_guid = tmp_guid;
>  
> -                     if (check_pool_label(sector, stack, tmp_devid,
> -                         tmp_bootpath, &tmp_guid))
> -                             continue;
> -                     if (pool_guid == 0)
> -                             pool_guid = tmp_guid;
> +             if ((ubbest = find_bestub(ub_array, ashift, sector)) == NULL ||
> +                 zio_read(&ubbest->ub_rootbp, osp, stack) != 0)
> +                     continue;
>  
> -                     if (find_best_root && ((pool_guid != tmp_guid) ||
> -                         vdev_uberblock_compare(&ubbest->ubp_uberblock,
> -                         &(current_uberblock)) <= 0))
> -                             continue;
> +             VERIFY_OS_TYPE(osp, DMU_OST_META);
>  
> -                     /* Got the MOS. Save it at the memory addr MOS. */
> -                     grub_memmove(MOS, &osp->os_meta_dnode, DNODE_SIZE);
> -                     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);
> -             }
> +             if (version >= SPA_VERSION_FEATURES &&
> +                 check_mos_features(&osp->os_meta_dnode, stack) != 0)
> +                     continue;
> +
> +             if (find_best_root && ((pool_guid != tmp_guid) ||
> +                 vdev_uberblock_compare(ubbest, &(current_uberblock)) <= 0))
> +                     continue;
> +
> +             /* Got the MOS. Save it at the memory addr MOS. */
> +             grub_memmove(MOS, &osp->os_meta_dnode, DNODE_SIZE);
> +             grub_memmove(&current_uberblock, ubbest, 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);
>       }
>  
>       /*
> @@ -1399,23 +1653,23 @@ zfs_open(char *filename)
>        * do not goto 'current_bootfs'.
>        */
>       if (is_top_dataset_file(filename)) {
> -             if ((errnum = get_objset_mdn(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(MOS,
> -                         &current_bootfs_obj, stack)))
> +                     if (errnum = get_default_bootfsobj(MOS,
> +                         &current_bootfs_obj, stack))
>                               return (0);
>  
> -                     if ((errnum = get_objset_mdn(MOS, NULL,
> -                         &current_bootfs_obj, mdn, stack)))
> +                     if (errnum = get_objset_mdn(MOS, NULL,
> +                         &current_bootfs_obj, mdn, stack))
>                               return (0);
>               } else {
> -                     if ((errnum = get_objset_mdn(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);
>                       }
> @@ -1515,7 +1769,7 @@ zfs_read(char *buf, int len)
>                */
>               uint64_t blkid = filepos / blksz;
>  
> -             if ((errnum = dmu_read(DNODE, blkid, file_buf, stack)))
> +             if (errnum = dmu_read(DNODE, blkid, file_buf, stack))
>                       return (0);
>  
>               file_start = blkid * blksz;
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/fsys_zfs.h
> --- a/tools/libfsimage/zfs/fsys_zfs.h Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/fsys_zfs.h Sat Oct 26 20:03:06 2013 +0400
> @@ -16,10 +16,17 @@
>   *  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.
>   */
> +
> +/*
> + * Copyright (c) 2012 by Delphix. All rights reserved.
> + * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
> + */
> +
>  #ifndef _FSYS_ZFS_H
>  #define      _FSYS_ZFS_H
>  
> @@ -95,26 +102,8 @@ typedef   unsigned int size_t;
>  #define      BSWAP_64(x)     ((BSWAP_32(x) << 32) | BSWAP_32((x) >> 32))
>  #define      P2ROUNDUP(x, align)     (-(-(x) & -(align)))
>  
> -/*
> - * XXX Match these macro up with real zfs once we have nvlist support so 
> that we
> - * can support large sector disks.
> - */
> -#define      UBERBLOCK_SIZE          (1ULL << UBERBLOCK_SHIFT)
> -#define      VDEV_UBERBLOCK_SHIFT    UBERBLOCK_SHIFT
> -#include <stddef.h>
> -#define      VDEV_UBERBLOCK_OFFSET(n) \
> -offsetof(vdev_label_t, vl_uberblock[(n) << VDEV_UBERBLOCK_SHIFT])
> -
>  typedef struct uberblock uberblock_t;
>  
> -/* XXX Uberblock_phys_t is no longer in the kernel zfs */
> -typedef struct uberblock_phys {
> -     uberblock_t     ubp_uberblock;
> -     char            ubp_pad[UBERBLOCK_SIZE - sizeof (uberblock_t) -
> -                             sizeof (zio_eck_t)];
> -     zio_eck_t       ubp_zec;
> -} uberblock_phys_t;
> -
>  /*
>   * Macros to get fields in a bp or DVA.
>   */
> @@ -137,10 +126,36 @@ typedef struct uberblock_phys {
>  #define      NV_ENCODE_NATIVE        0
>  #define      NV_ENCODE_XDR           1
>  #define      HOST_ENDIAN             1       /* for x86 machine */
> -#define      DATA_TYPE_UINT64        8
> -#define      DATA_TYPE_STRING        9
> -#define      DATA_TYPE_NVLIST        19
> -#define      DATA_TYPE_NVLIST_ARRAY  20
> +typedef enum {
> +     DATA_TYPE_UNKNOWN = 0,
> +     DATA_TYPE_BOOLEAN,
> +     DATA_TYPE_BYTE,
> +     DATA_TYPE_INT16,
> +     DATA_TYPE_UINT16,
> +     DATA_TYPE_INT32,
> +     DATA_TYPE_UINT32,
> +     DATA_TYPE_INT64,
> +     DATA_TYPE_UINT64,
> +     DATA_TYPE_STRING,
> +     DATA_TYPE_BYTE_ARRAY,
> +     DATA_TYPE_INT16_ARRAY,
> +     DATA_TYPE_UINT16_ARRAY,
> +     DATA_TYPE_INT32_ARRAY,
> +     DATA_TYPE_UINT32_ARRAY,
> +     DATA_TYPE_INT64_ARRAY,
> +     DATA_TYPE_UINT64_ARRAY,
> +     DATA_TYPE_STRING_ARRAY,
> +     DATA_TYPE_HRTIME,
> +     DATA_TYPE_NVLIST,
> +     DATA_TYPE_NVLIST_ARRAY,
> +     DATA_TYPE_BOOLEAN_VALUE,
> +     DATA_TYPE_INT8,
> +     DATA_TYPE_UINT8,
> +     DATA_TYPE_BOOLEAN_ARRAY,
> +     DATA_TYPE_INT8_ARRAY,
> +     DATA_TYPE_UINT8_ARRAY,
> +     DATA_TYPE_DOUBLE
> +} data_type_t;
>  
>  /*
>   * Decompression Entry - lzjb
> @@ -199,6 +214,7 @@ extern void fletcher_4_native(const void
>  extern void fletcher_4_byteswap(const void *, uint64_t, zio_cksum_t *);
>  extern void zio_checksum_SHA256(const void *, uint64_t, zio_cksum_t *);
>  extern int lzjb_decompress(void *, void *, size_t, size_t);
> +extern int lz4_decompress(void *, void *, size_t, size_t);
>  
>  #endif       /* FSYS_ZFS */
>  
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/zfs-include/dmu.h
> --- a/tools/libfsimage/zfs/zfs-include/dmu.h  Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/dmu.h  Sat Oct 26 20:03:06 2013 +0400
> @@ -16,11 +16,16 @@
>   *  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.
>   */
>  
> +/*
> + * Copyright (c) 2012 by Delphix. All rights reserved.
> + */
> +
>  #ifndef      _SYS_DMU_H
>  #define      _SYS_DMU_H
>  
> @@ -31,6 +36,41 @@
>   * The DMU also interacts with the SPA.  That interface is described in
>   * dmu_spa.h.
>   */
> +
> +#define      B_FALSE 0
> +#define      B_TRUE  1
> +
> +#define      DMU_OT_NEWTYPE 0x80
> +#define      DMU_OT_METADATA 0x40
> +#define      DMU_OT_BYTESWAP_MASK 0x3f
> +
> +#define      DMU_OT(byteswap, metadata) \
> +     (DMU_OT_NEWTYPE | \
> +     ((metadata) ? DMU_OT_METADATA : 0) | \
> +     ((byteswap) & DMU_OT_BYTESWAP_MASK))
> +
> +#define      DMU_OT_IS_VALID(ot) (((ot) & DMU_OT_NEWTYPE) ? \
> +     ((ot) & DMU_OT_BYTESWAP_MASK) < DMU_BSWAP_NUMFUNCS : \
> +     (ot) < DMU_OT_NUMTYPES)
> +
> +#define      DMU_OT_IS_METADATA(ot) (((ot) & DMU_OT_NEWTYPE) ? \
> +     ((ot) & DMU_OT_METADATA) : \
> +     dmu_ot[(ot)].ot_metadata)
> +
> +typedef enum dmu_object_byteswap {
> +     DMU_BSWAP_UINT8,
> +     DMU_BSWAP_UINT16,
> +     DMU_BSWAP_UINT32,
> +     DMU_BSWAP_UINT64,
> +     DMU_BSWAP_ZAP,
> +     DMU_BSWAP_DNODE,
> +     DMU_BSWAP_OBJSET,
> +     DMU_BSWAP_ZNODE,
> +     DMU_BSWAP_OLDACL,
> +     DMU_BSWAP_ACL,
> +     DMU_BSWAP_NUMFUNCS
> +} dmu_object_byteswap_t;
> +
>  typedef enum dmu_object_type {
>       DMU_OT_NONE,
>       /* general: */
> @@ -38,8 +78,8 @@ typedef enum dmu_object_type {
>       DMU_OT_OBJECT_ARRAY,            /* UINT64 */
>       DMU_OT_PACKED_NVLIST,           /* UINT8 (XDR by nvlist_pack/unpack) */
>       DMU_OT_PACKED_NVLIST_SIZE,      /* UINT64 */
> -     DMU_OT_BPLIST,                  /* UINT64 */
> -     DMU_OT_BPLIST_HDR,              /* UINT64 */
> +     DMU_OT_BPOBJ,                   /* UINT64 */
> +     DMU_OT_BPOBJ_HDR,               /* UINT64 */
>       /* spa: */
>       DMU_OT_SPACE_MAP_HEADER,        /* UINT64 */
>       DMU_OT_SPACE_MAP,               /* UINT64 */
> @@ -56,7 +96,7 @@ typedef enum dmu_object_type {
>       DMU_OT_DSL_DATASET,             /* UINT64 */
>       /* zpl: */
>       DMU_OT_ZNODE,                   /* ZNODE */
> -     DMU_OT_OLDACL,                  /* OLD ACL */
> +     DMU_OT_OLDACL,                  /* Old ACL */
>       DMU_OT_PLAIN_FILE_CONTENTS,     /* UINT8 */
>       DMU_OT_DIRECTORY_CONTENTS,      /* ZAP */
>       DMU_OT_MASTER_NODE,             /* ZAP */
> @@ -79,7 +119,7 @@ typedef enum dmu_object_type {
>       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_SCAN_QUEUE,              /* ZAP */
>       DMU_OT_USERGROUP_USED,          /* ZAP */
>       DMU_OT_USERGROUP_QUOTA,         /* ZAP */
>       DMU_OT_USERREFS,                /* ZAP */
> @@ -89,7 +129,24 @@ typedef enum dmu_object_type {
>       DMU_OT_SA_MASTER_NODE,          /* ZAP */
>       DMU_OT_SA_ATTR_REGISTRATION,    /* ZAP */
>       DMU_OT_SA_ATTR_LAYOUTS,         /* ZAP */
> -     DMU_OT_NUMTYPES
> +     DMU_OT_SCAN_XLATE,              /* ZAP */
> +     DMU_OT_DEDUP,                   /* fake dedup BP from ddt_bp_create() */
> +     DMU_OT_DEADLIST,                /* ZAP */
> +     DMU_OT_DEADLIST_HDR,            /* UINT64 */
> +     DMU_OT_DSL_CLONES,              /* ZAP */
> +     DMU_OT_BPOBJ_SUBOBJ,            /* UINT64 */
> +     DMU_OT_NUMTYPES,
> +
> +     DMU_OTN_UINT8_DATA = DMU_OT(DMU_BSWAP_UINT8, B_FALSE),
> +     DMU_OTN_UINT8_METADATA = DMU_OT(DMU_BSWAP_UINT8, B_TRUE),
> +     DMU_OTN_UINT16_DATA = DMU_OT(DMU_BSWAP_UINT16, B_FALSE),
> +     DMU_OTN_UINT16_METADATA = DMU_OT(DMU_BSWAP_UINT16, B_TRUE),
> +     DMU_OTN_UINT32_DATA = DMU_OT(DMU_BSWAP_UINT32, B_FALSE),
> +     DMU_OTN_UINT32_METADATA = DMU_OT(DMU_BSWAP_UINT32, B_TRUE),
> +     DMU_OTN_UINT64_DATA = DMU_OT(DMU_BSWAP_UINT64, B_FALSE),
> +     DMU_OTN_UINT64_METADATA = DMU_OT(DMU_BSWAP_UINT64, B_TRUE),
> +     DMU_OTN_ZAP_DATA = DMU_OT(DMU_BSWAP_ZAP, B_FALSE),
> +     DMU_OTN_ZAP_METADATA = DMU_OT(DMU_BSWAP_ZAP, B_TRUE),
>  } dmu_object_type_t;
>  
>  typedef enum dmu_objset_type {
> @@ -107,6 +164,9 @@ typedef enum dmu_objset_type {
>   */
>  #define      DMU_POOL_DIRECTORY_OBJECT       1
>  #define      DMU_POOL_CONFIG                 "config"
> +#define      DMU_POOL_FEATURES_FOR_READ      "features_for_read"
> +#define      DMU_POOL_FEATURES_FOR_WRITE     "features_for_write"
> +#define      DMU_POOL_FEATURE_DESCRIPTIONS   "feature_descriptions"
>  #define      DMU_POOL_ROOT_DATASET           "root_dataset"
>  #define      DMU_POOL_SYNC_BPLIST            "sync_bplist"
>  #define      DMU_POOL_ERRLOG_SCRUB           "errlog_scrub"
> diff -r 7c12aaa128e3 -r c2e11847cac0 
> tools/libfsimage/zfs/zfs-include/dsl_dataset.h
> --- a/tools/libfsimage/zfs/zfs-include/dsl_dataset.h  Thu Oct 24 22:46:20 
> 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/dsl_dataset.h  Sat Oct 26 20:03:06 
> 2013 +0400
> @@ -24,8 +24,6 @@
>  #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;
>       uint64_t ds_prev_snap_obj;
> diff -r 7c12aaa128e3 -r c2e11847cac0 
> tools/libfsimage/zfs/zfs-include/dsl_dir.h
> --- a/tools/libfsimage/zfs/zfs-include/dsl_dir.h      Thu Oct 24 22:46:20 
> 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/dsl_dir.h      Sat Oct 26 20:03:06 
> 2013 +0400
> @@ -24,8 +24,6 @@
>  #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 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/zfs-include/spa.h
> --- a/tools/libfsimage/zfs/zfs-include/spa.h  Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/spa.h  Sat Oct 26 20:03:06 2013 +0400
> @@ -16,11 +16,16 @@
>   *  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.
>   */
>  
> +/*
> + * Copyright (c) 2012 by Delphix. All rights reserved.
> + */
> +
>  #ifndef _SYS_SPA_H
>  #define      _SYS_SPA_H
>  
> @@ -65,7 +70,7 @@
>  /*
>   * Size of block to hold the configuration data (a packed nvlist)
>   */
> -#define      SPA_CONFIG_BLOCKSIZE    (1 << 14)
> +#define      SPA_CONFIG_BLOCKSIZE    (1ULL << 14)
>  
>  /*
>   * The DVA size encodings for LSIZE and PSIZE support blocks up to 32MB.
> diff -r 7c12aaa128e3 -r c2e11847cac0 
> tools/libfsimage/zfs/zfs-include/uberblock_impl.h
> --- a/tools/libfsimage/zfs/zfs-include/uberblock_impl.h       Thu Oct 24 
> 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/uberblock_impl.h       Sat Oct 26 
> 20:03:06 2013 +0400
> @@ -24,8 +24,6 @@
>  #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 7c12aaa128e3 -r c2e11847cac0 
> tools/libfsimage/zfs/zfs-include/vdev_impl.h
> --- a/tools/libfsimage/zfs/zfs-include/vdev_impl.h    Thu Oct 24 22:46:20 
> 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/vdev_impl.h    Sat Oct 26 20:03:06 
> 2013 +0400
> @@ -24,12 +24,30 @@
>  #ifndef _SYS_VDEV_IMPL_H
>  #define      _SYS_VDEV_IMPL_H
>  
> +/* helper macros */
> +#undef       offsetof
> +#if defined(__GNUC__)
> +#define      offsetof(s, m)  __builtin_offsetof(s, m)
> +#else
> +#define      offsetof(s, m)  ((size_t)(&(((s *)0)->m)))
> +#endif
> +#define      MAX(x, y)               ((x) > (y) ? (x) : (y))
> +
>  #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)
>  
> +#define      VDEV_UBERBLOCK_SHIFT(sh)                \
> +     MAX((sh), UBERBLOCK_SHIFT)
> +#define      VDEV_UBERBLOCK_COUNT(sh)                \
> +     (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT(sh))
> +#define      VDEV_UBERBLOCK_OFFSET(sh, n)    \
> +     offsetof(vdev_label_t, vl_uberblock[(n) << VDEV_UBERBLOCK_SHIFT(sh)])
> +#define      VDEV_UBERBLOCK_SIZE(sh)                 \
> +     (1ULL << VDEV_UBERBLOCK_SHIFT(sh))
> +
>  typedef struct vdev_phys {
>       char            vp_nvlist[VDEV_PHYS_SIZE - sizeof (zio_eck_t)];
>       zio_eck_t       vp_zbt;
> diff -r 7c12aaa128e3 -r c2e11847cac0 
> tools/libfsimage/zfs/zfs-include/zap_leaf.h
> --- a/tools/libfsimage/zfs/zfs-include/zap_leaf.h     Thu Oct 24 22:46:20 
> 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/zap_leaf.h     Sat Oct 26 20:03:06 
> 2013 +0400
> @@ -24,8 +24,6 @@
>  #ifndef      _SYS_ZAP_LEAF_H
>  #define      _SYS_ZAP_LEAF_H
>  
> -#pragma ident        "%Z%%M% %I%     %E% SMI"
> -
>  #define      ZAP_LEAF_MAGIC 0x2AB1EAF
>  
>  /* chunk size = 24 bytes */
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/zfs-include/zfs.h
> --- a/tools/libfsimage/zfs/zfs-include/zfs.h  Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/zfs.h  Sat Oct 26 20:03:06 2013 +0400
> @@ -16,9 +16,10 @@
>   *  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.
> + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights 
> reserved.
> + * Copyright (c) 2012 by Delphix. All rights reserved.
>   */
>  
>  #ifndef      _SYS_FS_ZFS_H
> @@ -27,7 +28,14 @@
>  /*
>   * On-disk version number.
>   */
> -#define      SPA_VERSION                     24ULL
> +#define      SPA_VERSION_INITIAL             1ULL
> +#define      SPA_VERSION_BEFORE_FEATURES     28ULL
> +#define      SPA_VERSION                     5000ULL
> +#define      SPA_VERSION_FEATURES            5000ULL
> +
> +#define      SPA_VERSION_IS_SUPPORTED(v) \
> +     (((v) >= SPA_VERSION_INITIAL && (v) <= SPA_VERSION_BEFORE_FEATURES) || \
> +     ((v) >= SPA_VERSION_FEATURES && (v) <= SPA_VERSION))
>  
>  /*
>   * The following are configuration names used in the nvlist describing a 
> pool's
> @@ -67,6 +75,7 @@
>  #define      ZPOOL_CONFIG_DDT_HISTOGRAM      "ddt_histogram"
>  #define      ZPOOL_CONFIG_DDT_OBJ_STATS      "ddt_object_stats"
>  #define      ZPOOL_CONFIG_DDT_STATS          "ddt_stats"
> +#define      ZPOOL_CONFIG_FEATURES_FOR_READ  "features_for_read"
>  /*
>   * 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
> diff -r 7c12aaa128e3 -r c2e11847cac0 
> tools/libfsimage/zfs/zfs-include/zfs_acl.h
> --- a/tools/libfsimage/zfs/zfs-include/zfs_acl.h      Thu Oct 24 22:46:20 
> 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/zfs_acl.h      Sat Oct 26 20:03:06 
> 2013 +0400
> @@ -24,8 +24,6 @@
>  #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 */
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/zfs-include/zio.h
> --- a/tools/libfsimage/zfs/zfs-include/zio.h  Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs-include/zio.h  Sat Oct 26 20:03:06 2013 +0400
> @@ -20,6 +20,9 @@
>   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
>   * Use is subject to license terms.
>   */
> +/*
> + * Copyright 2013 by Saso Kiselkov. All rights reserved.
> + */
>  
>  #ifndef _ZIO_H
>  #define      _ZIO_H
> @@ -73,6 +76,17 @@ enum zio_compress {
>       ZIO_COMPRESS_OFF,
>       ZIO_COMPRESS_LZJB,
>       ZIO_COMPRESS_EMPTY,
> +     ZIO_COMPRESS_GZIP_1,
> +     ZIO_COMPRESS_GZIP_2,
> +     ZIO_COMPRESS_GZIP_3,
> +     ZIO_COMPRESS_GZIP_4,
> +     ZIO_COMPRESS_GZIP_5,
> +     ZIO_COMPRESS_GZIP_6,
> +     ZIO_COMPRESS_GZIP_7,
> +     ZIO_COMPRESS_GZIP_8,
> +     ZIO_COMPRESS_GZIP_9,
> +     ZIO_COMPRESS_ZLE,
> +     ZIO_COMPRESS_LZ4,
>       ZIO_COMPRESS_FUNCTIONS
>  };
>  
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/zfs_fletcher.c
> --- a/tools/libfsimage/zfs/zfs_fletcher.c     Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs_fletcher.c     Sat Oct 26 20:03:06 2013 +0400
> @@ -21,8 +21,6 @@
>   * Use is subject to license terms.
>   */
>  
> -#pragma ident        "%Z%%M% %I%     %E% SMI"
> -
>  #include "fsys_zfs.h"
>  
>  
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/zfs_lz4.c
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/tools/libfsimage/zfs/zfs_lz4.c  Sat Oct 26 20:03:06 2013 +0400
> @@ -0,0 +1,313 @@
> +/*
> + * LZ4 - Fast LZ compression algorithm
> + * Header File
> + * Copyright (C) 2011-2013, Yann Collet.
> + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions are
> + * met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above
> + * copyright notice, this list of conditions and the following disclaimer
> + * in the documentation and/or other materials provided with the
> + * distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + * You can contact the author at :
> + * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
> + * - LZ4 source repository : http://code.google.com/p/lz4/
> + */
> +
> +#include "fsys_zfs.h"
> +#include <string.h>
> +
> +static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest,
> +                                         int isize, int maxOutputSize);
> +
> +int
> +lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len)
> +{
> +     const uint8_t *src = s_start;
> +     uint32_t bufsiz = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) |
> +         src[3];
> +
> +     /* invalid compressed buffer size encoded at start */
> +     if (bufsiz + 4 > s_len)
> +             return (1);
> +
> +     /*
> +      * Returns 0 on success (decompression function returned non-negative)
> +      * and non-zero on failure (decompression function returned negative).
> +      */
> +     return (LZ4_uncompress_unknownOutputSize(s_start + 4, d_start, bufsiz,
> +         d_len) < 0);
> +}
> +
> +/*
> + * CPU Feature Detection
> + */
> +
> +/* 32 or 64 bits ? */
> +#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || \
> +     defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || \
> +     defined(__LP64__) || defined(_LP64))
> +#define      LZ4_ARCH64      1
> +#else
> +#define      LZ4_ARCH64      0
> +#endif
> +
> +/*
> + * Little Endian or Big Endian?
> + * Note: overwrite the below #define if you know your architecture endianess.
> + */
> +#if (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || \
> +     defined(_BIG_ENDIAN) || defined(_ARCH_PPC) || defined(__PPC__) || \
> +     defined(__PPC) || defined(PPC) || defined(__powerpc__) || \
> +     defined(__powerpc) || defined(powerpc) || \
> +     ((defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))))
> +#define      LZ4_BIG_ENDIAN  1
> +#else
> +     /*
> +      * Little Endian assumed. PDP Endian and other very rare endian format
> +      * are unsupported.
> +      */
> +#endif
> +
> +/*
> + * Compiler Options
> + */
> +#if __STDC_VERSION__ >= 199901L      /* C99 */
> +/* "restrict" is a known keyword */
> +#else
> +/* Disable restrict */
> +#define      restrict
> +#endif
> +
> +#define      GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
> +
> +#define      lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) \
> +     | (((x) & 0xffu) << 8)))
> +
> +#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
> +#define      expect(expr, value)    (__builtin_expect((expr), (value)))
> +#else
> +#define      expect(expr, value)    (expr)
> +#endif
> +
> +#define      likely(expr)    expect((expr) != 0, 1)
> +#define      unlikely(expr)  expect((expr) != 0, 0)
> +
> +/* Basic types */
> +#define      BYTE    uint8_t
> +#define      U16     uint16_t
> +#define      U32     uint32_t
> +#define      S32     int32_t
> +#define      U64     uint64_t
> +
> +typedef struct _U16_S {
> +     U16 v;
> +} U16_S;
> +typedef struct _U32_S {
> +     U32 v;
> +} U32_S;
> +typedef struct _U64_S {
> +     U64 v;
> +} U64_S;
> +
> +#define      A64(x)  (((U64_S *)(x))->v)
> +#define      A32(x)  (((U32_S *)(x))->v)
> +#define      A16(x)  (((U16_S *)(x))->v)
> +
> +/*
> + * Constants
> + */
> +#define      MINMATCH 4
> +
> +#define      COPYLENGTH 8
> +#define      LASTLITERALS 5
> +
> +#define      ML_BITS 4
> +#define      ML_MASK ((1U<<ML_BITS)-1)
> +#define      RUN_BITS (8-ML_BITS)
> +#define      RUN_MASK ((1U<<RUN_BITS)-1)
> +
> +/*
> + * Architecture-specific macros
> + */
> +#if LZ4_ARCH64
> +#define      STEPSIZE 8
> +#define      UARCH U64
> +#define      AARCH A64
> +#define      LZ4_COPYSTEP(s, d)      A64(d) = A64(s); d += 8; s += 8;
> +#define      LZ4_COPYPACKET(s, d)    LZ4_COPYSTEP(s, d)
> +#define      LZ4_SECURECOPY(s, d, e) if (d < e) LZ4_WILDCOPY(s, d, e)
> +#define      HTYPE U32
> +#define      INITBASE(base)          const BYTE* const base = ip
> +#else
> +#define      STEPSIZE 4
> +#define      UARCH U32
> +#define      AARCH A32
> +#define      LZ4_COPYSTEP(s, d)      A32(d) = A32(s); d += 4; s += 4;
> +#define      LZ4_COPYPACKET(s, d)    LZ4_COPYSTEP(s, d); LZ4_COPYSTEP(s, d);
> +#define      LZ4_SECURECOPY          LZ4_WILDCOPY
> +#define      HTYPE const BYTE*
> +#define      INITBASE(base)          const int base = 0
> +#endif
> +
> +#if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE))
> +#define      LZ4_READ_LITTLEENDIAN_16(d, s, p) \
> +     { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }
> +#define      LZ4_WRITE_LITTLEENDIAN_16(p, i) \
> +     { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p += 2; }
> +#else
> +#define      LZ4_READ_LITTLEENDIAN_16(d, s, p) { d = (s) - A16(p); }
> +#define      LZ4_WRITE_LITTLEENDIAN_16(p, v)  { A16(p) = v; p += 2; }
> +#endif
> +
> +/* Macros */
> +#define      LZ4_WILDCOPY(s, d, e) do { LZ4_COPYPACKET(s, d) } while (d < e);
> +
> +/* Decompression functions */
> +
> +static int
> +LZ4_uncompress_unknownOutputSize(const char *source,
> +    char *dest, int isize, int maxOutputSize)
> +{
> +     /* Local Variables */
> +     const BYTE *restrict ip = (const BYTE *) source;
> +     const BYTE *const iend = ip + isize;
> +     const BYTE *restrict ref;
> +
> +     BYTE *restrict op = (BYTE *) dest;
> +     BYTE *const oend = op + maxOutputSize;
> +     BYTE *cpy;
> +
> +     size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 };
> +
> +     /* Main Loop */
> +     while (ip < iend) {
> +             BYTE token;
> +             int length;
> +
> +             /* get runlength */
> +             token = *ip++;
> +             if ((length = (token >> ML_BITS)) == RUN_MASK) {
> +                     int s = 255;
> +                     while ((ip < iend) && (s == 255)) {
> +                             s = *ip++;
> +                             length += s;
> +                     }
> +             }
> +             /* copy literals */
> +             cpy = op + length;
> +             if ((cpy > oend - COPYLENGTH) ||
> +                 (ip + length > iend - COPYLENGTH)) {
> +                     if (cpy > oend)
> +                             /*
> +                              * Error: request to write beyond destination
> +                              * buffer.
> +                              */
> +                             goto _output_error;
> +                     if (ip + length > iend)
> +                             /*
> +                              * Error : request to read beyond source
> +                              * buffer.
> +                              */
> +                             goto _output_error;
> +                     memcpy(op, ip, length);
> +                     op += length;
> +                     ip += length;
> +                     if (ip < iend)
> +                             /* Error : LZ4 format violation */
> +                             goto _output_error;
> +                     /* Necessarily EOF, due to parsing restrictions. */
> +                     break;
> +             }
> +             LZ4_WILDCOPY(ip, op, cpy);
> +             ip -= (op - cpy);
> +             op = cpy;
> +
> +             /* get offset */
> +             LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip);
> +             ip += 2;
> +             if (ref < (BYTE * const) dest)
> +                     /*
> +                      * Error: offset creates reference outside of
> +                      * destination buffer.
> +                      */
> +                     goto _output_error;
> +
> +             /* get matchlength */
> +             if ((length = (token & ML_MASK)) == ML_MASK) {
> +                     while (ip < iend) {
> +                             int s = *ip++;
> +                             length += s;
> +                             if (s == 255)
> +                                     continue;
> +                             break;
> +                     }
> +             }
> +             /* copy repeated sequence */
> +             if unlikely(op - ref < STEPSIZE) {
> +#if LZ4_ARCH64
> +                     size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
> +                     size_t dec2 = dec2table[op - ref];
> +#else
> +                     const int dec2 = 0;
> +#endif
> +                     *op++ = *ref++;
> +                     *op++ = *ref++;
> +                     *op++ = *ref++;
> +                     *op++ = *ref++;
> +                     ref -= dec[op - ref];
> +                     A32(op) = A32(ref);
> +                     op += STEPSIZE - 4;
> +                     ref -= dec2;
> +             } else {
> +                     LZ4_COPYSTEP(ref, op);
> +             }
> +             cpy = op + length - (STEPSIZE - 4);
> +             if (cpy > oend - COPYLENGTH) {
> +                     if (cpy > oend)
> +                             /*
> +                              * Error: request to write outside of
> +                              * destination buffer.
> +                              */
> +                             goto _output_error;
> +                     LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH));
> +                     while (op < cpy)
> +                             *op++ = *ref++;
> +                     op = cpy;
> +                     if (op == oend)
> +                             /*
> +                              * Check EOF (should never happen, since last
> +                              * 5 bytes are supposed to be literals).
> +                              */
> +                             break;
> +                     continue;
> +             }
> +             LZ4_SECURECOPY(ref, op, cpy);
> +             op = cpy;       /* correction */
> +     }
> +
> +     /* end of decoding */
> +     return (int)(((char *)op) - dest);
> +
> +     /* write overflow error detected */
> +     _output_error:
> +     return (int)(-(((char *)ip) - source));
> +}
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/zfs_lzjb.c
> --- a/tools/libfsimage/zfs/zfs_lzjb.c Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs_lzjb.c Sat Oct 26 20:03:06 2013 +0400
> @@ -21,8 +21,6 @@
>   * Use is subject to license terms.
>   */
>  
> -#pragma ident        "%Z%%M% %I%     %E% SMI"
> -
>  #include "fsys_zfs.h"
>  
>  #define      MATCH_BITS      6
> @@ -34,10 +32,10 @@
>  int
>  lzjb_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len)
>  {
> -     uint8_t *src = s_start;
> -     uint8_t *dst = d_start;
> -     uint8_t *d_end = (uint8_t *)d_start + d_len;
> -     uint8_t *cpy, 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) {
> @@ -49,7 +47,7 @@ lzjb_decompress(void *s_start, void *d_s
>                       int mlen = (src[0] >> (NBBY - MATCH_BITS)) + MATCH_MIN;
>                       int offset = ((src[0] << NBBY) | src[1]) & OFFSET_MASK;
>                       src += 2;
> -                     if ((cpy = dst - offset) < (uint8_t *)d_start)
> +                     if ((cpy = dst - offset) < (uchar_t *)d_start)
>                               return (-1);
>                       while (--mlen >= 0 && dst < d_end)
>                               *dst++ = *cpy++;
> diff -r 7c12aaa128e3 -r c2e11847cac0 tools/libfsimage/zfs/zfs_sha256.c
> --- a/tools/libfsimage/zfs/zfs_sha256.c       Thu Oct 24 22:46:20 2013 +0100
> +++ b/tools/libfsimage/zfs/zfs_sha256.c       Sat Oct 26 20:03:06 2013 +0400
> @@ -21,8 +21,6 @@
>   * Use is subject to license terms.
>   */
>  
> -#pragma ident        "%Z%%M% %I%     %E% SMI"
> -
>  #include "fsys_zfs.h"
>  
>  /*
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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