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

[Xen-devel] [PATCH 1 of 1] Update ZFS sources from illumos.org:



https://github.com/illumos/illumos-gate/tree/master/usr/src/grub/grub-0.97/stage2
Additional CFLAGS rules have been added after 'CFLAGS += -Werror -D_GNU_SOURCE' 
in Rules.mk

Signed-off-by: Igor Kozhukhov <ikozhukhov@xxxxxxxxx>
Asked-by: Ian Campbell <Ian.Campbell@xxxxxxxxxx>

diff -r 7c12aaa128e3 -r 7afe0b19c898 tools/libfsimage/zfs/Makefile
--- a/tools/libfsimage/zfs/Makefile     Thu Oct 24 22:46:20 2013 +0100
+++ b/tools/libfsimage/zfs/Makefile     Thu Oct 31 22:48:42 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
 
@@ -36,3 +36,8 @@ all: fs-all
 install: fs-install
 
 include $(XEN_ROOT)/tools/libfsimage/Rules.mk
+
+# need for build illumos ZFS
+CFLAGS += -Wno-parentheses
+CFLAGS += -Wno-unused
+# end
diff -r 7c12aaa128e3 -r 7afe0b19c898 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    Thu Oct 31 22:48:42 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 7afe0b19c898 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   Thu Oct 31 22:48:42 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 7afe0b19c898 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   Thu Oct 31 22:48:42 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 7afe0b19c898 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    Thu Oct 31 22:48:42 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 7afe0b19c898 
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    Thu Oct 31 22:48:42 
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 7afe0b19c898 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        Thu Oct 31 22:48:42 
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 7afe0b19c898 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    Thu Oct 31 22:48:42 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 7afe0b19c898 
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 Thu Oct 31 22:48:42 
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 7afe0b19c898 
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      Thu Oct 31 22:48:42 
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 7afe0b19c898 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       Thu Oct 31 22:48:42 
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 7afe0b19c898 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    Thu Oct 31 22:48:42 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 7afe0b19c898 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        Thu Oct 31 22:48:42 
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 7afe0b19c898 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    Thu Oct 31 22:48:42 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 7afe0b19c898 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       Thu Oct 31 22:48:42 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 7afe0b19c898 tools/libfsimage/zfs/zfs_lz4.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libfsimage/zfs/zfs_lz4.c    Thu Oct 31 22:48:42 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 7afe0b19c898 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   Thu Oct 31 22:48:42 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 7afe0b19c898 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 Thu Oct 31 22:48:42 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


 


Rackspace

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