diff --git a/include/sys/zap.h b/include/sys/zap.h index 68edf0f2b..66fbc1385 100644 --- a/include/sys/zap.h +++ b/include/sys/zap.h @@ -226,6 +226,9 @@ int zap_lookup_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf); int zap_lookup_uint64_by_dnode(dnode_t *dn, const uint64_t *key, int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf); +int zap_lookup_length_uint64_by_dnode(dnode_t *dn, const uint64_t *key, + int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf, + uint64_t *actual_num_integers); int zap_contains(objset_t *ds, uint64_t zapobj, const char *name); int zap_prefetch(objset_t *os, uint64_t zapobj, const char *name); int zap_prefetch_object(objset_t *os, uint64_t zapobj); diff --git a/include/sys/zap_impl.h b/include/sys/zap_impl.h index 5a5dd4773..d010c3c30 100644 --- a/include/sys/zap_impl.h +++ b/include/sys/zap_impl.h @@ -219,7 +219,8 @@ void fzap_byteswap(void *buf, size_t size); int fzap_count(zap_t *zap, uint64_t *count); int fzap_lookup(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers, void *buf, - char *realname, int rn_len, boolean_t *normalization_conflictp); + char *realname, int rn_len, boolean_t *normalization_conflictp, + uint64_t *actual_num_integers); void fzap_prefetch(zap_name_t *zn); int fzap_add(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers, const void *val, const void *tag, dmu_tx_t *tx); diff --git a/module/zfs/ddt_zap.c b/module/zfs/ddt_zap.c index f3418c473..9dbae6350 100644 --- a/module/zfs/ddt_zap.c +++ b/module/zfs/ddt_zap.c @@ -124,25 +124,19 @@ static int ddt_zap_lookup(dnode_t *dn, const ddt_key_t *ddk, void *phys, size_t psize) { uchar_t *cbuf; - uint64_t one, csize; + uint64_t csize; int error; - error = zap_length_uint64_by_dnode(dn, (uint64_t *)ddk, - DDT_KEY_WORDS, &one, &csize); - if (error) - return (error); + cbuf = kmem_alloc(psize + 1, KM_SLEEP); - ASSERT3U(one, ==, 1); - ASSERT3U(csize, <=, psize + 1); - - cbuf = kmem_alloc(csize, KM_SLEEP); - - error = zap_lookup_uint64_by_dnode(dn, (uint64_t *)ddk, - DDT_KEY_WORDS, 1, csize, cbuf); - if (error == 0) + error = zap_lookup_length_uint64_by_dnode(dn, (uint64_t *)ddk, + DDT_KEY_WORDS, 1, psize + 1, cbuf, &csize); + if (error == 0) { + ASSERT3U(csize, <=, psize + 1); ddt_zap_decompress(cbuf, phys, csize, psize); + } - kmem_free(cbuf, csize); + kmem_free(cbuf, psize + 1); return (error); } diff --git a/module/zfs/zap.c b/module/zfs/zap.c index 3e4e99779..b40d765e3 100644 --- a/module/zfs/zap.c +++ b/module/zfs/zap.c @@ -878,7 +878,8 @@ fzap_check(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers) int fzap_lookup(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers, void *buf, - char *realname, int rn_len, boolean_t *ncp) + char *realname, int rn_len, boolean_t *ncp, + uint64_t *actual_num_integers) { zap_leaf_t *l; zap_entry_handle_t zeh; @@ -898,6 +899,8 @@ fzap_lookup(zap_name_t *zn, } err = zap_entry_read(&zeh, integer_size, num_integers, buf); + if (err == 0 && actual_num_integers != NULL) + *actual_num_integers = zeh.zeh_num_integers; (void) zap_entry_read_name(zn->zn_zap, &zeh, rn_len, realname); if (ncp) { *ncp = zap_entry_normalization_conflict(&zeh, diff --git a/module/zfs/zap_micro.c b/module/zfs/zap_micro.c index be9743798..4e343ebf5 100644 --- a/module/zfs/zap_micro.c +++ b/module/zfs/zap_micro.c @@ -1145,7 +1145,7 @@ zap_lookup_impl(zap_t *zap, const char *name, if (!zap->zap_ismicro) { err = fzap_lookup(zn, integer_size, num_integers, buf, - realname, rn_len, ncp); + realname, rn_len, ncp, NULL); } else { zfs_btree_index_t idx; mzap_ent_t *mze = mze_find(zn, &idx); @@ -1300,8 +1300,9 @@ zap_prefetch_uint64_by_dnode(dnode_t *dn, const uint64_t *key, int key_numints) } static int -zap_lookup_uint64_impl(zap_t *zap, const uint64_t *key, - int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf) +zap_lookup_length_uint64_impl(zap_t *zap, const uint64_t *key, + int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf, + uint64_t *actual_num_integers) { zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); if (zn == NULL) { @@ -1310,7 +1311,7 @@ zap_lookup_uint64_impl(zap_t *zap, const uint64_t *key, } int err = fzap_lookup(zn, integer_size, num_integers, buf, - NULL, 0, NULL); + NULL, 0, NULL, actual_num_integers); zap_name_free(zn); zap_unlockdir(zap, FTAG); return (err); @@ -1326,9 +1327,9 @@ zap_lookup_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); if (err != 0) return (err); - err = zap_lookup_uint64_impl(zap, key, key_numints, integer_size, - num_integers, buf); - /* zap_lookup_uint64_impl() calls zap_unlockdir() */ + err = zap_lookup_length_uint64_impl(zap, key, key_numints, + integer_size, num_integers, buf, NULL); + /* zap_lookup_length_uint64_impl() calls zap_unlockdir() */ return (err); } @@ -1342,9 +1343,26 @@ zap_lookup_uint64_by_dnode(dnode_t *dn, const uint64_t *key, zap_lockdir_by_dnode(dn, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); if (err != 0) return (err); - err = zap_lookup_uint64_impl(zap, key, key_numints, integer_size, - num_integers, buf); - /* zap_lookup_uint64_impl() calls zap_unlockdir() */ + err = zap_lookup_length_uint64_impl(zap, key, key_numints, + integer_size, num_integers, buf, NULL); + /* zap_lookup_length_uint64_impl() calls zap_unlockdir() */ + return (err); +} + +int +zap_lookup_length_uint64_by_dnode(dnode_t *dn, const uint64_t *key, + int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf, + uint64_t *actual_num_integers) +{ + zap_t *zap; + + int err = + zap_lockdir_by_dnode(dn, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); + if (err != 0) + return (err); + err = zap_lookup_length_uint64_impl(zap, key, key_numints, + integer_size, num_integers, buf, actual_num_integers); + /* zap_lookup_length_uint64_impl() calls zap_unlockdir() */ return (err); } @@ -2042,6 +2060,7 @@ EXPORT_SYMBOL(zap_lookup); EXPORT_SYMBOL(zap_lookup_by_dnode); EXPORT_SYMBOL(zap_lookup_norm); EXPORT_SYMBOL(zap_lookup_uint64); +EXPORT_SYMBOL(zap_lookup_length_uint64_by_dnode); EXPORT_SYMBOL(zap_contains); EXPORT_SYMBOL(zap_prefetch); EXPORT_SYMBOL(zap_prefetch_uint64);