1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5f65e61c0Sahrens * Common Development and Distribution License (the "License"). 6f65e61c0Sahrens * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 211c17160aSKevin Crowe 22fa9e4066Sahrens /* 2347cb52daSJeff Bonwick * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 2452abb70eSMatthew Ahrens * Copyright (c) 2011, 2018 by Delphix. All rights reserved. 25bc9014e6SJustin Gibbs * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. 26c3d26abcSMatthew Ahrens * Copyright (c) 2014 Integros [integros.com] 271c17160aSKevin Crowe * Copyright 2017 Nexenta Systems, Inc. 28fa9e4066Sahrens */ 29fa9e4066Sahrens 30b24ab676SJeff Bonwick #include <sys/zio.h> 31fa9e4066Sahrens #include <sys/spa.h> 32fa9e4066Sahrens #include <sys/dmu.h> 33fa9e4066Sahrens #include <sys/zfs_context.h> 34fa9e4066Sahrens #include <sys/zap.h> 35ea8dc4b6Seschrock #include <sys/refcount.h> 36fa9e4066Sahrens #include <sys/zap_impl.h> 3787e5029aSahrens #include <sys/zap_leaf.h> 38fa9e4066Sahrens #include <sys/avl.h> 393f9d6ad7SLin Ling #include <sys/arc.h> 40b5152584SMatthew Ahrens #include <sys/dmu_objset.h> 41de8267e0Stimh 42de8267e0Stimh #ifdef _KERNEL 43de8267e0Stimh #include <sys/sunddi.h> 44de8267e0Stimh #endif 45fa9e4066Sahrens 46c1379625SJustin T. Gibbs extern inline mzap_phys_t *zap_m_phys(zap_t *zap); 47c1379625SJustin T. Gibbs 48ae972795SMatthew Ahrens static int mzap_upgrade(zap_t **zapp, 49ae972795SMatthew Ahrens void *tag, dmu_tx_t *tx, zap_flags_t flags); 50fa9e4066Sahrens 51b24ab676SJeff Bonwick uint64_t 52b24ab676SJeff Bonwick zap_getflags(zap_t *zap) 53b24ab676SJeff Bonwick { 54b24ab676SJeff Bonwick if (zap->zap_ismicro) 55b24ab676SJeff Bonwick return (0); 56c1379625SJustin T. Gibbs return (zap_f_phys(zap)->zap_flags); 57b24ab676SJeff Bonwick } 58b24ab676SJeff Bonwick 59b24ab676SJeff Bonwick int 60b24ab676SJeff Bonwick zap_hashbits(zap_t *zap) 61b24ab676SJeff Bonwick { 62b24ab676SJeff Bonwick if (zap_getflags(zap) & ZAP_FLAG_HASH64) 63b24ab676SJeff Bonwick return (48); 64b24ab676SJeff Bonwick else 65b24ab676SJeff Bonwick return (28); 66b24ab676SJeff Bonwick } 67b24ab676SJeff Bonwick 68b24ab676SJeff Bonwick uint32_t 69b24ab676SJeff Bonwick zap_maxcd(zap_t *zap) 70b24ab676SJeff Bonwick { 71b24ab676SJeff Bonwick if (zap_getflags(zap) & ZAP_FLAG_HASH64) 72b24ab676SJeff Bonwick return ((1<<16)-1); 73b24ab676SJeff Bonwick else 74b24ab676SJeff Bonwick return (-1U); 75b24ab676SJeff Bonwick } 76fa9e4066Sahrens 77da6c28aaSamw static uint64_t 78b24ab676SJeff Bonwick zap_hash(zap_name_t *zn) 79da6c28aaSamw { 80b24ab676SJeff Bonwick zap_t *zap = zn->zn_zap; 81b24ab676SJeff Bonwick uint64_t h = 0; 82da6c28aaSamw 83b24ab676SJeff Bonwick if (zap_getflags(zap) & ZAP_FLAG_PRE_HASHED_KEY) { 84b24ab676SJeff Bonwick ASSERT(zap_getflags(zap) & ZAP_FLAG_UINT64_KEY); 85b24ab676SJeff Bonwick h = *(uint64_t *)zn->zn_key_orig; 86b24ab676SJeff Bonwick } else { 87b24ab676SJeff Bonwick h = zap->zap_salt; 88b24ab676SJeff Bonwick ASSERT(h != 0); 89b24ab676SJeff Bonwick ASSERT(zfs_crc64_table[128] == ZFS_CRC64_POLY); 90b24ab676SJeff Bonwick 91486ae710SMatthew Ahrens if (zap_getflags(zap) & ZAP_FLAG_UINT64_KEY) { 92486ae710SMatthew Ahrens const uint64_t *wp = zn->zn_key_norm; 93486ae710SMatthew Ahrens 94486ae710SMatthew Ahrens ASSERT(zn->zn_key_intlen == 8); 95bf26014cSMatthew Ahrens for (int i = 0; i < zn->zn_key_norm_numints; 96bf26014cSMatthew Ahrens wp++, i++) { 97486ae710SMatthew Ahrens uint64_t word = *wp; 98486ae710SMatthew Ahrens 99bf26014cSMatthew Ahrens for (int j = 0; j < zn->zn_key_intlen; j++) { 100486ae710SMatthew Ahrens h = (h >> 8) ^ 101486ae710SMatthew Ahrens zfs_crc64_table[(h ^ word) & 0xFF]; 102486ae710SMatthew Ahrens word >>= NBBY; 103486ae710SMatthew Ahrens } 104486ae710SMatthew Ahrens } 105486ae710SMatthew Ahrens } else { 106486ae710SMatthew Ahrens const uint8_t *cp = zn->zn_key_norm; 107486ae710SMatthew Ahrens 108486ae710SMatthew Ahrens /* 109486ae710SMatthew Ahrens * We previously stored the terminating null on 110486ae710SMatthew Ahrens * disk, but didn't hash it, so we need to 111486ae710SMatthew Ahrens * continue to not hash it. (The 112486ae710SMatthew Ahrens * zn_key_*_numints includes the terminating 113486ae710SMatthew Ahrens * null for non-binary keys.) 114486ae710SMatthew Ahrens */ 115bf26014cSMatthew Ahrens int len = zn->zn_key_norm_numints - 1; 116486ae710SMatthew Ahrens 117486ae710SMatthew Ahrens ASSERT(zn->zn_key_intlen == 1); 118bf26014cSMatthew Ahrens for (int i = 0; i < len; cp++, i++) { 119486ae710SMatthew Ahrens h = (h >> 8) ^ 120486ae710SMatthew Ahrens zfs_crc64_table[(h ^ *cp) & 0xFF]; 121486ae710SMatthew Ahrens } 122486ae710SMatthew Ahrens } 123b24ab676SJeff Bonwick } 124da6c28aaSamw /* 125b24ab676SJeff Bonwick * Don't use all 64 bits, since we need some in the cookie for 126b24ab676SJeff Bonwick * the collision differentiator. We MUST use the high bits, 127b24ab676SJeff Bonwick * since those are the ones that we first pay attention to when 128da6c28aaSamw * chosing the bucket. 129da6c28aaSamw */ 130b24ab676SJeff Bonwick h &= ~((1ULL << (64 - zap_hashbits(zap))) - 1); 131da6c28aaSamw 132b24ab676SJeff Bonwick return (h); 133da6c28aaSamw } 134da6c28aaSamw 135da6c28aaSamw static int 1361c17160aSKevin Crowe zap_normalize(zap_t *zap, const char *name, char *namenorm, int normflags) 137da6c28aaSamw { 138b24ab676SJeff Bonwick ASSERT(!(zap_getflags(zap) & ZAP_FLAG_UINT64_KEY)); 139b24ab676SJeff Bonwick 140bf26014cSMatthew Ahrens size_t inlen = strlen(name) + 1; 141bf26014cSMatthew Ahrens size_t outlen = ZAP_MAXNAMELEN; 142da6c28aaSamw 143bf26014cSMatthew Ahrens int err = 0; 144da6c28aaSamw (void) u8_textprep_str((char *)name, &inlen, namenorm, &outlen, 1451c17160aSKevin Crowe normflags | U8_TEXTPREP_IGNORE_NULL | U8_TEXTPREP_IGNORE_INVALID, 1461c17160aSKevin Crowe U8_UNICODE_LATEST, &err); 147da6c28aaSamw 148da6c28aaSamw return (err); 149da6c28aaSamw } 150da6c28aaSamw 151da6c28aaSamw boolean_t 152da6c28aaSamw zap_match(zap_name_t *zn, const char *matchname) 153da6c28aaSamw { 154b24ab676SJeff Bonwick ASSERT(!(zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY)); 155b24ab676SJeff Bonwick 1561c17160aSKevin Crowe if (zn->zn_matchtype & MT_NORMALIZE) { 157da6c28aaSamw char norm[ZAP_MAXNAMELEN]; 158da6c28aaSamw 1591c17160aSKevin Crowe if (zap_normalize(zn->zn_zap, matchname, norm, 1601c17160aSKevin Crowe zn->zn_normflags) != 0) 161da6c28aaSamw return (B_FALSE); 162da6c28aaSamw 163b24ab676SJeff Bonwick return (strcmp(zn->zn_key_norm, norm) == 0); 164da6c28aaSamw } else { 165b24ab676SJeff Bonwick return (strcmp(zn->zn_key_orig, matchname) == 0); 166da6c28aaSamw } 167da6c28aaSamw } 168da6c28aaSamw 169da6c28aaSamw void 170da6c28aaSamw zap_name_free(zap_name_t *zn) 171da6c28aaSamw { 172da6c28aaSamw kmem_free(zn, sizeof (zap_name_t)); 173da6c28aaSamw } 174da6c28aaSamw 175da6c28aaSamw zap_name_t * 176b24ab676SJeff Bonwick zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt) 177da6c28aaSamw { 178da6c28aaSamw zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP); 179da6c28aaSamw 180da6c28aaSamw zn->zn_zap = zap; 181b24ab676SJeff Bonwick zn->zn_key_intlen = sizeof (*key); 182b24ab676SJeff Bonwick zn->zn_key_orig = key; 183486ae710SMatthew Ahrens zn->zn_key_orig_numints = strlen(zn->zn_key_orig) + 1; 184da6c28aaSamw zn->zn_matchtype = mt; 1851c17160aSKevin Crowe zn->zn_normflags = zap->zap_normflags; 1861c17160aSKevin Crowe 1871c17160aSKevin Crowe /* 1881c17160aSKevin Crowe * If we're dealing with a case sensitive lookup on a mixed or 1891c17160aSKevin Crowe * insensitive fs, remove U8_TEXTPREP_TOUPPER or the lookup 1901c17160aSKevin Crowe * will fold case to all caps overriding the lookup request. 1911c17160aSKevin Crowe */ 1921c17160aSKevin Crowe if (mt & MT_MATCH_CASE) 1931c17160aSKevin Crowe zn->zn_normflags &= ~U8_TEXTPREP_TOUPPER; 1941c17160aSKevin Crowe 195da6c28aaSamw if (zap->zap_normflags) { 1961c17160aSKevin Crowe /* 1971c17160aSKevin Crowe * We *must* use zap_normflags because this normalization is 1981c17160aSKevin Crowe * what the hash is computed from. 1991c17160aSKevin Crowe */ 2001c17160aSKevin Crowe if (zap_normalize(zap, key, zn->zn_normbuf, 2011c17160aSKevin Crowe zap->zap_normflags) != 0) { 202da6c28aaSamw zap_name_free(zn); 203da6c28aaSamw return (NULL); 204da6c28aaSamw } 205b24ab676SJeff Bonwick zn->zn_key_norm = zn->zn_normbuf; 206486ae710SMatthew Ahrens zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1; 207da6c28aaSamw } else { 2081c17160aSKevin Crowe if (mt != 0) { 209da6c28aaSamw zap_name_free(zn); 210da6c28aaSamw return (NULL); 211da6c28aaSamw } 212b24ab676SJeff Bonwick zn->zn_key_norm = zn->zn_key_orig; 213486ae710SMatthew Ahrens zn->zn_key_norm_numints = zn->zn_key_orig_numints; 214da6c28aaSamw } 215da6c28aaSamw 216b24ab676SJeff Bonwick zn->zn_hash = zap_hash(zn); 2171c17160aSKevin Crowe 2181c17160aSKevin Crowe if (zap->zap_normflags != zn->zn_normflags) { 2191c17160aSKevin Crowe /* 2201c17160aSKevin Crowe * We *must* use zn_normflags because this normalization is 2211c17160aSKevin Crowe * what the matching is based on. (Not the hash!) 2221c17160aSKevin Crowe */ 2231c17160aSKevin Crowe if (zap_normalize(zap, key, zn->zn_normbuf, 2241c17160aSKevin Crowe zn->zn_normflags) != 0) { 2251c17160aSKevin Crowe zap_name_free(zn); 2261c17160aSKevin Crowe return (NULL); 2271c17160aSKevin Crowe } 2281c17160aSKevin Crowe zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1; 2291c17160aSKevin Crowe } 2301c17160aSKevin Crowe 231b24ab676SJeff Bonwick return (zn); 232b24ab676SJeff Bonwick } 233b24ab676SJeff Bonwick 234b24ab676SJeff Bonwick zap_name_t * 235b24ab676SJeff Bonwick zap_name_alloc_uint64(zap_t *zap, const uint64_t *key, int numints) 236b24ab676SJeff Bonwick { 237b24ab676SJeff Bonwick zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP); 238b24ab676SJeff Bonwick 239b24ab676SJeff Bonwick ASSERT(zap->zap_normflags == 0); 240b24ab676SJeff Bonwick zn->zn_zap = zap; 241b24ab676SJeff Bonwick zn->zn_key_intlen = sizeof (*key); 242b24ab676SJeff Bonwick zn->zn_key_orig = zn->zn_key_norm = key; 243486ae710SMatthew Ahrens zn->zn_key_orig_numints = zn->zn_key_norm_numints = numints; 2441c17160aSKevin Crowe zn->zn_matchtype = 0; 245b24ab676SJeff Bonwick 246b24ab676SJeff Bonwick zn->zn_hash = zap_hash(zn); 247da6c28aaSamw return (zn); 248da6c28aaSamw } 249da6c28aaSamw 250fa9e4066Sahrens static void 251fa9e4066Sahrens mzap_byteswap(mzap_phys_t *buf, size_t size) 252fa9e4066Sahrens { 253fa9e4066Sahrens buf->mz_block_type = BSWAP_64(buf->mz_block_type); 254fa9e4066Sahrens buf->mz_salt = BSWAP_64(buf->mz_salt); 255ab04eb8eStimh buf->mz_normflags = BSWAP_64(buf->mz_normflags); 256bf26014cSMatthew Ahrens int max = (size / MZAP_ENT_LEN) - 1; 257bf26014cSMatthew Ahrens for (int i = 0; i < max; i++) { 258fa9e4066Sahrens buf->mz_chunk[i].mze_value = 259fa9e4066Sahrens BSWAP_64(buf->mz_chunk[i].mze_value); 260fa9e4066Sahrens buf->mz_chunk[i].mze_cd = 261fa9e4066Sahrens BSWAP_32(buf->mz_chunk[i].mze_cd); 262fa9e4066Sahrens } 263fa9e4066Sahrens } 264fa9e4066Sahrens 265fa9e4066Sahrens void 266fa9e4066Sahrens zap_byteswap(void *buf, size_t size) 267fa9e4066Sahrens { 268bf26014cSMatthew Ahrens uint64_t block_type = *(uint64_t *)buf; 269fa9e4066Sahrens 2705ad82045Snd if (block_type == ZBT_MICRO || block_type == BSWAP_64(ZBT_MICRO)) { 271fa9e4066Sahrens /* ASSERT(magic == ZAP_LEAF_MAGIC); */ 272fa9e4066Sahrens mzap_byteswap(buf, size); 2735ad82045Snd } else { 274fa9e4066Sahrens fzap_byteswap(buf, size); 275fa9e4066Sahrens } 276fa9e4066Sahrens } 277fa9e4066Sahrens 278fa9e4066Sahrens static int 279fa9e4066Sahrens mze_compare(const void *arg1, const void *arg2) 280fa9e4066Sahrens { 281fa9e4066Sahrens const mzap_ent_t *mze1 = arg1; 282fa9e4066Sahrens const mzap_ent_t *mze2 = arg2; 283fa9e4066Sahrens 284*c4ab0d3fSGvozden Neskovic int cmp = AVL_CMP(mze1->mze_hash, mze2->mze_hash); 285*c4ab0d3fSGvozden Neskovic if (likely(cmp)) 286*c4ab0d3fSGvozden Neskovic return (cmp); 287*c4ab0d3fSGvozden Neskovic 288*c4ab0d3fSGvozden Neskovic return (AVL_CMP(mze1->mze_cd, mze2->mze_cd)); 289fa9e4066Sahrens } 290fa9e4066Sahrens 291fa9e4066Sahrens static void 2923f9d6ad7SLin Ling mze_insert(zap_t *zap, int chunkid, uint64_t hash) 293fa9e4066Sahrens { 294fa9e4066Sahrens ASSERT(zap->zap_ismicro); 295fa9e4066Sahrens ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 296fa9e4066Sahrens 297bf26014cSMatthew Ahrens mzap_ent_t *mze = kmem_alloc(sizeof (mzap_ent_t), KM_SLEEP); 298fa9e4066Sahrens mze->mze_chunkid = chunkid; 299fa9e4066Sahrens mze->mze_hash = hash; 3003f9d6ad7SLin Ling mze->mze_cd = MZE_PHYS(zap, mze)->mze_cd; 3013f9d6ad7SLin Ling ASSERT(MZE_PHYS(zap, mze)->mze_name[0] != 0); 302fa9e4066Sahrens avl_add(&zap->zap_m.zap_avl, mze); 303fa9e4066Sahrens } 304fa9e4066Sahrens 305fa9e4066Sahrens static mzap_ent_t * 306da6c28aaSamw mze_find(zap_name_t *zn) 307fa9e4066Sahrens { 308fa9e4066Sahrens mzap_ent_t mze_tofind; 309fa9e4066Sahrens mzap_ent_t *mze; 310fa9e4066Sahrens avl_index_t idx; 311da6c28aaSamw avl_tree_t *avl = &zn->zn_zap->zap_m.zap_avl; 312fa9e4066Sahrens 313da6c28aaSamw ASSERT(zn->zn_zap->zap_ismicro); 314da6c28aaSamw ASSERT(RW_LOCK_HELD(&zn->zn_zap->zap_rwlock)); 315fa9e4066Sahrens 316da6c28aaSamw mze_tofind.mze_hash = zn->zn_hash; 3173f9d6ad7SLin Ling mze_tofind.mze_cd = 0; 318fa9e4066Sahrens 319fa9e4066Sahrens mze = avl_find(avl, &mze_tofind, &idx); 320fa9e4066Sahrens if (mze == NULL) 321fa9e4066Sahrens mze = avl_nearest(avl, idx, AVL_AFTER); 322da6c28aaSamw for (; mze && mze->mze_hash == zn->zn_hash; mze = AVL_NEXT(avl, mze)) { 3233f9d6ad7SLin Ling ASSERT3U(mze->mze_cd, ==, MZE_PHYS(zn->zn_zap, mze)->mze_cd); 3243f9d6ad7SLin Ling if (zap_match(zn, MZE_PHYS(zn->zn_zap, mze)->mze_name)) 325fa9e4066Sahrens return (mze); 326fa9e4066Sahrens } 3271c17160aSKevin Crowe 328fa9e4066Sahrens return (NULL); 329fa9e4066Sahrens } 330fa9e4066Sahrens 331fa9e4066Sahrens static uint32_t 332fa9e4066Sahrens mze_find_unused_cd(zap_t *zap, uint64_t hash) 333fa9e4066Sahrens { 334fa9e4066Sahrens mzap_ent_t mze_tofind; 335fa9e4066Sahrens avl_index_t idx; 336fa9e4066Sahrens avl_tree_t *avl = &zap->zap_m.zap_avl; 337fa9e4066Sahrens 338fa9e4066Sahrens ASSERT(zap->zap_ismicro); 339fa9e4066Sahrens ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); 340fa9e4066Sahrens 341fa9e4066Sahrens mze_tofind.mze_hash = hash; 3423f9d6ad7SLin Ling mze_tofind.mze_cd = 0; 343fa9e4066Sahrens 344bf26014cSMatthew Ahrens uint32_t cd = 0; 345bf26014cSMatthew Ahrens for (mzap_ent_t *mze = avl_find(avl, &mze_tofind, &idx); 346fa9e4066Sahrens mze && mze->mze_hash == hash; mze = AVL_NEXT(avl, mze)) { 3473f9d6ad7SLin Ling if (mze->mze_cd != cd) 348fa9e4066Sahrens break; 349fa9e4066Sahrens cd++; 350fa9e4066Sahrens } 351fa9e4066Sahrens 352fa9e4066Sahrens return (cd); 353fa9e4066Sahrens } 354fa9e4066Sahrens 355fa9e4066Sahrens static void 356fa9e4066Sahrens mze_remove(zap_t *zap, mzap_ent_t *mze) 357fa9e4066Sahrens { 358fa9e4066Sahrens ASSERT(zap->zap_ismicro); 359fa9e4066Sahrens ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 360fa9e4066Sahrens 361fa9e4066Sahrens avl_remove(&zap->zap_m.zap_avl, mze); 362fa9e4066Sahrens kmem_free(mze, sizeof (mzap_ent_t)); 363fa9e4066Sahrens } 364fa9e4066Sahrens 365fa9e4066Sahrens static void 366fa9e4066Sahrens mze_destroy(zap_t *zap) 367fa9e4066Sahrens { 368fa9e4066Sahrens mzap_ent_t *mze; 369fa9e4066Sahrens void *avlcookie = NULL; 370fa9e4066Sahrens 371fa9e4066Sahrens while (mze = avl_destroy_nodes(&zap->zap_m.zap_avl, &avlcookie)) 372fa9e4066Sahrens kmem_free(mze, sizeof (mzap_ent_t)); 373fa9e4066Sahrens avl_destroy(&zap->zap_m.zap_avl); 374fa9e4066Sahrens } 375fa9e4066Sahrens 376fa9e4066Sahrens static zap_t * 377fa9e4066Sahrens mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) 378fa9e4066Sahrens { 379fa9e4066Sahrens zap_t *winner; 38002525cd0SChunwei Chen uint64_t *zap_hdr = (uint64_t *)db->db_data; 38102525cd0SChunwei Chen uint64_t zap_block_type = zap_hdr[0]; 38202525cd0SChunwei Chen uint64_t zap_magic = zap_hdr[1]; 383fa9e4066Sahrens 384fa9e4066Sahrens ASSERT3U(MZAP_ENT_LEN, ==, sizeof (mzap_ent_phys_t)); 385fa9e4066Sahrens 386bf26014cSMatthew Ahrens zap_t *zap = kmem_zalloc(sizeof (zap_t), KM_SLEEP); 387fa9e4066Sahrens rw_init(&zap->zap_rwlock, 0, 0, 0); 388fa9e4066Sahrens rw_enter(&zap->zap_rwlock, RW_WRITER); 389fa9e4066Sahrens zap->zap_objset = os; 390fa9e4066Sahrens zap->zap_object = obj; 391fa9e4066Sahrens zap->zap_dbuf = db; 392fa9e4066Sahrens 39302525cd0SChunwei Chen if (zap_block_type != ZBT_MICRO) { 394fa9e4066Sahrens mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0); 395bf16b11eSMatthew Ahrens zap->zap_f.zap_block_shift = highbit64(db->db_size) - 1; 39602525cd0SChunwei Chen if (zap_block_type != ZBT_HEADER || zap_magic != ZAP_MAGIC) { 39702525cd0SChunwei Chen winner = NULL; /* No actual winner here... */ 39802525cd0SChunwei Chen goto handle_winner; 39902525cd0SChunwei Chen } 400fa9e4066Sahrens } else { 401fa9e4066Sahrens zap->zap_ismicro = TRUE; 402fa9e4066Sahrens } 403fa9e4066Sahrens 404fa9e4066Sahrens /* 405fa9e4066Sahrens * Make sure that zap_ismicro is set before we let others see 406fa9e4066Sahrens * it, because zap_lockdir() checks zap_ismicro without the lock 407fa9e4066Sahrens * held. 408fa9e4066Sahrens */ 40940510e8eSJosef 'Jeff' Sipek dmu_buf_init_user(&zap->zap_dbu, zap_evict_sync, NULL, &zap->zap_dbuf); 410bc9014e6SJustin Gibbs winner = dmu_buf_set_user(db, &zap->zap_dbu); 411fa9e4066Sahrens 41202525cd0SChunwei Chen if (winner != NULL) 41302525cd0SChunwei Chen goto handle_winner; 414fa9e4066Sahrens 415fa9e4066Sahrens if (zap->zap_ismicro) { 416c1379625SJustin T. Gibbs zap->zap_salt = zap_m_phys(zap)->mz_salt; 417c1379625SJustin T. Gibbs zap->zap_normflags = zap_m_phys(zap)->mz_normflags; 418fa9e4066Sahrens zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1; 419fa9e4066Sahrens avl_create(&zap->zap_m.zap_avl, mze_compare, 420fa9e4066Sahrens sizeof (mzap_ent_t), offsetof(mzap_ent_t, mze_node)); 421fa9e4066Sahrens 422bf26014cSMatthew Ahrens for (int i = 0; i < zap->zap_m.zap_num_chunks; i++) { 423fa9e4066Sahrens mzap_ent_phys_t *mze = 424c1379625SJustin T. Gibbs &zap_m_phys(zap)->mz_chunk[i]; 425fa9e4066Sahrens if (mze->mze_name[0]) { 426da6c28aaSamw zap_name_t *zn; 427da6c28aaSamw 428fa9e4066Sahrens zap->zap_m.zap_num_entries++; 4291c17160aSKevin Crowe zn = zap_name_alloc(zap, mze->mze_name, 0); 4303f9d6ad7SLin Ling mze_insert(zap, i, zn->zn_hash); 431da6c28aaSamw zap_name_free(zn); 432fa9e4066Sahrens } 433fa9e4066Sahrens } 434fa9e4066Sahrens } else { 435c1379625SJustin T. Gibbs zap->zap_salt = zap_f_phys(zap)->zap_salt; 436c1379625SJustin T. Gibbs zap->zap_normflags = zap_f_phys(zap)->zap_normflags; 437f65e61c0Sahrens 438f65e61c0Sahrens ASSERT3U(sizeof (struct zap_leaf_header), ==, 439f65e61c0Sahrens 2*ZAP_LEAF_CHUNKSIZE); 440f65e61c0Sahrens 441f65e61c0Sahrens /* 442f65e61c0Sahrens * The embedded pointer table should not overlap the 443f65e61c0Sahrens * other members. 444f65e61c0Sahrens */ 445f65e61c0Sahrens ASSERT3P(&ZAP_EMBEDDED_PTRTBL_ENT(zap, 0), >, 446c1379625SJustin T. Gibbs &zap_f_phys(zap)->zap_salt); 447f65e61c0Sahrens 448f65e61c0Sahrens /* 449f65e61c0Sahrens * The embedded pointer table should end at the end of 450f65e61c0Sahrens * the block 451f65e61c0Sahrens */ 452f65e61c0Sahrens ASSERT3U((uintptr_t)&ZAP_EMBEDDED_PTRTBL_ENT(zap, 453f65e61c0Sahrens 1<<ZAP_EMBEDDED_PTRTBL_SHIFT(zap)) - 454c1379625SJustin T. Gibbs (uintptr_t)zap_f_phys(zap), ==, 455f65e61c0Sahrens zap->zap_dbuf->db_size); 456fa9e4066Sahrens } 457fa9e4066Sahrens rw_exit(&zap->zap_rwlock); 458fa9e4066Sahrens return (zap); 45902525cd0SChunwei Chen 46002525cd0SChunwei Chen handle_winner: 46102525cd0SChunwei Chen rw_exit(&zap->zap_rwlock); 46202525cd0SChunwei Chen rw_destroy(&zap->zap_rwlock); 46302525cd0SChunwei Chen if (!zap->zap_ismicro) 46402525cd0SChunwei Chen mutex_destroy(&zap->zap_f.zap_num_entries_mtx); 46502525cd0SChunwei Chen kmem_free(zap, sizeof (zap_t)); 46602525cd0SChunwei Chen return (winner); 467fa9e4066Sahrens } 468fa9e4066Sahrens 469bf26014cSMatthew Ahrens /* 470bf26014cSMatthew Ahrens * This routine "consumes" the caller's hold on the dbuf, which must 471bf26014cSMatthew Ahrens * have the specified tag. 472bf26014cSMatthew Ahrens */ 473ae972795SMatthew Ahrens static int 474ae972795SMatthew Ahrens zap_lockdir_impl(dmu_buf_t *db, void *tag, dmu_tx_t *tx, 475c5f9e431Sahrens krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp) 476fa9e4066Sahrens { 477ae972795SMatthew Ahrens ASSERT0(db->db_offset); 478ae972795SMatthew Ahrens objset_t *os = dmu_buf_get_objset(db); 479ae972795SMatthew Ahrens uint64_t obj = db->db_object; 480fa9e4066Sahrens 481ae972795SMatthew Ahrens *zapp = NULL; 482fa9e4066Sahrens 483bf26014cSMatthew Ahrens zap_t *zap = dmu_buf_get_user(db); 48402525cd0SChunwei Chen if (zap == NULL) { 485fa9e4066Sahrens zap = mzap_open(os, obj, db); 48602525cd0SChunwei Chen if (zap == NULL) { 48702525cd0SChunwei Chen /* 48802525cd0SChunwei Chen * mzap_open() didn't like what it saw on-disk. 48902525cd0SChunwei Chen * Check for corruption! 49002525cd0SChunwei Chen */ 49102525cd0SChunwei Chen return (SET_ERROR(EIO)); 49202525cd0SChunwei Chen } 49302525cd0SChunwei Chen } 494fa9e4066Sahrens 495fa9e4066Sahrens /* 496fa9e4066Sahrens * We're checking zap_ismicro without the lock held, in order to 497fa9e4066Sahrens * tell what type of lock we want. Once we have some sort of 498fa9e4066Sahrens * lock, see if it really is the right type. In practice this 499fa9e4066Sahrens * can only be different if it was upgraded from micro to fat, 500fa9e4066Sahrens * and micro wanted WRITER but fat only needs READER. 501fa9e4066Sahrens */ 502bf26014cSMatthew Ahrens krw_t lt = (!zap->zap_ismicro && fatreader) ? RW_READER : lti; 503fa9e4066Sahrens rw_enter(&zap->zap_rwlock, lt); 504fa9e4066Sahrens if (lt != ((!zap->zap_ismicro && fatreader) ? RW_READER : lti)) { 505fa9e4066Sahrens /* it was upgraded, now we only need reader */ 506fa9e4066Sahrens ASSERT(lt == RW_WRITER); 507fa9e4066Sahrens ASSERT(RW_READER == 508fa9e4066Sahrens (!zap->zap_ismicro && fatreader) ? RW_READER : lti); 509fa9e4066Sahrens rw_downgrade(&zap->zap_rwlock); 510fa9e4066Sahrens lt = RW_READER; 511fa9e4066Sahrens } 512fa9e4066Sahrens 513fa9e4066Sahrens zap->zap_objset = os; 514fa9e4066Sahrens 515fa9e4066Sahrens if (lt == RW_WRITER) 516fa9e4066Sahrens dmu_buf_will_dirty(db, tx); 517fa9e4066Sahrens 518fa9e4066Sahrens ASSERT3P(zap->zap_dbuf, ==, db); 519fa9e4066Sahrens 520fa9e4066Sahrens ASSERT(!zap->zap_ismicro || 521fa9e4066Sahrens zap->zap_m.zap_num_entries <= zap->zap_m.zap_num_chunks); 522c5f9e431Sahrens if (zap->zap_ismicro && tx && adding && 523fa9e4066Sahrens zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) { 524fa9e4066Sahrens uint64_t newsz = db->db_size + SPA_MINBLOCKSIZE; 525fa9e4066Sahrens if (newsz > MZAP_MAX_BLKSZ) { 526fa9e4066Sahrens dprintf("upgrading obj %llu: num_entries=%u\n", 527fa9e4066Sahrens obj, zap->zap_m.zap_num_entries); 528fa9e4066Sahrens *zapp = zap; 529ae972795SMatthew Ahrens int err = mzap_upgrade(zapp, tag, tx, 0); 530ae972795SMatthew Ahrens if (err != 0) 531ae972795SMatthew Ahrens rw_exit(&zap->zap_rwlock); 532ae972795SMatthew Ahrens return (err); 533fa9e4066Sahrens } 534ae972795SMatthew Ahrens VERIFY0(dmu_object_set_blocksize(os, obj, newsz, 0, tx)); 535fa9e4066Sahrens zap->zap_m.zap_num_chunks = 536fa9e4066Sahrens db->db_size / MZAP_ENT_LEN - 1; 537fa9e4066Sahrens } 538fa9e4066Sahrens 539fa9e4066Sahrens *zapp = zap; 540fa9e4066Sahrens return (0); 541fa9e4066Sahrens } 542fa9e4066Sahrens 54379d72832SMatthew Ahrens static int 54479d72832SMatthew Ahrens zap_lockdir_by_dnode(dnode_t *dn, dmu_tx_t *tx, 54579d72832SMatthew Ahrens krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp) 54679d72832SMatthew Ahrens { 54779d72832SMatthew Ahrens dmu_buf_t *db; 54879d72832SMatthew Ahrens 549bf26014cSMatthew Ahrens int err = dmu_buf_hold_by_dnode(dn, 0, tag, &db, DMU_READ_NO_PREFETCH); 55079d72832SMatthew Ahrens if (err != 0) { 55179d72832SMatthew Ahrens return (err); 55279d72832SMatthew Ahrens } 553bf26014cSMatthew Ahrens #ifdef ZFS_DEBUG 554bf26014cSMatthew Ahrens { 555bf26014cSMatthew Ahrens dmu_object_info_t doi; 556bf26014cSMatthew Ahrens dmu_object_info_from_db(db, &doi); 557bf26014cSMatthew Ahrens ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP); 558bf26014cSMatthew Ahrens } 559bf26014cSMatthew Ahrens #endif 560bf26014cSMatthew Ahrens 56179d72832SMatthew Ahrens err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp); 56279d72832SMatthew Ahrens if (err != 0) { 56379d72832SMatthew Ahrens dmu_buf_rele(db, tag); 56479d72832SMatthew Ahrens } 56579d72832SMatthew Ahrens return (err); 56679d72832SMatthew Ahrens } 56779d72832SMatthew Ahrens 568ae972795SMatthew Ahrens int 569ae972795SMatthew Ahrens zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx, 570ae972795SMatthew Ahrens krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp) 571ae972795SMatthew Ahrens { 572ae972795SMatthew Ahrens dmu_buf_t *db; 573ae972795SMatthew Ahrens 574bf26014cSMatthew Ahrens int err = dmu_buf_hold(os, obj, 0, tag, &db, DMU_READ_NO_PREFETCH); 575ae972795SMatthew Ahrens if (err != 0) 576ae972795SMatthew Ahrens return (err); 577bf26014cSMatthew Ahrens #ifdef ZFS_DEBUG 578bf26014cSMatthew Ahrens { 579bf26014cSMatthew Ahrens dmu_object_info_t doi; 580bf26014cSMatthew Ahrens dmu_object_info_from_db(db, &doi); 581bf26014cSMatthew Ahrens ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP); 582bf26014cSMatthew Ahrens } 583bf26014cSMatthew Ahrens #endif 584ae972795SMatthew Ahrens err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp); 585ae972795SMatthew Ahrens if (err != 0) 586ae972795SMatthew Ahrens dmu_buf_rele(db, tag); 587ae972795SMatthew Ahrens return (err); 588ae972795SMatthew Ahrens } 589ae972795SMatthew Ahrens 590fa9e4066Sahrens void 591ae972795SMatthew Ahrens zap_unlockdir(zap_t *zap, void *tag) 592fa9e4066Sahrens { 593fa9e4066Sahrens rw_exit(&zap->zap_rwlock); 594ae972795SMatthew Ahrens dmu_buf_rele(zap->zap_dbuf, tag); 595fa9e4066Sahrens } 596fa9e4066Sahrens 597ad860c82Sbonwick static int 598ae972795SMatthew Ahrens mzap_upgrade(zap_t **zapp, void *tag, dmu_tx_t *tx, zap_flags_t flags) 599fa9e4066Sahrens { 600b24ab676SJeff Bonwick int err = 0; 601ad860c82Sbonwick zap_t *zap = *zapp; 602fa9e4066Sahrens 603fa9e4066Sahrens ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 604fa9e4066Sahrens 605bf26014cSMatthew Ahrens int sz = zap->zap_dbuf->db_size; 606bf26014cSMatthew Ahrens mzap_phys_t *mzp = zio_buf_alloc(sz); 607fa9e4066Sahrens bcopy(zap->zap_dbuf->db_data, mzp, sz); 608bf26014cSMatthew Ahrens int nchunks = zap->zap_m.zap_num_chunks; 609fa9e4066Sahrens 610b24ab676SJeff Bonwick if (!flags) { 611b24ab676SJeff Bonwick err = dmu_object_set_blocksize(zap->zap_objset, zap->zap_object, 612b24ab676SJeff Bonwick 1ULL << fzap_default_block_shift, 0, tx); 613bf26014cSMatthew Ahrens if (err != 0) { 614be3e2ab9SBrian Behlendorf zio_buf_free(mzp, sz); 615b24ab676SJeff Bonwick return (err); 616b24ab676SJeff Bonwick } 617ad860c82Sbonwick } 618fa9e4066Sahrens 619fa9e4066Sahrens dprintf("upgrading obj=%llu with %u chunks\n", 620fa9e4066Sahrens zap->zap_object, nchunks); 621da6c28aaSamw /* XXX destroy the avl later, so we can use the stored hash value */ 622fa9e4066Sahrens mze_destroy(zap); 623fa9e4066Sahrens 624b24ab676SJeff Bonwick fzap_upgrade(zap, tx, flags); 625fa9e4066Sahrens 626bf26014cSMatthew Ahrens for (int i = 0; i < nchunks; i++) { 627fa9e4066Sahrens mzap_ent_phys_t *mze = &mzp->mz_chunk[i]; 628fa9e4066Sahrens if (mze->mze_name[0] == 0) 629fa9e4066Sahrens continue; 630fa9e4066Sahrens dprintf("adding %s=%llu\n", 631fa9e4066Sahrens mze->mze_name, mze->mze_value); 632bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc(zap, mze->mze_name, 0); 633ae972795SMatthew Ahrens err = fzap_add_cd(zn, 8, 1, &mze->mze_value, mze->mze_cd, 634ae972795SMatthew Ahrens tag, tx); 635ad860c82Sbonwick zap = zn->zn_zap; /* fzap_add_cd() may change zap */ 636da6c28aaSamw zap_name_free(zn); 637bf26014cSMatthew Ahrens if (err != 0) 638ad860c82Sbonwick break; 639fa9e4066Sahrens } 640be3e2ab9SBrian Behlendorf zio_buf_free(mzp, sz); 641ad860c82Sbonwick *zapp = zap; 642ad860c82Sbonwick return (err); 643fa9e4066Sahrens } 644fa9e4066Sahrens 6451c17160aSKevin Crowe /* 6461c17160aSKevin Crowe * The "normflags" determine the behavior of the matchtype_t which is 6471c17160aSKevin Crowe * passed to zap_lookup_norm(). Names which have the same normalized 6481c17160aSKevin Crowe * version will be stored with the same hash value, and therefore we can 6491c17160aSKevin Crowe * perform normalization-insensitive lookups. We can be Unicode form- 6501c17160aSKevin Crowe * insensitive and/or case-insensitive. The following flags are valid for 6511c17160aSKevin Crowe * "normflags": 6521c17160aSKevin Crowe * 6531c17160aSKevin Crowe * U8_TEXTPREP_NFC 6541c17160aSKevin Crowe * U8_TEXTPREP_NFD 6551c17160aSKevin Crowe * U8_TEXTPREP_NFKC 6561c17160aSKevin Crowe * U8_TEXTPREP_NFKD 6571c17160aSKevin Crowe * U8_TEXTPREP_TOUPPER 6581c17160aSKevin Crowe * 6591c17160aSKevin Crowe * The *_NF* (Normalization Form) flags are mutually exclusive; at most one 6601c17160aSKevin Crowe * of them may be supplied. 6611c17160aSKevin Crowe */ 6622acef22dSMatthew Ahrens void 663b24ab676SJeff Bonwick mzap_create_impl(objset_t *os, uint64_t obj, int normflags, zap_flags_t flags, 664b24ab676SJeff Bonwick dmu_tx_t *tx) 665fa9e4066Sahrens { 666fa9e4066Sahrens dmu_buf_t *db; 667fa9e4066Sahrens 668bf26014cSMatthew Ahrens VERIFY0(dmu_buf_hold(os, obj, 0, FTAG, &db, DMU_READ_NO_PREFETCH)); 669fa9e4066Sahrens 670fa9e4066Sahrens dmu_buf_will_dirty(db, tx); 671bf26014cSMatthew Ahrens mzap_phys_t *zp = db->db_data; 672fa9e4066Sahrens zp->mz_block_type = ZBT_MICRO; 673fa9e4066Sahrens zp->mz_salt = ((uintptr_t)db ^ (uintptr_t)tx ^ (obj << 1)) | 1ULL; 674da6c28aaSamw zp->mz_normflags = normflags; 675b24ab676SJeff Bonwick 676b24ab676SJeff Bonwick if (flags != 0) { 677b24ab676SJeff Bonwick zap_t *zap; 678b24ab676SJeff Bonwick /* Only fat zap supports flags; upgrade immediately. */ 679bf26014cSMatthew Ahrens VERIFY0(zap_lockdir_impl(db, FTAG, tx, RW_WRITER, 680bf26014cSMatthew Ahrens B_FALSE, B_FALSE, &zap)); 681bf26014cSMatthew Ahrens VERIFY0(mzap_upgrade(&zap, FTAG, tx, flags)); 682ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 683bf26014cSMatthew Ahrens } else { 684bf26014cSMatthew Ahrens dmu_buf_rele(db, FTAG); 685b24ab676SJeff Bonwick } 686fa9e4066Sahrens } 687fa9e4066Sahrens 688fa9e4066Sahrens int 689fa9e4066Sahrens zap_create_claim(objset_t *os, uint64_t obj, dmu_object_type_t ot, 690fa9e4066Sahrens dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 691da6c28aaSamw { 69254811da5SToomas Soome return (zap_create_claim_dnsize(os, obj, ot, bonustype, bonuslen, 69354811da5SToomas Soome 0, tx)); 69454811da5SToomas Soome } 69554811da5SToomas Soome 69654811da5SToomas Soome int 69754811da5SToomas Soome zap_create_claim_dnsize(objset_t *os, uint64_t obj, dmu_object_type_t ot, 69854811da5SToomas Soome dmu_object_type_t bonustype, int bonuslen, int dnodesize, dmu_tx_t *tx) 69954811da5SToomas Soome { 70054811da5SToomas Soome return (zap_create_claim_norm_dnsize(os, obj, 70154811da5SToomas Soome 0, ot, bonustype, bonuslen, dnodesize, tx)); 702da6c28aaSamw } 703da6c28aaSamw 704da6c28aaSamw int 705da6c28aaSamw zap_create_claim_norm(objset_t *os, uint64_t obj, int normflags, 706da6c28aaSamw dmu_object_type_t ot, 707da6c28aaSamw dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 708fa9e4066Sahrens { 70954811da5SToomas Soome return (zap_create_claim_norm_dnsize(os, obj, normflags, ot, bonustype, 71054811da5SToomas Soome bonuslen, 0, tx)); 71154811da5SToomas Soome } 71254811da5SToomas Soome 71354811da5SToomas Soome int 71454811da5SToomas Soome zap_create_claim_norm_dnsize(objset_t *os, uint64_t obj, int normflags, 71554811da5SToomas Soome dmu_object_type_t ot, dmu_object_type_t bonustype, int bonuslen, 71654811da5SToomas Soome int dnodesize, dmu_tx_t *tx) 71754811da5SToomas Soome { 71854811da5SToomas Soome int err; 71954811da5SToomas Soome 72054811da5SToomas Soome err = dmu_object_claim_dnsize(os, obj, ot, 0, bonustype, bonuslen, 72154811da5SToomas Soome dnodesize, tx); 722fa9e4066Sahrens if (err != 0) 723fa9e4066Sahrens return (err); 724b24ab676SJeff Bonwick mzap_create_impl(os, obj, normflags, 0, tx); 725fa9e4066Sahrens return (0); 726fa9e4066Sahrens } 727fa9e4066Sahrens 728fa9e4066Sahrens uint64_t 729fa9e4066Sahrens zap_create(objset_t *os, dmu_object_type_t ot, 730fa9e4066Sahrens dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 731da6c28aaSamw { 732da6c28aaSamw return (zap_create_norm(os, 0, ot, bonustype, bonuslen, tx)); 733da6c28aaSamw } 734da6c28aaSamw 73554811da5SToomas Soome uint64_t 73654811da5SToomas Soome zap_create_dnsize(objset_t *os, dmu_object_type_t ot, 73754811da5SToomas Soome dmu_object_type_t bonustype, int bonuslen, int dnodesize, dmu_tx_t *tx) 73854811da5SToomas Soome { 73954811da5SToomas Soome return (zap_create_norm_dnsize(os, 0, ot, bonustype, bonuslen, 74054811da5SToomas Soome dnodesize, tx)); 74154811da5SToomas Soome } 74254811da5SToomas Soome 743da6c28aaSamw uint64_t 744da6c28aaSamw zap_create_norm(objset_t *os, int normflags, dmu_object_type_t ot, 745da6c28aaSamw dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 746fa9e4066Sahrens { 747bf26014cSMatthew Ahrens ASSERT3U(DMU_OT_BYTESWAP(ot), ==, DMU_BSWAP_ZAP); 74854811da5SToomas Soome return (zap_create_norm_dnsize(os, normflags, ot, bonustype, bonuslen, 74954811da5SToomas Soome 0, tx)); 75054811da5SToomas Soome } 75154811da5SToomas Soome 75254811da5SToomas Soome uint64_t 75354811da5SToomas Soome zap_create_norm_dnsize(objset_t *os, int normflags, dmu_object_type_t ot, 75454811da5SToomas Soome dmu_object_type_t bonustype, int bonuslen, int dnodesize, dmu_tx_t *tx) 75554811da5SToomas Soome { 75654811da5SToomas Soome uint64_t obj = dmu_object_alloc_dnsize(os, ot, 0, bonustype, bonuslen, 75754811da5SToomas Soome dnodesize, tx); 758fa9e4066Sahrens 759b24ab676SJeff Bonwick mzap_create_impl(os, obj, normflags, 0, tx); 760b24ab676SJeff Bonwick return (obj); 761b24ab676SJeff Bonwick } 762b24ab676SJeff Bonwick 763b24ab676SJeff Bonwick uint64_t 764b24ab676SJeff Bonwick zap_create_flags(objset_t *os, int normflags, zap_flags_t flags, 765b24ab676SJeff Bonwick dmu_object_type_t ot, int leaf_blockshift, int indirect_blockshift, 766b24ab676SJeff Bonwick dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 767b24ab676SJeff Bonwick { 768bf26014cSMatthew Ahrens ASSERT3U(DMU_OT_BYTESWAP(ot), ==, DMU_BSWAP_ZAP); 76954811da5SToomas Soome return (zap_create_flags_dnsize(os, normflags, flags, ot, 77054811da5SToomas Soome leaf_blockshift, indirect_blockshift, bonustype, bonuslen, 0, tx)); 77154811da5SToomas Soome } 77254811da5SToomas Soome 77354811da5SToomas Soome uint64_t 77454811da5SToomas Soome zap_create_flags_dnsize(objset_t *os, int normflags, zap_flags_t flags, 77554811da5SToomas Soome dmu_object_type_t ot, int leaf_blockshift, int indirect_blockshift, 77654811da5SToomas Soome dmu_object_type_t bonustype, int bonuslen, int dnodesize, dmu_tx_t *tx) 77754811da5SToomas Soome { 77854811da5SToomas Soome uint64_t obj = dmu_object_alloc_dnsize(os, ot, 0, bonustype, bonuslen, 77954811da5SToomas Soome dnodesize, tx); 780b24ab676SJeff Bonwick 781b24ab676SJeff Bonwick ASSERT(leaf_blockshift >= SPA_MINBLOCKSHIFT && 782b5152584SMatthew Ahrens leaf_blockshift <= SPA_OLD_MAXBLOCKSHIFT && 783b24ab676SJeff Bonwick indirect_blockshift >= SPA_MINBLOCKSHIFT && 784b5152584SMatthew Ahrens indirect_blockshift <= SPA_OLD_MAXBLOCKSHIFT); 785b24ab676SJeff Bonwick 786b24ab676SJeff Bonwick VERIFY(dmu_object_set_blocksize(os, obj, 787b24ab676SJeff Bonwick 1ULL << leaf_blockshift, indirect_blockshift, tx) == 0); 788b24ab676SJeff Bonwick 789b24ab676SJeff Bonwick mzap_create_impl(os, obj, normflags, flags, tx); 790fa9e4066Sahrens return (obj); 791fa9e4066Sahrens } 792fa9e4066Sahrens 793fa9e4066Sahrens int 794fa9e4066Sahrens zap_destroy(objset_t *os, uint64_t zapobj, dmu_tx_t *tx) 795fa9e4066Sahrens { 796fa9e4066Sahrens /* 797fa9e4066Sahrens * dmu_object_free will free the object number and free the 798fa9e4066Sahrens * data. Freeing the data will cause our pageout function to be 799fa9e4066Sahrens * called, which will destroy our data (zap_leaf_t's and zap_t). 800fa9e4066Sahrens */ 801fa9e4066Sahrens 802fa9e4066Sahrens return (dmu_object_free(os, zapobj, tx)); 803fa9e4066Sahrens } 804fa9e4066Sahrens 805fa9e4066Sahrens void 80640510e8eSJosef 'Jeff' Sipek zap_evict_sync(void *dbu) 807fa9e4066Sahrens { 808bc9014e6SJustin Gibbs zap_t *zap = dbu; 809fa9e4066Sahrens 810fa9e4066Sahrens rw_destroy(&zap->zap_rwlock); 811fa9e4066Sahrens 812f65e61c0Sahrens if (zap->zap_ismicro) 813fa9e4066Sahrens mze_destroy(zap); 814c25056deSgw else 815c25056deSgw mutex_destroy(&zap->zap_f.zap_num_entries_mtx); 816fa9e4066Sahrens 817fa9e4066Sahrens kmem_free(zap, sizeof (zap_t)); 818fa9e4066Sahrens } 819fa9e4066Sahrens 820fa9e4066Sahrens int 821fa9e4066Sahrens zap_count(objset_t *os, uint64_t zapobj, uint64_t *count) 822fa9e4066Sahrens { 823fa9e4066Sahrens zap_t *zap; 824fa9e4066Sahrens 825bf26014cSMatthew Ahrens int err = 826bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 827bf26014cSMatthew Ahrens if (err != 0) 828fa9e4066Sahrens return (err); 829fa9e4066Sahrens if (!zap->zap_ismicro) { 830fa9e4066Sahrens err = fzap_count(zap, count); 831fa9e4066Sahrens } else { 832fa9e4066Sahrens *count = zap->zap_m.zap_num_entries; 833fa9e4066Sahrens } 834ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 835fa9e4066Sahrens return (err); 836fa9e4066Sahrens } 837fa9e4066Sahrens 838fa9e4066Sahrens /* 839da6c28aaSamw * zn may be NULL; if not specified, it will be computed if needed. 840da6c28aaSamw * See also the comment above zap_entry_normalization_conflict(). 841da6c28aaSamw */ 842da6c28aaSamw static boolean_t 843da6c28aaSamw mzap_normalization_conflict(zap_t *zap, zap_name_t *zn, mzap_ent_t *mze) 844da6c28aaSamw { 845da6c28aaSamw int direction = AVL_BEFORE; 846da6c28aaSamw boolean_t allocdzn = B_FALSE; 847da6c28aaSamw 848da6c28aaSamw if (zap->zap_normflags == 0) 849da6c28aaSamw return (B_FALSE); 850da6c28aaSamw 851da6c28aaSamw again: 852bf26014cSMatthew Ahrens for (mzap_ent_t *other = avl_walk(&zap->zap_m.zap_avl, mze, direction); 853da6c28aaSamw other && other->mze_hash == mze->mze_hash; 854da6c28aaSamw other = avl_walk(&zap->zap_m.zap_avl, other, direction)) { 855da6c28aaSamw 856da6c28aaSamw if (zn == NULL) { 8573f9d6ad7SLin Ling zn = zap_name_alloc(zap, MZE_PHYS(zap, mze)->mze_name, 8581c17160aSKevin Crowe MT_NORMALIZE); 859da6c28aaSamw allocdzn = B_TRUE; 860da6c28aaSamw } 8613f9d6ad7SLin Ling if (zap_match(zn, MZE_PHYS(zap, other)->mze_name)) { 862da6c28aaSamw if (allocdzn) 863da6c28aaSamw zap_name_free(zn); 864da6c28aaSamw return (B_TRUE); 865da6c28aaSamw } 866da6c28aaSamw } 867da6c28aaSamw 868da6c28aaSamw if (direction == AVL_BEFORE) { 869da6c28aaSamw direction = AVL_AFTER; 870da6c28aaSamw goto again; 871da6c28aaSamw } 872da6c28aaSamw 873da6c28aaSamw if (allocdzn) 874da6c28aaSamw zap_name_free(zn); 875da6c28aaSamw return (B_FALSE); 876da6c28aaSamw } 877da6c28aaSamw 878da6c28aaSamw /* 879da6c28aaSamw * Routines for manipulating attributes. 880fa9e4066Sahrens */ 881fa9e4066Sahrens 882fa9e4066Sahrens int 883fa9e4066Sahrens zap_lookup(objset_t *os, uint64_t zapobj, const char *name, 884fa9e4066Sahrens uint64_t integer_size, uint64_t num_integers, void *buf) 885da6c28aaSamw { 886da6c28aaSamw return (zap_lookup_norm(os, zapobj, name, integer_size, 8871c17160aSKevin Crowe num_integers, buf, 0, NULL, 0, NULL)); 888da6c28aaSamw } 889da6c28aaSamw 890ae972795SMatthew Ahrens static int 891ae972795SMatthew Ahrens zap_lookup_impl(zap_t *zap, const char *name, 892da6c28aaSamw uint64_t integer_size, uint64_t num_integers, void *buf, 893da6c28aaSamw matchtype_t mt, char *realname, int rn_len, 894da6c28aaSamw boolean_t *ncp) 895fa9e4066Sahrens { 896ae972795SMatthew Ahrens int err = 0; 897fa9e4066Sahrens 898bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc(zap, name, mt); 899ae972795SMatthew Ahrens if (zn == NULL) 900be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 901da6c28aaSamw 902fa9e4066Sahrens if (!zap->zap_ismicro) { 903da6c28aaSamw err = fzap_lookup(zn, integer_size, num_integers, buf, 904da6c28aaSamw realname, rn_len, ncp); 905fa9e4066Sahrens } else { 906bf26014cSMatthew Ahrens mzap_ent_t *mze = mze_find(zn); 907fa9e4066Sahrens if (mze == NULL) { 908be6fd75aSMatthew Ahrens err = SET_ERROR(ENOENT); 909fa9e4066Sahrens } else { 910da6c28aaSamw if (num_integers < 1) { 911be6fd75aSMatthew Ahrens err = SET_ERROR(EOVERFLOW); 912da6c28aaSamw } else if (integer_size != 8) { 913be6fd75aSMatthew Ahrens err = SET_ERROR(EINVAL); 914da6c28aaSamw } else { 9153f9d6ad7SLin Ling *(uint64_t *)buf = 9163f9d6ad7SLin Ling MZE_PHYS(zap, mze)->mze_value; 917da6c28aaSamw (void) strlcpy(realname, 9183f9d6ad7SLin Ling MZE_PHYS(zap, mze)->mze_name, rn_len); 919da6c28aaSamw if (ncp) { 920da6c28aaSamw *ncp = mzap_normalization_conflict(zap, 921da6c28aaSamw zn, mze); 922da6c28aaSamw } 923da6c28aaSamw } 924fa9e4066Sahrens } 925fa9e4066Sahrens } 926da6c28aaSamw zap_name_free(zn); 927ae972795SMatthew Ahrens return (err); 928ae972795SMatthew Ahrens } 929ae972795SMatthew Ahrens 930ae972795SMatthew Ahrens int 931ae972795SMatthew Ahrens zap_lookup_norm(objset_t *os, uint64_t zapobj, const char *name, 932ae972795SMatthew Ahrens uint64_t integer_size, uint64_t num_integers, void *buf, 933ae972795SMatthew Ahrens matchtype_t mt, char *realname, int rn_len, 934ae972795SMatthew Ahrens boolean_t *ncp) 935ae972795SMatthew Ahrens { 936ae972795SMatthew Ahrens zap_t *zap; 937ae972795SMatthew Ahrens 938bf26014cSMatthew Ahrens int err = 939bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 940ae972795SMatthew Ahrens if (err != 0) 941ae972795SMatthew Ahrens return (err); 942ae972795SMatthew Ahrens err = zap_lookup_impl(zap, name, integer_size, 943ae972795SMatthew Ahrens num_integers, buf, mt, realname, rn_len, ncp); 944ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 945fa9e4066Sahrens return (err); 946fa9e4066Sahrens } 947fa9e4066Sahrens 94879d72832SMatthew Ahrens int 94979d72832SMatthew Ahrens zap_lookup_by_dnode(dnode_t *dn, const char *name, 95079d72832SMatthew Ahrens uint64_t integer_size, uint64_t num_integers, void *buf) 95179d72832SMatthew Ahrens { 95279d72832SMatthew Ahrens return (zap_lookup_norm_by_dnode(dn, name, integer_size, 9531c17160aSKevin Crowe num_integers, buf, 0, NULL, 0, NULL)); 95479d72832SMatthew Ahrens } 95579d72832SMatthew Ahrens 95679d72832SMatthew Ahrens int 95779d72832SMatthew Ahrens zap_lookup_norm_by_dnode(dnode_t *dn, const char *name, 95879d72832SMatthew Ahrens uint64_t integer_size, uint64_t num_integers, void *buf, 95979d72832SMatthew Ahrens matchtype_t mt, char *realname, int rn_len, 96079d72832SMatthew Ahrens boolean_t *ncp) 96179d72832SMatthew Ahrens { 96279d72832SMatthew Ahrens zap_t *zap; 96379d72832SMatthew Ahrens 964bf26014cSMatthew Ahrens int err = zap_lockdir_by_dnode(dn, NULL, RW_READER, TRUE, FALSE, 96579d72832SMatthew Ahrens FTAG, &zap); 96679d72832SMatthew Ahrens if (err != 0) 96779d72832SMatthew Ahrens return (err); 96879d72832SMatthew Ahrens err = zap_lookup_impl(zap, name, integer_size, 96979d72832SMatthew Ahrens num_integers, buf, mt, realname, rn_len, ncp); 97079d72832SMatthew Ahrens zap_unlockdir(zap, FTAG); 97179d72832SMatthew Ahrens return (err); 97279d72832SMatthew Ahrens } 97379d72832SMatthew Ahrens 974c7cd2421SGeorge Wilson int 975c7cd2421SGeorge Wilson zap_prefetch_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 976c7cd2421SGeorge Wilson int key_numints) 977c7cd2421SGeorge Wilson { 978c7cd2421SGeorge Wilson zap_t *zap; 979c7cd2421SGeorge Wilson 980bf26014cSMatthew Ahrens int err = 981bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 982bf26014cSMatthew Ahrens if (err != 0) 983c7cd2421SGeorge Wilson return (err); 984bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 985c7cd2421SGeorge Wilson if (zn == NULL) { 986ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 987be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 988c7cd2421SGeorge Wilson } 989c7cd2421SGeorge Wilson 990c7cd2421SGeorge Wilson fzap_prefetch(zn); 991c7cd2421SGeorge Wilson zap_name_free(zn); 992ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 993c7cd2421SGeorge Wilson return (err); 994c7cd2421SGeorge Wilson } 995c7cd2421SGeorge Wilson 996b24ab676SJeff Bonwick int 997b24ab676SJeff Bonwick zap_lookup_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 998b24ab676SJeff Bonwick int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf) 999b24ab676SJeff Bonwick { 1000b24ab676SJeff Bonwick zap_t *zap; 1001b24ab676SJeff Bonwick 1002bf26014cSMatthew Ahrens int err = 1003bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1004bf26014cSMatthew Ahrens if (err != 0) 1005b24ab676SJeff Bonwick return (err); 1006bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1007b24ab676SJeff Bonwick if (zn == NULL) { 1008ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1009be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1010b24ab676SJeff Bonwick } 1011b24ab676SJeff Bonwick 1012b24ab676SJeff Bonwick err = fzap_lookup(zn, integer_size, num_integers, buf, 1013b24ab676SJeff Bonwick NULL, 0, NULL); 1014b24ab676SJeff Bonwick zap_name_free(zn); 1015ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1016b24ab676SJeff Bonwick return (err); 1017b24ab676SJeff Bonwick } 1018b24ab676SJeff Bonwick 101992241e0bSTom Erickson int 102092241e0bSTom Erickson zap_contains(objset_t *os, uint64_t zapobj, const char *name) 102192241e0bSTom Erickson { 10222acef22dSMatthew Ahrens int err = zap_lookup_norm(os, zapobj, name, 0, 10231c17160aSKevin Crowe 0, NULL, 0, NULL, 0, NULL); 102492241e0bSTom Erickson if (err == EOVERFLOW || err == EINVAL) 102592241e0bSTom Erickson err = 0; /* found, but skipped reading the value */ 102692241e0bSTom Erickson return (err); 102792241e0bSTom Erickson } 102892241e0bSTom Erickson 1029fa9e4066Sahrens int 1030fa9e4066Sahrens zap_length(objset_t *os, uint64_t zapobj, const char *name, 1031fa9e4066Sahrens uint64_t *integer_size, uint64_t *num_integers) 1032fa9e4066Sahrens { 1033fa9e4066Sahrens zap_t *zap; 1034fa9e4066Sahrens 1035bf26014cSMatthew Ahrens int err = 1036bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1037bf26014cSMatthew Ahrens if (err != 0) 1038fa9e4066Sahrens return (err); 1039bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc(zap, name, 0); 1040da6c28aaSamw if (zn == NULL) { 1041ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1042be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1043da6c28aaSamw } 1044fa9e4066Sahrens if (!zap->zap_ismicro) { 1045da6c28aaSamw err = fzap_length(zn, integer_size, num_integers); 1046fa9e4066Sahrens } else { 1047bf26014cSMatthew Ahrens mzap_ent_t *mze = mze_find(zn); 1048fa9e4066Sahrens if (mze == NULL) { 1049be6fd75aSMatthew Ahrens err = SET_ERROR(ENOENT); 1050fa9e4066Sahrens } else { 1051fa9e4066Sahrens if (integer_size) 1052fa9e4066Sahrens *integer_size = 8; 1053fa9e4066Sahrens if (num_integers) 1054fa9e4066Sahrens *num_integers = 1; 1055fa9e4066Sahrens } 1056fa9e4066Sahrens } 1057da6c28aaSamw zap_name_free(zn); 1058ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1059fa9e4066Sahrens return (err); 1060fa9e4066Sahrens } 1061fa9e4066Sahrens 1062b24ab676SJeff Bonwick int 1063b24ab676SJeff Bonwick zap_length_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1064b24ab676SJeff Bonwick int key_numints, uint64_t *integer_size, uint64_t *num_integers) 1065b24ab676SJeff Bonwick { 1066b24ab676SJeff Bonwick zap_t *zap; 1067b24ab676SJeff Bonwick 1068bf26014cSMatthew Ahrens int err = 1069bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1070bf26014cSMatthew Ahrens if (err != 0) 1071b24ab676SJeff Bonwick return (err); 1072bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1073b24ab676SJeff Bonwick if (zn == NULL) { 1074ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1075be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1076b24ab676SJeff Bonwick } 1077b24ab676SJeff Bonwick err = fzap_length(zn, integer_size, num_integers); 1078b24ab676SJeff Bonwick zap_name_free(zn); 1079ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1080b24ab676SJeff Bonwick return (err); 1081b24ab676SJeff Bonwick } 1082b24ab676SJeff Bonwick 1083fa9e4066Sahrens static void 1084da6c28aaSamw mzap_addent(zap_name_t *zn, uint64_t value) 1085fa9e4066Sahrens { 1086da6c28aaSamw zap_t *zap = zn->zn_zap; 1087fa9e4066Sahrens int start = zap->zap_m.zap_alloc_next; 1088fa9e4066Sahrens 1089fa9e4066Sahrens ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 1090fa9e4066Sahrens 1091fa9e4066Sahrens #ifdef ZFS_DEBUG 1092bf26014cSMatthew Ahrens for (int i = 0; i < zap->zap_m.zap_num_chunks; i++) { 1093c1379625SJustin T. Gibbs mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i]; 1094b24ab676SJeff Bonwick ASSERT(strcmp(zn->zn_key_orig, mze->mze_name) != 0); 1095fa9e4066Sahrens } 1096fa9e4066Sahrens #endif 1097fa9e4066Sahrens 1098bf26014cSMatthew Ahrens uint32_t cd = mze_find_unused_cd(zap, zn->zn_hash); 1099fa9e4066Sahrens /* given the limited size of the microzap, this can't happen */ 1100b24ab676SJeff Bonwick ASSERT(cd < zap_maxcd(zap)); 1101fa9e4066Sahrens 1102fa9e4066Sahrens again: 1103bf26014cSMatthew Ahrens for (int i = start; i < zap->zap_m.zap_num_chunks; i++) { 1104c1379625SJustin T. Gibbs mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i]; 1105fa9e4066Sahrens if (mze->mze_name[0] == 0) { 1106fa9e4066Sahrens mze->mze_value = value; 1107fa9e4066Sahrens mze->mze_cd = cd; 1108b24ab676SJeff Bonwick (void) strcpy(mze->mze_name, zn->zn_key_orig); 1109fa9e4066Sahrens zap->zap_m.zap_num_entries++; 1110fa9e4066Sahrens zap->zap_m.zap_alloc_next = i+1; 1111fa9e4066Sahrens if (zap->zap_m.zap_alloc_next == 1112fa9e4066Sahrens zap->zap_m.zap_num_chunks) 1113fa9e4066Sahrens zap->zap_m.zap_alloc_next = 0; 11143f9d6ad7SLin Ling mze_insert(zap, i, zn->zn_hash); 1115fa9e4066Sahrens return; 1116fa9e4066Sahrens } 1117fa9e4066Sahrens } 1118fa9e4066Sahrens if (start != 0) { 1119fa9e4066Sahrens start = 0; 1120fa9e4066Sahrens goto again; 1121fa9e4066Sahrens } 1122fa9e4066Sahrens ASSERT(!"out of entries!"); 1123fa9e4066Sahrens } 1124fa9e4066Sahrens 1125b0c42cd4Sbzzz static int 1126b0c42cd4Sbzzz zap_add_impl(zap_t *zap, const char *key, 1127fa9e4066Sahrens int integer_size, uint64_t num_integers, 1128b0c42cd4Sbzzz const void *val, dmu_tx_t *tx, void *tag) 1129fa9e4066Sahrens { 1130fa9e4066Sahrens const uint64_t *intval = val; 1131bf26014cSMatthew Ahrens int err = 0; 1132fa9e4066Sahrens 1133bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc(zap, key, 0); 1134da6c28aaSamw if (zn == NULL) { 1135b0c42cd4Sbzzz zap_unlockdir(zap, tag); 1136be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1137da6c28aaSamw } 1138fa9e4066Sahrens if (!zap->zap_ismicro) { 1139b0c42cd4Sbzzz err = fzap_add(zn, integer_size, num_integers, val, tag, tx); 1140ad860c82Sbonwick zap = zn->zn_zap; /* fzap_add() may change zap */ 1141fa9e4066Sahrens } else if (integer_size != 8 || num_integers != 1 || 1142b24ab676SJeff Bonwick strlen(key) >= MZAP_NAME_LEN) { 1143b0c42cd4Sbzzz err = mzap_upgrade(&zn->zn_zap, tag, tx, 0); 1144ae972795SMatthew Ahrens if (err == 0) { 1145ae972795SMatthew Ahrens err = fzap_add(zn, integer_size, num_integers, val, 1146b0c42cd4Sbzzz tag, tx); 1147ae972795SMatthew Ahrens } 1148ad860c82Sbonwick zap = zn->zn_zap; /* fzap_add() may change zap */ 1149fa9e4066Sahrens } else { 1150bf26014cSMatthew Ahrens if (mze_find(zn) != NULL) { 1151be6fd75aSMatthew Ahrens err = SET_ERROR(EEXIST); 1152fa9e4066Sahrens } else { 1153da6c28aaSamw mzap_addent(zn, *intval); 1154fa9e4066Sahrens } 1155fa9e4066Sahrens } 1156ad860c82Sbonwick ASSERT(zap == zn->zn_zap); 1157da6c28aaSamw zap_name_free(zn); 1158ad860c82Sbonwick if (zap != NULL) /* may be NULL if fzap_add() failed */ 1159b0c42cd4Sbzzz zap_unlockdir(zap, tag); 1160b0c42cd4Sbzzz return (err); 1161b0c42cd4Sbzzz } 1162b0c42cd4Sbzzz 1163b0c42cd4Sbzzz int 1164b0c42cd4Sbzzz zap_add(objset_t *os, uint64_t zapobj, const char *key, 1165b0c42cd4Sbzzz int integer_size, uint64_t num_integers, 1166b0c42cd4Sbzzz const void *val, dmu_tx_t *tx) 1167b0c42cd4Sbzzz { 1168b0c42cd4Sbzzz zap_t *zap; 1169b0c42cd4Sbzzz int err; 1170b0c42cd4Sbzzz 1171b0c42cd4Sbzzz err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1172b0c42cd4Sbzzz if (err != 0) 1173b0c42cd4Sbzzz return (err); 1174b0c42cd4Sbzzz err = zap_add_impl(zap, key, integer_size, num_integers, val, tx, FTAG); 1175b0c42cd4Sbzzz /* zap_add_impl() calls zap_unlockdir() */ 1176b0c42cd4Sbzzz return (err); 1177b0c42cd4Sbzzz } 1178b0c42cd4Sbzzz 1179b0c42cd4Sbzzz int 1180b0c42cd4Sbzzz zap_add_by_dnode(dnode_t *dn, const char *key, 1181b0c42cd4Sbzzz int integer_size, uint64_t num_integers, 1182b0c42cd4Sbzzz const void *val, dmu_tx_t *tx) 1183b0c42cd4Sbzzz { 1184b0c42cd4Sbzzz zap_t *zap; 1185b0c42cd4Sbzzz int err; 1186b0c42cd4Sbzzz 1187b0c42cd4Sbzzz err = zap_lockdir_by_dnode(dn, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1188b0c42cd4Sbzzz if (err != 0) 1189b0c42cd4Sbzzz return (err); 1190b0c42cd4Sbzzz err = zap_add_impl(zap, key, integer_size, num_integers, val, tx, FTAG); 1191b0c42cd4Sbzzz /* zap_add_impl() calls zap_unlockdir() */ 1192fa9e4066Sahrens return (err); 1193fa9e4066Sahrens } 1194fa9e4066Sahrens 1195b24ab676SJeff Bonwick int 1196b24ab676SJeff Bonwick zap_add_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1197b24ab676SJeff Bonwick int key_numints, int integer_size, uint64_t num_integers, 1198b24ab676SJeff Bonwick const void *val, dmu_tx_t *tx) 1199b24ab676SJeff Bonwick { 1200b24ab676SJeff Bonwick zap_t *zap; 1201b24ab676SJeff Bonwick 1202bf26014cSMatthew Ahrens int err = 1203bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1204bf26014cSMatthew Ahrens if (err != 0) 1205b24ab676SJeff Bonwick return (err); 1206bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1207b24ab676SJeff Bonwick if (zn == NULL) { 1208ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1209be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1210b24ab676SJeff Bonwick } 1211ae972795SMatthew Ahrens err = fzap_add(zn, integer_size, num_integers, val, FTAG, tx); 1212b24ab676SJeff Bonwick zap = zn->zn_zap; /* fzap_add() may change zap */ 1213b24ab676SJeff Bonwick zap_name_free(zn); 1214b24ab676SJeff Bonwick if (zap != NULL) /* may be NULL if fzap_add() failed */ 1215ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1216b24ab676SJeff Bonwick return (err); 1217b24ab676SJeff Bonwick } 1218b24ab676SJeff Bonwick 1219fa9e4066Sahrens int 1220fa9e4066Sahrens zap_update(objset_t *os, uint64_t zapobj, const char *name, 1221fa9e4066Sahrens int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx) 1222fa9e4066Sahrens { 1223fa9e4066Sahrens zap_t *zap; 12243f9d6ad7SLin Ling uint64_t oldval; 1225fa9e4066Sahrens const uint64_t *intval = val; 1226fa9e4066Sahrens 12273f9d6ad7SLin Ling #ifdef ZFS_DEBUG 12283f9d6ad7SLin Ling /* 12293f9d6ad7SLin Ling * If there is an old value, it shouldn't change across the 12303f9d6ad7SLin Ling * lockdir (eg, due to bprewrite's xlation). 12313f9d6ad7SLin Ling */ 12323f9d6ad7SLin Ling if (integer_size == 8 && num_integers == 1) 12333f9d6ad7SLin Ling (void) zap_lookup(os, zapobj, name, 8, 1, &oldval); 12343f9d6ad7SLin Ling #endif 12353f9d6ad7SLin Ling 1236bf26014cSMatthew Ahrens int err = 1237bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1238bf26014cSMatthew Ahrens if (err != 0) 1239fa9e4066Sahrens return (err); 1240bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc(zap, name, 0); 1241da6c28aaSamw if (zn == NULL) { 1242ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1243be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1244da6c28aaSamw } 1245fa9e4066Sahrens if (!zap->zap_ismicro) { 1246ae972795SMatthew Ahrens err = fzap_update(zn, integer_size, num_integers, val, 1247ae972795SMatthew Ahrens FTAG, tx); 1248ad860c82Sbonwick zap = zn->zn_zap; /* fzap_update() may change zap */ 1249fa9e4066Sahrens } else if (integer_size != 8 || num_integers != 1 || 1250fa9e4066Sahrens strlen(name) >= MZAP_NAME_LEN) { 1251fa9e4066Sahrens dprintf("upgrading obj %llu: intsz=%u numint=%llu name=%s\n", 1252fa9e4066Sahrens zapobj, integer_size, num_integers, name); 1253ae972795SMatthew Ahrens err = mzap_upgrade(&zn->zn_zap, FTAG, tx, 0); 1254ae972795SMatthew Ahrens if (err == 0) { 1255ad860c82Sbonwick err = fzap_update(zn, integer_size, num_integers, 1256ae972795SMatthew Ahrens val, FTAG, tx); 1257ae972795SMatthew Ahrens } 1258ad860c82Sbonwick zap = zn->zn_zap; /* fzap_update() may change zap */ 1259fa9e4066Sahrens } else { 1260bf26014cSMatthew Ahrens mzap_ent_t *mze = mze_find(zn); 1261fa9e4066Sahrens if (mze != NULL) { 12623f9d6ad7SLin Ling ASSERT3U(MZE_PHYS(zap, mze)->mze_value, ==, oldval); 12633f9d6ad7SLin Ling MZE_PHYS(zap, mze)->mze_value = *intval; 1264fa9e4066Sahrens } else { 1265da6c28aaSamw mzap_addent(zn, *intval); 1266fa9e4066Sahrens } 1267fa9e4066Sahrens } 1268ad860c82Sbonwick ASSERT(zap == zn->zn_zap); 1269da6c28aaSamw zap_name_free(zn); 1270ad860c82Sbonwick if (zap != NULL) /* may be NULL if fzap_upgrade() failed */ 1271ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1272455d5089Sahrens return (err); 1273fa9e4066Sahrens } 1274fa9e4066Sahrens 1275b24ab676SJeff Bonwick int 1276b24ab676SJeff Bonwick zap_update_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1277b24ab676SJeff Bonwick int key_numints, 1278b24ab676SJeff Bonwick int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx) 1279b24ab676SJeff Bonwick { 1280b24ab676SJeff Bonwick zap_t *zap; 1281b24ab676SJeff Bonwick 1282bf26014cSMatthew Ahrens int err = 1283bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1284bf26014cSMatthew Ahrens if (err != 0) 1285b24ab676SJeff Bonwick return (err); 1286bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1287b24ab676SJeff Bonwick if (zn == NULL) { 1288ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1289be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1290b24ab676SJeff Bonwick } 1291ae972795SMatthew Ahrens err = fzap_update(zn, integer_size, num_integers, val, FTAG, tx); 1292b24ab676SJeff Bonwick zap = zn->zn_zap; /* fzap_update() may change zap */ 1293b24ab676SJeff Bonwick zap_name_free(zn); 1294b24ab676SJeff Bonwick if (zap != NULL) /* may be NULL if fzap_upgrade() failed */ 1295ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1296b24ab676SJeff Bonwick return (err); 1297b24ab676SJeff Bonwick } 1298b24ab676SJeff Bonwick 1299fa9e4066Sahrens int 1300fa9e4066Sahrens zap_remove(objset_t *os, uint64_t zapobj, const char *name, dmu_tx_t *tx) 1301da6c28aaSamw { 13021c17160aSKevin Crowe return (zap_remove_norm(os, zapobj, name, 0, tx)); 1303da6c28aaSamw } 1304da6c28aaSamw 1305b0c42cd4Sbzzz static int 1306b0c42cd4Sbzzz zap_remove_impl(zap_t *zap, const char *name, 1307da6c28aaSamw matchtype_t mt, dmu_tx_t *tx) 1308fa9e4066Sahrens { 1309b0c42cd4Sbzzz int err = 0; 1310fa9e4066Sahrens 1311bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc(zap, name, mt); 1312b0c42cd4Sbzzz if (zn == NULL) 1313be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1314fa9e4066Sahrens if (!zap->zap_ismicro) { 1315da6c28aaSamw err = fzap_remove(zn, tx); 1316fa9e4066Sahrens } else { 1317bf26014cSMatthew Ahrens mzap_ent_t *mze = mze_find(zn); 1318fa9e4066Sahrens if (mze == NULL) { 1319be6fd75aSMatthew Ahrens err = SET_ERROR(ENOENT); 1320fa9e4066Sahrens } else { 1321fa9e4066Sahrens zap->zap_m.zap_num_entries--; 1322c1379625SJustin T. Gibbs bzero(&zap_m_phys(zap)->mz_chunk[mze->mze_chunkid], 1323fa9e4066Sahrens sizeof (mzap_ent_phys_t)); 1324fa9e4066Sahrens mze_remove(zap, mze); 1325fa9e4066Sahrens } 1326fa9e4066Sahrens } 1327da6c28aaSamw zap_name_free(zn); 1328b0c42cd4Sbzzz return (err); 1329b0c42cd4Sbzzz } 1330b0c42cd4Sbzzz 1331b0c42cd4Sbzzz int 1332b0c42cd4Sbzzz zap_remove_norm(objset_t *os, uint64_t zapobj, const char *name, 1333b0c42cd4Sbzzz matchtype_t mt, dmu_tx_t *tx) 1334b0c42cd4Sbzzz { 1335b0c42cd4Sbzzz zap_t *zap; 1336b0c42cd4Sbzzz int err; 1337b0c42cd4Sbzzz 1338b0c42cd4Sbzzz err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap); 1339b0c42cd4Sbzzz if (err) 1340b0c42cd4Sbzzz return (err); 1341b0c42cd4Sbzzz err = zap_remove_impl(zap, name, mt, tx); 1342b0c42cd4Sbzzz zap_unlockdir(zap, FTAG); 1343b0c42cd4Sbzzz return (err); 1344b0c42cd4Sbzzz } 1345b0c42cd4Sbzzz 1346b0c42cd4Sbzzz int 1347b0c42cd4Sbzzz zap_remove_by_dnode(dnode_t *dn, const char *name, dmu_tx_t *tx) 1348b0c42cd4Sbzzz { 1349b0c42cd4Sbzzz zap_t *zap; 1350b0c42cd4Sbzzz int err; 1351b0c42cd4Sbzzz 1352b0c42cd4Sbzzz err = zap_lockdir_by_dnode(dn, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap); 1353b0c42cd4Sbzzz if (err) 1354b0c42cd4Sbzzz return (err); 1355b0c42cd4Sbzzz err = zap_remove_impl(zap, name, 0, tx); 1356ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1357fa9e4066Sahrens return (err); 1358fa9e4066Sahrens } 1359fa9e4066Sahrens 1360b24ab676SJeff Bonwick int 1361b24ab676SJeff Bonwick zap_remove_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1362b24ab676SJeff Bonwick int key_numints, dmu_tx_t *tx) 1363b24ab676SJeff Bonwick { 1364b24ab676SJeff Bonwick zap_t *zap; 1365b24ab676SJeff Bonwick 1366bf26014cSMatthew Ahrens int err = 1367bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap); 1368bf26014cSMatthew Ahrens if (err != 0) 1369b24ab676SJeff Bonwick return (err); 1370bf26014cSMatthew Ahrens zap_name_t *zn = zap_name_alloc_uint64(zap, key, key_numints); 1371b24ab676SJeff Bonwick if (zn == NULL) { 1372ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1373be6fd75aSMatthew Ahrens return (SET_ERROR(ENOTSUP)); 1374b24ab676SJeff Bonwick } 1375b24ab676SJeff Bonwick err = fzap_remove(zn, tx); 1376b24ab676SJeff Bonwick zap_name_free(zn); 1377ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1378b24ab676SJeff Bonwick return (err); 1379b24ab676SJeff Bonwick } 1380b24ab676SJeff Bonwick 1381fa9e4066Sahrens /* 1382fa9e4066Sahrens * Routines for iterating over the attributes. 1383fa9e4066Sahrens */ 1384fa9e4066Sahrens 138552abb70eSMatthew Ahrens static void 138652abb70eSMatthew Ahrens zap_cursor_init_impl(zap_cursor_t *zc, objset_t *os, uint64_t zapobj, 138752abb70eSMatthew Ahrens uint64_t serialized, boolean_t prefetch) 1388fa9e4066Sahrens { 1389fa9e4066Sahrens zc->zc_objset = os; 139087e5029aSahrens zc->zc_zap = NULL; 139187e5029aSahrens zc->zc_leaf = NULL; 1392fa9e4066Sahrens zc->zc_zapobj = zapobj; 1393b24ab676SJeff Bonwick zc->zc_serialized = serialized; 1394b24ab676SJeff Bonwick zc->zc_hash = 0; 1395b24ab676SJeff Bonwick zc->zc_cd = 0; 139652abb70eSMatthew Ahrens zc->zc_prefetch = prefetch; 139752abb70eSMatthew Ahrens } 139852abb70eSMatthew Ahrens void 139952abb70eSMatthew Ahrens zap_cursor_init_serialized(zap_cursor_t *zc, objset_t *os, uint64_t zapobj, 140052abb70eSMatthew Ahrens uint64_t serialized) 140152abb70eSMatthew Ahrens { 140252abb70eSMatthew Ahrens zap_cursor_init_impl(zc, os, zapobj, serialized, B_TRUE); 1403fa9e4066Sahrens } 1404fa9e4066Sahrens 140552abb70eSMatthew Ahrens /* 140652abb70eSMatthew Ahrens * Initialize a cursor at the beginning of the ZAP object. The entire 140752abb70eSMatthew Ahrens * ZAP object will be prefetched. 140852abb70eSMatthew Ahrens */ 140987e5029aSahrens void 141087e5029aSahrens zap_cursor_init(zap_cursor_t *zc, objset_t *os, uint64_t zapobj) 141187e5029aSahrens { 141252abb70eSMatthew Ahrens zap_cursor_init_impl(zc, os, zapobj, 0, B_TRUE); 141352abb70eSMatthew Ahrens } 141452abb70eSMatthew Ahrens 141552abb70eSMatthew Ahrens /* 141652abb70eSMatthew Ahrens * Initialize a cursor at the beginning, but request that we not prefetch 141752abb70eSMatthew Ahrens * the entire ZAP object. 141852abb70eSMatthew Ahrens */ 141952abb70eSMatthew Ahrens void 142052abb70eSMatthew Ahrens zap_cursor_init_noprefetch(zap_cursor_t *zc, objset_t *os, uint64_t zapobj) 142152abb70eSMatthew Ahrens { 142252abb70eSMatthew Ahrens zap_cursor_init_impl(zc, os, zapobj, 0, B_FALSE); 142387e5029aSahrens } 142487e5029aSahrens 142587e5029aSahrens void 142687e5029aSahrens zap_cursor_fini(zap_cursor_t *zc) 142787e5029aSahrens { 142887e5029aSahrens if (zc->zc_zap) { 142987e5029aSahrens rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); 1430ae972795SMatthew Ahrens zap_unlockdir(zc->zc_zap, NULL); 143187e5029aSahrens zc->zc_zap = NULL; 143287e5029aSahrens } 143387e5029aSahrens if (zc->zc_leaf) { 143487e5029aSahrens rw_enter(&zc->zc_leaf->l_rwlock, RW_READER); 143587e5029aSahrens zap_put_leaf(zc->zc_leaf); 143687e5029aSahrens zc->zc_leaf = NULL; 143787e5029aSahrens } 143887e5029aSahrens zc->zc_objset = NULL; 143987e5029aSahrens } 144087e5029aSahrens 1441fa9e4066Sahrens uint64_t 1442fa9e4066Sahrens zap_cursor_serialize(zap_cursor_t *zc) 1443fa9e4066Sahrens { 1444fa9e4066Sahrens if (zc->zc_hash == -1ULL) 1445fa9e4066Sahrens return (-1ULL); 1446b24ab676SJeff Bonwick if (zc->zc_zap == NULL) 1447b24ab676SJeff Bonwick return (zc->zc_serialized); 1448b24ab676SJeff Bonwick ASSERT((zc->zc_hash & zap_maxcd(zc->zc_zap)) == 0); 1449b24ab676SJeff Bonwick ASSERT(zc->zc_cd < zap_maxcd(zc->zc_zap)); 1450b24ab676SJeff Bonwick 1451b24ab676SJeff Bonwick /* 1452b24ab676SJeff Bonwick * We want to keep the high 32 bits of the cursor zero if we can, so 1453b24ab676SJeff Bonwick * that 32-bit programs can access this. So usually use a small 1454b24ab676SJeff Bonwick * (28-bit) hash value so we can fit 4 bits of cd into the low 32-bits 1455b24ab676SJeff Bonwick * of the cursor. 1456b24ab676SJeff Bonwick * 1457b24ab676SJeff Bonwick * [ collision differentiator | zap_hashbits()-bit hash value ] 1458b24ab676SJeff Bonwick */ 1459b24ab676SJeff Bonwick return ((zc->zc_hash >> (64 - zap_hashbits(zc->zc_zap))) | 1460b24ab676SJeff Bonwick ((uint64_t)zc->zc_cd << zap_hashbits(zc->zc_zap))); 1461fa9e4066Sahrens } 1462fa9e4066Sahrens 1463fa9e4066Sahrens int 1464fa9e4066Sahrens zap_cursor_retrieve(zap_cursor_t *zc, zap_attribute_t *za) 1465fa9e4066Sahrens { 1466fa9e4066Sahrens int err; 1467fa9e4066Sahrens 1468fa9e4066Sahrens if (zc->zc_hash == -1ULL) 1469be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT)); 1470fa9e4066Sahrens 147187e5029aSahrens if (zc->zc_zap == NULL) { 1472b24ab676SJeff Bonwick int hb; 147387e5029aSahrens err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL, 1474ae972795SMatthew Ahrens RW_READER, TRUE, FALSE, NULL, &zc->zc_zap); 1475bf26014cSMatthew Ahrens if (err != 0) 147687e5029aSahrens return (err); 1477b24ab676SJeff Bonwick 1478b24ab676SJeff Bonwick /* 1479b24ab676SJeff Bonwick * To support zap_cursor_init_serialized, advance, retrieve, 1480b24ab676SJeff Bonwick * we must add to the existing zc_cd, which may already 1481b24ab676SJeff Bonwick * be 1 due to the zap_cursor_advance. 1482b24ab676SJeff Bonwick */ 1483b24ab676SJeff Bonwick ASSERT(zc->zc_hash == 0); 1484b24ab676SJeff Bonwick hb = zap_hashbits(zc->zc_zap); 1485b24ab676SJeff Bonwick zc->zc_hash = zc->zc_serialized << (64 - hb); 1486b24ab676SJeff Bonwick zc->zc_cd += zc->zc_serialized >> hb; 1487b24ab676SJeff Bonwick if (zc->zc_cd >= zap_maxcd(zc->zc_zap)) /* corrupt serialized */ 1488b24ab676SJeff Bonwick zc->zc_cd = 0; 148987e5029aSahrens } else { 149087e5029aSahrens rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); 149187e5029aSahrens } 149287e5029aSahrens if (!zc->zc_zap->zap_ismicro) { 149387e5029aSahrens err = fzap_cursor_retrieve(zc->zc_zap, zc, za); 1494fa9e4066Sahrens } else { 1495bf26014cSMatthew Ahrens avl_index_t idx; 1496bf26014cSMatthew Ahrens mzap_ent_t mze_tofind; 1497bf26014cSMatthew Ahrens 1498fa9e4066Sahrens mze_tofind.mze_hash = zc->zc_hash; 14993f9d6ad7SLin Ling mze_tofind.mze_cd = zc->zc_cd; 1500fa9e4066Sahrens 1501bf26014cSMatthew Ahrens mzap_ent_t *mze = 1502bf26014cSMatthew Ahrens avl_find(&zc->zc_zap->zap_m.zap_avl, &mze_tofind, &idx); 150387e5029aSahrens if (mze == NULL) { 150487e5029aSahrens mze = avl_nearest(&zc->zc_zap->zap_m.zap_avl, 150587e5029aSahrens idx, AVL_AFTER); 150687e5029aSahrens } 1507fa9e4066Sahrens if (mze) { 15083f9d6ad7SLin Ling mzap_ent_phys_t *mzep = MZE_PHYS(zc->zc_zap, mze); 15093f9d6ad7SLin Ling ASSERT3U(mze->mze_cd, ==, mzep->mze_cd); 1510da6c28aaSamw za->za_normalization_conflict = 1511da6c28aaSamw mzap_normalization_conflict(zc->zc_zap, NULL, mze); 1512fa9e4066Sahrens za->za_integer_length = 8; 1513fa9e4066Sahrens za->za_num_integers = 1; 15143f9d6ad7SLin Ling za->za_first_integer = mzep->mze_value; 15153f9d6ad7SLin Ling (void) strcpy(za->za_name, mzep->mze_name); 1516fa9e4066Sahrens zc->zc_hash = mze->mze_hash; 15173f9d6ad7SLin Ling zc->zc_cd = mze->mze_cd; 1518fa9e4066Sahrens err = 0; 1519fa9e4066Sahrens } else { 1520fa9e4066Sahrens zc->zc_hash = -1ULL; 1521be6fd75aSMatthew Ahrens err = SET_ERROR(ENOENT); 1522fa9e4066Sahrens } 1523fa9e4066Sahrens } 152487e5029aSahrens rw_exit(&zc->zc_zap->zap_rwlock); 1525fa9e4066Sahrens return (err); 1526fa9e4066Sahrens } 1527fa9e4066Sahrens 1528fa9e4066Sahrens void 1529fa9e4066Sahrens zap_cursor_advance(zap_cursor_t *zc) 1530fa9e4066Sahrens { 1531fa9e4066Sahrens if (zc->zc_hash == -1ULL) 1532fa9e4066Sahrens return; 1533fa9e4066Sahrens zc->zc_cd++; 1534fa9e4066Sahrens } 1535fa9e4066Sahrens 1536fa9e4066Sahrens int 1537fa9e4066Sahrens zap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs) 1538fa9e4066Sahrens { 1539fa9e4066Sahrens zap_t *zap; 1540fa9e4066Sahrens 1541bf26014cSMatthew Ahrens int err = 1542bf26014cSMatthew Ahrens zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1543bf26014cSMatthew Ahrens if (err != 0) 1544fa9e4066Sahrens return (err); 1545fa9e4066Sahrens 1546fa9e4066Sahrens bzero(zs, sizeof (zap_stats_t)); 1547fa9e4066Sahrens 1548fa9e4066Sahrens if (zap->zap_ismicro) { 1549fa9e4066Sahrens zs->zs_blocksize = zap->zap_dbuf->db_size; 1550fa9e4066Sahrens zs->zs_num_entries = zap->zap_m.zap_num_entries; 1551fa9e4066Sahrens zs->zs_num_blocks = 1; 1552fa9e4066Sahrens } else { 1553fa9e4066Sahrens fzap_get_stats(zap, zs); 1554fa9e4066Sahrens } 1555ae972795SMatthew Ahrens zap_unlockdir(zap, FTAG); 1556fa9e4066Sahrens return (0); 1557fa9e4066Sahrens } 1558