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 */ 21168404Spjd/* 22219089Spjd * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23307287Smav * Copyright (c) 2011, 2016 by Delphix. All rights reserved. 24288549Smav * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. 25297112Smav * Copyright (c) 2014 Integros [integros.com] 26168404Spjd */ 27168404Spjd 28219089Spjd#include <sys/zio.h> 29168404Spjd#include <sys/spa.h> 30168404Spjd#include <sys/dmu.h> 31168404Spjd#include <sys/zfs_context.h> 32168404Spjd#include <sys/zap.h> 33168404Spjd#include <sys/refcount.h> 34168404Spjd#include <sys/zap_impl.h> 35168404Spjd#include <sys/zap_leaf.h> 36168404Spjd#include <sys/avl.h> 37219089Spjd#include <sys/arc.h> 38276081Sdelphij#include <sys/dmu_objset.h> 39168404Spjd 40185029Spjd#ifdef _KERNEL 41185029Spjd#include <sys/sunddi.h> 42185029Spjd#endif 43168404Spjd 44277585Sdelphijextern inline mzap_phys_t *zap_m_phys(zap_t *zap); 45277585Sdelphij 46307287Smavstatic int mzap_upgrade(zap_t **zapp, 47307287Smav void *tag, dmu_tx_t *tx, zap_flags_t flags); 48168404Spjd 49219089Spjduint64_t 50219089Spjdzap_getflags(zap_t *zap) 51219089Spjd{ 52219089Spjd if (zap->zap_ismicro) 53219089Spjd return (0); 54277585Sdelphij return (zap_f_phys(zap)->zap_flags); 55219089Spjd} 56168404Spjd 57219089Spjdint 58219089Spjdzap_hashbits(zap_t *zap) 59219089Spjd{ 60219089Spjd if (zap_getflags(zap) & ZAP_FLAG_HASH64) 61219089Spjd return (48); 62219089Spjd else 63219089Spjd return (28); 64219089Spjd} 65219089Spjd 66219089Spjduint32_t 67219089Spjdzap_maxcd(zap_t *zap) 68219089Spjd{ 69219089Spjd if (zap_getflags(zap) & ZAP_FLAG_HASH64) 70219089Spjd return ((1<<16)-1); 71219089Spjd else 72219089Spjd return (-1U); 73219089Spjd} 74219089Spjd 75185029Spjdstatic uint64_t 76219089Spjdzap_hash(zap_name_t *zn) 77185029Spjd{ 78219089Spjd zap_t *zap = zn->zn_zap; 79219089Spjd uint64_t h = 0; 80185029Spjd 81219089Spjd if (zap_getflags(zap) & ZAP_FLAG_PRE_HASHED_KEY) { 82219089Spjd ASSERT(zap_getflags(zap) & ZAP_FLAG_UINT64_KEY); 83219089Spjd h = *(uint64_t *)zn->zn_key_orig; 84219089Spjd } else { 85219089Spjd h = zap->zap_salt; 86219089Spjd ASSERT(h != 0); 87219089Spjd ASSERT(zfs_crc64_table[128] == ZFS_CRC64_POLY); 88185029Spjd 89219089Spjd if (zap_getflags(zap) & ZAP_FLAG_UINT64_KEY) { 90219089Spjd int i; 91219089Spjd const uint64_t *wp = zn->zn_key_norm; 92219089Spjd 93219089Spjd ASSERT(zn->zn_key_intlen == 8); 94219089Spjd for (i = 0; i < zn->zn_key_norm_numints; wp++, i++) { 95219089Spjd int j; 96219089Spjd uint64_t word = *wp; 97219089Spjd 98219089Spjd for (j = 0; j < zn->zn_key_intlen; j++) { 99219089Spjd h = (h >> 8) ^ 100219089Spjd zfs_crc64_table[(h ^ word) & 0xFF]; 101219089Spjd word >>= NBBY; 102219089Spjd } 103219089Spjd } 104219089Spjd } else { 105219089Spjd int i, len; 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 */ 115219089Spjd len = zn->zn_key_norm_numints - 1; 116219089Spjd 117219089Spjd ASSERT(zn->zn_key_intlen == 1); 118219089Spjd for (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 136185029Spjdzap_normalize(zap_t *zap, const char *name, char *namenorm) 137185029Spjd{ 138185029Spjd size_t inlen, outlen; 139185029Spjd int err; 140185029Spjd 141219089Spjd ASSERT(!(zap_getflags(zap) & ZAP_FLAG_UINT64_KEY)); 142219089Spjd 143185029Spjd inlen = strlen(name) + 1; 144185029Spjd outlen = ZAP_MAXNAMELEN; 145185029Spjd 146185029Spjd err = 0; 147185029Spjd (void) u8_textprep_str((char *)name, &inlen, namenorm, &outlen, 148219089Spjd zap->zap_normflags | U8_TEXTPREP_IGNORE_NULL | 149219089Spjd U8_TEXTPREP_IGNORE_INVALID, U8_UNICODE_LATEST, &err); 150185029Spjd 151185029Spjd return (err); 152185029Spjd} 153185029Spjd 154185029Spjdboolean_t 155185029Spjdzap_match(zap_name_t *zn, const char *matchname) 156185029Spjd{ 157219089Spjd ASSERT(!(zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY)); 158219089Spjd 159185029Spjd if (zn->zn_matchtype == MT_FIRST) { 160185029Spjd char norm[ZAP_MAXNAMELEN]; 161185029Spjd 162185029Spjd if (zap_normalize(zn->zn_zap, matchname, norm) != 0) 163185029Spjd return (B_FALSE); 164185029Spjd 165219089Spjd return (strcmp(zn->zn_key_norm, norm) == 0); 166185029Spjd } else { 167185029Spjd /* MT_BEST or MT_EXACT */ 168219089Spjd return (strcmp(zn->zn_key_orig, matchname) == 0); 169185029Spjd } 170185029Spjd} 171185029Spjd 172185029Spjdvoid 173185029Spjdzap_name_free(zap_name_t *zn) 174185029Spjd{ 175185029Spjd kmem_free(zn, sizeof (zap_name_t)); 176185029Spjd} 177185029Spjd 178185029Spjdzap_name_t * 179219089Spjdzap_name_alloc(zap_t *zap, const char *key, matchtype_t mt) 180185029Spjd{ 181185029Spjd zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP); 182185029Spjd 183185029Spjd zn->zn_zap = zap; 184219089Spjd zn->zn_key_intlen = sizeof (*key); 185219089Spjd zn->zn_key_orig = key; 186219089Spjd zn->zn_key_orig_numints = strlen(zn->zn_key_orig) + 1; 187185029Spjd zn->zn_matchtype = mt; 188185029Spjd if (zap->zap_normflags) { 189219089Spjd if (zap_normalize(zap, key, zn->zn_normbuf) != 0) { 190185029Spjd zap_name_free(zn); 191185029Spjd return (NULL); 192185029Spjd } 193219089Spjd zn->zn_key_norm = zn->zn_normbuf; 194219089Spjd zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1; 195185029Spjd } else { 196185029Spjd if (mt != MT_EXACT) { 197185029Spjd zap_name_free(zn); 198185029Spjd return (NULL); 199185029Spjd } 200219089Spjd zn->zn_key_norm = zn->zn_key_orig; 201219089Spjd zn->zn_key_norm_numints = zn->zn_key_orig_numints; 202185029Spjd } 203185029Spjd 204219089Spjd zn->zn_hash = zap_hash(zn); 205185029Spjd return (zn); 206185029Spjd} 207185029Spjd 208219089Spjdzap_name_t * 209219089Spjdzap_name_alloc_uint64(zap_t *zap, const uint64_t *key, int numints) 210219089Spjd{ 211219089Spjd zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP); 212219089Spjd 213219089Spjd ASSERT(zap->zap_normflags == 0); 214219089Spjd zn->zn_zap = zap; 215219089Spjd zn->zn_key_intlen = sizeof (*key); 216219089Spjd zn->zn_key_orig = zn->zn_key_norm = key; 217219089Spjd zn->zn_key_orig_numints = zn->zn_key_norm_numints = numints; 218219089Spjd zn->zn_matchtype = MT_EXACT; 219219089Spjd 220219089Spjd zn->zn_hash = zap_hash(zn); 221219089Spjd return (zn); 222219089Spjd} 223219089Spjd 224168404Spjdstatic void 225168404Spjdmzap_byteswap(mzap_phys_t *buf, size_t size) 226168404Spjd{ 227168404Spjd int i, max; 228168404Spjd buf->mz_block_type = BSWAP_64(buf->mz_block_type); 229168404Spjd buf->mz_salt = BSWAP_64(buf->mz_salt); 230185029Spjd buf->mz_normflags = BSWAP_64(buf->mz_normflags); 231168404Spjd max = (size / MZAP_ENT_LEN) - 1; 232168404Spjd for (i = 0; i < max; i++) { 233168404Spjd buf->mz_chunk[i].mze_value = 234168404Spjd BSWAP_64(buf->mz_chunk[i].mze_value); 235168404Spjd buf->mz_chunk[i].mze_cd = 236168404Spjd BSWAP_32(buf->mz_chunk[i].mze_cd); 237168404Spjd } 238168404Spjd} 239168404Spjd 240168404Spjdvoid 241168404Spjdzap_byteswap(void *buf, size_t size) 242168404Spjd{ 243168404Spjd uint64_t block_type; 244168404Spjd 245168404Spjd block_type = *(uint64_t *)buf; 246168404Spjd 247168404Spjd if (block_type == ZBT_MICRO || block_type == BSWAP_64(ZBT_MICRO)) { 248168404Spjd /* ASSERT(magic == ZAP_LEAF_MAGIC); */ 249168404Spjd mzap_byteswap(buf, size); 250168404Spjd } else { 251168404Spjd fzap_byteswap(buf, size); 252168404Spjd } 253168404Spjd} 254168404Spjd 255168404Spjdstatic int 256168404Spjdmze_compare(const void *arg1, const void *arg2) 257168404Spjd{ 258168404Spjd const mzap_ent_t *mze1 = arg1; 259168404Spjd const mzap_ent_t *mze2 = arg2; 260168404Spjd 261168404Spjd if (mze1->mze_hash > mze2->mze_hash) 262168404Spjd return (+1); 263168404Spjd if (mze1->mze_hash < mze2->mze_hash) 264168404Spjd return (-1); 265219089Spjd if (mze1->mze_cd > mze2->mze_cd) 266168404Spjd return (+1); 267219089Spjd if (mze1->mze_cd < mze2->mze_cd) 268168404Spjd return (-1); 269168404Spjd return (0); 270168404Spjd} 271168404Spjd 272197150Spjdstatic int 273219089Spjdmze_insert(zap_t *zap, int chunkid, uint64_t hash) 274168404Spjd{ 275168404Spjd mzap_ent_t *mze; 276197150Spjd avl_index_t idx; 277168404Spjd 278168404Spjd ASSERT(zap->zap_ismicro); 279168404Spjd ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 280168404Spjd 281168404Spjd mze = kmem_alloc(sizeof (mzap_ent_t), KM_SLEEP); 282168404Spjd mze->mze_chunkid = chunkid; 283168404Spjd mze->mze_hash = hash; 284219089Spjd mze->mze_cd = MZE_PHYS(zap, mze)->mze_cd; 285219089Spjd ASSERT(MZE_PHYS(zap, mze)->mze_name[0] != 0); 286197150Spjd if (avl_find(&zap->zap_m.zap_avl, mze, &idx) != NULL) { 287197150Spjd kmem_free(mze, sizeof (mzap_ent_t)); 288197150Spjd return (EEXIST); 289197150Spjd } 290197150Spjd avl_insert(&zap->zap_m.zap_avl, mze, idx); 291197150Spjd return (0); 292168404Spjd} 293168404Spjd 294168404Spjdstatic mzap_ent_t * 295185029Spjdmze_find(zap_name_t *zn) 296168404Spjd{ 297168404Spjd mzap_ent_t mze_tofind; 298168404Spjd mzap_ent_t *mze; 299168404Spjd avl_index_t idx; 300185029Spjd avl_tree_t *avl = &zn->zn_zap->zap_m.zap_avl; 301168404Spjd 302185029Spjd ASSERT(zn->zn_zap->zap_ismicro); 303185029Spjd ASSERT(RW_LOCK_HELD(&zn->zn_zap->zap_rwlock)); 304168404Spjd 305185029Spjd mze_tofind.mze_hash = zn->zn_hash; 306219089Spjd mze_tofind.mze_cd = 0; 307168404Spjd 308185029Spjdagain: 309168404Spjd mze = avl_find(avl, &mze_tofind, &idx); 310168404Spjd if (mze == NULL) 311168404Spjd mze = avl_nearest(avl, idx, AVL_AFTER); 312185029Spjd for (; mze && mze->mze_hash == zn->zn_hash; mze = AVL_NEXT(avl, mze)) { 313219089Spjd ASSERT3U(mze->mze_cd, ==, MZE_PHYS(zn->zn_zap, mze)->mze_cd); 314219089Spjd if (zap_match(zn, MZE_PHYS(zn->zn_zap, mze)->mze_name)) 315168404Spjd return (mze); 316168404Spjd } 317185029Spjd if (zn->zn_matchtype == MT_BEST) { 318185029Spjd zn->zn_matchtype = MT_FIRST; 319185029Spjd goto again; 320185029Spjd } 321168404Spjd return (NULL); 322168404Spjd} 323168404Spjd 324168404Spjdstatic uint32_t 325168404Spjdmze_find_unused_cd(zap_t *zap, uint64_t hash) 326168404Spjd{ 327168404Spjd mzap_ent_t mze_tofind; 328168404Spjd mzap_ent_t *mze; 329168404Spjd avl_index_t idx; 330168404Spjd avl_tree_t *avl = &zap->zap_m.zap_avl; 331168404Spjd uint32_t cd; 332168404Spjd 333168404Spjd ASSERT(zap->zap_ismicro); 334168404Spjd ASSERT(RW_LOCK_HELD(&zap->zap_rwlock)); 335168404Spjd 336168404Spjd mze_tofind.mze_hash = hash; 337219089Spjd mze_tofind.mze_cd = 0; 338168404Spjd 339168404Spjd cd = 0; 340168404Spjd for (mze = avl_find(avl, &mze_tofind, &idx); 341168404Spjd mze && mze->mze_hash == hash; mze = AVL_NEXT(avl, mze)) { 342219089Spjd if (mze->mze_cd != cd) 343168404Spjd break; 344168404Spjd cd++; 345168404Spjd } 346168404Spjd 347168404Spjd return (cd); 348168404Spjd} 349168404Spjd 350168404Spjdstatic void 351168404Spjdmze_remove(zap_t *zap, mzap_ent_t *mze) 352168404Spjd{ 353168404Spjd ASSERT(zap->zap_ismicro); 354168404Spjd ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 355168404Spjd 356168404Spjd avl_remove(&zap->zap_m.zap_avl, mze); 357168404Spjd kmem_free(mze, sizeof (mzap_ent_t)); 358168404Spjd} 359168404Spjd 360168404Spjdstatic void 361168404Spjdmze_destroy(zap_t *zap) 362168404Spjd{ 363168404Spjd mzap_ent_t *mze; 364168404Spjd void *avlcookie = NULL; 365168404Spjd 366168404Spjd while (mze = avl_destroy_nodes(&zap->zap_m.zap_avl, &avlcookie)) 367168404Spjd kmem_free(mze, sizeof (mzap_ent_t)); 368168404Spjd avl_destroy(&zap->zap_m.zap_avl); 369168404Spjd} 370168404Spjd 371168404Spjdstatic zap_t * 372168404Spjdmzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db) 373168404Spjd{ 374168404Spjd zap_t *winner; 375168404Spjd zap_t *zap; 376168404Spjd int i; 377168404Spjd 378168404Spjd ASSERT3U(MZAP_ENT_LEN, ==, sizeof (mzap_ent_phys_t)); 379168404Spjd 380168404Spjd zap = kmem_zalloc(sizeof (zap_t), KM_SLEEP); 381219089Spjd rw_init(&zap->zap_rwlock, 0, 0, 0); 382168404Spjd rw_enter(&zap->zap_rwlock, RW_WRITER); 383168404Spjd zap->zap_objset = os; 384168404Spjd zap->zap_object = obj; 385168404Spjd zap->zap_dbuf = db; 386168404Spjd 387185029Spjd if (*(uint64_t *)db->db_data != ZBT_MICRO) { 388219089Spjd mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0); 389265740Sdelphij zap->zap_f.zap_block_shift = highbit64(db->db_size) - 1; 390168404Spjd } else { 391168404Spjd zap->zap_ismicro = TRUE; 392168404Spjd } 393168404Spjd 394168404Spjd /* 395168404Spjd * Make sure that zap_ismicro is set before we let others see 396168404Spjd * it, because zap_lockdir() checks zap_ismicro without the lock 397168404Spjd * held. 398168404Spjd */ 399288549Smav dmu_buf_init_user(&zap->zap_dbu, zap_evict, &zap->zap_dbuf); 400288549Smav winner = dmu_buf_set_user(db, &zap->zap_dbu); 401168404Spjd 402168404Spjd if (winner != NULL) { 403172443Spjd rw_exit(&zap->zap_rwlock); 404172443Spjd rw_destroy(&zap->zap_rwlock); 405168404Spjd if (!zap->zap_ismicro) 406168404Spjd mutex_destroy(&zap->zap_f.zap_num_entries_mtx); 407168404Spjd kmem_free(zap, sizeof (zap_t)); 408168404Spjd return (winner); 409168404Spjd } 410168404Spjd 411168404Spjd if (zap->zap_ismicro) { 412277585Sdelphij zap->zap_salt = zap_m_phys(zap)->mz_salt; 413277585Sdelphij zap->zap_normflags = zap_m_phys(zap)->mz_normflags; 414168404Spjd zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1; 415168404Spjd avl_create(&zap->zap_m.zap_avl, mze_compare, 416168404Spjd sizeof (mzap_ent_t), offsetof(mzap_ent_t, mze_node)); 417168404Spjd 418168404Spjd for (i = 0; i < zap->zap_m.zap_num_chunks; i++) { 419168404Spjd mzap_ent_phys_t *mze = 420277585Sdelphij &zap_m_phys(zap)->mz_chunk[i]; 421168404Spjd if (mze->mze_name[0]) { 422185029Spjd zap_name_t *zn; 423185029Spjd 424185029Spjd zn = zap_name_alloc(zap, mze->mze_name, 425185029Spjd MT_EXACT); 426219089Spjd if (mze_insert(zap, i, zn->zn_hash) == 0) 427197150Spjd zap->zap_m.zap_num_entries++; 428197150Spjd else { 429197150Spjd printf("ZFS WARNING: Duplicated ZAP " 430197172Spjd "entry detected (%s).\n", 431197150Spjd mze->mze_name); 432197150Spjd } 433185029Spjd zap_name_free(zn); 434168404Spjd } 435168404Spjd } 436168404Spjd } else { 437277585Sdelphij zap->zap_salt = zap_f_phys(zap)->zap_salt; 438277585Sdelphij zap->zap_normflags = zap_f_phys(zap)->zap_normflags; 439168404Spjd 440168404Spjd ASSERT3U(sizeof (struct zap_leaf_header), ==, 441168404Spjd 2*ZAP_LEAF_CHUNKSIZE); 442168404Spjd 443168404Spjd /* 444168404Spjd * The embedded pointer table should not overlap the 445168404Spjd * other members. 446168404Spjd */ 447168404Spjd ASSERT3P(&ZAP_EMBEDDED_PTRTBL_ENT(zap, 0), >, 448277585Sdelphij &zap_f_phys(zap)->zap_salt); 449168404Spjd 450168404Spjd /* 451168404Spjd * The embedded pointer table should end at the end of 452168404Spjd * the block 453168404Spjd */ 454168404Spjd ASSERT3U((uintptr_t)&ZAP_EMBEDDED_PTRTBL_ENT(zap, 455168404Spjd 1<<ZAP_EMBEDDED_PTRTBL_SHIFT(zap)) - 456277585Sdelphij (uintptr_t)zap_f_phys(zap), ==, 457168404Spjd zap->zap_dbuf->db_size); 458168404Spjd } 459168404Spjd rw_exit(&zap->zap_rwlock); 460168404Spjd return (zap); 461168404Spjd} 462168404Spjd 463307287Smavstatic int 464307287Smavzap_lockdir_impl(dmu_buf_t *db, void *tag, dmu_tx_t *tx, 465185029Spjd krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp) 466168404Spjd{ 467168404Spjd zap_t *zap; 468168404Spjd krw_t lt; 469168404Spjd 470307287Smav ASSERT0(db->db_offset); 471307287Smav objset_t *os = dmu_buf_get_objset(db); 472307287Smav uint64_t obj = db->db_object; 473307287Smav 474168404Spjd *zapp = NULL; 475168404Spjd 476168404Spjd#ifdef ZFS_DEBUG 477168404Spjd { 478168404Spjd dmu_object_info_t doi; 479168404Spjd dmu_object_info_from_db(db, &doi); 480236884Smm ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP); 481168404Spjd } 482168404Spjd#endif 483168404Spjd 484168404Spjd zap = dmu_buf_get_user(db); 485168404Spjd if (zap == NULL) 486168404Spjd zap = mzap_open(os, obj, db); 487168404Spjd 488168404Spjd /* 489168404Spjd * We're checking zap_ismicro without the lock held, in order to 490168404Spjd * tell what type of lock we want. Once we have some sort of 491168404Spjd * lock, see if it really is the right type. In practice this 492168404Spjd * can only be different if it was upgraded from micro to fat, 493168404Spjd * and micro wanted WRITER but fat only needs READER. 494168404Spjd */ 495168404Spjd lt = (!zap->zap_ismicro && fatreader) ? RW_READER : lti; 496168404Spjd rw_enter(&zap->zap_rwlock, lt); 497168404Spjd if (lt != ((!zap->zap_ismicro && fatreader) ? RW_READER : lti)) { 498168404Spjd /* it was upgraded, now we only need reader */ 499168404Spjd ASSERT(lt == RW_WRITER); 500168404Spjd ASSERT(RW_READER == 501168404Spjd (!zap->zap_ismicro && fatreader) ? RW_READER : lti); 502168404Spjd rw_downgrade(&zap->zap_rwlock); 503168404Spjd lt = RW_READER; 504168404Spjd } 505168404Spjd 506168404Spjd zap->zap_objset = os; 507168404Spjd 508168404Spjd if (lt == RW_WRITER) 509168404Spjd dmu_buf_will_dirty(db, tx); 510168404Spjd 511168404Spjd ASSERT3P(zap->zap_dbuf, ==, db); 512168404Spjd 513168404Spjd ASSERT(!zap->zap_ismicro || 514168404Spjd zap->zap_m.zap_num_entries <= zap->zap_m.zap_num_chunks); 515185029Spjd if (zap->zap_ismicro && tx && adding && 516168404Spjd zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) { 517168404Spjd uint64_t newsz = db->db_size + SPA_MINBLOCKSIZE; 518168404Spjd if (newsz > MZAP_MAX_BLKSZ) { 519168404Spjd dprintf("upgrading obj %llu: num_entries=%u\n", 520168404Spjd obj, zap->zap_m.zap_num_entries); 521168404Spjd *zapp = zap; 522307287Smav int err = mzap_upgrade(zapp, tag, tx, 0); 523307287Smav if (err != 0) 524307287Smav rw_exit(&zap->zap_rwlock); 525307287Smav return (err); 526168404Spjd } 527307287Smav VERIFY0(dmu_object_set_blocksize(os, obj, newsz, 0, tx)); 528168404Spjd zap->zap_m.zap_num_chunks = 529168404Spjd db->db_size / MZAP_ENT_LEN - 1; 530168404Spjd } 531168404Spjd 532168404Spjd *zapp = zap; 533168404Spjd return (0); 534168404Spjd} 535168404Spjd 536307292Smavstatic int 537307292Smavzap_lockdir_by_dnode(dnode_t *dn, dmu_tx_t *tx, 538307292Smav krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp) 539307292Smav{ 540307292Smav dmu_buf_t *db; 541307292Smav int err; 542307292Smav 543307292Smav err = dmu_buf_hold_by_dnode(dn, 0, tag, &db, DMU_READ_NO_PREFETCH); 544307292Smav if (err != 0) { 545307292Smav return (err); 546307292Smav } 547307292Smav err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp); 548307292Smav if (err != 0) { 549307292Smav dmu_buf_rele(db, tag); 550307292Smav } 551307292Smav return (err); 552307292Smav} 553307292Smav 554307287Smavint 555307287Smavzap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx, 556307287Smav krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp) 557307287Smav{ 558307287Smav dmu_buf_t *db; 559307287Smav int err; 560307287Smav 561307287Smav err = dmu_buf_hold(os, obj, 0, tag, &db, DMU_READ_NO_PREFETCH); 562307287Smav if (err != 0) 563307287Smav return (err); 564307287Smav err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp); 565307287Smav if (err != 0) 566307287Smav dmu_buf_rele(db, tag); 567307287Smav return (err); 568307287Smav} 569307287Smav 570168404Spjdvoid 571307287Smavzap_unlockdir(zap_t *zap, void *tag) 572168404Spjd{ 573168404Spjd rw_exit(&zap->zap_rwlock); 574307287Smav dmu_buf_rele(zap->zap_dbuf, tag); 575168404Spjd} 576168404Spjd 577185029Spjdstatic int 578307287Smavmzap_upgrade(zap_t **zapp, void *tag, dmu_tx_t *tx, zap_flags_t flags) 579168404Spjd{ 580168404Spjd mzap_phys_t *mzp; 581219089Spjd int i, sz, nchunks; 582219089Spjd int err = 0; 583185029Spjd zap_t *zap = *zapp; 584168404Spjd 585168404Spjd ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 586168404Spjd 587168404Spjd sz = zap->zap_dbuf->db_size; 588288546Smav mzp = zio_buf_alloc(sz); 589168404Spjd bcopy(zap->zap_dbuf->db_data, mzp, sz); 590168404Spjd nchunks = zap->zap_m.zap_num_chunks; 591168404Spjd 592219089Spjd if (!flags) { 593219089Spjd err = dmu_object_set_blocksize(zap->zap_objset, zap->zap_object, 594219089Spjd 1ULL << fzap_default_block_shift, 0, tx); 595219089Spjd if (err) { 596288546Smav zio_buf_free(mzp, sz); 597219089Spjd return (err); 598219089Spjd } 599185029Spjd } 600168404Spjd 601168404Spjd dprintf("upgrading obj=%llu with %u chunks\n", 602168404Spjd zap->zap_object, nchunks); 603185029Spjd /* XXX destroy the avl later, so we can use the stored hash value */ 604168404Spjd mze_destroy(zap); 605168404Spjd 606219089Spjd fzap_upgrade(zap, tx, flags); 607168404Spjd 608168404Spjd for (i = 0; i < nchunks; i++) { 609168404Spjd mzap_ent_phys_t *mze = &mzp->mz_chunk[i]; 610185029Spjd zap_name_t *zn; 611168404Spjd if (mze->mze_name[0] == 0) 612168404Spjd continue; 613168404Spjd dprintf("adding %s=%llu\n", 614168404Spjd mze->mze_name, mze->mze_value); 615185029Spjd zn = zap_name_alloc(zap, mze->mze_name, MT_EXACT); 616307287Smav err = fzap_add_cd(zn, 8, 1, &mze->mze_value, mze->mze_cd, 617307287Smav tag, tx); 618185029Spjd zap = zn->zn_zap; /* fzap_add_cd() may change zap */ 619185029Spjd zap_name_free(zn); 620185029Spjd if (err) 621185029Spjd break; 622168404Spjd } 623288546Smav zio_buf_free(mzp, sz); 624185029Spjd *zapp = zap; 625185029Spjd return (err); 626168404Spjd} 627168404Spjd 628263390Sdelphijvoid 629219089Spjdmzap_create_impl(objset_t *os, uint64_t obj, int normflags, zap_flags_t flags, 630219089Spjd dmu_tx_t *tx) 631168404Spjd{ 632168404Spjd dmu_buf_t *db; 633168404Spjd mzap_phys_t *zp; 634168404Spjd 635219089Spjd VERIFY(0 == dmu_buf_hold(os, obj, 0, FTAG, &db, DMU_READ_NO_PREFETCH)); 636168404Spjd 637168404Spjd#ifdef ZFS_DEBUG 638168404Spjd { 639168404Spjd dmu_object_info_t doi; 640168404Spjd dmu_object_info_from_db(db, &doi); 641236884Smm ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP); 642168404Spjd } 643168404Spjd#endif 644168404Spjd 645168404Spjd dmu_buf_will_dirty(db, tx); 646168404Spjd zp = db->db_data; 647168404Spjd zp->mz_block_type = ZBT_MICRO; 648168404Spjd zp->mz_salt = ((uintptr_t)db ^ (uintptr_t)tx ^ (obj << 1)) | 1ULL; 649185029Spjd zp->mz_normflags = normflags; 650168404Spjd dmu_buf_rele(db, FTAG); 651219089Spjd 652219089Spjd if (flags != 0) { 653219089Spjd zap_t *zap; 654219089Spjd /* Only fat zap supports flags; upgrade immediately. */ 655219089Spjd VERIFY(0 == zap_lockdir(os, obj, tx, RW_WRITER, 656307287Smav B_FALSE, B_FALSE, FTAG, &zap)); 657307287Smav VERIFY3U(0, ==, mzap_upgrade(&zap, FTAG, tx, flags)); 658307287Smav zap_unlockdir(zap, FTAG); 659219089Spjd } 660168404Spjd} 661168404Spjd 662168404Spjdint 663168404Spjdzap_create_claim(objset_t *os, uint64_t obj, dmu_object_type_t ot, 664168404Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 665168404Spjd{ 666185029Spjd return (zap_create_claim_norm(os, obj, 667185029Spjd 0, ot, bonustype, bonuslen, tx)); 668185029Spjd} 669185029Spjd 670185029Spjdint 671185029Spjdzap_create_claim_norm(objset_t *os, uint64_t obj, int normflags, 672185029Spjd dmu_object_type_t ot, 673185029Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 674185029Spjd{ 675168404Spjd int err; 676168404Spjd 677168404Spjd err = dmu_object_claim(os, obj, ot, 0, bonustype, bonuslen, tx); 678168404Spjd if (err != 0) 679168404Spjd return (err); 680219089Spjd mzap_create_impl(os, obj, normflags, 0, tx); 681168404Spjd return (0); 682168404Spjd} 683168404Spjd 684168404Spjduint64_t 685168404Spjdzap_create(objset_t *os, dmu_object_type_t ot, 686168404Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 687168404Spjd{ 688185029Spjd return (zap_create_norm(os, 0, ot, bonustype, bonuslen, tx)); 689185029Spjd} 690185029Spjd 691185029Spjduint64_t 692185029Spjdzap_create_norm(objset_t *os, int normflags, dmu_object_type_t ot, 693185029Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 694185029Spjd{ 695168404Spjd uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx); 696168404Spjd 697219089Spjd mzap_create_impl(os, obj, normflags, 0, tx); 698168404Spjd return (obj); 699168404Spjd} 700168404Spjd 701219089Spjduint64_t 702219089Spjdzap_create_flags(objset_t *os, int normflags, zap_flags_t flags, 703219089Spjd dmu_object_type_t ot, int leaf_blockshift, int indirect_blockshift, 704219089Spjd dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) 705219089Spjd{ 706219089Spjd uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx); 707219089Spjd 708219089Spjd ASSERT(leaf_blockshift >= SPA_MINBLOCKSHIFT && 709276081Sdelphij leaf_blockshift <= SPA_OLD_MAXBLOCKSHIFT && 710219089Spjd indirect_blockshift >= SPA_MINBLOCKSHIFT && 711276081Sdelphij indirect_blockshift <= SPA_OLD_MAXBLOCKSHIFT); 712219089Spjd 713219089Spjd VERIFY(dmu_object_set_blocksize(os, obj, 714219089Spjd 1ULL << leaf_blockshift, indirect_blockshift, tx) == 0); 715219089Spjd 716219089Spjd mzap_create_impl(os, obj, normflags, flags, tx); 717219089Spjd return (obj); 718219089Spjd} 719219089Spjd 720168404Spjdint 721168404Spjdzap_destroy(objset_t *os, uint64_t zapobj, dmu_tx_t *tx) 722168404Spjd{ 723168404Spjd /* 724168404Spjd * dmu_object_free will free the object number and free the 725168404Spjd * data. Freeing the data will cause our pageout function to be 726168404Spjd * called, which will destroy our data (zap_leaf_t's and zap_t). 727168404Spjd */ 728168404Spjd 729168404Spjd return (dmu_object_free(os, zapobj, tx)); 730168404Spjd} 731168404Spjd 732168404Spjdvoid 733288549Smavzap_evict(void *dbu) 734168404Spjd{ 735288549Smav zap_t *zap = dbu; 736168404Spjd 737168404Spjd rw_destroy(&zap->zap_rwlock); 738168404Spjd 739168404Spjd if (zap->zap_ismicro) 740168404Spjd mze_destroy(zap); 741168404Spjd else 742168404Spjd mutex_destroy(&zap->zap_f.zap_num_entries_mtx); 743168404Spjd 744168404Spjd kmem_free(zap, sizeof (zap_t)); 745168404Spjd} 746168404Spjd 747168404Spjdint 748168404Spjdzap_count(objset_t *os, uint64_t zapobj, uint64_t *count) 749168404Spjd{ 750168404Spjd zap_t *zap; 751168404Spjd int err; 752168404Spjd 753307287Smav err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 754168404Spjd if (err) 755168404Spjd return (err); 756168404Spjd if (!zap->zap_ismicro) { 757168404Spjd err = fzap_count(zap, count); 758168404Spjd } else { 759168404Spjd *count = zap->zap_m.zap_num_entries; 760168404Spjd } 761307287Smav zap_unlockdir(zap, FTAG); 762168404Spjd return (err); 763168404Spjd} 764168404Spjd 765168404Spjd/* 766185029Spjd * zn may be NULL; if not specified, it will be computed if needed. 767185029Spjd * See also the comment above zap_entry_normalization_conflict(). 768168404Spjd */ 769185029Spjdstatic boolean_t 770185029Spjdmzap_normalization_conflict(zap_t *zap, zap_name_t *zn, mzap_ent_t *mze) 771185029Spjd{ 772185029Spjd mzap_ent_t *other; 773185029Spjd int direction = AVL_BEFORE; 774185029Spjd boolean_t allocdzn = B_FALSE; 775168404Spjd 776185029Spjd if (zap->zap_normflags == 0) 777185029Spjd return (B_FALSE); 778185029Spjd 779185029Spjdagain: 780185029Spjd for (other = avl_walk(&zap->zap_m.zap_avl, mze, direction); 781185029Spjd other && other->mze_hash == mze->mze_hash; 782185029Spjd other = avl_walk(&zap->zap_m.zap_avl, other, direction)) { 783185029Spjd 784185029Spjd if (zn == NULL) { 785219089Spjd zn = zap_name_alloc(zap, MZE_PHYS(zap, mze)->mze_name, 786185029Spjd MT_FIRST); 787185029Spjd allocdzn = B_TRUE; 788185029Spjd } 789219089Spjd if (zap_match(zn, MZE_PHYS(zap, other)->mze_name)) { 790185029Spjd if (allocdzn) 791185029Spjd zap_name_free(zn); 792185029Spjd return (B_TRUE); 793185029Spjd } 794185029Spjd } 795185029Spjd 796185029Spjd if (direction == AVL_BEFORE) { 797185029Spjd direction = AVL_AFTER; 798185029Spjd goto again; 799185029Spjd } 800185029Spjd 801185029Spjd if (allocdzn) 802185029Spjd zap_name_free(zn); 803185029Spjd return (B_FALSE); 804185029Spjd} 805185029Spjd 806185029Spjd/* 807185029Spjd * Routines for manipulating attributes. 808185029Spjd */ 809185029Spjd 810168404Spjdint 811168404Spjdzap_lookup(objset_t *os, uint64_t zapobj, const char *name, 812168404Spjd uint64_t integer_size, uint64_t num_integers, void *buf) 813168404Spjd{ 814185029Spjd return (zap_lookup_norm(os, zapobj, name, integer_size, 815185029Spjd num_integers, buf, MT_EXACT, NULL, 0, NULL)); 816185029Spjd} 817185029Spjd 818307287Smavstatic int 819307287Smavzap_lookup_impl(zap_t *zap, const char *name, 820185029Spjd uint64_t integer_size, uint64_t num_integers, void *buf, 821185029Spjd matchtype_t mt, char *realname, int rn_len, 822185029Spjd boolean_t *ncp) 823185029Spjd{ 824307287Smav int err = 0; 825168404Spjd mzap_ent_t *mze; 826185029Spjd zap_name_t *zn; 827168404Spjd 828185029Spjd zn = zap_name_alloc(zap, name, mt); 829307287Smav if (zn == NULL) 830249195Smm return (SET_ERROR(ENOTSUP)); 831185029Spjd 832168404Spjd if (!zap->zap_ismicro) { 833185029Spjd err = fzap_lookup(zn, integer_size, num_integers, buf, 834185029Spjd realname, rn_len, ncp); 835168404Spjd } else { 836185029Spjd mze = mze_find(zn); 837168404Spjd if (mze == NULL) { 838249195Smm err = SET_ERROR(ENOENT); 839168404Spjd } else { 840185029Spjd if (num_integers < 1) { 841249195Smm err = SET_ERROR(EOVERFLOW); 842185029Spjd } else if (integer_size != 8) { 843249195Smm err = SET_ERROR(EINVAL); 844185029Spjd } else { 845219089Spjd *(uint64_t *)buf = 846219089Spjd MZE_PHYS(zap, mze)->mze_value; 847185029Spjd (void) strlcpy(realname, 848219089Spjd MZE_PHYS(zap, mze)->mze_name, rn_len); 849185029Spjd if (ncp) { 850185029Spjd *ncp = mzap_normalization_conflict(zap, 851185029Spjd zn, mze); 852185029Spjd } 853185029Spjd } 854168404Spjd } 855168404Spjd } 856185029Spjd zap_name_free(zn); 857168404Spjd return (err); 858168404Spjd} 859168404Spjd 860168404Spjdint 861307287Smavzap_lookup_norm(objset_t *os, uint64_t zapobj, const char *name, 862307287Smav uint64_t integer_size, uint64_t num_integers, void *buf, 863307287Smav matchtype_t mt, char *realname, int rn_len, 864307287Smav boolean_t *ncp) 865307287Smav{ 866307287Smav zap_t *zap; 867307287Smav int err; 868307287Smav 869307287Smav err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 870307287Smav if (err != 0) 871307287Smav return (err); 872307287Smav err = zap_lookup_impl(zap, name, integer_size, 873307287Smav num_integers, buf, mt, realname, rn_len, ncp); 874307287Smav zap_unlockdir(zap, FTAG); 875307287Smav return (err); 876307287Smav} 877307287Smav 878307287Smavint 879307292Smavzap_lookup_by_dnode(dnode_t *dn, const char *name, 880307292Smav uint64_t integer_size, uint64_t num_integers, void *buf) 881307292Smav{ 882307292Smav return (zap_lookup_norm_by_dnode(dn, name, integer_size, 883307292Smav num_integers, buf, MT_EXACT, NULL, 0, NULL)); 884307292Smav} 885307292Smav 886307292Smavint 887307292Smavzap_lookup_norm_by_dnode(dnode_t *dn, const char *name, 888307292Smav uint64_t integer_size, uint64_t num_integers, void *buf, 889307292Smav matchtype_t mt, char *realname, int rn_len, 890307292Smav boolean_t *ncp) 891307292Smav{ 892307292Smav zap_t *zap; 893307292Smav int err; 894307292Smav 895307292Smav err = zap_lockdir_by_dnode(dn, NULL, RW_READER, TRUE, FALSE, 896307292Smav FTAG, &zap); 897307292Smav if (err != 0) 898307292Smav return (err); 899307292Smav err = zap_lookup_impl(zap, name, integer_size, 900307292Smav num_integers, buf, mt, realname, rn_len, ncp); 901307292Smav zap_unlockdir(zap, FTAG); 902307292Smav return (err); 903307292Smav} 904307292Smav 905307292Smavint 906219089Spjdzap_prefetch_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 907219089Spjd int key_numints) 908219089Spjd{ 909219089Spjd zap_t *zap; 910219089Spjd int err; 911219089Spjd zap_name_t *zn; 912219089Spjd 913307287Smav err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 914219089Spjd if (err) 915219089Spjd return (err); 916219089Spjd zn = zap_name_alloc_uint64(zap, key, key_numints); 917219089Spjd if (zn == NULL) { 918307287Smav zap_unlockdir(zap, FTAG); 919249195Smm return (SET_ERROR(ENOTSUP)); 920219089Spjd } 921219089Spjd 922219089Spjd fzap_prefetch(zn); 923219089Spjd zap_name_free(zn); 924307287Smav zap_unlockdir(zap, FTAG); 925219089Spjd return (err); 926219089Spjd} 927219089Spjd 928219089Spjdint 929219089Spjdzap_lookup_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 930219089Spjd int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf) 931219089Spjd{ 932219089Spjd zap_t *zap; 933219089Spjd int err; 934219089Spjd zap_name_t *zn; 935219089Spjd 936307287Smav err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 937219089Spjd if (err) 938219089Spjd return (err); 939219089Spjd zn = zap_name_alloc_uint64(zap, key, key_numints); 940219089Spjd if (zn == NULL) { 941307287Smav zap_unlockdir(zap, FTAG); 942249195Smm return (SET_ERROR(ENOTSUP)); 943219089Spjd } 944219089Spjd 945219089Spjd err = fzap_lookup(zn, integer_size, num_integers, buf, 946219089Spjd NULL, 0, NULL); 947219089Spjd zap_name_free(zn); 948307287Smav zap_unlockdir(zap, FTAG); 949219089Spjd return (err); 950219089Spjd} 951219089Spjd 952219089Spjdint 953219089Spjdzap_contains(objset_t *os, uint64_t zapobj, const char *name) 954219089Spjd{ 955263390Sdelphij int err = zap_lookup_norm(os, zapobj, name, 0, 956263390Sdelphij 0, NULL, MT_EXACT, NULL, 0, NULL); 957219089Spjd if (err == EOVERFLOW || err == EINVAL) 958219089Spjd err = 0; /* found, but skipped reading the value */ 959219089Spjd return (err); 960219089Spjd} 961219089Spjd 962219089Spjdint 963168404Spjdzap_length(objset_t *os, uint64_t zapobj, const char *name, 964168404Spjd uint64_t *integer_size, uint64_t *num_integers) 965168404Spjd{ 966168404Spjd zap_t *zap; 967168404Spjd int err; 968168404Spjd mzap_ent_t *mze; 969185029Spjd zap_name_t *zn; 970168404Spjd 971307287Smav err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 972168404Spjd if (err) 973168404Spjd return (err); 974185029Spjd zn = zap_name_alloc(zap, name, MT_EXACT); 975185029Spjd if (zn == NULL) { 976307287Smav zap_unlockdir(zap, FTAG); 977249195Smm return (SET_ERROR(ENOTSUP)); 978185029Spjd } 979168404Spjd if (!zap->zap_ismicro) { 980185029Spjd err = fzap_length(zn, integer_size, num_integers); 981168404Spjd } else { 982185029Spjd mze = mze_find(zn); 983168404Spjd if (mze == NULL) { 984249195Smm err = SET_ERROR(ENOENT); 985168404Spjd } else { 986168404Spjd if (integer_size) 987168404Spjd *integer_size = 8; 988168404Spjd if (num_integers) 989168404Spjd *num_integers = 1; 990168404Spjd } 991168404Spjd } 992185029Spjd zap_name_free(zn); 993307287Smav zap_unlockdir(zap, FTAG); 994168404Spjd return (err); 995168404Spjd} 996168404Spjd 997219089Spjdint 998219089Spjdzap_length_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 999219089Spjd int key_numints, uint64_t *integer_size, uint64_t *num_integers) 1000219089Spjd{ 1001219089Spjd zap_t *zap; 1002219089Spjd int err; 1003219089Spjd zap_name_t *zn; 1004219089Spjd 1005307287Smav err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1006219089Spjd if (err) 1007219089Spjd return (err); 1008219089Spjd zn = zap_name_alloc_uint64(zap, key, key_numints); 1009219089Spjd if (zn == NULL) { 1010307287Smav zap_unlockdir(zap, FTAG); 1011249195Smm return (SET_ERROR(ENOTSUP)); 1012219089Spjd } 1013219089Spjd err = fzap_length(zn, integer_size, num_integers); 1014219089Spjd zap_name_free(zn); 1015307287Smav zap_unlockdir(zap, FTAG); 1016219089Spjd return (err); 1017219089Spjd} 1018219089Spjd 1019168404Spjdstatic void 1020185029Spjdmzap_addent(zap_name_t *zn, uint64_t value) 1021168404Spjd{ 1022168404Spjd int i; 1023185029Spjd zap_t *zap = zn->zn_zap; 1024168404Spjd int start = zap->zap_m.zap_alloc_next; 1025168404Spjd uint32_t cd; 1026168404Spjd 1027168404Spjd ASSERT(RW_WRITE_HELD(&zap->zap_rwlock)); 1028168404Spjd 1029168404Spjd#ifdef ZFS_DEBUG 1030168404Spjd for (i = 0; i < zap->zap_m.zap_num_chunks; i++) { 1031277585Sdelphij mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i]; 1032219089Spjd ASSERT(strcmp(zn->zn_key_orig, mze->mze_name) != 0); 1033168404Spjd } 1034168404Spjd#endif 1035168404Spjd 1036185029Spjd cd = mze_find_unused_cd(zap, zn->zn_hash); 1037168404Spjd /* given the limited size of the microzap, this can't happen */ 1038219089Spjd ASSERT(cd < zap_maxcd(zap)); 1039168404Spjd 1040168404Spjdagain: 1041168404Spjd for (i = start; i < zap->zap_m.zap_num_chunks; i++) { 1042277585Sdelphij mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i]; 1043168404Spjd if (mze->mze_name[0] == 0) { 1044168404Spjd mze->mze_value = value; 1045168404Spjd mze->mze_cd = cd; 1046219089Spjd (void) strcpy(mze->mze_name, zn->zn_key_orig); 1047168404Spjd zap->zap_m.zap_num_entries++; 1048168404Spjd zap->zap_m.zap_alloc_next = i+1; 1049168404Spjd if (zap->zap_m.zap_alloc_next == 1050168404Spjd zap->zap_m.zap_num_chunks) 1051168404Spjd zap->zap_m.zap_alloc_next = 0; 1052219089Spjd VERIFY(0 == mze_insert(zap, i, zn->zn_hash)); 1053168404Spjd return; 1054168404Spjd } 1055168404Spjd } 1056168404Spjd if (start != 0) { 1057168404Spjd start = 0; 1058168404Spjd goto again; 1059168404Spjd } 1060168404Spjd ASSERT(!"out of entries!"); 1061168404Spjd} 1062168404Spjd 1063168404Spjdint 1064219089Spjdzap_add(objset_t *os, uint64_t zapobj, const char *key, 1065168404Spjd int integer_size, uint64_t num_integers, 1066168404Spjd const void *val, dmu_tx_t *tx) 1067168404Spjd{ 1068168404Spjd zap_t *zap; 1069168404Spjd int err; 1070168404Spjd mzap_ent_t *mze; 1071168404Spjd const uint64_t *intval = val; 1072185029Spjd zap_name_t *zn; 1073168404Spjd 1074307287Smav err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1075168404Spjd if (err) 1076168404Spjd return (err); 1077219089Spjd zn = zap_name_alloc(zap, key, MT_EXACT); 1078185029Spjd if (zn == NULL) { 1079307287Smav zap_unlockdir(zap, FTAG); 1080249195Smm return (SET_ERROR(ENOTSUP)); 1081185029Spjd } 1082168404Spjd if (!zap->zap_ismicro) { 1083307287Smav err = fzap_add(zn, integer_size, num_integers, val, FTAG, tx); 1084185029Spjd zap = zn->zn_zap; /* fzap_add() may change zap */ 1085168404Spjd } else if (integer_size != 8 || num_integers != 1 || 1086219089Spjd strlen(key) >= MZAP_NAME_LEN) { 1087307287Smav err = mzap_upgrade(&zn->zn_zap, FTAG, tx, 0); 1088307287Smav if (err == 0) { 1089307287Smav err = fzap_add(zn, integer_size, num_integers, val, 1090307287Smav FTAG, tx); 1091307287Smav } 1092185029Spjd zap = zn->zn_zap; /* fzap_add() may change zap */ 1093168404Spjd } else { 1094185029Spjd mze = mze_find(zn); 1095168404Spjd if (mze != NULL) { 1096249195Smm err = SET_ERROR(EEXIST); 1097168404Spjd } else { 1098185029Spjd mzap_addent(zn, *intval); 1099168404Spjd } 1100168404Spjd } 1101185029Spjd ASSERT(zap == zn->zn_zap); 1102185029Spjd zap_name_free(zn); 1103185029Spjd if (zap != NULL) /* may be NULL if fzap_add() failed */ 1104307287Smav zap_unlockdir(zap, FTAG); 1105168404Spjd return (err); 1106168404Spjd} 1107168404Spjd 1108168404Spjdint 1109219089Spjdzap_add_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1110219089Spjd int key_numints, int integer_size, uint64_t num_integers, 1111219089Spjd const void *val, dmu_tx_t *tx) 1112219089Spjd{ 1113219089Spjd zap_t *zap; 1114219089Spjd int err; 1115219089Spjd zap_name_t *zn; 1116219089Spjd 1117307287Smav err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1118219089Spjd if (err) 1119219089Spjd return (err); 1120219089Spjd zn = zap_name_alloc_uint64(zap, key, key_numints); 1121219089Spjd if (zn == NULL) { 1122307287Smav zap_unlockdir(zap, FTAG); 1123249195Smm return (SET_ERROR(ENOTSUP)); 1124219089Spjd } 1125307287Smav err = fzap_add(zn, integer_size, num_integers, val, FTAG, tx); 1126219089Spjd zap = zn->zn_zap; /* fzap_add() may change zap */ 1127219089Spjd zap_name_free(zn); 1128219089Spjd if (zap != NULL) /* may be NULL if fzap_add() failed */ 1129307287Smav zap_unlockdir(zap, FTAG); 1130219089Spjd return (err); 1131219089Spjd} 1132219089Spjd 1133219089Spjdint 1134168404Spjdzap_update(objset_t *os, uint64_t zapobj, const char *name, 1135168404Spjd int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx) 1136168404Spjd{ 1137168404Spjd zap_t *zap; 1138168404Spjd mzap_ent_t *mze; 1139219089Spjd uint64_t oldval; 1140168404Spjd const uint64_t *intval = val; 1141185029Spjd zap_name_t *zn; 1142168404Spjd int err; 1143168404Spjd 1144219089Spjd#ifdef ZFS_DEBUG 1145219089Spjd /* 1146219089Spjd * If there is an old value, it shouldn't change across the 1147219089Spjd * lockdir (eg, due to bprewrite's xlation). 1148219089Spjd */ 1149219089Spjd if (integer_size == 8 && num_integers == 1) 1150219089Spjd (void) zap_lookup(os, zapobj, name, 8, 1, &oldval); 1151219089Spjd#endif 1152219089Spjd 1153307287Smav err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1154168404Spjd if (err) 1155168404Spjd return (err); 1156185029Spjd zn = zap_name_alloc(zap, name, MT_EXACT); 1157185029Spjd if (zn == NULL) { 1158307287Smav zap_unlockdir(zap, FTAG); 1159249195Smm return (SET_ERROR(ENOTSUP)); 1160185029Spjd } 1161168404Spjd if (!zap->zap_ismicro) { 1162307287Smav err = fzap_update(zn, integer_size, num_integers, val, 1163307287Smav FTAG, tx); 1164185029Spjd zap = zn->zn_zap; /* fzap_update() may change zap */ 1165168404Spjd } else if (integer_size != 8 || num_integers != 1 || 1166168404Spjd strlen(name) >= MZAP_NAME_LEN) { 1167168404Spjd dprintf("upgrading obj %llu: intsz=%u numint=%llu name=%s\n", 1168168404Spjd zapobj, integer_size, num_integers, name); 1169307287Smav err = mzap_upgrade(&zn->zn_zap, FTAG, tx, 0); 1170307287Smav if (err == 0) { 1171185029Spjd err = fzap_update(zn, integer_size, num_integers, 1172307287Smav val, FTAG, tx); 1173307287Smav } 1174185029Spjd zap = zn->zn_zap; /* fzap_update() may change zap */ 1175168404Spjd } else { 1176185029Spjd mze = mze_find(zn); 1177168404Spjd if (mze != NULL) { 1178219089Spjd ASSERT3U(MZE_PHYS(zap, mze)->mze_value, ==, oldval); 1179219089Spjd MZE_PHYS(zap, mze)->mze_value = *intval; 1180168404Spjd } else { 1181185029Spjd mzap_addent(zn, *intval); 1182168404Spjd } 1183168404Spjd } 1184185029Spjd ASSERT(zap == zn->zn_zap); 1185185029Spjd zap_name_free(zn); 1186185029Spjd if (zap != NULL) /* may be NULL if fzap_upgrade() failed */ 1187307287Smav zap_unlockdir(zap, FTAG); 1188168404Spjd return (err); 1189168404Spjd} 1190168404Spjd 1191168404Spjdint 1192219089Spjdzap_update_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1193219089Spjd int key_numints, 1194219089Spjd int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx) 1195219089Spjd{ 1196219089Spjd zap_t *zap; 1197219089Spjd zap_name_t *zn; 1198219089Spjd int err; 1199219089Spjd 1200307287Smav err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap); 1201219089Spjd if (err) 1202219089Spjd return (err); 1203219089Spjd zn = zap_name_alloc_uint64(zap, key, key_numints); 1204219089Spjd if (zn == NULL) { 1205307287Smav zap_unlockdir(zap, FTAG); 1206249195Smm return (SET_ERROR(ENOTSUP)); 1207219089Spjd } 1208307287Smav err = fzap_update(zn, integer_size, num_integers, val, FTAG, tx); 1209219089Spjd zap = zn->zn_zap; /* fzap_update() may change zap */ 1210219089Spjd zap_name_free(zn); 1211219089Spjd if (zap != NULL) /* may be NULL if fzap_upgrade() failed */ 1212307287Smav zap_unlockdir(zap, FTAG); 1213219089Spjd return (err); 1214219089Spjd} 1215219089Spjd 1216219089Spjdint 1217168404Spjdzap_remove(objset_t *os, uint64_t zapobj, const char *name, dmu_tx_t *tx) 1218168404Spjd{ 1219185029Spjd return (zap_remove_norm(os, zapobj, name, MT_EXACT, tx)); 1220185029Spjd} 1221185029Spjd 1222185029Spjdint 1223185029Spjdzap_remove_norm(objset_t *os, uint64_t zapobj, const char *name, 1224185029Spjd matchtype_t mt, dmu_tx_t *tx) 1225185029Spjd{ 1226168404Spjd zap_t *zap; 1227168404Spjd int err; 1228168404Spjd mzap_ent_t *mze; 1229185029Spjd zap_name_t *zn; 1230168404Spjd 1231307287Smav err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap); 1232168404Spjd if (err) 1233168404Spjd return (err); 1234185029Spjd zn = zap_name_alloc(zap, name, mt); 1235185029Spjd if (zn == NULL) { 1236307287Smav zap_unlockdir(zap, FTAG); 1237249195Smm return (SET_ERROR(ENOTSUP)); 1238185029Spjd } 1239168404Spjd if (!zap->zap_ismicro) { 1240185029Spjd err = fzap_remove(zn, tx); 1241168404Spjd } else { 1242185029Spjd mze = mze_find(zn); 1243168404Spjd if (mze == NULL) { 1244249195Smm err = SET_ERROR(ENOENT); 1245168404Spjd } else { 1246168404Spjd zap->zap_m.zap_num_entries--; 1247277585Sdelphij bzero(&zap_m_phys(zap)->mz_chunk[mze->mze_chunkid], 1248168404Spjd sizeof (mzap_ent_phys_t)); 1249168404Spjd mze_remove(zap, mze); 1250168404Spjd } 1251168404Spjd } 1252185029Spjd zap_name_free(zn); 1253307287Smav zap_unlockdir(zap, FTAG); 1254168404Spjd return (err); 1255168404Spjd} 1256168404Spjd 1257219089Spjdint 1258219089Spjdzap_remove_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key, 1259219089Spjd int key_numints, dmu_tx_t *tx) 1260219089Spjd{ 1261219089Spjd zap_t *zap; 1262219089Spjd int err; 1263219089Spjd zap_name_t *zn; 1264219089Spjd 1265307287Smav err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap); 1266219089Spjd if (err) 1267219089Spjd return (err); 1268219089Spjd zn = zap_name_alloc_uint64(zap, key, key_numints); 1269219089Spjd if (zn == NULL) { 1270307287Smav zap_unlockdir(zap, FTAG); 1271249195Smm return (SET_ERROR(ENOTSUP)); 1272219089Spjd } 1273219089Spjd err = fzap_remove(zn, tx); 1274219089Spjd zap_name_free(zn); 1275307287Smav zap_unlockdir(zap, FTAG); 1276219089Spjd return (err); 1277219089Spjd} 1278219089Spjd 1279168404Spjd/* 1280168404Spjd * Routines for iterating over the attributes. 1281168404Spjd */ 1282168404Spjd 1283168404Spjdvoid 1284168404Spjdzap_cursor_init_serialized(zap_cursor_t *zc, objset_t *os, uint64_t zapobj, 1285168404Spjd uint64_t serialized) 1286168404Spjd{ 1287168404Spjd zc->zc_objset = os; 1288168404Spjd zc->zc_zap = NULL; 1289168404Spjd zc->zc_leaf = NULL; 1290168404Spjd zc->zc_zapobj = zapobj; 1291219089Spjd zc->zc_serialized = serialized; 1292219089Spjd zc->zc_hash = 0; 1293219089Spjd zc->zc_cd = 0; 1294168404Spjd} 1295168404Spjd 1296168404Spjdvoid 1297168404Spjdzap_cursor_init(zap_cursor_t *zc, objset_t *os, uint64_t zapobj) 1298168404Spjd{ 1299168404Spjd zap_cursor_init_serialized(zc, os, zapobj, 0); 1300168404Spjd} 1301168404Spjd 1302168404Spjdvoid 1303168404Spjdzap_cursor_fini(zap_cursor_t *zc) 1304168404Spjd{ 1305168404Spjd if (zc->zc_zap) { 1306168404Spjd rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); 1307307287Smav zap_unlockdir(zc->zc_zap, NULL); 1308168404Spjd zc->zc_zap = NULL; 1309168404Spjd } 1310168404Spjd if (zc->zc_leaf) { 1311168404Spjd rw_enter(&zc->zc_leaf->l_rwlock, RW_READER); 1312168404Spjd zap_put_leaf(zc->zc_leaf); 1313168404Spjd zc->zc_leaf = NULL; 1314168404Spjd } 1315168404Spjd zc->zc_objset = NULL; 1316168404Spjd} 1317168404Spjd 1318168404Spjduint64_t 1319168404Spjdzap_cursor_serialize(zap_cursor_t *zc) 1320168404Spjd{ 1321168404Spjd if (zc->zc_hash == -1ULL) 1322168404Spjd return (-1ULL); 1323219089Spjd if (zc->zc_zap == NULL) 1324219089Spjd return (zc->zc_serialized); 1325219089Spjd ASSERT((zc->zc_hash & zap_maxcd(zc->zc_zap)) == 0); 1326219089Spjd ASSERT(zc->zc_cd < zap_maxcd(zc->zc_zap)); 1327219089Spjd 1328219089Spjd /* 1329219089Spjd * We want to keep the high 32 bits of the cursor zero if we can, so 1330219089Spjd * that 32-bit programs can access this. So usually use a small 1331219089Spjd * (28-bit) hash value so we can fit 4 bits of cd into the low 32-bits 1332219089Spjd * of the cursor. 1333219089Spjd * 1334219089Spjd * [ collision differentiator | zap_hashbits()-bit hash value ] 1335219089Spjd */ 1336219089Spjd return ((zc->zc_hash >> (64 - zap_hashbits(zc->zc_zap))) | 1337219089Spjd ((uint64_t)zc->zc_cd << zap_hashbits(zc->zc_zap))); 1338168404Spjd} 1339168404Spjd 1340168404Spjdint 1341168404Spjdzap_cursor_retrieve(zap_cursor_t *zc, zap_attribute_t *za) 1342168404Spjd{ 1343168404Spjd int err; 1344168404Spjd avl_index_t idx; 1345168404Spjd mzap_ent_t mze_tofind; 1346168404Spjd mzap_ent_t *mze; 1347168404Spjd 1348168404Spjd if (zc->zc_hash == -1ULL) 1349249195Smm return (SET_ERROR(ENOENT)); 1350168404Spjd 1351168404Spjd if (zc->zc_zap == NULL) { 1352219089Spjd int hb; 1353168404Spjd err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL, 1354307287Smav RW_READER, TRUE, FALSE, NULL, &zc->zc_zap); 1355168404Spjd if (err) 1356168404Spjd return (err); 1357219089Spjd 1358219089Spjd /* 1359219089Spjd * To support zap_cursor_init_serialized, advance, retrieve, 1360219089Spjd * we must add to the existing zc_cd, which may already 1361219089Spjd * be 1 due to the zap_cursor_advance. 1362219089Spjd */ 1363219089Spjd ASSERT(zc->zc_hash == 0); 1364219089Spjd hb = zap_hashbits(zc->zc_zap); 1365219089Spjd zc->zc_hash = zc->zc_serialized << (64 - hb); 1366219089Spjd zc->zc_cd += zc->zc_serialized >> hb; 1367219089Spjd if (zc->zc_cd >= zap_maxcd(zc->zc_zap)) /* corrupt serialized */ 1368219089Spjd zc->zc_cd = 0; 1369168404Spjd } else { 1370168404Spjd rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); 1371168404Spjd } 1372168404Spjd if (!zc->zc_zap->zap_ismicro) { 1373168404Spjd err = fzap_cursor_retrieve(zc->zc_zap, zc, za); 1374168404Spjd } else { 1375168404Spjd mze_tofind.mze_hash = zc->zc_hash; 1376219089Spjd mze_tofind.mze_cd = zc->zc_cd; 1377168404Spjd 1378168404Spjd mze = avl_find(&zc->zc_zap->zap_m.zap_avl, &mze_tofind, &idx); 1379168404Spjd if (mze == NULL) { 1380168404Spjd mze = avl_nearest(&zc->zc_zap->zap_m.zap_avl, 1381168404Spjd idx, AVL_AFTER); 1382168404Spjd } 1383168404Spjd if (mze) { 1384219089Spjd mzap_ent_phys_t *mzep = MZE_PHYS(zc->zc_zap, mze); 1385219089Spjd ASSERT3U(mze->mze_cd, ==, mzep->mze_cd); 1386185029Spjd za->za_normalization_conflict = 1387185029Spjd mzap_normalization_conflict(zc->zc_zap, NULL, mze); 1388168404Spjd za->za_integer_length = 8; 1389168404Spjd za->za_num_integers = 1; 1390219089Spjd za->za_first_integer = mzep->mze_value; 1391219089Spjd (void) strcpy(za->za_name, mzep->mze_name); 1392168404Spjd zc->zc_hash = mze->mze_hash; 1393219089Spjd zc->zc_cd = mze->mze_cd; 1394168404Spjd err = 0; 1395168404Spjd } else { 1396168404Spjd zc->zc_hash = -1ULL; 1397249195Smm err = SET_ERROR(ENOENT); 1398168404Spjd } 1399168404Spjd } 1400168404Spjd rw_exit(&zc->zc_zap->zap_rwlock); 1401168404Spjd return (err); 1402168404Spjd} 1403168404Spjd 1404168404Spjdvoid 1405168404Spjdzap_cursor_advance(zap_cursor_t *zc) 1406168404Spjd{ 1407168404Spjd if (zc->zc_hash == -1ULL) 1408168404Spjd return; 1409168404Spjd zc->zc_cd++; 1410219089Spjd} 1411219089Spjd 1412219089Spjdint 1413219089Spjdzap_cursor_move_to_key(zap_cursor_t *zc, const char *name, matchtype_t mt) 1414219089Spjd{ 1415219089Spjd int err = 0; 1416219089Spjd mzap_ent_t *mze; 1417219089Spjd zap_name_t *zn; 1418219089Spjd 1419219089Spjd if (zc->zc_zap == NULL) { 1420219089Spjd err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL, 1421307294Smav RW_READER, TRUE, FALSE, FTAG, &zc->zc_zap); 1422219089Spjd if (err) 1423219089Spjd return (err); 1424219089Spjd } else { 1425219089Spjd rw_enter(&zc->zc_zap->zap_rwlock, RW_READER); 1426168404Spjd } 1427219089Spjd 1428219089Spjd zn = zap_name_alloc(zc->zc_zap, name, mt); 1429219089Spjd if (zn == NULL) { 1430219089Spjd rw_exit(&zc->zc_zap->zap_rwlock); 1431249195Smm return (SET_ERROR(ENOTSUP)); 1432219089Spjd } 1433219089Spjd 1434219089Spjd if (!zc->zc_zap->zap_ismicro) { 1435219089Spjd err = fzap_cursor_move_to_key(zc, zn); 1436219089Spjd } else { 1437219089Spjd mze = mze_find(zn); 1438219089Spjd if (mze == NULL) { 1439249195Smm err = SET_ERROR(ENOENT); 1440219089Spjd goto out; 1441219089Spjd } 1442219089Spjd zc->zc_hash = mze->mze_hash; 1443219089Spjd zc->zc_cd = mze->mze_cd; 1444219089Spjd } 1445219089Spjd 1446219089Spjdout: 1447219089Spjd zap_name_free(zn); 1448219089Spjd rw_exit(&zc->zc_zap->zap_rwlock); 1449219089Spjd return (err); 1450168404Spjd} 1451168404Spjd 1452168404Spjdint 1453168404Spjdzap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs) 1454168404Spjd{ 1455168404Spjd int err; 1456168404Spjd zap_t *zap; 1457168404Spjd 1458307287Smav err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap); 1459168404Spjd if (err) 1460168404Spjd return (err); 1461168404Spjd 1462168404Spjd bzero(zs, sizeof (zap_stats_t)); 1463168404Spjd 1464168404Spjd if (zap->zap_ismicro) { 1465168404Spjd zs->zs_blocksize = zap->zap_dbuf->db_size; 1466168404Spjd zs->zs_num_entries = zap->zap_m.zap_num_entries; 1467168404Spjd zs->zs_num_blocks = 1; 1468168404Spjd } else { 1469168404Spjd fzap_get_stats(zap, zs); 1470168404Spjd } 1471307287Smav zap_unlockdir(zap, FTAG); 1472168404Spjd return (0); 1473168404Spjd} 1474209962Smm 1475209962Smmint 1476307292Smavzap_count_write_by_dnode(dnode_t *dn, const char *name, int add, 1477307057Smav refcount_t *towrite, refcount_t *tooverwrite) 1478209962Smm{ 1479209962Smm zap_t *zap; 1480209962Smm int err = 0; 1481209962Smm 1482209962Smm /* 1483209962Smm * Since, we don't have a name, we cannot figure out which blocks will 1484209962Smm * be affected in this operation. So, account for the worst case : 1485209962Smm * - 3 blocks overwritten: target leaf, ptrtbl block, header block 1486209962Smm * - 4 new blocks written if adding: 1487307057Smav * - 2 blocks for possibly split leaves, 1488307057Smav * - 2 grown ptrtbl blocks 1489209962Smm * 1490307287Smav * This also accommodates the case where an add operation to a fairly 1491209962Smm * large microzap results in a promotion to fatzap. 1492209962Smm */ 1493209962Smm if (name == NULL) { 1494307057Smav (void) refcount_add_many(towrite, 1495307057Smav (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE, FTAG); 1496209962Smm return (err); 1497209962Smm } 1498209962Smm 1499209962Smm /* 1500228103Smm * We lock the zap with adding == FALSE. Because, if we pass 1501209962Smm * the actual value of add, it could trigger a mzap_upgrade(). 1502209962Smm * At present we are just evaluating the possibility of this operation 1503307287Smav * and hence we do not want to trigger an upgrade. 1504209962Smm */ 1505307292Smav err = zap_lockdir_by_dnode(dn, NULL, RW_READER, TRUE, FALSE, 1506307287Smav FTAG, &zap); 1507307287Smav if (err != 0) 1508209962Smm return (err); 1509209962Smm 1510209962Smm if (!zap->zap_ismicro) { 1511209962Smm zap_name_t *zn = zap_name_alloc(zap, name, MT_EXACT); 1512209962Smm if (zn) { 1513209962Smm err = fzap_count_write(zn, add, towrite, 1514209962Smm tooverwrite); 1515209962Smm zap_name_free(zn); 1516209962Smm } else { 1517209962Smm /* 1518209962Smm * We treat this case as similar to (name == NULL) 1519209962Smm */ 1520307057Smav (void) refcount_add_many(towrite, 1521307057Smav (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE, FTAG); 1522209962Smm } 1523209962Smm } else { 1524209962Smm /* 1525209962Smm * We are here if (name != NULL) and this is a micro-zap. 1526209962Smm * We account for the header block depending on whether it 1527209962Smm * is freeable. 1528209962Smm * 1529209962Smm * Incase of an add-operation it is hard to find out 1530209962Smm * if this add will promote this microzap to fatzap. 1531209962Smm * Hence, we consider the worst case and account for the 1532209962Smm * blocks assuming this microzap would be promoted to a 1533209962Smm * fatzap. 1534209962Smm * 1535209962Smm * 1 block overwritten : header block 1536209962Smm * 4 new blocks written : 2 new split leaf, 2 grown 1537209962Smm * ptrtbl blocks 1538209962Smm */ 1539307057Smav if (dmu_buf_freeable(zap->zap_dbuf)) { 1540307057Smav (void) refcount_add_many(tooverwrite, 1541307057Smav MZAP_MAX_BLKSZ, FTAG); 1542307057Smav } else { 1543307057Smav (void) refcount_add_many(towrite, 1544307057Smav MZAP_MAX_BLKSZ, FTAG); 1545307057Smav } 1546209962Smm 1547209962Smm if (add) { 1548307057Smav (void) refcount_add_many(towrite, 1549307057Smav 4 * MZAP_MAX_BLKSZ, FTAG); 1550209962Smm } 1551209962Smm } 1552209962Smm 1553307287Smav zap_unlockdir(zap, FTAG); 1554209962Smm return (err); 1555209962Smm} 1556