1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21321545Smav 22168404Spjd/* 23219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24339115Smav * Copyright (c) 2011, 2017 by Delphix. All rights reserved. 25286575Smav * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. 26296519Smav * Copyright (c) 2014 Integros [integros.com] 27321545Smav * Copyright 2017 Nexenta Systems, Inc. 28168404Spjd */ 29168404Spjd 30219089Spjd#include <sys/zio.h> 31168404Spjd#include <sys/spa.h> 32168404Spjd#include <sys/dmu.h> 33168404Spjd#include <sys/zfs_context.h> 34168404Spjd#include <sys/zap.h> 35168404Spjd#include <sys/refcount.h> 36168404Spjd#include <sys/zap_impl.h> 37168404Spjd#include <sys/zap_leaf.h> 38168404Spjd#include <sys/avl.h> 39219089Spjd#include <sys/arc.h> 40274337Sdelphij#include <sys/dmu_objset.h> 41168404Spjd 42185029Spjd#ifdef _KERNEL 43185029Spjd#include <sys/sunddi.h> 44185029Spjd#endif 45168404Spjd 46275782Sdelphijextern inline mzap_phys_t *zap_m_phys(zap_t *zap); 47275782Sdelphij 48307286Smavstatic int mzap_upgrade(zap_t **zapp, 49307286Smav void *tag, dmu_tx_t *tx, zap_flags_t flags); 50168404Spjd 51219089Spjduint64_t 52219089Spjdzap_getflags(zap_t *zap) 53219089Spjd{ 54219089Spjd if (zap->zap_ismicro) 55219089Spjd return (0); 56275782Sdelphij return (zap_f_phys(zap)->zap_flags); 57219089Spjd} 58168404Spjd 59219089Spjdint 60219089Spjdzap_hashbits(zap_t *zap) 61219089Spjd{ 62219089Spjd if (zap_getflags(zap) & ZAP_FLAG_HASH64) 63219089Spjd return (48); 64219089Spjd else 65219089Spjd return (28); 66219089Spjd} 67219089Spjd 68219089Spjduint32_t 69219089Spjdzap_maxcd(zap_t *zap) 70219089Spjd{ 71219089Spjd if (zap_getflags(zap) & ZAP_FLAG_HASH64) 72219089Spjd return ((1<<16)-1); 73219089Spjd else 74219089Spjd return (-1U); 75219089Spjd} 76219089Spjd 77185029Spjdstatic uint64_t 78219089Spjdzap_hash(zap_name_t *zn) 79185029Spjd{ 80219089Spjd zap_t *zap = zn->zn_zap; 81219089Spjd uint64_t h = 0; 82185029Spjd 83219089Spjd if (zap_getflags(zap) & ZAP_FLAG_PRE_HASHED_KEY) { 84219089Spjd ASSERT(zap_getflags(zap) & ZAP_FLAG_UINT64_KEY); 85219089Spjd h = *(uint64_t *)zn->zn_key_orig; 86219089Spjd } else { 87219089Spjd h = zap->zap_salt; 88219089Spjd ASSERT(h != 0); 89219089Spjd ASSERT(zfs_crc64_table[128] == ZFS_CRC64_POLY); 90185029Spjd 91219089Spjd if (zap_getflags(zap) & ZAP_FLAG_UINT64_KEY) { 92219089Spjd const uint64_t *wp = zn->zn_key_norm; 93219089Spjd 94219089Spjd ASSERT(zn->zn_key_intlen == 8); 95339115Smav for (int i = 0; i < zn->zn_key_norm_numints; 96339115Smav wp++, i++) { 97219089Spjd uint64_t word = *wp; 98219089Spjd 99339115Smav for (int j = 0; j < zn->zn_key_intlen; j++) { 100219089Spjd h = (h >> 8) ^ 101219089Spjd zfs_crc64_table[(h ^ word) & 0xFF]; 102219089Spjd word >>= NBBY; 103219089Spjd } 104219089Spjd } 105219089Spjd } else { 106219089Spjd const uint8_t *cp = zn->zn_key_norm; 107219089Spjd 108219089Spjd /* 109219089Spjd * We previously stored the terminating null on 110219089Spjd * disk, but didn't hash it, so we need to 111219089Spjd * continue to not hash it. (The 112219089Spjd * zn_key_*_numints includes the terminating 113219089Spjd * null for non-binary keys.) 114219089Spjd */ 115339115Smav int len = zn->zn_key_norm_numints - 1; 116219089Spjd 117219089Spjd ASSERT(zn->zn_key_intlen == 1); 118339115Smav for (int i = 0; i < len; cp++, i++) { 119219089Spjd h = (h >> 8) ^ 120219089Spjd zfs_crc64_table[(h ^ *cp) & 0xFF]; 121219089Spjd } 122219089Spjd } 123185029Spjd } 124185029Spjd /* 125219089Spjd * Don't use all 64 bits, since we need some in the cookie for 126219089Spjd * the collision differentiator. We MUST use the high bits, 127219089Spjd * since those are the ones that we first pay attention to when 128185029Spjd * chosing the bucket. 129185029Spjd */ 130219089Spjd h &= ~((1ULL << (64 - zap_hashbits(zap))) - 1); 131185029Spjd 132219089Spjd return (h); 133185029Spjd} 134185029Spjd 135185029Spjdstatic int 136321545Smavzap_normalize(zap_t *zap, const char *name, char *namenorm, int normflags) 137185029Spjd{ 138219089Spjd ASSERT(!(zap_getflags(zap) & ZAP_FLAG_UINT64_KEY)); 139219089Spjd 140339115Smav size_t inlen = strlen(name) + 1; 141339115Smav size_t outlen = ZAP_MAXNAMELEN; 142185029Spjd 143339115Smav int err = 0; 144185029Spjd (void) u8_textprep_str((char *)name, &inlen, namenorm, &outlen, 145321545Smav normflags | U8_TEXTPREP_IGNORE_NULL | U8_TEXTPREP_IGNORE_INVALID, 146321545Smav U8_UNICODE_LATEST, &err); 147185029Spjd 148185029Spjd return (err); 149185029Spjd} 150185029Spjd 151185029Spjdboolean_t 152185029Spjdzap_match(zap_name_t *zn, const char *matchname) 153185029Spjd{ 154219089Spjd ASSERT(!(zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY)); 155219089Spjd 156321545Smav if (zn->zn_matchtype & MT_NORMALIZE) { 157185029Spjd char norm[ZAP_MAXNAMELEN]; 158185029Spjd 159321545Smav if (zap_normalize(zn->zn_zap, matchname, norm, 160321545Smav zn->zn_normflags) != 0) 161185029Spjd return (B_FALSE); 162185029Spjd 163219089Spjd return (strcmp(zn->zn_key_norm, norm) == 0); 164185029Spjd } else { 165219089Spjd return (strcmp(zn->zn_key_orig, matchname) == 0); 166185029Spjd } 167185029Spjd} 168185029Spjd 169185029Spjdvoid 170185029Spjdzap_name_free(zap_name_t *zn) 171185029Spjd{ 172185029Spjd kmem_free(zn, sizeof (zap_name_t)); 173185029Spjd} 174185029Spjd 175185029Spjdzap_name_t * 176219089Spjdzap_name_alloc(zap_t *zap, const char *key, matchtype_t mt) 177185029Spjd{ 178185029Spjd zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP); 179185029Spjd 180185029Spjd zn->zn_zap = zap; 181219089Spjd zn->zn_key_intlen = sizeof (*key); 182219089Spjd zn->zn_key_orig = key; 183219089Spjd zn->zn_key_orig_numints = strlen(zn->zn_key_orig) + 1; 184185029Spjd zn->zn_matchtype = mt; 185321545Smav zn->zn_normflags = zap->zap_normflags; 186321545Smav 187321545Smav /* 188321545Smav * If we're dealing with a case sensitive lookup on a mixed or 189321545Smav * insensitive fs, remove U8_TEXTPREP_TOUPPER or the lookup 190321545Smav * will fold case to all caps overriding the lookup request. 191321545Smav */ 192321545Smav if (mt & MT_MATCH_CASE) 193321545Smav zn->zn_normflags &= ~U8_TEXTPREP_TOUPPER; 194321545Smav 195185029Spjd if (zap->zap_normflags) { 196321545Smav /* 197321545Smav * We *must* use zap_normflags because this normalization is 198321545Smav * what the hash is computed from. 199321545Smav */ 200321545Smav if (zap_normalize(zap, key, zn->zn_normbuf, 201321545Smav zap->zap_normflags) != 0) { 202185029Spjd zap_name_free(zn); 203185029Spjd return (NULL); 204185029Spjd } 205219089Spjd zn->zn_key_norm = zn->zn_normbuf; 206219089Spjd zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1; 207185029Spjd } else { 208321545Smav if (mt != 0) { 209185029Spjd zap_name_free(zn); 210185029Spjd return (NULL); 211185029Spjd } 212219089Spjd zn->zn_key_norm = zn->zn_key_orig; 213219089Spjd zn->zn_key_norm_numints = zn->zn_key_orig_numints; 214185029Spjd } 215185029Spjd 216219089Spjd zn->zn_hash = zap_hash(zn); 217321545Smav 218321545Smav if (zap->zap_normflags != zn->zn_normflags) { 219321545Smav /* 220321545Smav * We *must* use zn_normflags because this normalization is 221321545Smav * what the matching is based on. (Not the hash!) 222321545Smav */ 223321545Smav if (zap_normalize(zap, key, zn->zn_normbuf, 224321545Smav zn->zn_normflags) != 0) { 225321545Smav zap_name_free(zn); 226321545Smav return (NULL); 227321545Smav } 228321545Smav zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1; 229321545Smav } 230321545Smav 231185029Spjd return (zn); 232185029Spjd} 233185029Spjd 234219089Spjdzap_name_t * 235219089Spjdzap_name_alloc_uint64(zap_t *zap, const uint64_t *key, int numints) 236219089Spjd{ 237219089Spjd zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP); 238219089Spjd 239219089Spjd ASSERT(zap->zap_normflags == 0); 240219089Spjd zn->zn_zap = zap; 241219089Spjd zn->zn_key_intlen = sizeof (*key); 242219089Spjd zn->zn_key_orig = zn->zn_key_norm = key; 243219089Spjd zn->zn_key_orig_numints = zn->zn_key_norm_numints = numints; 244321545Smav zn->zn_matchtype = 0; 245219089Spjd 246219089Spjd zn->zn_hash = zap_hash(zn); 247219089Spjd return (zn); 248219089Spjd} 249219089Spjd 250168404Spjdstatic void 251168404Spjdmzap_byteswap(mzap_phys_t *buf, size_t size) 252168404Spjd{ 253168404Spjd buf->mz_block_type = BSWAP_64(buf->mz_block_type); 254168404Spjd buf->mz_salt = BSWAP_64(buf->mz_salt); 255185029Spjd buf->mz_normflags = BSWAP_64(buf->mz_normflags); 256339115Smav int max = (size / MZAP_ENT_LEN) - 1; 257339115Smav for (int i = 0; i < max; i++) { 258168404Spjd buf->mz_chunk[i].mze_value = 259168404Spjd BSWAP_64(buf->mz_chunk[i].mze_value); 260168404Spjd buf->mz_chunk[i].mze_cd = 261168404Spjd BSWAP_32(buf->mz_chunk[i].mze_cd); 262168404Spjd } 263168404Spjd} 264168404Spjd 265168404Spjdvoid 266168404Spjdzap_byteswap(void *buf, size_t size) 267168404Spjd{ 268339115Smav uint64_t block_type = *(uint64_t *)buf; 269168404Spjd 270168404Spjd if (block_type == ZBT_MICRO || block_type == BSWAP_64(ZBT_MICRO)) { 271168404Spjd /* ASSERT(magic == ZAP_LEAF_MAGIC); */ 272168404Spjd mzap_byteswap(buf, size); 273168404Spjd } else { 274168404Spjd fzap_byteswap(buf, size); 275168404Spjd } 276168404Spjd} 277168404Spjd 278168404Spjdstatic int 279168404Spjdmze_compare(const void *arg1, const void *arg2) 280168404Spjd{ 281168404Spjd const mzap_ent_t *mze1 = arg1; 282168404Spjd const mzap_ent_t *mze2 = arg2; 283168404Spjd 284339158Smav int cmp = AVL_CMP(mze1->mze_hash, mze2->mze_hash); 285339158Smav if (likely(cmp)) 286339158Smav return (cmp); 287339158Smav 288339158Smav return (AVL_CMP(mze1->mze_cd, mze2->mze_cd)); 289168404Spjd} 290168404Spjd 291197150Spjdstatic int 292219089Spjdmze_insert(zap_t *zap, int chunkid, uint64_t hash) 293168404Spjd{ 294197150Spjd avl_index_t idx; 295168404Spjd 296168404Spjd ASSERT(zap->zap_ismicro); 297168404Spjd ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 298168404Spjd 299339115Smav mzap_ent_t *mze = kmem_alloc(sizeof (mzap_ent_t), KM_SLEEP); 300168404Spjd mze->mze_chunkid = chunkid; 301168404Spjd mze->mze_hash = hash; 302219089Spjd mze->mze_cd = MZE_PHYS(zap, mze)->mze_cd; 303219089Spjd ASSERT(MZE_PHYS(zap, mze)->mze_name[0] != 0); 304197150Spjd if (avl_find(&zap->zap_m.zap_avl, mze, &idx) != NULL) { 305197150Spjd kmem_free(mze, sizeof (mzap_ent_t)); 306197150Spjd return (EEXIST); 307197150Spjd } 308197150Spjd avl_insert(&zap->zap_m.zap_avl, mze, idx); 309197150Spjd return (0); 310168404Spjd} 311168404Spjd 312168404Spjdstatic mzap_ent_t * 313185029Spjdmze_find(zap_name_t *zn) 314168404Spjd{ 315168404Spjd mzap_ent_t mze_tofind; 316168404Spjd mzap_ent_t *mze; 317168404Spjd avl_index_t idx; 318185029Spjd avl_tree_t *avl = &zn->zn_zap->zap_m.zap_avl; 319168404Spjd 320185029Spjd ASSERT(zn->zn_zap->zap_ismicro); 321185029Spjd ASSERT(RW_LOCK_HELD(&zn->zn_zap->zap_rwlock)); 322168404Spjd 323185029Spjd mze_tofind.mze_hash = zn->zn_hash; 324219089Spjd mze_tofind.mze_cd = 0; 325168404Spjd 326168404Spjd mze = avl_find(avl, &mze_tofind, &idx); 327168404Spjd if (mze == NULL) 328168404Spjd mze = avl_nearest(avl, idx, AVL_AFTER); 329185029Spjd for (; mze && mze->mze_hash == zn->zn_hash; mze = AVL_NEXT(avl, mze)) { 330219089Spjd ASSERT3U(mze->mze_cd, ==, MZE_PHYS(zn->zn_zap, mze)->mze_cd); 331219089Spjd if (zap_match(zn, MZE_PHYS(zn->zn_zap, mze)->mze_name)) 332168404Spjd return (mze); 333168404Spjd } 334321545Smav 335168404Spjd return (NULL); 336168404Spjd} 337168404Spjd 338168404Spjdstatic uint32_t 339168404Spjdmze_find_unused_cd(zap_t *zap, uint64_t hash) 340168404Spjd{ 341168404Spjd mzap_ent_t mze_tofind; 342168404Spjd avl_index_t idx; 343168404Spjd avl_tree_t *avl = &zap->zap_m.zap_avl; 344168404Spjd 345168404Spjd ASSERT(zap->zap_ismicro); 346168404Spjd ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); 347168404Spjd 348168404Spjd mze_tofind.mze_hash = hash; 349219089Spjd mze_tofind.mze_cd = 0; 350168404Spjd 351339115Smav uint32_t cd = 0; 352339115Smav for (mzap_ent_t *mze = avl_find(avl, &mze_tofind, &idx); 353168404Spjd mze && mze->mze_hash == hash; mze = AVL_NEXT(avl, mze)) { 354219089Spjd if (mze->mze_cd != cd) 355168404Spjd break; 356168404Spjd cd++; 357168404Spjd } 358168404Spjd 359168404Spjd return (cd); 360168404Spjd} 361168404Spjd 362168404Spjdstatic void 363168404Spjdmze_remove(zap_t *zap, mzap_ent_t *mze) 364168404Spjd{ 365168404Spjd ASSERT(zap->zap_ismicro); 366168404Spjd ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 367168404Spjd 368168404Spjd avl_remove(&zap->zap_m.zap_avl, mze); 369168404Spjd kmem_free(mze, sizeof (mzap_ent_t)); 370168404Spjd} 371168404Spjd 372168404Spjdstatic void 373168404Spjdmze_destroy(zap_t *zap) 374168404Spjd{ 375168404Spjd mzap_ent_t *mze; 376168404Spjd void *avlcookie = NULL; 377168404Spjd 378168404Spjd while (mze = avl_destroy_nodes(&zap->zap_m.zap_avl, &avlcookie)) 379168404Spjd kmem_free(mze, sizeof (mzap_ent_t)); 380168404Spjd avl_destroy(&zap->zap_m.zap_avl); 381168404Spjd} 382168404Spjd 383168404Spjdstatic zap_t * 384168404Spjdmzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) 385168404Spjd{ 386168404Spjd zap_t *winner; 387299439Smav uint64_t *zap_hdr = (uint64_t *)db->db_data; 388299439Smav uint64_t zap_block_type = zap_hdr[0]; 389299439Smav uint64_t zap_magic = zap_hdr[1]; 390168404Spjd 391168404Spjd ASSERT3U(MZAP_ENT_LEN, ==, sizeof (mzap_ent_phys_t)); 392168404Spjd 393339115Smav zap_t *zap = kmem_zalloc(sizeof (zap_t), KM_SLEEP); 394219089Spjd rw_init(&zap->zap_rwlock, 0, 0, 0); 395168404Spjd rw_enter(&zap->zap_rwlock, RW_WRITER); 396168404Spjd zap->zap_objset = os; 397168404Spjd zap->zap_object = obj; 398168404Spjd zap->zap_dbuf = db; 399168404Spjd 400299439Smav if (zap_block_type != ZBT_MICRO) { 401219089Spjd mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0); 402264669Sdelphij zap->zap_f.zap_block_shift = highbit64(db->db_size) - 1; 403299439Smav if (zap_block_type != ZBT_HEADER || zap_magic != ZAP_MAGIC) { 404299439Smav winner = NULL; /* No actual winner here... */ 405299439Smav goto handle_winner; 406299439Smav } 407168404Spjd } else { 408168404Spjd zap->zap_ismicro = TRUE; 409168404Spjd } 410168404Spjd 411168404Spjd /* 412168404Spjd * Make sure that zap_ismicro is set before we let others see 413168404Spjd * it, because zap_lockdir() checks zap_ismicro without the lock 414168404Spjd * held. 415168404Spjd */ 416321527Smav dmu_buf_init_user(&zap->zap_dbu, zap_evict_sync, NULL, &zap->zap_dbuf); 417286575Smav winner = dmu_buf_set_user(db, &zap->zap_dbu); 418168404Spjd 419299439Smav if (winner != NULL) 420299439Smav goto handle_winner; 421168404Spjd 422168404Spjd if (zap->zap_ismicro) { 423275782Sdelphij zap->zap_salt = zap_m_phys(zap)->mz_salt; 424275782Sdelphij zap->zap_normflags = zap_m_phys(zap)->mz_normflags; 425168404Spjd zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1; 426168404Spjd avl_create(&zap->zap_m.zap_avl, mze_compare, 427168404Spjd sizeof (mzap_ent_t), offsetof(mzap_ent_t, mze_node)); 428168404Spjd 429339115Smav for (int i = 0; i < zap->zap_m.zap_num_chunks; i++) { 430168404Spjd mzap_ent_phys_t *mze = 431275782Sdelphij &zap_m_phys(zap)->mz_chunk[i]; 432168404Spjd if (mze->mze_name[0]) { 433185029Spjd zap_name_t *zn; 434185029Spjd 435321545Smav zn = zap_name_alloc(zap, mze->mze_name, 0); 436219089Spjd if (mze_insert(zap, i, zn->zn_hash) == 0) 437197150Spjd zap->zap_m.zap_num_entries++; 438197150Spjd else { 439197150Spjd printf("ZFS WARNING: Duplicated ZAP " 440197172Spjd "entry detected (%s).\n", 441197150Spjd mze->mze_name); 442197150Spjd } 443185029Spjd zap_name_free(zn); 444168404Spjd } 445168404Spjd } 446168404Spjd } else { 447275782Sdelphij zap->zap_salt = zap_f_phys(zap)->zap_salt; 448275782Sdelphij zap->zap_normflags = zap_f_phys(zap)->zap_normflags; 449168404Spjd 450168404Spjd ASSERT3U(sizeof (struct zap_leaf_header), ==, 451168404Spjd 2*ZAP_LEAF_CHUNKSIZE); 452168404Spjd 453168404Spjd /* 454168404Spjd * The embedded pointer table should not overlap the 455168404Spjd * other members. 456168404Spjd */ 457168404Spjd ASSERT3P(&ZAP_EMBEDDED_PTRTBL_ENT(zap, 0), >, 458275782Sdelphij &zap_f_phys(zap)->zap_salt); 459168404Spjd 460168404Spjd /* 461168404Spjd * The embedded pointer table should end at the end of 462168404Spjd * the block 463168404Spjd */ 464168404Spjd ASSERT3U((uintptr_t)&ZAP_EMBEDDED_PTRTBL_ENT(zap, 465168404Spjd 1<<ZAP_EMBEDDED_PTRTBL_SHIFT(zap)) - 466275782Sdelphij (uintptr_t)zap_f_phys(zap), ==, 467168404Spjd zap->zap_dbuf->db_size); 468168404Spjd } 469168404Spjd rw_exit(&zap->zap_rwlock); 470168404Spjd return (zap); 471299439Smav 472299439Smavhandle_winner: 473299439Smav rw_exit(&zap->zap_rwlock); 474299439Smav rw_destroy(&zap->zap_rwlock); 475299439Smav if (!zap->zap_ismicro) 476299439Smav mutex_destroy(&zap->zap_f.zap_num_entries_mtx); 477299439Smav kmem_free(zap, sizeof (zap_t)); 478299439Smav return (winner); 479168404Spjd} 480168404Spjd 481339115Smav/* 482339115Smav * This routine "consumes" the caller's hold on the dbuf, which must 483339115Smav * have the specified tag. 484339115Smav */ 485307286Smavstatic int 486307286Smavzap_lockdir_impl(dmu_buf_t *db, void *tag, dmu_tx_t *tx, 487185029Spjd krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp) 488168404Spjd{ 489307286Smav ASSERT0(db->db_offset); 490307286Smav objset_t *os = dmu_buf_get_objset(db); 491307286Smav uint64_t obj = db->db_object; 492307286Smav 493168404Spjd *zapp = NULL; 494168404Spjd 495339115Smav zap_t *zap = dmu_buf_get_user(db); 496299439Smav if (zap == NULL) { 497168404Spjd zap = mzap_open(os, obj, db); 498299439Smav if (zap == NULL) { 499299439Smav /* 500299439Smav * mzap_open() didn't like what it saw on-disk. 501299439Smav * Check for corruption! 502299439Smav */ 503299439Smav return (SET_ERROR(EIO)); 504299439Smav } 505299439Smav } 506168404Spjd 507168404Spjd /* 508168404Spjd * We're checking zap_ismicro without the lock held, in order to 509168404Spjd * tell what type of lock we want. Once we have some sort of 510168404Spjd * lock, see if it really is the right type. In practice this 511168404Spjd * can only be different if it was upgraded from micro to fat, 512168404Spjd * and micro wanted WRITER but fat only needs READER. 513168404Spjd */ 514339115Smav krw_t lt = (!zap->zap_ismicro && fatreader) ? RW_READER : lti; 515168404Spjd rw_enter(&zap->zap_rwlock, lt); 516168404Spjd if (lt != ((!zap->zap_ismicro && fatreader) ? RW_READER : lti)) { 517168404Spjd /* it was upgraded, now we only need reader */ 518168404Spjd ASSERT(lt == RW_WRITER); 519168404Spjd ASSERT(RW_READER == 520168404Spjd (!zap->zap_ismicro && fatreader) ? RW_READER : lti); 521168404Spjd rw_downgrade(&zap->zap_rwlock); 522168404Spjd lt = RW_READER; 523168404Spjd } 524168404Spjd 525168404Spjd zap->zap_objset = os; 526168404Spjd 527168404Spjd if (lt == RW_WRITER) 528168404Spjd dmu_buf_will_dirty(db, tx); 529168404Spjd 530168404Spjd ASSERT3P(zap->zap_dbuf, ==, db); 531168404Spjd 532168404Spjd ASSERT(!zap->zap_ismicro || 533168404Spjd zap->zap_m.zap_num_entries <= zap->zap_m.zap_num_chunks); 534185029Spjd if (zap->zap_ismicro && tx && adding && 535168404Spjd zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) { 536168404Spjd uint64_t newsz = db->db_size + SPA_MINBLOCKSIZE; 537168404Spjd if (newsz > MZAP_MAX_BLKSZ) { 538168404Spjd dprintf("upgrading obj %llu: num_entries=%u\n", 539168404Spjd obj, zap->zap_m.zap_num_entries); 540168404Spjd *zapp = zap; 541307286Smav int err = mzap_upgrade(zapp, tag, tx, 0); 542307286Smav if (err != 0) 543307286Smav rw_exit(&zap->zap_rwlock); 544307286Smav return (err); 545168404Spjd } 546307286Smav VERIFY0(dmu_object_set_blocksize(os, obj, newsz, 0, tx)); 547168404Spjd zap->zap_m.zap_num_chunks = 548168404Spjd db->db_size / MZAP_ENT_LEN - 1; 549168404Spjd } 550168404Spjd 551168404Spjd *zapp = zap; 552168404Spjd return (0); 553168404Spjd} 554168404Spjd 555307290Smavstatic int 556307290Smavzap_lockdir_by_dnode(dnode_t *dn, dmu_tx_t *tx, 557307290Smav krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp) 558307290Smav{ 559307290Smav dmu_buf_t *db; 560307290Smav 561339115Smav int err = dmu_buf_hold_by_dnode(dn, 0, tag, &db, DMU_READ_NO_PREFETCH); 562307290Smav if (err != 0) { 563307290Smav return (err); 564307290Smav } 565339115Smav#ifdef ZFS_DEBUG 566339115Smav { 567339115Smav dmu_object_info_t doi; 568339115Smav dmu_object_info_from_db(db, &doi); 569339115Smav ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP); 570339115Smav } 571339115Smav#endif 572339115Smav 573307290Smav err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp); 574307290Smav if (err != 0) { 575307290Smav dmu_buf_rele(db, tag); 576307290Smav } 577307290Smav return (err); 578307290Smav} 579307290Smav 580307286Smavint 581307286Smavzap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx, 582307286Smav krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp) 583307286Smav{ 584307286Smav dmu_buf_t *db; 585307286Smav 586339115Smav int err = dmu_buf_hold(os, obj, 0, tag, &db, DMU_READ_NO_PREFETCH); 587307286Smav if (err != 0) 588307286Smav return (err); 589339115Smav#ifdef ZFS_DEBUG 590339115Smav { 591339115Smav dmu_object_info_t doi; 592339115Smav dmu_object_info_from_db(db, &doi); 593339115Smav ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP); 594339115Smav } 595339115Smav#endif 596307286Smav err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp); 597307286Smav if (err != 0) 598307286Smav dmu_buf_rele(db, tag); 599307286Smav return (err); 600307286Smav} 601307286Smav 602168404Spjdvoid 603307286Smavzap_unlockdir(zap_t *zap, void *tag) 604168404Spjd{ 605168404Spjd rw_exit(&zap->zap_rwlock); 606307286Smav dmu_buf_rele(zap->zap_dbuf, tag); 607168404Spjd} 608168404Spjd 609185029Spjdstatic int 610307286Smavmzap_upgrade(zap_t **zapp, void *tag, dmu_tx_t *tx, zap_flags_t flags) 611168404Spjd{ 612219089Spjd int err = 0; 613185029Spjd zap_t *zap = *zapp; 614168404Spjd 615168404Spjd ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 616168404Spjd 617339115Smav int sz = zap->zap_dbuf->db_size; 618339115Smav mzap_phys_t *mzp = zio_buf_alloc(sz); 619168404Spjd bcopy(zap->zap_dbuf->db_data, mzp, sz); 620339115Smav int nchunks = zap->zap_m.zap_num_chunks; 621168404Spjd 622219089Spjd if (!flags) { 623219089Spjd err = dmu_object_set_blocksize(zap->zap_objset, zap->zap_object, 624219089Spjd 1ULL << fzap_default_block_shift, 0, tx); 625339115Smav if (err != 0) { 626286556Smav zio_buf_free(mzp, sz); 627219089Spjd return (err); 628219089Spjd } 629185029Spjd } 630168404Spjd 631168404Spjd dprintf("upgrading obj=%llu with %u chunks\n", 632168404Spjd zap->zap_object, nchunks); 633185029Spjd /* XXX destroy the avl later, so we can use the stored hash value */ 634168404Spjd mze_destroy(zap); 635168404Spjd 636219089Spjd fzap_upgrade(zap, tx, flags); 637168404Spjd 638339115Smav for (int i = 0; i < nchunks; i++) { 639168404Spjd mzap_ent_phys_t *mze = &mzp->mz_chunk[i]; 640168404Spjd if (mze->mze_name[0] == 0) 641168404Spjd continue; 642168404Spjd dprintf("adding %s=%llu\n", 643168404Spjd mze->mze_name, mze->mze_value); 644339115Smav zap_name_t *zn = zap_name_alloc(zap, mze->mze_name, 0); 645307286Smav err = fzap_add_cd(zn, 8, 1, &mze->mze_value, mze->mze_cd, 646307286Smav tag, tx); 647185029Spjd zap = zn->zn_zap; /* fzap_add_cd() may change zap */ 648185029Spjd zap_name_free(zn); 649339115Smav if (err != 0) 650185029Spjd break; 651168404Spjd } 652286556Smav zio_buf_free(mzp, sz); 653185029Spjd *zapp = zap; 654185029Spjd return (err); 655168404Spjd} 656168404Spjd 657321545Smav/* 658321545Smav * The "normflags" determine the behavior of the matchtype_t which is 659321545Smav * passed to zap_lookup_norm(). Names which have the same normalized 660321545Smav * version will be stored with the same hash value, and therefore we can 661321545Smav * perform normalization-insensitive lookups. We can be Unicode form- 662321545Smav * insensitive and/or case-insensitive. The following flags are valid for 663321545Smav * "normflags": 664321545Smav * 665321545Smav * U8_TEXTPREP_NFC 666321545Smav * U8_TEXTPREP_NFD 667321545Smav * U8_TEXTPREP_NFKC 668321545Smav * U8_TEXTPREP_NFKD 669321545Smav * U8_TEXTPREP_TOUPPER 670321545Smav * 671321545Smav * The *_NF* (Normalization Form) flags are mutually exclusive; at most one 672321545Smav * of them may be supplied. 673321545Smav */ 674259813Sdelphijvoid 675219089Spjdmzap_create_impl(objset_t *os, uint64_t obj, int normflags, zap_flags_t flags, 676219089Spjd dmu_tx_t *tx) 677168404Spjd{ 678168404Spjd dmu_buf_t *db; 679168404Spjd 680339115Smav VERIFY0(dmu_buf_hold(os, obj, 0, FTAG, &db, DMU_READ_NO_PREFETCH)); 681168404Spjd 682168404Spjd dmu_buf_will_dirty(db, tx); 683339115Smav mzap_phys_t *zp = db->db_data; 684168404Spjd zp->mz_block_type = ZBT_MICRO; 685168404Spjd zp->mz_salt = ((uintptr_t)db ^ (uintptr_t)tx ^ (obj << 1)) | 1ULL; 686185029Spjd zp->mz_normflags = normflags; 687219089Spjd 688219089Spjd if (flags != 0) { 689219089Spjd zap_t *zap; 690219089Spjd /* Only fat zap supports flags; upgrade immediately. */ 691339115Smav VERIFY0(zap_lockdir_impl(db, FTAG, tx, RW_WRITER, 692339115Smav B_FALSE, B_FALSE, &zap)); 693339115Smav VERIFY0(mzap_upgrade(&zap, FTAG, tx, flags)); 694307286Smav zap_unlockdir(zap, FTAG); 695339115Smav } else { 696339115Smav dmu_buf_rele(db, FTAG); 697219089Spjd } 698168404Spjd} 699168404Spjd 700168404Spjdint 701168404Spjdzap_create_claim(objset_t *os, uint64_t obj, dmu_object_type_t ot, 702168404Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 703168404Spjd{ 704185029Spjd return (zap_create_claim_norm(os, obj, 705185029Spjd 0, ot, bonustype, bonuslen, tx)); 706185029Spjd} 707185029Spjd 708185029Spjdint 709185029Spjdzap_create_claim_norm(objset_t *os, uint64_t obj, int normflags, 710185029Spjd dmu_object_type_t ot, 711185029Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 712185029Spjd{ 713339115Smav ASSERT3U(DMU_OT_BYTESWAP(ot), ==, DMU_BSWAP_ZAP); 714339115Smav int err = dmu_object_claim(os, obj, ot, 0, bonustype, bonuslen, tx); 715168404Spjd if (err != 0) 716168404Spjd return (err); 717219089Spjd mzap_create_impl(os, obj, normflags, 0, tx); 718168404Spjd return (0); 719168404Spjd} 720168404Spjd 721168404Spjduint64_t 722168404Spjdzap_create(objset_t *os, dmu_object_type_t ot, 723168404Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 724168404Spjd{ 725185029Spjd return (zap_create_norm(os, 0, ot, bonustype, bonuslen, tx)); 726185029Spjd} 727185029Spjd 728185029Spjduint64_t 729185029Spjdzap_create_norm(objset_t *os, int normflags, dmu_object_type_t ot, 730185029Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 731185029Spjd{ 732339115Smav ASSERT3U(DMU_OT_BYTESWAP(ot), ==, DMU_BSWAP_ZAP); 733168404Spjd uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx); 734168404Spjd 735219089Spjd mzap_create_impl(os, obj, normflags, 0, tx); 736168404Spjd return (obj); 737168404Spjd} 738168404Spjd 739219089Spjduint64_t 740219089Spjdzap_create_flags(objset_t *os, int normflags, zap_flags_t flags, 741219089Spjd dmu_object_type_t ot, int leaf_blockshift, int indirect_blockshift, 742219089Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 743219089Spjd{ 744339115Smav ASSERT3U(DMU_OT_BYTESWAP(ot), ==, DMU_BSWAP_ZAP); 745219089Spjd uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx); 746219089Spjd 747219089Spjd ASSERT(leaf_blockshift >= SPA_MINBLOCKSHIFT && 748274337Sdelphij leaf_blockshift <= SPA_OLD_MAXBLOCKSHIFT && 749219089Spjd indirect_blockshift >= SPA_MINBLOCKSHIFT && 750274337Sdelphij indirect_blockshift <= SPA_OLD_MAXBLOCKSHIFT); 751219089Spjd 752219089Spjd VERIFY(dmu_object_set_blocksize(os, obj, 753219089Spjd 1ULL << leaf_blockshift, indirect_blockshift, tx) == 0); 754219089Spjd 755219089Spjd mzap_create_impl(os, obj, normflags, flags, tx); 756219089Spjd return (obj); 757219089Spjd} 758219089Spjd 759168404Spjdint 760168404Spjdzap_destroy(objset_t *os, uint64_t zapobj, dmu_tx_t *tx) 761168404Spjd{ 762168404Spjd /* 763168404Spjd * dmu_object_free will free the object number and free the 764168404Spjd * data. Freeing the data will cause our pageout function to be 765168404Spjd * called, which will destroy our data (zap_leaf_t's and zap_t). 766168404Spjd */ 767168404Spjd 768168404Spjd return (dmu_object_free(os, zapobj, tx)); 769168404Spjd} 770168404Spjd 771168404Spjdvoid 772321527Smavzap_evict_sync(void *dbu) 773168404Spjd{ 774286575Smav zap_t *zap = dbu; 775168404Spjd 776168404Spjd rw_destroy(&zap->zap_rwlock); 777168404Spjd 778168404Spjd if (zap->zap_ismicro) 779168404Spjd mze_destroy(zap); 780168404Spjd else 781168404Spjd mutex_destroy(&zap->zap_f.zap_num_entries_mtx); 782168404Spjd 783168404Spjd kmem_free(zap, sizeof (zap_t)); 784168404Spjd} 785168404Spjd 786168404Spjdint 787168404Spjdzap_count(objset_t *os, uint64_t zapobj, uint64_t *count) 788168404Spjd{ 789168404Spjd zap_t *zap; 790168404Spjd 791339115Smav int err = 792339115Smav zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 793339115Smav if (err != 0) 794168404Spjd return (err); 795168404Spjd if (!zap->zap_ismicro) { 796168404Spjd err = fzap_count(zap, count); 797168404Spjd } else { 798168404Spjd *count = zap->zap_m.zap_num_entries; 799168404Spjd } 800307286Smav zap_unlockdir(zap, FTAG); 801168404Spjd return (err); 802168404Spjd} 803168404Spjd 804168404Spjd/* 805185029Spjd * zn may be NULL; if not specified, it will be computed if needed. 806185029Spjd * See also the comment above zap_entry_normalization_conflict(). 807168404Spjd */ 808185029Spjdstatic boolean_t 809185029Spjdmzap_normalization_conflict(zap_t *zap, zap_name_t *zn, mzap_ent_t *mze) 810185029Spjd{ 811185029Spjd int direction = AVL_BEFORE; 812185029Spjd boolean_t allocdzn = B_FALSE; 813168404Spjd 814185029Spjd if (zap->zap_normflags == 0) 815185029Spjd return (B_FALSE); 816185029Spjd 817185029Spjdagain: 818339115Smav for (mzap_ent_t *other = avl_walk(&zap->zap_m.zap_avl, mze, direction); 819185029Spjd other && other->mze_hash == mze->mze_hash; 820185029Spjd other = avl_walk(&zap->zap_m.zap_avl, other, direction)) { 821185029Spjd 822185029Spjd if (zn == NULL) { 823219089Spjd zn = zap_name_alloc(zap, MZE_PHYS(zap, mze)->mze_name, 824321545Smav MT_NORMALIZE); 825185029Spjd allocdzn = B_TRUE; 826185029Spjd } 827219089Spjd if (zap_match(zn, MZE_PHYS(zap, other)->mze_name)) { 828185029Spjd if (allocdzn) 829185029Spjd zap_name_free(zn); 830185029Spjd return (B_TRUE); 831185029Spjd } 832185029Spjd } 833185029Spjd 834185029Spjd if (direction == AVL_BEFORE) { 835185029Spjd direction = AVL_AFTER; 836185029Spjd goto again; 837185029Spjd } 838185029Spjd 839185029Spjd if (allocdzn) 840185029Spjd zap_name_free(zn); 841185029Spjd return (B_FALSE); 842185029Spjd} 843185029Spjd 844185029Spjd/* 845185029Spjd * Routines for manipulating attributes. 846185029Spjd */ 847185029Spjd 848168404Spjdint 849168404Spjdzap_lookup(objset_t *os, uint64_t zapobj, const char *name, 850168404Spjd uint64_t integer_size, uint64_t num_integers, void *buf) 851168404Spjd{ 852185029Spjd return (zap_lookup_norm(os, zapobj, name, integer_size, 853321545Smav num_integers, buf, 0, NULL, 0, NULL)); 854185029Spjd} 855185029Spjd 856307286Smavstatic int 857307286Smavzap_lookup_impl(zap_t *zap, const char *name, 858185029Spjd uint64_t integer_size, uint64_t num_integers, void *buf, 859185029Spjd matchtype_t mt, char *realname, int rn_len, 860185029Spjd boolean_t *ncp) 861185029Spjd{ 862307286Smav int err = 0; 863168404Spjd 864339115Smav zap_name_t *zn = zap_name_alloc(zap, name, mt); 865307286Smav if (zn == NULL) 866249195Smm return (SET_ERROR(ENOTSUP)); 867185029Spjd 868168404Spjd if (!zap->zap_ismicro) { 869185029Spjd err = fzap_lookup(zn, integer_size, num_integers, buf, 870185029Spjd realname, rn_len, ncp); 871168404Spjd } else { 872339115Smav mzap_ent_t *mze = mze_find(zn); 873168404Spjd if (mze == NULL) { 874249195Smm err = SET_ERROR(ENOENT); 875168404Spjd } else { 876185029Spjd if (num_integers < 1) { 877249195Smm err = SET_ERROR(EOVERFLOW); 878185029Spjd } else if (integer_size != 8) { 879249195Smm err = SET_ERROR(EINVAL); 880185029Spjd } else { 881219089Spjd *(uint64_t *)buf = 882219089Spjd MZE_PHYS(zap, mze)->mze_value; 883185029Spjd (void) strlcpy(realname, 884219089Spjd MZE_PHYS(zap, mze)->mze_name, rn_len); 885185029Spjd if (ncp) { 886185029Spjd *ncp = mzap_normalization_conflict(zap, 887185029Spjd zn, mze); 888185029Spjd } 889185029Spjd } 890168404Spjd } 891168404Spjd } 892185029Spjd zap_name_free(zn); 893168404Spjd return (err); 894168404Spjd} 895168404Spjd 896168404Spjdint 897307286Smavzap_lookup_norm(objset_t *os, uint64_t zapobj, const char *name, 898307286Smav uint64_t integer_size, uint64_t num_integers, void *buf, 899307286Smav matchtype_t mt, char *realname, int rn_len, 900307286Smav boolean_t *ncp) 901307286Smav{ 902307286Smav zap_t *zap; 903307286Smav 904339115Smav int err = 905339115Smav zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 906307286Smav if (err != 0) 907307286Smav return (err); 908307286Smav err = zap_lookup_impl(zap, name, integer_size, 909307286Smav num_integers, buf, mt, realname, rn_len, ncp); 910307286Smav zap_unlockdir(zap, FTAG); 911307286Smav return (err); 912307286Smav} 913307286Smav 914307286Smavint 915307290Smavzap_lookup_by_dnode(dnode_t *dn, const char *name, 916307290Smav uint64_t integer_size, uint64_t num_integers, void *buf) 917307290Smav{ 918307290Smav return (zap_lookup_norm_by_dnode(dn, name, integer_size, 919321545Smav num_integers, buf, 0, NULL, 0, NULL)); 920307290Smav} 921307290Smav 922307290Smavint 923307290Smavzap_lookup_norm_by_dnode(dnode_t *dn, const char *name, 924307290Smav uint64_t integer_size, uint64_t num_integers, void *buf, 925307290Smav matchtype_t mt, char *realname, int rn_len, 926307290Smav boolean_t *ncp) 927307290Smav{ 928307290Smav zap_t *zap; 929307290Smav 930339115Smav int err = zap_lockdir_by_dnode(dn, NULL, RW_READER, TRUE, FALSE, 931307290Smav FTAG, &zap); 932307290Smav if (err != 0) 933307290Smav return (err); 934307290Smav err = zap_lookup_impl(zap, name, integer_size, 935307290Smav num_integers, buf, mt, realname, rn_len, ncp); 936307290Smav zap_unlockdir(zap, FTAG); 937307290Smav return (err); 938307290Smav} 939307290Smav 940307290Smavint 941219089Spjdzap_prefetch_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 942219089Spjd int key_numints) 943219089Spjd{ 944219089Spjd zap_t *zap; 945219089Spjd 946339115Smav int err = 947339115Smav zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 948339115Smav if (err != 0) 949219089Spjd return (err); 950339115Smav zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 951219089Spjd if (zn == NULL) { 952307286Smav zap_unlockdir(zap, FTAG); 953249195Smm return (SET_ERROR(ENOTSUP)); 954219089Spjd } 955219089Spjd 956219089Spjd fzap_prefetch(zn); 957219089Spjd zap_name_free(zn); 958307286Smav zap_unlockdir(zap, FTAG); 959219089Spjd return (err); 960219089Spjd} 961219089Spjd 962219089Spjdint 963219089Spjdzap_lookup_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 964219089Spjd int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf) 965219089Spjd{ 966219089Spjd zap_t *zap; 967219089Spjd 968339115Smav int err = 969339115Smav zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 970339115Smav if (err != 0) 971219089Spjd return (err); 972339115Smav zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 973219089Spjd if (zn == NULL) { 974307286Smav zap_unlockdir(zap, FTAG); 975249195Smm return (SET_ERROR(ENOTSUP)); 976219089Spjd } 977219089Spjd 978219089Spjd err = fzap_lookup(zn, integer_size, num_integers, buf, 979219089Spjd NULL, 0, NULL); 980219089Spjd zap_name_free(zn); 981307286Smav zap_unlockdir(zap, FTAG); 982219089Spjd return (err); 983219089Spjd} 984219089Spjd 985219089Spjdint 986219089Spjdzap_contains(objset_t *os, uint64_t zapobj, const char *name) 987219089Spjd{ 988259813Sdelphij int err = zap_lookup_norm(os, zapobj, name, 0, 989321545Smav 0, NULL, 0, NULL, 0, NULL); 990219089Spjd if (err == EOVERFLOW || err == EINVAL) 991219089Spjd err = 0; /* found, but skipped reading the value */ 992219089Spjd return (err); 993219089Spjd} 994219089Spjd 995219089Spjdint 996168404Spjdzap_length(objset_t *os, uint64_t zapobj, const char *name, 997168404Spjd uint64_t *integer_size, uint64_t *num_integers) 998168404Spjd{ 999168404Spjd zap_t *zap; 1000168404Spjd 1001339115Smav int err = 1002339115Smav zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1003339115Smav if (err != 0) 1004168404Spjd return (err); 1005339115Smav zap_name_t *zn = zap_name_alloc(zap, name, 0); 1006185029Spjd if (zn == NULL) { 1007307286Smav zap_unlockdir(zap, FTAG); 1008249195Smm return (SET_ERROR(ENOTSUP)); 1009185029Spjd } 1010168404Spjd if (!zap->zap_ismicro) { 1011185029Spjd err = fzap_length(zn, integer_size, num_integers); 1012168404Spjd } else { 1013339115Smav mzap_ent_t *mze = mze_find(zn); 1014168404Spjd if (mze == NULL) { 1015249195Smm err = SET_ERROR(ENOENT); 1016168404Spjd } else { 1017168404Spjd if (integer_size) 1018168404Spjd *integer_size = 8; 1019168404Spjd if (num_integers) 1020168404Spjd *num_integers = 1; 1021168404Spjd } 1022168404Spjd } 1023185029Spjd zap_name_free(zn); 1024307286Smav zap_unlockdir(zap, FTAG); 1025168404Spjd return (err); 1026168404Spjd} 1027168404Spjd 1028219089Spjdint 1029219089Spjdzap_length_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1030219089Spjd int key_numints, uint64_t *integer_size, uint64_t *num_integers) 1031219089Spjd{ 1032219089Spjd zap_t *zap; 1033219089Spjd 1034339115Smav int err = 1035339115Smav zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1036339115Smav if (err != 0) 1037219089Spjd return (err); 1038339115Smav zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1039219089Spjd if (zn == NULL) { 1040307286Smav zap_unlockdir(zap, FTAG); 1041249195Smm return (SET_ERROR(ENOTSUP)); 1042219089Spjd } 1043219089Spjd err = fzap_length(zn, integer_size, num_integers); 1044219089Spjd zap_name_free(zn); 1045307286Smav zap_unlockdir(zap, FTAG); 1046219089Spjd return (err); 1047219089Spjd} 1048219089Spjd 1049168404Spjdstatic void 1050185029Spjdmzap_addent(zap_name_t *zn, uint64_t value) 1051168404Spjd{ 1052185029Spjd zap_t *zap = zn->zn_zap; 1053168404Spjd int start = zap->zap_m.zap_alloc_next; 1054168404Spjd 1055168404Spjd ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 1056168404Spjd 1057168404Spjd#ifdef ZFS_DEBUG 1058339115Smav for (int i = 0; i < zap->zap_m.zap_num_chunks; i++) { 1059275782Sdelphij mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i]; 1060219089Spjd ASSERT(strcmp(zn->zn_key_orig, mze->mze_name) != 0); 1061168404Spjd } 1062168404Spjd#endif 1063168404Spjd 1064339115Smav uint32_t cd = mze_find_unused_cd(zap, zn->zn_hash); 1065168404Spjd /* given the limited size of the microzap, this can't happen */ 1066219089Spjd ASSERT(cd < zap_maxcd(zap)); 1067168404Spjd 1068168404Spjdagain: 1069339115Smav for (int i = start; i < zap->zap_m.zap_num_chunks; i++) { 1070275782Sdelphij mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i]; 1071168404Spjd if (mze->mze_name[0] == 0) { 1072168404Spjd mze->mze_value = value; 1073168404Spjd mze->mze_cd = cd; 1074219089Spjd (void) strcpy(mze->mze_name, zn->zn_key_orig); 1075168404Spjd zap->zap_m.zap_num_entries++; 1076168404Spjd zap->zap_m.zap_alloc_next = i+1; 1077168404Spjd if (zap->zap_m.zap_alloc_next == 1078168404Spjd zap->zap_m.zap_num_chunks) 1079168404Spjd zap->zap_m.zap_alloc_next = 0; 1080219089Spjd VERIFY(0 == mze_insert(zap, i, zn->zn_hash)); 1081168404Spjd return; 1082168404Spjd } 1083168404Spjd } 1084168404Spjd if (start != 0) { 1085168404Spjd start = 0; 1086168404Spjd goto again; 1087168404Spjd } 1088168404Spjd ASSERT(!"out of entries!"); 1089168404Spjd} 1090168404Spjd 1091321549Smavstatic int 1092321549Smavzap_add_impl(zap_t *zap, const char *key, 1093168404Spjd int integer_size, uint64_t num_integers, 1094321549Smav const void *val, dmu_tx_t *tx, void *tag) 1095168404Spjd{ 1096339115Smav const uint64_t *intval = val; 1097321549Smav int err = 0; 1098168404Spjd 1099339115Smav zap_name_t *zn = zap_name_alloc(zap, key, 0); 1100185029Spjd if (zn == NULL) { 1101321549Smav zap_unlockdir(zap, tag); 1102249195Smm return (SET_ERROR(ENOTSUP)); 1103185029Spjd } 1104168404Spjd if (!zap->zap_ismicro) { 1105321549Smav err = fzap_add(zn, integer_size, num_integers, val, tag, tx); 1106185029Spjd zap = zn->zn_zap; /* fzap_add() may change zap */ 1107168404Spjd } else if (integer_size != 8 || num_integers != 1 || 1108219089Spjd strlen(key) >= MZAP_NAME_LEN) { 1109321549Smav err = mzap_upgrade(&zn->zn_zap, tag, tx, 0); 1110307286Smav if (err == 0) { 1111307286Smav err = fzap_add(zn, integer_size, num_integers, val, 1112321549Smav tag, tx); 1113307286Smav } 1114185029Spjd zap = zn->zn_zap; /* fzap_add() may change zap */ 1115168404Spjd } else { 1116339115Smav if (mze_find(zn) != NULL) { 1117249195Smm err = SET_ERROR(EEXIST); 1118168404Spjd } else { 1119185029Spjd mzap_addent(zn, *intval); 1120168404Spjd } 1121168404Spjd } 1122185029Spjd ASSERT(zap == zn->zn_zap); 1123185029Spjd zap_name_free(zn); 1124185029Spjd if (zap != NULL) /* may be NULL if fzap_add() failed */ 1125321549Smav zap_unlockdir(zap, tag); 1126168404Spjd return (err); 1127168404Spjd} 1128168404Spjd 1129168404Spjdint 1130321549Smavzap_add(objset_t *os, uint64_t zapobj, const char *key, 1131321549Smav int integer_size, uint64_t num_integers, 1132321549Smav const void *val, dmu_tx_t *tx) 1133321549Smav{ 1134321549Smav zap_t *zap; 1135321549Smav int err; 1136321549Smav 1137321549Smav err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1138321549Smav if (err != 0) 1139321549Smav return (err); 1140321549Smav err = zap_add_impl(zap, key, integer_size, num_integers, val, tx, FTAG); 1141321549Smav /* zap_add_impl() calls zap_unlockdir() */ 1142321549Smav return (err); 1143321549Smav} 1144321549Smav 1145321549Smavint 1146321549Smavzap_add_by_dnode(dnode_t *dn, const char *key, 1147321549Smav int integer_size, uint64_t num_integers, 1148321549Smav const void *val, dmu_tx_t *tx) 1149321549Smav{ 1150321549Smav zap_t *zap; 1151321549Smav int err; 1152321549Smav 1153321549Smav err = zap_lockdir_by_dnode(dn, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1154321549Smav if (err != 0) 1155321549Smav return (err); 1156321549Smav err = zap_add_impl(zap, key, integer_size, num_integers, val, tx, FTAG); 1157321549Smav /* zap_add_impl() calls zap_unlockdir() */ 1158321549Smav return (err); 1159321549Smav} 1160321549Smav 1161321549Smavint 1162219089Spjdzap_add_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1163219089Spjd int key_numints, int integer_size, uint64_t num_integers, 1164219089Spjd const void *val, dmu_tx_t *tx) 1165219089Spjd{ 1166219089Spjd zap_t *zap; 1167219089Spjd 1168339115Smav int err = 1169339115Smav zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1170339115Smav if (err != 0) 1171219089Spjd return (err); 1172339115Smav zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1173219089Spjd if (zn == NULL) { 1174307286Smav zap_unlockdir(zap, FTAG); 1175249195Smm return (SET_ERROR(ENOTSUP)); 1176219089Spjd } 1177307286Smav err = fzap_add(zn, integer_size, num_integers, val, FTAG, tx); 1178219089Spjd zap = zn->zn_zap; /* fzap_add() may change zap */ 1179219089Spjd zap_name_free(zn); 1180219089Spjd if (zap != NULL) /* may be NULL if fzap_add() failed */ 1181307286Smav zap_unlockdir(zap, FTAG); 1182219089Spjd return (err); 1183219089Spjd} 1184219089Spjd 1185219089Spjdint 1186168404Spjdzap_update(objset_t *os, uint64_t zapobj, const char *name, 1187168404Spjd int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx) 1188168404Spjd{ 1189168404Spjd zap_t *zap; 1190219089Spjd uint64_t oldval; 1191168404Spjd const uint64_t *intval = val; 1192168404Spjd 1193219089Spjd#ifdef ZFS_DEBUG 1194219089Spjd /* 1195219089Spjd * If there is an old value, it shouldn't change across the 1196219089Spjd * lockdir (eg, due to bprewrite's xlation). 1197219089Spjd */ 1198219089Spjd if (integer_size == 8 && num_integers == 1) 1199219089Spjd (void) zap_lookup(os, zapobj, name, 8, 1, &oldval); 1200219089Spjd#endif 1201219089Spjd 1202339115Smav int err = 1203339115Smav zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1204339115Smav if (err != 0) 1205168404Spjd return (err); 1206339115Smav zap_name_t *zn = zap_name_alloc(zap, name, 0); 1207185029Spjd if (zn == NULL) { 1208307286Smav zap_unlockdir(zap, FTAG); 1209249195Smm return (SET_ERROR(ENOTSUP)); 1210185029Spjd } 1211168404Spjd if (!zap->zap_ismicro) { 1212307286Smav err = fzap_update(zn, integer_size, num_integers, val, 1213307286Smav FTAG, tx); 1214185029Spjd zap = zn->zn_zap; /* fzap_update() may change zap */ 1215168404Spjd } else if (integer_size != 8 || num_integers != 1 || 1216168404Spjd strlen(name) >= MZAP_NAME_LEN) { 1217168404Spjd dprintf("upgrading obj %llu: intsz=%u numint=%llu name=%s\n", 1218168404Spjd zapobj, integer_size, num_integers, name); 1219307286Smav err = mzap_upgrade(&zn->zn_zap, FTAG, tx, 0); 1220307286Smav if (err == 0) { 1221185029Spjd err = fzap_update(zn, integer_size, num_integers, 1222307286Smav val, FTAG, tx); 1223307286Smav } 1224185029Spjd zap = zn->zn_zap; /* fzap_update() may change zap */ 1225168404Spjd } else { 1226339115Smav mzap_ent_t *mze = mze_find(zn); 1227168404Spjd if (mze != NULL) { 1228219089Spjd ASSERT3U(MZE_PHYS(zap, mze)->mze_value, ==, oldval); 1229219089Spjd MZE_PHYS(zap, mze)->mze_value = *intval; 1230168404Spjd } else { 1231185029Spjd mzap_addent(zn, *intval); 1232168404Spjd } 1233168404Spjd } 1234185029Spjd ASSERT(zap == zn->zn_zap); 1235185029Spjd zap_name_free(zn); 1236185029Spjd if (zap != NULL) /* may be NULL if fzap_upgrade() failed */ 1237307286Smav zap_unlockdir(zap, FTAG); 1238168404Spjd return (err); 1239168404Spjd} 1240168404Spjd 1241168404Spjdint 1242219089Spjdzap_update_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1243219089Spjd int key_numints, 1244219089Spjd int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx) 1245219089Spjd{ 1246219089Spjd zap_t *zap; 1247219089Spjd 1248339115Smav int err = 1249339115Smav zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1250339115Smav if (err != 0) 1251219089Spjd return (err); 1252339115Smav zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1253219089Spjd if (zn == NULL) { 1254307286Smav zap_unlockdir(zap, FTAG); 1255249195Smm return (SET_ERROR(ENOTSUP)); 1256219089Spjd } 1257307286Smav err = fzap_update(zn, integer_size, num_integers, val, FTAG, tx); 1258219089Spjd zap = zn->zn_zap; /* fzap_update() may change zap */ 1259219089Spjd zap_name_free(zn); 1260219089Spjd if (zap != NULL) /* may be NULL if fzap_upgrade() failed */ 1261307286Smav zap_unlockdir(zap, FTAG); 1262219089Spjd return (err); 1263219089Spjd} 1264219089Spjd 1265219089Spjdint 1266168404Spjdzap_remove(objset_t *os, uint64_t zapobj, const char *name, dmu_tx_t *tx) 1267168404Spjd{ 1268321545Smav return (zap_remove_norm(os, zapobj, name, 0, tx)); 1269185029Spjd} 1270185029Spjd 1271321549Smavstatic int 1272321549Smavzap_remove_impl(zap_t *zap, const char *name, 1273185029Spjd matchtype_t mt, dmu_tx_t *tx) 1274185029Spjd{ 1275321549Smav int err = 0; 1276168404Spjd 1277339115Smav zap_name_t *zn = zap_name_alloc(zap, name, mt); 1278321549Smav if (zn == NULL) 1279249195Smm return (SET_ERROR(ENOTSUP)); 1280168404Spjd if (!zap->zap_ismicro) { 1281185029Spjd err = fzap_remove(zn, tx); 1282168404Spjd } else { 1283339115Smav mzap_ent_t *mze = mze_find(zn); 1284168404Spjd if (mze == NULL) { 1285249195Smm err = SET_ERROR(ENOENT); 1286168404Spjd } else { 1287168404Spjd zap->zap_m.zap_num_entries--; 1288275782Sdelphij bzero(&zap_m_phys(zap)->mz_chunk[mze->mze_chunkid], 1289168404Spjd sizeof (mzap_ent_phys_t)); 1290168404Spjd mze_remove(zap, mze); 1291168404Spjd } 1292168404Spjd } 1293185029Spjd zap_name_free(zn); 1294321549Smav return (err); 1295321549Smav} 1296321549Smav 1297321549Smavint 1298321549Smavzap_remove_norm(objset_t *os, uint64_t zapobj, const char *name, 1299321549Smav matchtype_t mt, dmu_tx_t *tx) 1300321549Smav{ 1301321549Smav zap_t *zap; 1302321549Smav int err; 1303321549Smav 1304321549Smav err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap); 1305321549Smav if (err) 1306321549Smav return (err); 1307321549Smav err = zap_remove_impl(zap, name, mt, tx); 1308307286Smav zap_unlockdir(zap, FTAG); 1309168404Spjd return (err); 1310168404Spjd} 1311168404Spjd 1312219089Spjdint 1313321549Smavzap_remove_by_dnode(dnode_t *dn, const char *name, dmu_tx_t *tx) 1314321549Smav{ 1315321549Smav zap_t *zap; 1316321549Smav int err; 1317321549Smav 1318321549Smav err = zap_lockdir_by_dnode(dn, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap); 1319321549Smav if (err) 1320321549Smav return (err); 1321321549Smav err = zap_remove_impl(zap, name, 0, tx); 1322321549Smav zap_unlockdir(zap, FTAG); 1323321549Smav return (err); 1324321549Smav} 1325321549Smav 1326321549Smavint 1327219089Spjdzap_remove_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1328219089Spjd int key_numints, dmu_tx_t *tx) 1329219089Spjd{ 1330219089Spjd zap_t *zap; 1331219089Spjd 1332339115Smav int err = 1333339115Smav zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap); 1334339115Smav if (err != 0) 1335219089Spjd return (err); 1336339115Smav zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1337219089Spjd if (zn == NULL) { 1338307286Smav zap_unlockdir(zap, FTAG); 1339249195Smm return (SET_ERROR(ENOTSUP)); 1340219089Spjd } 1341219089Spjd err = fzap_remove(zn, tx); 1342219089Spjd zap_name_free(zn); 1343307286Smav zap_unlockdir(zap, FTAG); 1344219089Spjd return (err); 1345219089Spjd} 1346219089Spjd 1347168404Spjd/* 1348168404Spjd * Routines for iterating over the attributes. 1349168404Spjd */ 1350168404Spjd 1351168404Spjdvoid 1352168404Spjdzap_cursor_init_serialized(zap_cursor_t *zc, objset_t *os, uint64_t zapobj, 1353168404Spjd uint64_t serialized) 1354168404Spjd{ 1355168404Spjd zc->zc_objset = os; 1356168404Spjd zc->zc_zap = NULL; 1357168404Spjd zc->zc_leaf = NULL; 1358168404Spjd zc->zc_zapobj = zapobj; 1359219089Spjd zc->zc_serialized = serialized; 1360219089Spjd zc->zc_hash = 0; 1361219089Spjd zc->zc_cd = 0; 1362168404Spjd} 1363168404Spjd 1364168404Spjdvoid 1365168404Spjdzap_cursor_init(zap_cursor_t *zc, objset_t *os, uint64_t zapobj) 1366168404Spjd{ 1367168404Spjd zap_cursor_init_serialized(zc, os, zapobj, 0); 1368168404Spjd} 1369168404Spjd 1370168404Spjdvoid 1371168404Spjdzap_cursor_fini(zap_cursor_t *zc) 1372168404Spjd{ 1373168404Spjd if (zc->zc_zap) { 1374168404Spjd rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); 1375307286Smav zap_unlockdir(zc->zc_zap, NULL); 1376168404Spjd zc->zc_zap = NULL; 1377168404Spjd } 1378168404Spjd if (zc->zc_leaf) { 1379168404Spjd rw_enter(&zc->zc_leaf->l_rwlock, RW_READER); 1380168404Spjd zap_put_leaf(zc->zc_leaf); 1381168404Spjd zc->zc_leaf = NULL; 1382168404Spjd } 1383168404Spjd zc->zc_objset = NULL; 1384168404Spjd} 1385168404Spjd 1386168404Spjduint64_t 1387168404Spjdzap_cursor_serialize(zap_cursor_t *zc) 1388168404Spjd{ 1389168404Spjd if (zc->zc_hash == -1ULL) 1390168404Spjd return (-1ULL); 1391219089Spjd if (zc->zc_zap == NULL) 1392219089Spjd return (zc->zc_serialized); 1393219089Spjd ASSERT((zc->zc_hash & zap_maxcd(zc->zc_zap)) == 0); 1394219089Spjd ASSERT(zc->zc_cd < zap_maxcd(zc->zc_zap)); 1395219089Spjd 1396219089Spjd /* 1397219089Spjd * We want to keep the high 32 bits of the cursor zero if we can, so 1398219089Spjd * that 32-bit programs can access this. So usually use a small 1399219089Spjd * (28-bit) hash value so we can fit 4 bits of cd into the low 32-bits 1400219089Spjd * of the cursor. 1401219089Spjd * 1402219089Spjd * [ collision differentiator | zap_hashbits()-bit hash value ] 1403219089Spjd */ 1404219089Spjd return ((zc->zc_hash >> (64 - zap_hashbits(zc->zc_zap))) | 1405219089Spjd ((uint64_t)zc->zc_cd << zap_hashbits(zc->zc_zap))); 1406168404Spjd} 1407168404Spjd 1408168404Spjdint 1409168404Spjdzap_cursor_retrieve(zap_cursor_t *zc, zap_attribute_t *za) 1410168404Spjd{ 1411168404Spjd int err; 1412168404Spjd 1413168404Spjd if (zc->zc_hash == -1ULL) 1414249195Smm return (SET_ERROR(ENOENT)); 1415168404Spjd 1416168404Spjd if (zc->zc_zap == NULL) { 1417219089Spjd int hb; 1418168404Spjd err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL, 1419307286Smav RW_READER, TRUE, FALSE, NULL, &zc->zc_zap); 1420339115Smav if (err != 0) 1421168404Spjd return (err); 1422219089Spjd 1423219089Spjd /* 1424219089Spjd * To support zap_cursor_init_serialized, advance, retrieve, 1425219089Spjd * we must add to the existing zc_cd, which may already 1426219089Spjd * be 1 due to the zap_cursor_advance. 1427219089Spjd */ 1428219089Spjd ASSERT(zc->zc_hash == 0); 1429219089Spjd hb = zap_hashbits(zc->zc_zap); 1430219089Spjd zc->zc_hash = zc->zc_serialized << (64 - hb); 1431219089Spjd zc->zc_cd += zc->zc_serialized >> hb; 1432219089Spjd if (zc->zc_cd >= zap_maxcd(zc->zc_zap)) /* corrupt serialized */ 1433219089Spjd zc->zc_cd = 0; 1434168404Spjd } else { 1435168404Spjd rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); 1436168404Spjd } 1437168404Spjd if (!zc->zc_zap->zap_ismicro) { 1438168404Spjd err = fzap_cursor_retrieve(zc->zc_zap, zc, za); 1439168404Spjd } else { 1440339115Smav avl_index_t idx; 1441339115Smav mzap_ent_t mze_tofind; 1442339115Smav 1443168404Spjd mze_tofind.mze_hash = zc->zc_hash; 1444219089Spjd mze_tofind.mze_cd = zc->zc_cd; 1445168404Spjd 1446339115Smav mzap_ent_t *mze = 1447339115Smav avl_find(&zc->zc_zap->zap_m.zap_avl, &mze_tofind, &idx); 1448168404Spjd if (mze == NULL) { 1449168404Spjd mze = avl_nearest(&zc->zc_zap->zap_m.zap_avl, 1450168404Spjd idx, AVL_AFTER); 1451168404Spjd } 1452168404Spjd if (mze) { 1453219089Spjd mzap_ent_phys_t *mzep = MZE_PHYS(zc->zc_zap, mze); 1454219089Spjd ASSERT3U(mze->mze_cd, ==, mzep->mze_cd); 1455185029Spjd za->za_normalization_conflict = 1456185029Spjd mzap_normalization_conflict(zc->zc_zap, NULL, mze); 1457168404Spjd za->za_integer_length = 8; 1458168404Spjd za->za_num_integers = 1; 1459219089Spjd za->za_first_integer = mzep->mze_value; 1460219089Spjd (void) strcpy(za->za_name, mzep->mze_name); 1461168404Spjd zc->zc_hash = mze->mze_hash; 1462219089Spjd zc->zc_cd = mze->mze_cd; 1463168404Spjd err = 0; 1464168404Spjd } else { 1465168404Spjd zc->zc_hash = -1ULL; 1466249195Smm err = SET_ERROR(ENOENT); 1467168404Spjd } 1468168404Spjd } 1469168404Spjd rw_exit(&zc->zc_zap->zap_rwlock); 1470168404Spjd return (err); 1471168404Spjd} 1472168404Spjd 1473168404Spjdvoid 1474168404Spjdzap_cursor_advance(zap_cursor_t *zc) 1475168404Spjd{ 1476168404Spjd if (zc->zc_hash == -1ULL) 1477168404Spjd return; 1478168404Spjd zc->zc_cd++; 1479219089Spjd} 1480219089Spjd 1481219089Spjdint 1482219089Spjdzap_cursor_move_to_key(zap_cursor_t *zc, const char *name, matchtype_t mt) 1483219089Spjd{ 1484219089Spjd int err = 0; 1485219089Spjd mzap_ent_t *mze; 1486219089Spjd zap_name_t *zn; 1487219089Spjd 1488219089Spjd if (zc->zc_zap == NULL) { 1489219089Spjd err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL, 1490307293Smav RW_READER, TRUE, FALSE, FTAG, &zc->zc_zap); 1491219089Spjd if (err) 1492219089Spjd return (err); 1493219089Spjd } else { 1494219089Spjd rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); 1495168404Spjd } 1496219089Spjd 1497219089Spjd zn = zap_name_alloc(zc->zc_zap, name, mt); 1498219089Spjd if (zn == NULL) { 1499219089Spjd rw_exit(&zc->zc_zap->zap_rwlock); 1500249195Smm return (SET_ERROR(ENOTSUP)); 1501219089Spjd } 1502219089Spjd 1503219089Spjd if (!zc->zc_zap->zap_ismicro) { 1504219089Spjd err = fzap_cursor_move_to_key(zc, zn); 1505219089Spjd } else { 1506219089Spjd mze = mze_find(zn); 1507219089Spjd if (mze == NULL) { 1508249195Smm err = SET_ERROR(ENOENT); 1509219089Spjd goto out; 1510219089Spjd } 1511219089Spjd zc->zc_hash = mze->mze_hash; 1512219089Spjd zc->zc_cd = mze->mze_cd; 1513219089Spjd } 1514219089Spjd 1515219089Spjdout: 1516219089Spjd zap_name_free(zn); 1517219089Spjd rw_exit(&zc->zc_zap->zap_rwlock); 1518219089Spjd return (err); 1519168404Spjd} 1520168404Spjd 1521168404Spjdint 1522168404Spjdzap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs) 1523168404Spjd{ 1524168404Spjd zap_t *zap; 1525168404Spjd 1526339115Smav int err = 1527339115Smav zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1528339115Smav if (err != 0) 1529168404Spjd return (err); 1530168404Spjd 1531168404Spjd bzero(zs, sizeof (zap_stats_t)); 1532168404Spjd 1533168404Spjd if (zap->zap_ismicro) { 1534168404Spjd zs->zs_blocksize = zap->zap_dbuf->db_size; 1535168404Spjd zs->zs_num_entries = zap->zap_m.zap_num_entries; 1536168404Spjd zs->zs_num_blocks = 1; 1537168404Spjd } else { 1538168404Spjd fzap_get_stats(zap, zs); 1539168404Spjd } 1540307286Smav zap_unlockdir(zap, FTAG); 1541168404Spjd return (0); 1542168404Spjd} 1543