diff --git a/zfs/lib/libzpool/include/sys/zap.h b/zfs/lib/libzpool/include/sys/zap.h index f88cc068bd..687f7fcd75 100644 --- a/zfs/lib/libzpool/include/sys/zap.h +++ b/zfs/lib/libzpool/include/sys/zap.h @@ -316,6 +316,11 @@ void zap_cursor_advance(zap_cursor_t *zc); */ uint64_t zap_cursor_serialize(zap_cursor_t *zc); +/* + * Advance the cursor to the attribute having the key. + */ +int zap_cursor_move_to_key(zap_cursor_t *zc, const char *name, matchtype_t mt); + /* * Initialize a zap cursor pointing to the position recorded by * zap_cursor_serialize (in the "serialized" argument). You can also diff --git a/zfs/lib/libzpool/include/sys/zap_impl.h b/zfs/lib/libzpool/include/sys/zap_impl.h index 0dc02ab6b0..159ffaf8b0 100644 --- a/zfs/lib/libzpool/include/sys/zap_impl.h +++ b/zfs/lib/libzpool/include/sys/zap_impl.h @@ -210,6 +210,7 @@ int fzap_add_cd(zap_name_t *zn, uint64_t integer_size, uint64_t num_integers, const void *val, uint32_t cd, dmu_tx_t *tx); void fzap_upgrade(zap_t *zap, dmu_tx_t *tx); +int fzap_cursor_move_to_key(zap_cursor_t *zc, zap_name_t *zn); #ifdef __cplusplus } diff --git a/zfs/lib/libzpool/zap.c b/zfs/lib/libzpool/zap.c index ca859ec355..4e4677e503 100644 --- a/zfs/lib/libzpool/zap.c +++ b/zfs/lib/libzpool/zap.c @@ -1080,6 +1080,29 @@ zap_stats_ptrtbl(zap_t *zap, uint64_t *tbl, int len, zap_stats_t *zs) } } +int fzap_cursor_move_to_key(zap_cursor_t *zc, zap_name_t *zn) +{ + int err; + zap_leaf_t *l; + zap_entry_handle_t zeh; + + if (zn->zn_name_orij && strlen(zn->zn_name_orij) > ZAP_MAXNAMELEN) + return (E2BIG); + + err = zap_deref_leaf(zc->zc_zap, zn->zn_hash, NULL, RW_READER, &l); + if (err != 0) + return (err); + + err = zap_leaf_lookup(l, zn, &zeh); + if (err != 0) + return (err); + + zc->zc_leaf = l; + zc->zc_hash = zeh.zeh_hash; + zc->zc_cd = zeh.zeh_cd; + return 0; +} + void fzap_get_stats(zap_t *zap, zap_stats_t *zs) { diff --git a/zfs/lib/libzpool/zap_micro.c b/zfs/lib/libzpool/zap_micro.c index abba42775b..b2db2eeaea 100644 --- a/zfs/lib/libzpool/zap_micro.c +++ b/zfs/lib/libzpool/zap_micro.c @@ -1045,6 +1045,45 @@ zap_cursor_advance(zap_cursor_t *zc) } } +int zap_cursor_move_to_key(zap_cursor_t *zc, const char *name, matchtype_t mt) +{ + int err = 0; + mzap_ent_t *mze; + zap_name_t *zn; + + if (zc->zc_zap == NULL) { + err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL, + RW_READER, TRUE, FALSE, &zc->zc_zap); + if (err) + return (err); + } else { + rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); + } + + zn = zap_name_alloc(zc->zc_zap, name, mt); + if (zn == NULL) { + rw_exit(&zc->zc_zap->zap_rwlock); + return (ENOTSUP); + } + + if (!zc->zc_zap->zap_ismicro) { + err = fzap_cursor_move_to_key(zc, zn); + } else { + mze = mze_find(zn); + if (mze == NULL) { + err = (ENOENT); + goto out; + } + zc->zc_hash = mze->mze_hash; + zc->zc_cd = mze->mze_phys.mze_cd; + } + +out: + zap_name_free(zn); + rw_exit(&zc->zc_zap->zap_rwlock); + return (err); +} + int zap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs) {