summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToomas Soome <tsoome@me.com>2019-11-21 09:35:29 +0200
committerToomas Soome <tsoome@me.com>2020-02-07 15:47:58 +0200
commitfdefee4c75361dc5ea202f7e1f7c49f8a27ea043 (patch)
tree39d6a491fadfbecc82598bf2def023ff5bce8d0d
parent8af765f5897d30449b941438e8d833f02dac74f8 (diff)
downloadillumos-joyent-fdefee4c75361dc5ea202f7e1f7c49f8a27ea043.tar.gz
12266 loader: rewrite zfs reader zap code to use malloc
Reviewed by: Gergő Mihály Doma <domag02@gmail.com> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/boot/Makefile.version2
-rw-r--r--usr/src/boot/lib/libstand/zfs/zfsimpl.c436
-rw-r--r--usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h11
3 files changed, 282 insertions, 167 deletions
diff --git a/usr/src/boot/Makefile.version b/usr/src/boot/Makefile.version
index b4fb4691f4..4c3af63cb9 100644
--- a/usr/src/boot/Makefile.version
+++ b/usr/src/boot/Makefile.version
@@ -33,4 +33,4 @@ LOADER_VERSION = 1.1
# Use date like formatting here, YYYY.MM.DD.XX, without leading zeroes.
# The version is processed from left to right, the version number can only
# be increased.
-BOOT_VERSION = $(LOADER_VERSION)-2020.02.02.1
+BOOT_VERSION = $(LOADER_VERSION)-2020.02.03.1
diff --git a/usr/src/boot/lib/libstand/zfs/zfsimpl.c b/usr/src/boot/lib/libstand/zfs/zfsimpl.c
index 212b5faa52..c291ef771e 100644
--- a/usr/src/boot/lib/libstand/zfs/zfsimpl.c
+++ b/usr/src/boot/lib/libstand/zfs/zfsimpl.c
@@ -137,7 +137,6 @@ static spa_list_t zfs_pools;
static const dnode_phys_t *dnode_cache_obj;
static uint64_t dnode_cache_bn;
static char *dnode_cache_buf;
-static char *zap_scratch;
static char *zfs_temp_buf, *zfs_temp_end, *zfs_temp_ptr;
#define TEMP_SIZE (1024 * 1024)
@@ -167,7 +166,6 @@ zfs_init(void)
zfs_temp_end = zfs_temp_buf + TEMP_SIZE;
zfs_temp_ptr = zfs_temp_buf;
dnode_cache_buf = malloc(SPA_MAXBLOCKSIZE);
- zap_scratch = malloc(SPA_MAXBLOCKSIZE);
zfs_init_crc();
}
@@ -2303,26 +2301,20 @@ dnode_read(const spa_t *spa, const dnode_phys_t *dnode, off_t offset,
}
/*
- * Lookup a value in a microzap directory. Assumes that the zap
- * scratch buffer contains the directory contents.
+ * Lookup a value in a microzap directory.
*/
static int
-mzap_lookup(const dnode_phys_t *dnode, const char *name, uint64_t *value)
+mzap_lookup(const mzap_phys_t *mz, size_t size, const char *name,
+ uint64_t *value)
{
- const mzap_phys_t *mz;
const mzap_ent_phys_t *mze;
- size_t size;
int chunks, i;
/*
* Microzap objects use exactly one block. Read the whole
* thing.
*/
- size = dnode->dn_datablkszsec * 512;
-
- mz = (const mzap_phys_t *) zap_scratch;
chunks = size / MZAP_ENT_LEN - 1;
-
for (i = 0; i < chunks; i++) {
mze = &mz->mz_chunk[i];
if (strcmp(mze->mze_name, name) == 0) {
@@ -2465,91 +2457,166 @@ fzap_check_size(uint64_t integer_size, uint64_t num_integers)
return (0);
}
-/*
- * Lookup a value in a fatzap directory. Assumes that the zap scratch
- * buffer contains the directory header.
- */
+static void
+zap_leaf_free(zap_leaf_t *leaf)
+{
+ free(leaf->l_phys);
+ free(leaf);
+}
+
static int
-fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name,
- uint64_t integer_size, uint64_t num_integers, void *value)
+zap_get_leaf_byblk(fat_zap_t *zap, uint64_t blk, zap_leaf_t **lp)
{
- int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
- zap_phys_t zh = *(zap_phys_t *)zap_scratch;
- fat_zap_t z;
- uint64_t *ptrtbl;
- uint64_t hash;
- int rc;
+ int bs = FZAP_BLOCK_SHIFT(zap);
+ int err;
- if (zh.zap_magic != ZAP_MAGIC)
- return (EIO);
+ *lp = malloc(sizeof (**lp));
+ if (*lp == NULL)
+ return (ENOMEM);
- if ((rc = fzap_check_size(integer_size, num_integers)) != 0)
- return (rc);
+ (*lp)->l_bs = bs;
+ (*lp)->l_phys = malloc(1 << bs);
- z.zap_block_shift = ilog2(bsize);
- z.zap_phys = (zap_phys_t *)zap_scratch;
+ if ((*lp)->l_phys == NULL) {
+ free(*lp);
+ return (ENOMEM);
+ }
+ err = dnode_read(zap->zap_spa, zap->zap_dnode, blk << bs, (*lp)->l_phys,
+ 1 << bs);
+ if (err != 0) {
+ zap_leaf_free(*lp);
+ }
+ return (err);
+}
- /*
- * Figure out where the pointer table is and read it in if necessary.
- */
- if (zh.zap_ptrtbl.zt_blk) {
- rc = dnode_read(spa, dnode, zh.zap_ptrtbl.zt_blk * bsize,
- zap_scratch, bsize);
- if (rc)
- return (rc);
- ptrtbl = (uint64_t *)zap_scratch;
+static int
+zap_table_load(fat_zap_t *zap, zap_table_phys_t *tbl, uint64_t idx,
+ uint64_t *valp)
+{
+ int bs = FZAP_BLOCK_SHIFT(zap);
+ uint64_t blk = idx >> (bs - 3);
+ uint64_t off = idx & ((1 << (bs - 3)) - 1);
+ uint64_t *buf;
+ int rc;
+
+ buf = malloc(1 << zap->zap_block_shift);
+ if (buf == NULL)
+ return (ENOMEM);
+ rc = dnode_read(zap->zap_spa, zap->zap_dnode, (tbl->zt_blk + blk) << bs,
+ buf, 1 << zap->zap_block_shift);
+ if (rc == 0)
+ *valp = buf[off];
+ free(buf);
+ return (rc);
+}
+
+static int
+zap_idx_to_blk(fat_zap_t *zap, uint64_t idx, uint64_t *valp)
+{
+ if (zap->zap_phys->zap_ptrtbl.zt_numblks == 0) {
+ *valp = ZAP_EMBEDDED_PTRTBL_ENT(zap, idx);
+ return (0);
} else {
- ptrtbl = &ZAP_EMBEDDED_PTRTBL_ENT(&z, 0);
+ return (zap_table_load(zap, &zap->zap_phys->zap_ptrtbl,
+ idx, valp));
}
+}
- hash = zap_hash(zh.zap_salt, name);
+#define ZAP_HASH_IDX(hash, n) (((n) == 0) ? 0 : ((hash) >> (64 - (n))))
+static int
+zap_deref_leaf(fat_zap_t *zap, uint64_t h, zap_leaf_t **lp)
+{
+ uint64_t idx, blk;
+ int err;
- zap_leaf_t zl;
- zl.l_bs = z.zap_block_shift;
+ idx = ZAP_HASH_IDX(h, zap->zap_phys->zap_ptrtbl.zt_shift);
+ err = zap_idx_to_blk(zap, idx, &blk);
+ if (err != 0)
+ return (err);
+ return (zap_get_leaf_byblk(zap, blk, lp));
+}
- off_t off = ptrtbl[hash >> (64 - zh.zap_ptrtbl.zt_shift)] << zl.l_bs;
- zap_leaf_chunk_t *zc;
+#define CHAIN_END 0xffff /* end of the chunk chain */
+#define LEAF_HASH(l, h) \
+ ((ZAP_LEAF_HASH_NUMENTRIES(l)-1) & \
+ ((h) >> \
+ (64 - ZAP_LEAF_HASH_SHIFT(l) - (l)->l_phys->l_hdr.lh_prefix_len)))
+#define LEAF_HASH_ENTPTR(l, h) (&(l)->l_phys->l_hash[LEAF_HASH(l, h)])
- rc = dnode_read(spa, dnode, off, zap_scratch, bsize);
- if (rc)
- return (rc);
-
- zl.l_phys = (zap_leaf_phys_t *)zap_scratch;
+static int
+zap_leaf_lookup(zap_leaf_t *zl, uint64_t hash, const char *name,
+ uint64_t integer_size, uint64_t num_integers, void *value)
+{
+ int rc;
+ uint16_t *chunkp;
+ struct zap_leaf_entry *le;
/*
* Make sure this chunk matches our hash.
*/
- if (zl.l_phys->l_hdr.lh_prefix_len > 0 &&
- zl.l_phys->l_hdr.lh_prefix !=
- hash >> (64 - zl.l_phys->l_hdr.lh_prefix_len))
- return (ENOENT);
+ if (zl->l_phys->l_hdr.lh_prefix_len > 0 &&
+ zl->l_phys->l_hdr.lh_prefix !=
+ hash >> (64 - zl->l_phys->l_hdr.lh_prefix_len))
+ return (EIO);
- /*
- * Hash within the chunk to find our entry.
- */
- int shift = (64 - ZAP_LEAF_HASH_SHIFT(&zl) -
- zl.l_phys->l_hdr.lh_prefix_len);
- int h = (hash >> shift) & ((1 << ZAP_LEAF_HASH_SHIFT(&zl)) - 1);
- h = zl.l_phys->l_hash[h];
- if (h == 0xffff)
- return (ENOENT);
- zc = &ZAP_LEAF_CHUNK(&zl, h);
- while (zc->l_entry.le_hash != hash) {
- if (zc->l_entry.le_next == 0xffff) {
- zc = 0;
+ rc = ENOENT;
+ for (chunkp = LEAF_HASH_ENTPTR(zl, hash);
+ *chunkp != CHAIN_END; chunkp = &le->le_next) {
+ zap_leaf_chunk_t *zc;
+ uint16_t chunk = *chunkp;
+
+ le = ZAP_LEAF_ENTRY(zl, chunk);
+ if (le->le_hash != hash)
+ continue;
+ zc = &ZAP_LEAF_CHUNK(zl, chunk);
+ if (fzap_name_equal(zl, zc, name)) {
+ if (zc->l_entry.le_value_intlen > integer_size) {
+ rc = EINVAL;
+ } else {
+ fzap_leaf_array(zl, zc, integer_size,
+ num_integers, value);
+ rc = 0;
+ }
break;
}
- zc = &ZAP_LEAF_CHUNK(&zl, zc->l_entry.le_next);
}
- if (fzap_name_equal(&zl, zc, name)) {
- if (zc->l_entry.le_value_intlen > integer_size)
- return (EINVAL);
+ return (rc);
+}
- fzap_leaf_array(&zl, zc, integer_size, num_integers, value);
- return (0);
- }
+/*
+ * Lookup a value in a fatzap directory.
+ */
+static int
+fzap_lookup(const spa_t *spa, const dnode_phys_t *dnode, zap_phys_t *zh,
+ const char *name, uint64_t integer_size, uint64_t num_integers,
+ void *value)
+{
+ int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
+ fat_zap_t z;
+ zap_leaf_t *zl;
+ uint64_t hash;
+ int rc;
- return (ENOENT);
+ if (zh->zap_magic != ZAP_MAGIC)
+ return (EIO);
+
+ if ((rc = fzap_check_size(integer_size, num_integers)) != 0)
+ return (rc);
+
+ z.zap_block_shift = ilog2(bsize);
+ z.zap_phys = zh;
+ z.zap_spa = spa;
+ z.zap_dnode = dnode;
+
+ hash = zap_hash(zh->zap_salt, name);
+ rc = zap_deref_leaf(&z, hash, &zl);
+ if (rc != 0)
+ return (rc);
+
+ rc = zap_leaf_lookup(zl, hash, name, integer_size, num_integers, value);
+
+ zap_leaf_free(zl);
+ return (rc);
}
/*
@@ -2560,74 +2627,79 @@ zap_lookup(const spa_t *spa, const dnode_phys_t *dnode, const char *name,
uint64_t integer_size, uint64_t num_integers, void *value)
{
int rc;
- uint64_t zap_type;
+ zap_phys_t *zap;
size_t size = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
- rc = dnode_read(spa, dnode, 0, zap_scratch, size);
+ zap = malloc(size);
+ if (zap == NULL)
+ return (ENOMEM);
+
+ rc = dnode_read(spa, dnode, 0, zap, size);
if (rc)
- return (rc);
+ goto done;
- zap_type = *(uint64_t *)zap_scratch;
- if (zap_type == ZBT_MICRO)
- return (mzap_lookup(dnode, name, value));
- else if (zap_type == ZBT_HEADER) {
- return (fzap_lookup(spa, dnode, name, integer_size,
- num_integers, value));
+ switch (zap->zap_block_type) {
+ case ZBT_MICRO:
+ rc = mzap_lookup((const mzap_phys_t *)zap, size, name, value);
+ break;
+ case ZBT_HEADER:
+ rc = fzap_lookup(spa, dnode, zap, name, integer_size,
+ num_integers, value);
+ break;
+ default:
+ printf("ZFS: invalid zap_type=%" PRIx64 "\n",
+ zap->zap_block_type);
+ rc = EIO;
}
- printf("ZFS: invalid zap_type=%d\n", (int)zap_type);
- return (EIO);
+done:
+ free(zap);
+ return (rc);
}
/*
- * List a microzap directory. Assumes that the zap scratch buffer contains
- * the directory contents.
+ * List a microzap directory.
*/
static int
-mzap_list(const dnode_phys_t *dnode, int (*callback)(const char *, uint64_t))
+mzap_list(const mzap_phys_t *mz, size_t size,
+ int (*callback)(const char *, uint64_t))
{
- const mzap_phys_t *mz;
const mzap_ent_phys_t *mze;
- size_t size;
int chunks, i, rc;
/*
* Microzap objects use exactly one block. Read the whole
* thing.
*/
- size = dnode->dn_datablkszsec * 512;
- mz = (const mzap_phys_t *) zap_scratch;
+ rc = 0;
chunks = size / MZAP_ENT_LEN - 1;
-
for (i = 0; i < chunks; i++) {
mze = &mz->mz_chunk[i];
if (mze->mze_name[0]) {
rc = callback(mze->mze_name, mze->mze_value);
if (rc != 0)
- return (rc);
+ break;
}
}
- return (0);
+ return (rc);
}
/*
- * List a fatzap directory. Assumes that the zap scratch buffer contains
- * the directory header.
+ * List a fatzap directory.
*/
static int
-fzap_list(const spa_t *spa, const dnode_phys_t *dnode,
+fzap_list(const spa_t *spa, const dnode_phys_t *dnode, zap_phys_t *zh,
int (*callback)(const char *, uint64_t))
{
int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
- zap_phys_t zh = *(zap_phys_t *)zap_scratch;
fat_zap_t z;
int i, j, rc;
- if (zh.zap_magic != ZAP_MAGIC)
+ if (zh->zap_magic != ZAP_MAGIC)
return (EIO);
z.zap_block_shift = ilog2(bsize);
- z.zap_phys = (zap_phys_t *)zap_scratch;
+ z.zap_phys = zh;
/*
* This assumes that the leaf blocks start at block 1. The
@@ -2635,15 +2707,19 @@ fzap_list(const spa_t *spa, const dnode_phys_t *dnode,
*/
zap_leaf_t zl;
zl.l_bs = z.zap_block_shift;
- for (i = 0; i < zh.zap_num_leafs; i++) {
+ zl.l_phys = malloc(bsize);
+ if (zl.l_phys == NULL)
+ return (ENOMEM);
+
+ for (i = 0; i < zh->zap_num_leafs; i++) {
off_t off = ((off_t)(i + 1)) << zl.l_bs;
char name[256], *p;
uint64_t value;
- if (dnode_read(spa, dnode, off, zap_scratch, bsize))
+ if (dnode_read(spa, dnode, off, zl.l_phys, bsize)) {
+ free(zl.l_phys);
return (EIO);
-
- zl.l_phys = (zap_leaf_phys_t *)zap_scratch;
+ }
for (j = 0; j < ZAP_LEAF_NUMCHUNKS(&zl); j++) {
zap_leaf_chunk_t *zc, *nc;
@@ -2680,11 +2756,14 @@ fzap_list(const spa_t *spa, const dnode_phys_t *dnode,
/* printf("%s 0x%jx\n", name, (uintmax_t)value); */
rc = callback((const char *)name, value);
- if (rc != 0)
+ if (rc != 0) {
+ free(zl.l_phys);
return (rc);
+ }
}
}
+ free(zl.l_phys);
return (0);
}
@@ -2702,17 +2781,24 @@ static int zfs_printf(const char *name, uint64_t value __unused)
static int
zap_list(const spa_t *spa, const dnode_phys_t *dnode)
{
- uint64_t zap_type;
- size_t size = dnode->dn_datablkszsec * 512;
+ zap_phys_t *zap;
+ size_t size = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
+ int rc;
- if (dnode_read(spa, dnode, 0, zap_scratch, size))
- return (EIO);
+ zap = malloc(size);
+ if (zap == NULL)
+ return (ENOMEM);
- zap_type = *(uint64_t *)zap_scratch;
- if (zap_type == ZBT_MICRO)
- return (mzap_list(dnode, zfs_printf));
- else
- return (fzap_list(spa, dnode, zfs_printf));
+ rc = dnode_read(spa, dnode, 0, zap, size);
+ if (rc == 0) {
+ if (zap->zap_block_type == ZBT_MICRO)
+ rc = mzap_list((const mzap_phys_t *)zap, size,
+ zfs_printf);
+ else
+ rc = fzap_list(spa, dnode, zap, zfs_printf);
+ }
+ free(zap);
+ return (rc);
}
static int
@@ -2726,24 +2812,20 @@ objset_get_dnode(const spa_t *spa, const objset_phys_t *os, uint64_t objnum,
dnode, sizeof (dnode_phys_t)));
}
+/*
+ * Lookup a name in a microzap directory.
+ */
static int
-mzap_rlookup(const spa_t *spa __unused, const dnode_phys_t *dnode, char *name,
- uint64_t value)
+mzap_rlookup(const mzap_phys_t *mz, size_t size, char *name, uint64_t value)
{
- const mzap_phys_t *mz;
const mzap_ent_phys_t *mze;
- size_t size;
int chunks, i;
/*
* Microzap objects use exactly one block. Read the whole
* thing.
*/
- size = dnode->dn_datablkszsec * 512;
-
- mz = (const mzap_phys_t *)zap_scratch;
chunks = size / MZAP_ENT_LEN - 1;
-
for (i = 0; i < chunks; i++) {
mze = &mz->mz_chunk[i];
if (value == mze->mze_value) {
@@ -2781,19 +2863,19 @@ fzap_name_copy(const zap_leaf_t *zl, const zap_leaf_chunk_t *zc, char *name)
}
static int
-fzap_rlookup(const spa_t *spa, const dnode_phys_t *dnode, char *name,
- uint64_t value)
+fzap_rlookup(const spa_t *spa, const dnode_phys_t *dnode, zap_phys_t *zh,
+ char *name, uint64_t value)
{
int bsize = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
- zap_phys_t zh = *(zap_phys_t *)zap_scratch;
fat_zap_t z;
- int i, j;
+ uint64_t i;
+ int j, rc;
- if (zh.zap_magic != ZAP_MAGIC)
+ if (zh->zap_magic != ZAP_MAGIC)
return (EIO);
z.zap_block_shift = ilog2(bsize);
- z.zap_phys = (zap_phys_t *)zap_scratch;
+ z.zap_phys = zh;
/*
* This assumes that the leaf blocks start at block 1. The
@@ -2801,13 +2883,16 @@ fzap_rlookup(const spa_t *spa, const dnode_phys_t *dnode, char *name,
*/
zap_leaf_t zl;
zl.l_bs = z.zap_block_shift;
- for (i = 0; i < zh.zap_num_leafs; i++) {
- off_t off = ((off_t)(i + 1)) << zl.l_bs;
+ zl.l_phys = malloc(bsize);
+ if (zl.l_phys == NULL)
+ return (ENOMEM);
- if (dnode_read(spa, dnode, off, zap_scratch, bsize))
- return (EIO);
+ for (i = 0; i < zh->zap_num_leafs; i++) {
+ off_t off = ((off_t)(i + 1)) << zl.l_bs;
- zl.l_phys = (zap_leaf_phys_t *)zap_scratch;
+ rc = dnode_read(spa, dnode, off, zl.l_phys, bsize);
+ if (rc != 0)
+ goto done;
for (j = 0; j < ZAP_LEAF_NUMCHUNKS(&zl); j++) {
zap_leaf_chunk_t *zc;
@@ -2821,31 +2906,39 @@ fzap_rlookup(const spa_t *spa, const dnode_phys_t *dnode, char *name,
if (fzap_leaf_value(&zl, zc) == value) {
fzap_name_copy(&zl, zc, name);
- return (0);
+ goto done;
}
}
}
- return (ENOENT);
+ rc = ENOENT;
+done:
+ free(zl.l_phys);
+ return (rc);
}
static int
zap_rlookup(const spa_t *spa, const dnode_phys_t *dnode, char *name,
uint64_t value)
{
+ zap_phys_t *zap;
+ size_t size = dnode->dn_datablkszsec << SPA_MINBLOCKSHIFT;
int rc;
- uint64_t zap_type;
- size_t size = dnode->dn_datablkszsec * 512;
- rc = dnode_read(spa, dnode, 0, zap_scratch, size);
- if (rc)
- return (rc);
+ zap = malloc(size);
+ if (zap == NULL)
+ return (ENOMEM);
- zap_type = *(uint64_t *)zap_scratch;
- if (zap_type == ZBT_MICRO)
- return (mzap_rlookup(spa, dnode, name, value));
- else
- return (fzap_rlookup(spa, dnode, name, value));
+ rc = dnode_read(spa, dnode, 0, zap, size);
+ if (rc == 0) {
+ if (zap->zap_block_type == ZBT_MICRO)
+ rc = mzap_rlookup((const mzap_phys_t *)zap, size,
+ name, value);
+ else
+ rc = fzap_rlookup(spa, dnode, zap, name, value);
+ }
+ free(zap);
+ return (rc);
}
static int
@@ -2997,10 +3090,12 @@ int
zfs_callback_dataset(const spa_t *spa, uint64_t objnum,
int (*callback)(const char *, uint64_t))
{
- uint64_t dir_obj, child_dir_zapobj, zap_type;
+ uint64_t dir_obj, child_dir_zapobj;
dnode_phys_t child_dir_zap, dir, dataset;
dsl_dataset_phys_t *ds;
dsl_dir_phys_t *dd;
+ zap_phys_t *zap;
+ size_t size;
int err;
err = objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset);
@@ -3026,16 +3121,24 @@ zfs_callback_dataset(const spa_t *spa, uint64_t objnum,
return (err);
}
- err = dnode_read(spa, &child_dir_zap, 0, zap_scratch,
- child_dir_zap.dn_datablkszsec * 512);
- if (err != 0)
- return (err);
+ size = child_dir_zap.dn_datablkszsec << SPA_MINBLOCKSHIFT;
+ zap = malloc(size);
+ if (zap != NULL) {
+ err = dnode_read(spa, &child_dir_zap, 0, zap, size);
+ if (err != 0)
+ goto done;
- zap_type = *(uint64_t *)zap_scratch;
- if (zap_type == ZBT_MICRO)
- return (mzap_list(&child_dir_zap, callback));
- else
- return (fzap_list(spa, &child_dir_zap, callback));
+ if (zap->zap_block_type == ZBT_MICRO)
+ err = mzap_list((const mzap_phys_t *)zap, size,
+ callback);
+ else
+ err = fzap_list(spa, &child_dir_zap, zap, callback);
+ } else {
+ err = ENOMEM;
+ }
+done:
+ free(zap);
+ return (err);
}
/*
@@ -3166,7 +3269,8 @@ static int
check_mos_features(const spa_t *spa)
{
dnode_phys_t dir;
- uint64_t objnum, zap_type;
+ zap_phys_t *zap;
+ uint64_t objnum;
size_t size;
int rc;
@@ -3190,16 +3294,22 @@ check_mos_features(const spa_t *spa)
if (dir.dn_type != DMU_OTN_ZAP_METADATA)
return (EIO);
- size = dir.dn_datablkszsec * 512;
- if (dnode_read(spa, &dir, 0, zap_scratch, size))
+ size = dir.dn_datablkszsec << SPA_MINBLOCKSHIFT;
+ zap = malloc(size);
+ if (zap == NULL)
+ return (ENOMEM);
+
+ if (dnode_read(spa, &dir, 0, zap, size)) {
+ free(zap);
return (EIO);
+ }
- zap_type = *(uint64_t *)zap_scratch;
- if (zap_type == ZBT_MICRO)
- rc = mzap_list(&dir, check_feature);
+ if (zap->zap_block_type == ZBT_MICRO)
+ rc = mzap_list((const mzap_phys_t *)zap, size, check_feature);
else
- rc = fzap_list(spa, &dir, check_feature);
+ rc = fzap_list(spa, &dir, zap, check_feature);
+ free(zap);
return (rc);
}
diff --git a/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h b/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h
index c57181b670..4993ca754c 100644
--- a/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h
+++ b/usr/src/boot/sys/cddl/boot/zfs/zfsimpl.h
@@ -1339,8 +1339,7 @@ typedef struct dsl_dataset_phys {
#define ZAP_HASHBITS 28
#define MZAP_ENT_LEN 64
#define MZAP_NAME_LEN (MZAP_ENT_LEN - 8 - 4 - 2)
-#define MZAP_MAX_BLKSHIFT SPA_MAXBLOCKSHIFT
-#define MZAP_MAX_BLKSZ (1 << MZAP_MAX_BLKSHIFT)
+#define MZAP_MAX_BLKSZ SPA_OLD_MAXBLOCKSIZE
typedef struct mzap_ent_phys {
uint64_t mze_value;
@@ -1352,7 +1351,8 @@ typedef struct mzap_ent_phys {
typedef struct mzap_phys {
uint64_t mz_block_type; /* ZBT_MICRO */
uint64_t mz_salt;
- uint64_t mz_pad[6];
+ uint64_t mz_normflags;
+ uint64_t mz_pad[5];
mzap_ent_phys_t mz_chunk[1];
/* actually variable size depending on block size */
} mzap_phys_t;
@@ -1409,6 +1409,8 @@ typedef struct zap_phys {
uint64_t zap_num_leafs; /* number of leafs */
uint64_t zap_num_entries; /* number of entries */
uint64_t zap_salt; /* salt to stir into hash function */
+ uint64_t zap_normflags; /* flags for u8_textprep_str() */
+ uint64_t zap_flags; /* zap_flags_t */
/*
* This structure is followed by padding, and then the embedded
* pointer table. The embedded pointer table takes up second
@@ -1419,9 +1421,12 @@ typedef struct zap_phys {
typedef struct zap_table_phys zap_table_phys_t;
+struct spa;
typedef struct fat_zap {
int zap_block_shift; /* block size shift */
zap_phys_t *zap_phys;
+ const struct spa *zap_spa;
+ const dnode_phys_t *zap_dnode;
} fat_zap_t;
#define ZAP_LEAF_MAGIC 0x2AB1EAF