xref: /illumos-gate/usr/src/uts/common/fs/zfs/zap_micro.c (revision 1c17160ac558f98048951327f4e9248d8f46acc0)
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  */
21*1c17160aSKevin Crowe 
22fa9e4066Sahrens /*
2347cb52daSJeff Bonwick  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24ae972795SMatthew Ahrens  * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
25bc9014e6SJustin Gibbs  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
26c3d26abcSMatthew Ahrens  * Copyright (c) 2014 Integros [integros.com]
27*1c17160aSKevin 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 			int i;
93486ae710SMatthew Ahrens 			const uint64_t *wp = zn->zn_key_norm;
94486ae710SMatthew Ahrens 
95486ae710SMatthew Ahrens 			ASSERT(zn->zn_key_intlen == 8);
96486ae710SMatthew Ahrens 			for (i = 0; i < zn->zn_key_norm_numints; wp++, i++) {
97486ae710SMatthew Ahrens 				int j;
98486ae710SMatthew Ahrens 				uint64_t word = *wp;
99486ae710SMatthew Ahrens 
100486ae710SMatthew Ahrens 				for (j = 0; j < zn->zn_key_intlen; j++) {
101486ae710SMatthew Ahrens 					h = (h >> 8) ^
102486ae710SMatthew Ahrens 					    zfs_crc64_table[(h ^ word) & 0xFF];
103486ae710SMatthew Ahrens 					word >>= NBBY;
104486ae710SMatthew Ahrens 				}
105486ae710SMatthew Ahrens 			}
106486ae710SMatthew Ahrens 		} else {
107486ae710SMatthew Ahrens 			int i, len;
108486ae710SMatthew Ahrens 			const uint8_t *cp = zn->zn_key_norm;
109486ae710SMatthew Ahrens 
110486ae710SMatthew Ahrens 			/*
111486ae710SMatthew Ahrens 			 * We previously stored the terminating null on
112486ae710SMatthew Ahrens 			 * disk, but didn't hash it, so we need to
113486ae710SMatthew Ahrens 			 * continue to not hash it.  (The
114486ae710SMatthew Ahrens 			 * zn_key_*_numints includes the terminating
115486ae710SMatthew Ahrens 			 * null for non-binary keys.)
116486ae710SMatthew Ahrens 			 */
117486ae710SMatthew Ahrens 			len = zn->zn_key_norm_numints - 1;
118486ae710SMatthew Ahrens 
119486ae710SMatthew Ahrens 			ASSERT(zn->zn_key_intlen == 1);
120486ae710SMatthew Ahrens 			for (i = 0; i < len; cp++, i++) {
121486ae710SMatthew Ahrens 				h = (h >> 8) ^
122486ae710SMatthew Ahrens 				    zfs_crc64_table[(h ^ *cp) & 0xFF];
123486ae710SMatthew Ahrens 			}
124486ae710SMatthew Ahrens 		}
125b24ab676SJeff Bonwick 	}
126da6c28aaSamw 	/*
127b24ab676SJeff Bonwick 	 * Don't use all 64 bits, since we need some in the cookie for
128b24ab676SJeff Bonwick 	 * the collision differentiator.  We MUST use the high bits,
129b24ab676SJeff Bonwick 	 * since those are the ones that we first pay attention to when
130da6c28aaSamw 	 * chosing the bucket.
131da6c28aaSamw 	 */
132b24ab676SJeff Bonwick 	h &= ~((1ULL << (64 - zap_hashbits(zap))) - 1);
133da6c28aaSamw 
134b24ab676SJeff Bonwick 	return (h);
135da6c28aaSamw }
136da6c28aaSamw 
137da6c28aaSamw static int
138*1c17160aSKevin Crowe zap_normalize(zap_t *zap, const char *name, char *namenorm, int normflags)
139da6c28aaSamw {
140da6c28aaSamw 	size_t inlen, outlen;
141da6c28aaSamw 	int err;
142da6c28aaSamw 
143b24ab676SJeff Bonwick 	ASSERT(!(zap_getflags(zap) & ZAP_FLAG_UINT64_KEY));
144b24ab676SJeff Bonwick 
145da6c28aaSamw 	inlen = strlen(name) + 1;
146da6c28aaSamw 	outlen = ZAP_MAXNAMELEN;
147da6c28aaSamw 
148da6c28aaSamw 	err = 0;
149da6c28aaSamw 	(void) u8_textprep_str((char *)name, &inlen, namenorm, &outlen,
150*1c17160aSKevin Crowe 	    normflags | U8_TEXTPREP_IGNORE_NULL | U8_TEXTPREP_IGNORE_INVALID,
151*1c17160aSKevin Crowe 	    U8_UNICODE_LATEST, &err);
152da6c28aaSamw 
153da6c28aaSamw 	return (err);
154da6c28aaSamw }
155da6c28aaSamw 
156da6c28aaSamw boolean_t
157da6c28aaSamw zap_match(zap_name_t *zn, const char *matchname)
158da6c28aaSamw {
159b24ab676SJeff Bonwick 	ASSERT(!(zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY));
160b24ab676SJeff Bonwick 
161*1c17160aSKevin Crowe 	if (zn->zn_matchtype & MT_NORMALIZE) {
162da6c28aaSamw 		char norm[ZAP_MAXNAMELEN];
163da6c28aaSamw 
164*1c17160aSKevin Crowe 		if (zap_normalize(zn->zn_zap, matchname, norm,
165*1c17160aSKevin Crowe 		    zn->zn_normflags) != 0)
166da6c28aaSamw 			return (B_FALSE);
167da6c28aaSamw 
168b24ab676SJeff Bonwick 		return (strcmp(zn->zn_key_norm, norm) == 0);
169da6c28aaSamw 	} else {
170b24ab676SJeff Bonwick 		return (strcmp(zn->zn_key_orig, matchname) == 0);
171da6c28aaSamw 	}
172da6c28aaSamw }
173da6c28aaSamw 
174da6c28aaSamw void
175da6c28aaSamw zap_name_free(zap_name_t *zn)
176da6c28aaSamw {
177da6c28aaSamw 	kmem_free(zn, sizeof (zap_name_t));
178da6c28aaSamw }
179da6c28aaSamw 
180da6c28aaSamw zap_name_t *
181b24ab676SJeff Bonwick zap_name_alloc(zap_t *zap, const char *key, matchtype_t mt)
182da6c28aaSamw {
183da6c28aaSamw 	zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP);
184da6c28aaSamw 
185da6c28aaSamw 	zn->zn_zap = zap;
186b24ab676SJeff Bonwick 	zn->zn_key_intlen = sizeof (*key);
187b24ab676SJeff Bonwick 	zn->zn_key_orig = key;
188486ae710SMatthew Ahrens 	zn->zn_key_orig_numints = strlen(zn->zn_key_orig) + 1;
189da6c28aaSamw 	zn->zn_matchtype = mt;
190*1c17160aSKevin Crowe 	zn->zn_normflags = zap->zap_normflags;
191*1c17160aSKevin Crowe 
192*1c17160aSKevin Crowe 	/*
193*1c17160aSKevin Crowe 	 * If we're dealing with a case sensitive lookup on a mixed or
194*1c17160aSKevin Crowe 	 * insensitive fs, remove U8_TEXTPREP_TOUPPER or the lookup
195*1c17160aSKevin Crowe 	 * will fold case to all caps overriding the lookup request.
196*1c17160aSKevin Crowe 	 */
197*1c17160aSKevin Crowe 	if (mt & MT_MATCH_CASE)
198*1c17160aSKevin Crowe 		zn->zn_normflags &= ~U8_TEXTPREP_TOUPPER;
199*1c17160aSKevin Crowe 
200da6c28aaSamw 	if (zap->zap_normflags) {
201*1c17160aSKevin Crowe 		/*
202*1c17160aSKevin Crowe 		 * We *must* use zap_normflags because this normalization is
203*1c17160aSKevin Crowe 		 * what the hash is computed from.
204*1c17160aSKevin Crowe 		 */
205*1c17160aSKevin Crowe 		if (zap_normalize(zap, key, zn->zn_normbuf,
206*1c17160aSKevin Crowe 		    zap->zap_normflags) != 0) {
207da6c28aaSamw 			zap_name_free(zn);
208da6c28aaSamw 			return (NULL);
209da6c28aaSamw 		}
210b24ab676SJeff Bonwick 		zn->zn_key_norm = zn->zn_normbuf;
211486ae710SMatthew Ahrens 		zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1;
212da6c28aaSamw 	} else {
213*1c17160aSKevin Crowe 		if (mt != 0) {
214da6c28aaSamw 			zap_name_free(zn);
215da6c28aaSamw 			return (NULL);
216da6c28aaSamw 		}
217b24ab676SJeff Bonwick 		zn->zn_key_norm = zn->zn_key_orig;
218486ae710SMatthew Ahrens 		zn->zn_key_norm_numints = zn->zn_key_orig_numints;
219da6c28aaSamw 	}
220da6c28aaSamw 
221b24ab676SJeff Bonwick 	zn->zn_hash = zap_hash(zn);
222*1c17160aSKevin Crowe 
223*1c17160aSKevin Crowe 	if (zap->zap_normflags != zn->zn_normflags) {
224*1c17160aSKevin Crowe 		/*
225*1c17160aSKevin Crowe 		 * We *must* use zn_normflags because this normalization is
226*1c17160aSKevin Crowe 		 * what the matching is based on.  (Not the hash!)
227*1c17160aSKevin Crowe 		 */
228*1c17160aSKevin Crowe 		if (zap_normalize(zap, key, zn->zn_normbuf,
229*1c17160aSKevin Crowe 		    zn->zn_normflags) != 0) {
230*1c17160aSKevin Crowe 			zap_name_free(zn);
231*1c17160aSKevin Crowe 			return (NULL);
232*1c17160aSKevin Crowe 		}
233*1c17160aSKevin Crowe 		zn->zn_key_norm_numints = strlen(zn->zn_key_norm) + 1;
234*1c17160aSKevin Crowe 	}
235*1c17160aSKevin Crowe 
236b24ab676SJeff Bonwick 	return (zn);
237b24ab676SJeff Bonwick }
238b24ab676SJeff Bonwick 
239b24ab676SJeff Bonwick zap_name_t *
240b24ab676SJeff Bonwick zap_name_alloc_uint64(zap_t *zap, const uint64_t *key, int numints)
241b24ab676SJeff Bonwick {
242b24ab676SJeff Bonwick 	zap_name_t *zn = kmem_alloc(sizeof (zap_name_t), KM_SLEEP);
243b24ab676SJeff Bonwick 
244b24ab676SJeff Bonwick 	ASSERT(zap->zap_normflags == 0);
245b24ab676SJeff Bonwick 	zn->zn_zap = zap;
246b24ab676SJeff Bonwick 	zn->zn_key_intlen = sizeof (*key);
247b24ab676SJeff Bonwick 	zn->zn_key_orig = zn->zn_key_norm = key;
248486ae710SMatthew Ahrens 	zn->zn_key_orig_numints = zn->zn_key_norm_numints = numints;
249*1c17160aSKevin Crowe 	zn->zn_matchtype = 0;
250b24ab676SJeff Bonwick 
251b24ab676SJeff Bonwick 	zn->zn_hash = zap_hash(zn);
252da6c28aaSamw 	return (zn);
253da6c28aaSamw }
254da6c28aaSamw 
255fa9e4066Sahrens static void
256fa9e4066Sahrens mzap_byteswap(mzap_phys_t *buf, size_t size)
257fa9e4066Sahrens {
258fa9e4066Sahrens 	int i, max;
259fa9e4066Sahrens 	buf->mz_block_type = BSWAP_64(buf->mz_block_type);
260fa9e4066Sahrens 	buf->mz_salt = BSWAP_64(buf->mz_salt);
261ab04eb8eStimh 	buf->mz_normflags = BSWAP_64(buf->mz_normflags);
262fa9e4066Sahrens 	max = (size / MZAP_ENT_LEN) - 1;
263fa9e4066Sahrens 	for (i = 0; i < max; i++) {
264fa9e4066Sahrens 		buf->mz_chunk[i].mze_value =
265fa9e4066Sahrens 		    BSWAP_64(buf->mz_chunk[i].mze_value);
266fa9e4066Sahrens 		buf->mz_chunk[i].mze_cd =
267fa9e4066Sahrens 		    BSWAP_32(buf->mz_chunk[i].mze_cd);
268fa9e4066Sahrens 	}
269fa9e4066Sahrens }
270fa9e4066Sahrens 
271fa9e4066Sahrens void
272fa9e4066Sahrens zap_byteswap(void *buf, size_t size)
273fa9e4066Sahrens {
274fa9e4066Sahrens 	uint64_t block_type;
275fa9e4066Sahrens 
276fa9e4066Sahrens 	block_type = *(uint64_t *)buf;
277fa9e4066Sahrens 
2785ad82045Snd 	if (block_type == ZBT_MICRO || block_type == BSWAP_64(ZBT_MICRO)) {
279fa9e4066Sahrens 		/* ASSERT(magic == ZAP_LEAF_MAGIC); */
280fa9e4066Sahrens 		mzap_byteswap(buf, size);
2815ad82045Snd 	} else {
282fa9e4066Sahrens 		fzap_byteswap(buf, size);
283fa9e4066Sahrens 	}
284fa9e4066Sahrens }
285fa9e4066Sahrens 
286fa9e4066Sahrens static int
287fa9e4066Sahrens mze_compare(const void *arg1, const void *arg2)
288fa9e4066Sahrens {
289fa9e4066Sahrens 	const mzap_ent_t *mze1 = arg1;
290fa9e4066Sahrens 	const mzap_ent_t *mze2 = arg2;
291fa9e4066Sahrens 
292fa9e4066Sahrens 	if (mze1->mze_hash > mze2->mze_hash)
293fa9e4066Sahrens 		return (+1);
294fa9e4066Sahrens 	if (mze1->mze_hash < mze2->mze_hash)
295fa9e4066Sahrens 		return (-1);
2963f9d6ad7SLin Ling 	if (mze1->mze_cd > mze2->mze_cd)
297fa9e4066Sahrens 		return (+1);
2983f9d6ad7SLin Ling 	if (mze1->mze_cd < mze2->mze_cd)
299fa9e4066Sahrens 		return (-1);
300fa9e4066Sahrens 	return (0);
301fa9e4066Sahrens }
302fa9e4066Sahrens 
303fa9e4066Sahrens static void
3043f9d6ad7SLin Ling mze_insert(zap_t *zap, int chunkid, uint64_t hash)
305fa9e4066Sahrens {
306fa9e4066Sahrens 	mzap_ent_t *mze;
307fa9e4066Sahrens 
308fa9e4066Sahrens 	ASSERT(zap->zap_ismicro);
309fa9e4066Sahrens 	ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
310fa9e4066Sahrens 
311fa9e4066Sahrens 	mze = kmem_alloc(sizeof (mzap_ent_t), KM_SLEEP);
312fa9e4066Sahrens 	mze->mze_chunkid = chunkid;
313fa9e4066Sahrens 	mze->mze_hash = hash;
3143f9d6ad7SLin Ling 	mze->mze_cd = MZE_PHYS(zap, mze)->mze_cd;
3153f9d6ad7SLin Ling 	ASSERT(MZE_PHYS(zap, mze)->mze_name[0] != 0);
316fa9e4066Sahrens 	avl_add(&zap->zap_m.zap_avl, mze);
317fa9e4066Sahrens }
318fa9e4066Sahrens 
319fa9e4066Sahrens static mzap_ent_t *
320da6c28aaSamw mze_find(zap_name_t *zn)
321fa9e4066Sahrens {
322fa9e4066Sahrens 	mzap_ent_t mze_tofind;
323fa9e4066Sahrens 	mzap_ent_t *mze;
324fa9e4066Sahrens 	avl_index_t idx;
325da6c28aaSamw 	avl_tree_t *avl = &zn->zn_zap->zap_m.zap_avl;
326fa9e4066Sahrens 
327da6c28aaSamw 	ASSERT(zn->zn_zap->zap_ismicro);
328da6c28aaSamw 	ASSERT(RW_LOCK_HELD(&zn->zn_zap->zap_rwlock));
329fa9e4066Sahrens 
330da6c28aaSamw 	mze_tofind.mze_hash = zn->zn_hash;
3313f9d6ad7SLin Ling 	mze_tofind.mze_cd = 0;
332fa9e4066Sahrens 
333fa9e4066Sahrens 	mze = avl_find(avl, &mze_tofind, &idx);
334fa9e4066Sahrens 	if (mze == NULL)
335fa9e4066Sahrens 		mze = avl_nearest(avl, idx, AVL_AFTER);
336da6c28aaSamw 	for (; mze && mze->mze_hash == zn->zn_hash; mze = AVL_NEXT(avl, mze)) {
3373f9d6ad7SLin Ling 		ASSERT3U(mze->mze_cd, ==, MZE_PHYS(zn->zn_zap, mze)->mze_cd);
3383f9d6ad7SLin Ling 		if (zap_match(zn, MZE_PHYS(zn->zn_zap, mze)->mze_name))
339fa9e4066Sahrens 			return (mze);
340fa9e4066Sahrens 	}
341*1c17160aSKevin Crowe 
342fa9e4066Sahrens 	return (NULL);
343fa9e4066Sahrens }
344fa9e4066Sahrens 
345fa9e4066Sahrens static uint32_t
346fa9e4066Sahrens mze_find_unused_cd(zap_t *zap, uint64_t hash)
347fa9e4066Sahrens {
348fa9e4066Sahrens 	mzap_ent_t mze_tofind;
349fa9e4066Sahrens 	mzap_ent_t *mze;
350fa9e4066Sahrens 	avl_index_t idx;
351fa9e4066Sahrens 	avl_tree_t *avl = &zap->zap_m.zap_avl;
352fa9e4066Sahrens 	uint32_t cd;
353fa9e4066Sahrens 
354fa9e4066Sahrens 	ASSERT(zap->zap_ismicro);
355fa9e4066Sahrens 	ASSERT(RW_LOCK_HELD(&zap->zap_rwlock));
356fa9e4066Sahrens 
357fa9e4066Sahrens 	mze_tofind.mze_hash = hash;
3583f9d6ad7SLin Ling 	mze_tofind.mze_cd = 0;
359fa9e4066Sahrens 
360fa9e4066Sahrens 	cd = 0;
361fa9e4066Sahrens 	for (mze = avl_find(avl, &mze_tofind, &idx);
362fa9e4066Sahrens 	    mze && mze->mze_hash == hash; mze = AVL_NEXT(avl, mze)) {
3633f9d6ad7SLin Ling 		if (mze->mze_cd != cd)
364fa9e4066Sahrens 			break;
365fa9e4066Sahrens 		cd++;
366fa9e4066Sahrens 	}
367fa9e4066Sahrens 
368fa9e4066Sahrens 	return (cd);
369fa9e4066Sahrens }
370fa9e4066Sahrens 
371fa9e4066Sahrens static void
372fa9e4066Sahrens mze_remove(zap_t *zap, mzap_ent_t *mze)
373fa9e4066Sahrens {
374fa9e4066Sahrens 	ASSERT(zap->zap_ismicro);
375fa9e4066Sahrens 	ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
376fa9e4066Sahrens 
377fa9e4066Sahrens 	avl_remove(&zap->zap_m.zap_avl, mze);
378fa9e4066Sahrens 	kmem_free(mze, sizeof (mzap_ent_t));
379fa9e4066Sahrens }
380fa9e4066Sahrens 
381fa9e4066Sahrens static void
382fa9e4066Sahrens mze_destroy(zap_t *zap)
383fa9e4066Sahrens {
384fa9e4066Sahrens 	mzap_ent_t *mze;
385fa9e4066Sahrens 	void *avlcookie = NULL;
386fa9e4066Sahrens 
387fa9e4066Sahrens 	while (mze = avl_destroy_nodes(&zap->zap_m.zap_avl, &avlcookie))
388fa9e4066Sahrens 		kmem_free(mze, sizeof (mzap_ent_t));
389fa9e4066Sahrens 	avl_destroy(&zap->zap_m.zap_avl);
390fa9e4066Sahrens }
391fa9e4066Sahrens 
392fa9e4066Sahrens static zap_t *
393fa9e4066Sahrens mzap_open(objset_t *os, uint64_t obj, dmu_buf_t *db)
394fa9e4066Sahrens {
395fa9e4066Sahrens 	zap_t *winner;
396fa9e4066Sahrens 	zap_t *zap;
397fa9e4066Sahrens 	int i;
39802525cd0SChunwei Chen 	uint64_t *zap_hdr = (uint64_t *)db->db_data;
39902525cd0SChunwei Chen 	uint64_t zap_block_type = zap_hdr[0];
40002525cd0SChunwei Chen 	uint64_t zap_magic = zap_hdr[1];
401fa9e4066Sahrens 
402fa9e4066Sahrens 	ASSERT3U(MZAP_ENT_LEN, ==, sizeof (mzap_ent_phys_t));
403fa9e4066Sahrens 
404fa9e4066Sahrens 	zap = kmem_zalloc(sizeof (zap_t), KM_SLEEP);
405fa9e4066Sahrens 	rw_init(&zap->zap_rwlock, 0, 0, 0);
406fa9e4066Sahrens 	rw_enter(&zap->zap_rwlock, RW_WRITER);
407fa9e4066Sahrens 	zap->zap_objset = os;
408fa9e4066Sahrens 	zap->zap_object = obj;
409fa9e4066Sahrens 	zap->zap_dbuf = db;
410fa9e4066Sahrens 
41102525cd0SChunwei Chen 	if (zap_block_type != ZBT_MICRO) {
412fa9e4066Sahrens 		mutex_init(&zap->zap_f.zap_num_entries_mtx, 0, 0, 0);
413bf16b11eSMatthew Ahrens 		zap->zap_f.zap_block_shift = highbit64(db->db_size) - 1;
41402525cd0SChunwei Chen 		if (zap_block_type != ZBT_HEADER || zap_magic != ZAP_MAGIC) {
41502525cd0SChunwei Chen 			winner = NULL;	/* No actual winner here... */
41602525cd0SChunwei Chen 			goto handle_winner;
41702525cd0SChunwei Chen 		}
418fa9e4066Sahrens 	} else {
419fa9e4066Sahrens 		zap->zap_ismicro = TRUE;
420fa9e4066Sahrens 	}
421fa9e4066Sahrens 
422fa9e4066Sahrens 	/*
423fa9e4066Sahrens 	 * Make sure that zap_ismicro is set before we let others see
424fa9e4066Sahrens 	 * it, because zap_lockdir() checks zap_ismicro without the lock
425fa9e4066Sahrens 	 * held.
426fa9e4066Sahrens 	 */
42740510e8eSJosef 'Jeff' Sipek 	dmu_buf_init_user(&zap->zap_dbu, zap_evict_sync, NULL, &zap->zap_dbuf);
428bc9014e6SJustin Gibbs 	winner = dmu_buf_set_user(db, &zap->zap_dbu);
429fa9e4066Sahrens 
43002525cd0SChunwei Chen 	if (winner != NULL)
43102525cd0SChunwei Chen 		goto handle_winner;
432fa9e4066Sahrens 
433fa9e4066Sahrens 	if (zap->zap_ismicro) {
434c1379625SJustin T. Gibbs 		zap->zap_salt = zap_m_phys(zap)->mz_salt;
435c1379625SJustin T. Gibbs 		zap->zap_normflags = zap_m_phys(zap)->mz_normflags;
436fa9e4066Sahrens 		zap->zap_m.zap_num_chunks = db->db_size / MZAP_ENT_LEN - 1;
437fa9e4066Sahrens 		avl_create(&zap->zap_m.zap_avl, mze_compare,
438fa9e4066Sahrens 		    sizeof (mzap_ent_t), offsetof(mzap_ent_t, mze_node));
439fa9e4066Sahrens 
440fa9e4066Sahrens 		for (i = 0; i < zap->zap_m.zap_num_chunks; i++) {
441fa9e4066Sahrens 			mzap_ent_phys_t *mze =
442c1379625SJustin T. Gibbs 			    &zap_m_phys(zap)->mz_chunk[i];
443fa9e4066Sahrens 			if (mze->mze_name[0]) {
444da6c28aaSamw 				zap_name_t *zn;
445da6c28aaSamw 
446fa9e4066Sahrens 				zap->zap_m.zap_num_entries++;
447*1c17160aSKevin Crowe 				zn = zap_name_alloc(zap, mze->mze_name, 0);
4483f9d6ad7SLin Ling 				mze_insert(zap, i, zn->zn_hash);
449da6c28aaSamw 				zap_name_free(zn);
450fa9e4066Sahrens 			}
451fa9e4066Sahrens 		}
452fa9e4066Sahrens 	} else {
453c1379625SJustin T. Gibbs 		zap->zap_salt = zap_f_phys(zap)->zap_salt;
454c1379625SJustin T. Gibbs 		zap->zap_normflags = zap_f_phys(zap)->zap_normflags;
455f65e61c0Sahrens 
456f65e61c0Sahrens 		ASSERT3U(sizeof (struct zap_leaf_header), ==,
457f65e61c0Sahrens 		    2*ZAP_LEAF_CHUNKSIZE);
458f65e61c0Sahrens 
459f65e61c0Sahrens 		/*
460f65e61c0Sahrens 		 * The embedded pointer table should not overlap the
461f65e61c0Sahrens 		 * other members.
462f65e61c0Sahrens 		 */
463f65e61c0Sahrens 		ASSERT3P(&ZAP_EMBEDDED_PTRTBL_ENT(zap, 0), >,
464c1379625SJustin T. Gibbs 		    &zap_f_phys(zap)->zap_salt);
465f65e61c0Sahrens 
466f65e61c0Sahrens 		/*
467f65e61c0Sahrens 		 * The embedded pointer table should end at the end of
468f65e61c0Sahrens 		 * the block
469f65e61c0Sahrens 		 */
470f65e61c0Sahrens 		ASSERT3U((uintptr_t)&ZAP_EMBEDDED_PTRTBL_ENT(zap,
471f65e61c0Sahrens 		    1<<ZAP_EMBEDDED_PTRTBL_SHIFT(zap)) -
472c1379625SJustin T. Gibbs 		    (uintptr_t)zap_f_phys(zap), ==,
473f65e61c0Sahrens 		    zap->zap_dbuf->db_size);
474fa9e4066Sahrens 	}
475fa9e4066Sahrens 	rw_exit(&zap->zap_rwlock);
476fa9e4066Sahrens 	return (zap);
47702525cd0SChunwei Chen 
47802525cd0SChunwei Chen handle_winner:
47902525cd0SChunwei Chen 	rw_exit(&zap->zap_rwlock);
48002525cd0SChunwei Chen 	rw_destroy(&zap->zap_rwlock);
48102525cd0SChunwei Chen 	if (!zap->zap_ismicro)
48202525cd0SChunwei Chen 		mutex_destroy(&zap->zap_f.zap_num_entries_mtx);
48302525cd0SChunwei Chen 	kmem_free(zap, sizeof (zap_t));
48402525cd0SChunwei Chen 	return (winner);
485fa9e4066Sahrens }
486fa9e4066Sahrens 
487ae972795SMatthew Ahrens static int
488ae972795SMatthew Ahrens zap_lockdir_impl(dmu_buf_t *db, void *tag, dmu_tx_t *tx,
489c5f9e431Sahrens     krw_t lti, boolean_t fatreader, boolean_t adding, zap_t **zapp)
490fa9e4066Sahrens {
491fa9e4066Sahrens 	zap_t *zap;
492fa9e4066Sahrens 	krw_t lt;
493fa9e4066Sahrens 
494ae972795SMatthew Ahrens 	ASSERT0(db->db_offset);
495ae972795SMatthew Ahrens 	objset_t *os = dmu_buf_get_objset(db);
496ae972795SMatthew Ahrens 	uint64_t obj = db->db_object;
497fa9e4066Sahrens 
498ae972795SMatthew Ahrens 	*zapp = NULL;
499fa9e4066Sahrens 
500fa9e4066Sahrens #ifdef ZFS_DEBUG
501fa9e4066Sahrens 	{
502fa9e4066Sahrens 		dmu_object_info_t doi;
503fa9e4066Sahrens 		dmu_object_info_from_db(db, &doi);
504ad135b5dSChristopher Siden 		ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP);
505fa9e4066Sahrens 	}
506fa9e4066Sahrens #endif
507fa9e4066Sahrens 
508fa9e4066Sahrens 	zap = dmu_buf_get_user(db);
50902525cd0SChunwei Chen 	if (zap == NULL) {
510fa9e4066Sahrens 		zap = mzap_open(os, obj, db);
51102525cd0SChunwei Chen 		if (zap == NULL) {
51202525cd0SChunwei Chen 			/*
51302525cd0SChunwei Chen 			 * mzap_open() didn't like what it saw on-disk.
51402525cd0SChunwei Chen 			 * Check for corruption!
51502525cd0SChunwei Chen 			 */
51602525cd0SChunwei Chen 			return (SET_ERROR(EIO));
51702525cd0SChunwei Chen 		}
51802525cd0SChunwei Chen 	}
519fa9e4066Sahrens 
520fa9e4066Sahrens 	/*
521fa9e4066Sahrens 	 * We're checking zap_ismicro without the lock held, in order to
522fa9e4066Sahrens 	 * tell what type of lock we want.  Once we have some sort of
523fa9e4066Sahrens 	 * lock, see if it really is the right type.  In practice this
524fa9e4066Sahrens 	 * can only be different if it was upgraded from micro to fat,
525fa9e4066Sahrens 	 * and micro wanted WRITER but fat only needs READER.
526fa9e4066Sahrens 	 */
527fa9e4066Sahrens 	lt = (!zap->zap_ismicro && fatreader) ? RW_READER : lti;
528fa9e4066Sahrens 	rw_enter(&zap->zap_rwlock, lt);
529fa9e4066Sahrens 	if (lt != ((!zap->zap_ismicro && fatreader) ? RW_READER : lti)) {
530fa9e4066Sahrens 		/* it was upgraded, now we only need reader */
531fa9e4066Sahrens 		ASSERT(lt == RW_WRITER);
532fa9e4066Sahrens 		ASSERT(RW_READER ==
533fa9e4066Sahrens 		    (!zap->zap_ismicro && fatreader) ? RW_READER : lti);
534fa9e4066Sahrens 		rw_downgrade(&zap->zap_rwlock);
535fa9e4066Sahrens 		lt = RW_READER;
536fa9e4066Sahrens 	}
537fa9e4066Sahrens 
538fa9e4066Sahrens 	zap->zap_objset = os;
539fa9e4066Sahrens 
540fa9e4066Sahrens 	if (lt == RW_WRITER)
541fa9e4066Sahrens 		dmu_buf_will_dirty(db, tx);
542fa9e4066Sahrens 
543fa9e4066Sahrens 	ASSERT3P(zap->zap_dbuf, ==, db);
544fa9e4066Sahrens 
545fa9e4066Sahrens 	ASSERT(!zap->zap_ismicro ||
546fa9e4066Sahrens 	    zap->zap_m.zap_num_entries <= zap->zap_m.zap_num_chunks);
547c5f9e431Sahrens 	if (zap->zap_ismicro && tx && adding &&
548fa9e4066Sahrens 	    zap->zap_m.zap_num_entries == zap->zap_m.zap_num_chunks) {
549fa9e4066Sahrens 		uint64_t newsz = db->db_size + SPA_MINBLOCKSIZE;
550fa9e4066Sahrens 		if (newsz > MZAP_MAX_BLKSZ) {
551fa9e4066Sahrens 			dprintf("upgrading obj %llu: num_entries=%u\n",
552fa9e4066Sahrens 			    obj, zap->zap_m.zap_num_entries);
553fa9e4066Sahrens 			*zapp = zap;
554ae972795SMatthew Ahrens 			int err = mzap_upgrade(zapp, tag, tx, 0);
555ae972795SMatthew Ahrens 			if (err != 0)
556ae972795SMatthew Ahrens 				rw_exit(&zap->zap_rwlock);
557ae972795SMatthew Ahrens 			return (err);
558fa9e4066Sahrens 		}
559ae972795SMatthew Ahrens 		VERIFY0(dmu_object_set_blocksize(os, obj, newsz, 0, tx));
560fa9e4066Sahrens 		zap->zap_m.zap_num_chunks =
561fa9e4066Sahrens 		    db->db_size / MZAP_ENT_LEN - 1;
562fa9e4066Sahrens 	}
563fa9e4066Sahrens 
564fa9e4066Sahrens 	*zapp = zap;
565fa9e4066Sahrens 	return (0);
566fa9e4066Sahrens }
567fa9e4066Sahrens 
56879d72832SMatthew Ahrens static int
56979d72832SMatthew Ahrens zap_lockdir_by_dnode(dnode_t *dn, dmu_tx_t *tx,
57079d72832SMatthew Ahrens     krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp)
57179d72832SMatthew Ahrens {
57279d72832SMatthew Ahrens 	dmu_buf_t *db;
57379d72832SMatthew Ahrens 	int err;
57479d72832SMatthew Ahrens 
57579d72832SMatthew Ahrens 	err = dmu_buf_hold_by_dnode(dn, 0, tag, &db, DMU_READ_NO_PREFETCH);
57679d72832SMatthew Ahrens 	if (err != 0) {
57779d72832SMatthew Ahrens 		return (err);
57879d72832SMatthew Ahrens 	}
57979d72832SMatthew Ahrens 	err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp);
58079d72832SMatthew Ahrens 	if (err != 0) {
58179d72832SMatthew Ahrens 		dmu_buf_rele(db, tag);
58279d72832SMatthew Ahrens 	}
58379d72832SMatthew Ahrens 	return (err);
58479d72832SMatthew Ahrens }
58579d72832SMatthew Ahrens 
586ae972795SMatthew Ahrens int
587ae972795SMatthew Ahrens zap_lockdir(objset_t *os, uint64_t obj, dmu_tx_t *tx,
588ae972795SMatthew Ahrens     krw_t lti, boolean_t fatreader, boolean_t adding, void *tag, zap_t **zapp)
589ae972795SMatthew Ahrens {
590ae972795SMatthew Ahrens 	dmu_buf_t *db;
591ae972795SMatthew Ahrens 	int err;
592ae972795SMatthew Ahrens 
593ae972795SMatthew Ahrens 	err = dmu_buf_hold(os, obj, 0, tag, &db, DMU_READ_NO_PREFETCH);
594ae972795SMatthew Ahrens 	if (err != 0)
595ae972795SMatthew Ahrens 		return (err);
596ae972795SMatthew Ahrens 	err = zap_lockdir_impl(db, tag, tx, lti, fatreader, adding, zapp);
597ae972795SMatthew Ahrens 	if (err != 0)
598ae972795SMatthew Ahrens 		dmu_buf_rele(db, tag);
599ae972795SMatthew Ahrens 	return (err);
600ae972795SMatthew Ahrens }
601ae972795SMatthew Ahrens 
602fa9e4066Sahrens void
603ae972795SMatthew Ahrens zap_unlockdir(zap_t *zap, void *tag)
604fa9e4066Sahrens {
605fa9e4066Sahrens 	rw_exit(&zap->zap_rwlock);
606ae972795SMatthew Ahrens 	dmu_buf_rele(zap->zap_dbuf, tag);
607fa9e4066Sahrens }
608fa9e4066Sahrens 
609ad860c82Sbonwick static int
610ae972795SMatthew Ahrens mzap_upgrade(zap_t **zapp, void *tag, dmu_tx_t *tx, zap_flags_t flags)
611fa9e4066Sahrens {
612fa9e4066Sahrens 	mzap_phys_t *mzp;
613b24ab676SJeff Bonwick 	int i, sz, nchunks;
614b24ab676SJeff Bonwick 	int err = 0;
615ad860c82Sbonwick 	zap_t *zap = *zapp;
616fa9e4066Sahrens 
617fa9e4066Sahrens 	ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
618fa9e4066Sahrens 
619fa9e4066Sahrens 	sz = zap->zap_dbuf->db_size;
620be3e2ab9SBrian Behlendorf 	mzp = zio_buf_alloc(sz);
621fa9e4066Sahrens 	bcopy(zap->zap_dbuf->db_data, mzp, sz);
622fa9e4066Sahrens 	nchunks = zap->zap_m.zap_num_chunks;
623fa9e4066Sahrens 
624b24ab676SJeff Bonwick 	if (!flags) {
625b24ab676SJeff Bonwick 		err = dmu_object_set_blocksize(zap->zap_objset, zap->zap_object,
626b24ab676SJeff Bonwick 		    1ULL << fzap_default_block_shift, 0, tx);
627b24ab676SJeff Bonwick 		if (err) {
628be3e2ab9SBrian Behlendorf 			zio_buf_free(mzp, sz);
629b24ab676SJeff Bonwick 			return (err);
630b24ab676SJeff Bonwick 		}
631ad860c82Sbonwick 	}
632fa9e4066Sahrens 
633fa9e4066Sahrens 	dprintf("upgrading obj=%llu with %u chunks\n",
634fa9e4066Sahrens 	    zap->zap_object, nchunks);
635da6c28aaSamw 	/* XXX destroy the avl later, so we can use the stored hash value */
636fa9e4066Sahrens 	mze_destroy(zap);
637fa9e4066Sahrens 
638b24ab676SJeff Bonwick 	fzap_upgrade(zap, tx, flags);
639fa9e4066Sahrens 
640fa9e4066Sahrens 	for (i = 0; i < nchunks; i++) {
641fa9e4066Sahrens 		mzap_ent_phys_t *mze = &mzp->mz_chunk[i];
642da6c28aaSamw 		zap_name_t *zn;
643fa9e4066Sahrens 		if (mze->mze_name[0] == 0)
644fa9e4066Sahrens 			continue;
645fa9e4066Sahrens 		dprintf("adding %s=%llu\n",
646fa9e4066Sahrens 		    mze->mze_name, mze->mze_value);
647*1c17160aSKevin Crowe 		zn = zap_name_alloc(zap, mze->mze_name, 0);
648ae972795SMatthew Ahrens 		err = fzap_add_cd(zn, 8, 1, &mze->mze_value, mze->mze_cd,
649ae972795SMatthew Ahrens 		    tag, tx);
650ad860c82Sbonwick 		zap = zn->zn_zap;	/* fzap_add_cd() may change zap */
651da6c28aaSamw 		zap_name_free(zn);
652ad860c82Sbonwick 		if (err)
653ad860c82Sbonwick 			break;
654fa9e4066Sahrens 	}
655be3e2ab9SBrian Behlendorf 	zio_buf_free(mzp, sz);
656ad860c82Sbonwick 	*zapp = zap;
657ad860c82Sbonwick 	return (err);
658fa9e4066Sahrens }
659fa9e4066Sahrens 
660*1c17160aSKevin Crowe /*
661*1c17160aSKevin Crowe  * The "normflags" determine the behavior of the matchtype_t which is
662*1c17160aSKevin Crowe  * passed to zap_lookup_norm().  Names which have the same normalized
663*1c17160aSKevin Crowe  * version will be stored with the same hash value, and therefore we can
664*1c17160aSKevin Crowe  * perform normalization-insensitive lookups.  We can be Unicode form-
665*1c17160aSKevin Crowe  * insensitive and/or case-insensitive.  The following flags are valid for
666*1c17160aSKevin Crowe  * "normflags":
667*1c17160aSKevin Crowe  *
668*1c17160aSKevin Crowe  * U8_TEXTPREP_NFC
669*1c17160aSKevin Crowe  * U8_TEXTPREP_NFD
670*1c17160aSKevin Crowe  * U8_TEXTPREP_NFKC
671*1c17160aSKevin Crowe  * U8_TEXTPREP_NFKD
672*1c17160aSKevin Crowe  * U8_TEXTPREP_TOUPPER
673*1c17160aSKevin Crowe  *
674*1c17160aSKevin Crowe  * The *_NF* (Normalization Form) flags are mutually exclusive; at most one
675*1c17160aSKevin Crowe  * of them may be supplied.
676*1c17160aSKevin Crowe  */
6772acef22dSMatthew Ahrens void
678b24ab676SJeff Bonwick mzap_create_impl(objset_t *os, uint64_t obj, int normflags, zap_flags_t flags,
679b24ab676SJeff Bonwick     dmu_tx_t *tx)
680fa9e4066Sahrens {
681fa9e4066Sahrens 	dmu_buf_t *db;
682fa9e4066Sahrens 	mzap_phys_t *zp;
683fa9e4066Sahrens 
68447cb52daSJeff Bonwick 	VERIFY(0 == dmu_buf_hold(os, obj, 0, FTAG, &db, DMU_READ_NO_PREFETCH));
685fa9e4066Sahrens 
686fa9e4066Sahrens #ifdef ZFS_DEBUG
687fa9e4066Sahrens 	{
688fa9e4066Sahrens 		dmu_object_info_t doi;
689fa9e4066Sahrens 		dmu_object_info_from_db(db, &doi);
690ad135b5dSChristopher Siden 		ASSERT3U(DMU_OT_BYTESWAP(doi.doi_type), ==, DMU_BSWAP_ZAP);
691fa9e4066Sahrens 	}
692fa9e4066Sahrens #endif
693fa9e4066Sahrens 
694fa9e4066Sahrens 	dmu_buf_will_dirty(db, tx);
695fa9e4066Sahrens 	zp = db->db_data;
696fa9e4066Sahrens 	zp->mz_block_type = ZBT_MICRO;
697fa9e4066Sahrens 	zp->mz_salt = ((uintptr_t)db ^ (uintptr_t)tx ^ (obj << 1)) | 1ULL;
698da6c28aaSamw 	zp->mz_normflags = normflags;
699ea8dc4b6Seschrock 	dmu_buf_rele(db, FTAG);
700b24ab676SJeff Bonwick 
701b24ab676SJeff Bonwick 	if (flags != 0) {
702b24ab676SJeff Bonwick 		zap_t *zap;
703b24ab676SJeff Bonwick 		/* Only fat zap supports flags; upgrade immediately. */
704b24ab676SJeff Bonwick 		VERIFY(0 == zap_lockdir(os, obj, tx, RW_WRITER,
705ae972795SMatthew Ahrens 		    B_FALSE, B_FALSE, FTAG, &zap));
706ae972795SMatthew Ahrens 		VERIFY3U(0, ==, mzap_upgrade(&zap, FTAG, tx, flags));
707ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
708b24ab676SJeff Bonwick 	}
709fa9e4066Sahrens }
710fa9e4066Sahrens 
711fa9e4066Sahrens int
712fa9e4066Sahrens zap_create_claim(objset_t *os, uint64_t obj, dmu_object_type_t ot,
713fa9e4066Sahrens     dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
714da6c28aaSamw {
715da6c28aaSamw 	return (zap_create_claim_norm(os, obj,
716da6c28aaSamw 	    0, ot, bonustype, bonuslen, tx));
717da6c28aaSamw }
718da6c28aaSamw 
719da6c28aaSamw int
720da6c28aaSamw zap_create_claim_norm(objset_t *os, uint64_t obj, int normflags,
721da6c28aaSamw     dmu_object_type_t ot,
722da6c28aaSamw     dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
723fa9e4066Sahrens {
724fa9e4066Sahrens 	int err;
725fa9e4066Sahrens 
726fa9e4066Sahrens 	err = dmu_object_claim(os, obj, ot, 0, bonustype, bonuslen, tx);
727fa9e4066Sahrens 	if (err != 0)
728fa9e4066Sahrens 		return (err);
729b24ab676SJeff Bonwick 	mzap_create_impl(os, obj, normflags, 0, tx);
730fa9e4066Sahrens 	return (0);
731fa9e4066Sahrens }
732fa9e4066Sahrens 
733fa9e4066Sahrens uint64_t
734fa9e4066Sahrens zap_create(objset_t *os, dmu_object_type_t ot,
735fa9e4066Sahrens     dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
736da6c28aaSamw {
737da6c28aaSamw 	return (zap_create_norm(os, 0, ot, bonustype, bonuslen, tx));
738da6c28aaSamw }
739da6c28aaSamw 
740da6c28aaSamw uint64_t
741da6c28aaSamw zap_create_norm(objset_t *os, int normflags, dmu_object_type_t ot,
742da6c28aaSamw     dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
743fa9e4066Sahrens {
744fa9e4066Sahrens 	uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx);
745fa9e4066Sahrens 
746b24ab676SJeff Bonwick 	mzap_create_impl(os, obj, normflags, 0, tx);
747b24ab676SJeff Bonwick 	return (obj);
748b24ab676SJeff Bonwick }
749b24ab676SJeff Bonwick 
750b24ab676SJeff Bonwick uint64_t
751b24ab676SJeff Bonwick zap_create_flags(objset_t *os, int normflags, zap_flags_t flags,
752b24ab676SJeff Bonwick     dmu_object_type_t ot, int leaf_blockshift, int indirect_blockshift,
753b24ab676SJeff Bonwick     dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
754b24ab676SJeff Bonwick {
755b24ab676SJeff Bonwick 	uint64_t obj = dmu_object_alloc(os, ot, 0, bonustype, bonuslen, tx);
756b24ab676SJeff Bonwick 
757b24ab676SJeff Bonwick 	ASSERT(leaf_blockshift >= SPA_MINBLOCKSHIFT &&
758b5152584SMatthew Ahrens 	    leaf_blockshift <= SPA_OLD_MAXBLOCKSHIFT &&
759b24ab676SJeff Bonwick 	    indirect_blockshift >= SPA_MINBLOCKSHIFT &&
760b5152584SMatthew Ahrens 	    indirect_blockshift <= SPA_OLD_MAXBLOCKSHIFT);
761b24ab676SJeff Bonwick 
762b24ab676SJeff Bonwick 	VERIFY(dmu_object_set_blocksize(os, obj,
763b24ab676SJeff Bonwick 	    1ULL << leaf_blockshift, indirect_blockshift, tx) == 0);
764b24ab676SJeff Bonwick 
765b24ab676SJeff Bonwick 	mzap_create_impl(os, obj, normflags, flags, tx);
766fa9e4066Sahrens 	return (obj);
767fa9e4066Sahrens }
768fa9e4066Sahrens 
769fa9e4066Sahrens int
770fa9e4066Sahrens zap_destroy(objset_t *os, uint64_t zapobj, dmu_tx_t *tx)
771fa9e4066Sahrens {
772fa9e4066Sahrens 	/*
773fa9e4066Sahrens 	 * dmu_object_free will free the object number and free the
774fa9e4066Sahrens 	 * data.  Freeing the data will cause our pageout function to be
775fa9e4066Sahrens 	 * called, which will destroy our data (zap_leaf_t's and zap_t).
776fa9e4066Sahrens 	 */
777fa9e4066Sahrens 
778fa9e4066Sahrens 	return (dmu_object_free(os, zapobj, tx));
779fa9e4066Sahrens }
780fa9e4066Sahrens 
781fa9e4066Sahrens void
78240510e8eSJosef 'Jeff' Sipek zap_evict_sync(void *dbu)
783fa9e4066Sahrens {
784bc9014e6SJustin Gibbs 	zap_t *zap = dbu;
785fa9e4066Sahrens 
786fa9e4066Sahrens 	rw_destroy(&zap->zap_rwlock);
787fa9e4066Sahrens 
788f65e61c0Sahrens 	if (zap->zap_ismicro)
789fa9e4066Sahrens 		mze_destroy(zap);
790c25056deSgw 	else
791c25056deSgw 		mutex_destroy(&zap->zap_f.zap_num_entries_mtx);
792fa9e4066Sahrens 
793fa9e4066Sahrens 	kmem_free(zap, sizeof (zap_t));
794fa9e4066Sahrens }
795fa9e4066Sahrens 
796fa9e4066Sahrens int
797fa9e4066Sahrens zap_count(objset_t *os, uint64_t zapobj, uint64_t *count)
798fa9e4066Sahrens {
799fa9e4066Sahrens 	zap_t *zap;
800fa9e4066Sahrens 	int err;
801fa9e4066Sahrens 
802ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
803fa9e4066Sahrens 	if (err)
804fa9e4066Sahrens 		return (err);
805fa9e4066Sahrens 	if (!zap->zap_ismicro) {
806fa9e4066Sahrens 		err = fzap_count(zap, count);
807fa9e4066Sahrens 	} else {
808fa9e4066Sahrens 		*count = zap->zap_m.zap_num_entries;
809fa9e4066Sahrens 	}
810ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
811fa9e4066Sahrens 	return (err);
812fa9e4066Sahrens }
813fa9e4066Sahrens 
814fa9e4066Sahrens /*
815da6c28aaSamw  * zn may be NULL; if not specified, it will be computed if needed.
816da6c28aaSamw  * See also the comment above zap_entry_normalization_conflict().
817da6c28aaSamw  */
818da6c28aaSamw static boolean_t
819da6c28aaSamw mzap_normalization_conflict(zap_t *zap, zap_name_t *zn, mzap_ent_t *mze)
820da6c28aaSamw {
821da6c28aaSamw 	mzap_ent_t *other;
822da6c28aaSamw 	int direction = AVL_BEFORE;
823da6c28aaSamw 	boolean_t allocdzn = B_FALSE;
824da6c28aaSamw 
825da6c28aaSamw 	if (zap->zap_normflags == 0)
826da6c28aaSamw 		return (B_FALSE);
827da6c28aaSamw 
828da6c28aaSamw again:
829da6c28aaSamw 	for (other = avl_walk(&zap->zap_m.zap_avl, mze, direction);
830da6c28aaSamw 	    other && other->mze_hash == mze->mze_hash;
831da6c28aaSamw 	    other = avl_walk(&zap->zap_m.zap_avl, other, direction)) {
832da6c28aaSamw 
833da6c28aaSamw 		if (zn == NULL) {
8343f9d6ad7SLin Ling 			zn = zap_name_alloc(zap, MZE_PHYS(zap, mze)->mze_name,
835*1c17160aSKevin Crowe 			    MT_NORMALIZE);
836da6c28aaSamw 			allocdzn = B_TRUE;
837da6c28aaSamw 		}
8383f9d6ad7SLin Ling 		if (zap_match(zn, MZE_PHYS(zap, other)->mze_name)) {
839da6c28aaSamw 			if (allocdzn)
840da6c28aaSamw 				zap_name_free(zn);
841da6c28aaSamw 			return (B_TRUE);
842da6c28aaSamw 		}
843da6c28aaSamw 	}
844da6c28aaSamw 
845da6c28aaSamw 	if (direction == AVL_BEFORE) {
846da6c28aaSamw 		direction = AVL_AFTER;
847da6c28aaSamw 		goto again;
848da6c28aaSamw 	}
849da6c28aaSamw 
850da6c28aaSamw 	if (allocdzn)
851da6c28aaSamw 		zap_name_free(zn);
852da6c28aaSamw 	return (B_FALSE);
853da6c28aaSamw }
854da6c28aaSamw 
855da6c28aaSamw /*
856da6c28aaSamw  * Routines for manipulating attributes.
857fa9e4066Sahrens  */
858fa9e4066Sahrens 
859fa9e4066Sahrens int
860fa9e4066Sahrens zap_lookup(objset_t *os, uint64_t zapobj, const char *name,
861fa9e4066Sahrens     uint64_t integer_size, uint64_t num_integers, void *buf)
862da6c28aaSamw {
863da6c28aaSamw 	return (zap_lookup_norm(os, zapobj, name, integer_size,
864*1c17160aSKevin Crowe 	    num_integers, buf, 0, NULL, 0, NULL));
865da6c28aaSamw }
866da6c28aaSamw 
867ae972795SMatthew Ahrens static int
868ae972795SMatthew Ahrens zap_lookup_impl(zap_t *zap, const char *name,
869da6c28aaSamw     uint64_t integer_size, uint64_t num_integers, void *buf,
870da6c28aaSamw     matchtype_t mt, char *realname, int rn_len,
871da6c28aaSamw     boolean_t *ncp)
872fa9e4066Sahrens {
873ae972795SMatthew Ahrens 	int err = 0;
874fa9e4066Sahrens 	mzap_ent_t *mze;
875da6c28aaSamw 	zap_name_t *zn;
876fa9e4066Sahrens 
877da6c28aaSamw 	zn = zap_name_alloc(zap, name, mt);
878ae972795SMatthew Ahrens 	if (zn == NULL)
879be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
880da6c28aaSamw 
881fa9e4066Sahrens 	if (!zap->zap_ismicro) {
882da6c28aaSamw 		err = fzap_lookup(zn, integer_size, num_integers, buf,
883da6c28aaSamw 		    realname, rn_len, ncp);
884fa9e4066Sahrens 	} else {
885da6c28aaSamw 		mze = mze_find(zn);
886fa9e4066Sahrens 		if (mze == NULL) {
887be6fd75aSMatthew Ahrens 			err = SET_ERROR(ENOENT);
888fa9e4066Sahrens 		} else {
889da6c28aaSamw 			if (num_integers < 1) {
890be6fd75aSMatthew Ahrens 				err = SET_ERROR(EOVERFLOW);
891da6c28aaSamw 			} else if (integer_size != 8) {
892be6fd75aSMatthew Ahrens 				err = SET_ERROR(EINVAL);
893da6c28aaSamw 			} else {
8943f9d6ad7SLin Ling 				*(uint64_t *)buf =
8953f9d6ad7SLin Ling 				    MZE_PHYS(zap, mze)->mze_value;
896da6c28aaSamw 				(void) strlcpy(realname,
8973f9d6ad7SLin Ling 				    MZE_PHYS(zap, mze)->mze_name, rn_len);
898da6c28aaSamw 				if (ncp) {
899da6c28aaSamw 					*ncp = mzap_normalization_conflict(zap,
900da6c28aaSamw 					    zn, mze);
901da6c28aaSamw 				}
902da6c28aaSamw 			}
903fa9e4066Sahrens 		}
904fa9e4066Sahrens 	}
905da6c28aaSamw 	zap_name_free(zn);
906ae972795SMatthew Ahrens 	return (err);
907ae972795SMatthew Ahrens }
908ae972795SMatthew Ahrens 
909ae972795SMatthew Ahrens int
910ae972795SMatthew Ahrens zap_lookup_norm(objset_t *os, uint64_t zapobj, const char *name,
911ae972795SMatthew Ahrens     uint64_t integer_size, uint64_t num_integers, void *buf,
912ae972795SMatthew Ahrens     matchtype_t mt, char *realname, int rn_len,
913ae972795SMatthew Ahrens     boolean_t *ncp)
914ae972795SMatthew Ahrens {
915ae972795SMatthew Ahrens 	zap_t *zap;
916ae972795SMatthew Ahrens 	int err;
917ae972795SMatthew Ahrens 
918ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
919ae972795SMatthew Ahrens 	if (err != 0)
920ae972795SMatthew Ahrens 		return (err);
921ae972795SMatthew Ahrens 	err = zap_lookup_impl(zap, name, integer_size,
922ae972795SMatthew Ahrens 	    num_integers, buf, mt, realname, rn_len, ncp);
923ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
924fa9e4066Sahrens 	return (err);
925fa9e4066Sahrens }
926fa9e4066Sahrens 
92779d72832SMatthew Ahrens int
92879d72832SMatthew Ahrens zap_lookup_by_dnode(dnode_t *dn, const char *name,
92979d72832SMatthew Ahrens     uint64_t integer_size, uint64_t num_integers, void *buf)
93079d72832SMatthew Ahrens {
93179d72832SMatthew Ahrens 	return (zap_lookup_norm_by_dnode(dn, name, integer_size,
932*1c17160aSKevin Crowe 	    num_integers, buf, 0, NULL, 0, NULL));
93379d72832SMatthew Ahrens }
93479d72832SMatthew Ahrens 
93579d72832SMatthew Ahrens int
93679d72832SMatthew Ahrens zap_lookup_norm_by_dnode(dnode_t *dn, const char *name,
93779d72832SMatthew Ahrens     uint64_t integer_size, uint64_t num_integers, void *buf,
93879d72832SMatthew Ahrens     matchtype_t mt, char *realname, int rn_len,
93979d72832SMatthew Ahrens     boolean_t *ncp)
94079d72832SMatthew Ahrens {
94179d72832SMatthew Ahrens 	zap_t *zap;
94279d72832SMatthew Ahrens 	int err;
94379d72832SMatthew Ahrens 
94479d72832SMatthew Ahrens 	err = zap_lockdir_by_dnode(dn, NULL, RW_READER, TRUE, FALSE,
94579d72832SMatthew Ahrens 	    FTAG, &zap);
94679d72832SMatthew Ahrens 	if (err != 0)
94779d72832SMatthew Ahrens 		return (err);
94879d72832SMatthew Ahrens 	err = zap_lookup_impl(zap, name, integer_size,
94979d72832SMatthew Ahrens 	    num_integers, buf, mt, realname, rn_len, ncp);
95079d72832SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
95179d72832SMatthew Ahrens 	return (err);
95279d72832SMatthew Ahrens }
95379d72832SMatthew Ahrens 
954c7cd2421SGeorge Wilson int
955c7cd2421SGeorge Wilson zap_prefetch_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
956c7cd2421SGeorge Wilson     int key_numints)
957c7cd2421SGeorge Wilson {
958c7cd2421SGeorge Wilson 	zap_t *zap;
959c7cd2421SGeorge Wilson 	int err;
960c7cd2421SGeorge Wilson 	zap_name_t *zn;
961c7cd2421SGeorge Wilson 
962ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
963c7cd2421SGeorge Wilson 	if (err)
964c7cd2421SGeorge Wilson 		return (err);
965c7cd2421SGeorge Wilson 	zn = zap_name_alloc_uint64(zap, key, key_numints);
966c7cd2421SGeorge Wilson 	if (zn == NULL) {
967ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
968be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
969c7cd2421SGeorge Wilson 	}
970c7cd2421SGeorge Wilson 
971c7cd2421SGeorge Wilson 	fzap_prefetch(zn);
972c7cd2421SGeorge Wilson 	zap_name_free(zn);
973ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
974c7cd2421SGeorge Wilson 	return (err);
975c7cd2421SGeorge Wilson }
976c7cd2421SGeorge Wilson 
977b24ab676SJeff Bonwick int
978b24ab676SJeff Bonwick zap_lookup_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
979b24ab676SJeff Bonwick     int key_numints, uint64_t integer_size, uint64_t num_integers, void *buf)
980b24ab676SJeff Bonwick {
981b24ab676SJeff Bonwick 	zap_t *zap;
982b24ab676SJeff Bonwick 	int err;
983b24ab676SJeff Bonwick 	zap_name_t *zn;
984b24ab676SJeff Bonwick 
985ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
986b24ab676SJeff Bonwick 	if (err)
987b24ab676SJeff Bonwick 		return (err);
988b24ab676SJeff Bonwick 	zn = zap_name_alloc_uint64(zap, key, key_numints);
989b24ab676SJeff Bonwick 	if (zn == NULL) {
990ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
991be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
992b24ab676SJeff Bonwick 	}
993b24ab676SJeff Bonwick 
994b24ab676SJeff Bonwick 	err = fzap_lookup(zn, integer_size, num_integers, buf,
995b24ab676SJeff Bonwick 	    NULL, 0, NULL);
996b24ab676SJeff Bonwick 	zap_name_free(zn);
997ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
998b24ab676SJeff Bonwick 	return (err);
999b24ab676SJeff Bonwick }
1000b24ab676SJeff Bonwick 
100192241e0bSTom Erickson int
100292241e0bSTom Erickson zap_contains(objset_t *os, uint64_t zapobj, const char *name)
100392241e0bSTom Erickson {
10042acef22dSMatthew Ahrens 	int err = zap_lookup_norm(os, zapobj, name, 0,
1005*1c17160aSKevin Crowe 	    0, NULL, 0, NULL, 0, NULL);
100692241e0bSTom Erickson 	if (err == EOVERFLOW || err == EINVAL)
100792241e0bSTom Erickson 		err = 0; /* found, but skipped reading the value */
100892241e0bSTom Erickson 	return (err);
100992241e0bSTom Erickson }
101092241e0bSTom Erickson 
1011fa9e4066Sahrens int
1012fa9e4066Sahrens zap_length(objset_t *os, uint64_t zapobj, const char *name,
1013fa9e4066Sahrens     uint64_t *integer_size, uint64_t *num_integers)
1014fa9e4066Sahrens {
1015fa9e4066Sahrens 	zap_t *zap;
1016fa9e4066Sahrens 	int err;
1017fa9e4066Sahrens 	mzap_ent_t *mze;
1018da6c28aaSamw 	zap_name_t *zn;
1019fa9e4066Sahrens 
1020ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
1021fa9e4066Sahrens 	if (err)
1022fa9e4066Sahrens 		return (err);
1023*1c17160aSKevin Crowe 	zn = zap_name_alloc(zap, name, 0);
1024da6c28aaSamw 	if (zn == NULL) {
1025ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1026be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
1027da6c28aaSamw 	}
1028fa9e4066Sahrens 	if (!zap->zap_ismicro) {
1029da6c28aaSamw 		err = fzap_length(zn, integer_size, num_integers);
1030fa9e4066Sahrens 	} else {
1031da6c28aaSamw 		mze = mze_find(zn);
1032fa9e4066Sahrens 		if (mze == NULL) {
1033be6fd75aSMatthew Ahrens 			err = SET_ERROR(ENOENT);
1034fa9e4066Sahrens 		} else {
1035fa9e4066Sahrens 			if (integer_size)
1036fa9e4066Sahrens 				*integer_size = 8;
1037fa9e4066Sahrens 			if (num_integers)
1038fa9e4066Sahrens 				*num_integers = 1;
1039fa9e4066Sahrens 		}
1040fa9e4066Sahrens 	}
1041da6c28aaSamw 	zap_name_free(zn);
1042ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
1043fa9e4066Sahrens 	return (err);
1044fa9e4066Sahrens }
1045fa9e4066Sahrens 
1046b24ab676SJeff Bonwick int
1047b24ab676SJeff Bonwick zap_length_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
1048b24ab676SJeff Bonwick     int key_numints, uint64_t *integer_size, uint64_t *num_integers)
1049b24ab676SJeff Bonwick {
1050b24ab676SJeff Bonwick 	zap_t *zap;
1051b24ab676SJeff Bonwick 	int err;
1052b24ab676SJeff Bonwick 	zap_name_t *zn;
1053b24ab676SJeff Bonwick 
1054ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
1055b24ab676SJeff Bonwick 	if (err)
1056b24ab676SJeff Bonwick 		return (err);
1057b24ab676SJeff Bonwick 	zn = zap_name_alloc_uint64(zap, key, key_numints);
1058b24ab676SJeff Bonwick 	if (zn == NULL) {
1059ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1060be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
1061b24ab676SJeff Bonwick 	}
1062b24ab676SJeff Bonwick 	err = fzap_length(zn, integer_size, num_integers);
1063b24ab676SJeff Bonwick 	zap_name_free(zn);
1064ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
1065b24ab676SJeff Bonwick 	return (err);
1066b24ab676SJeff Bonwick }
1067b24ab676SJeff Bonwick 
1068fa9e4066Sahrens static void
1069da6c28aaSamw mzap_addent(zap_name_t *zn, uint64_t value)
1070fa9e4066Sahrens {
1071fa9e4066Sahrens 	int i;
1072da6c28aaSamw 	zap_t *zap = zn->zn_zap;
1073fa9e4066Sahrens 	int start = zap->zap_m.zap_alloc_next;
1074fa9e4066Sahrens 	uint32_t cd;
1075fa9e4066Sahrens 
1076fa9e4066Sahrens 	ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
1077fa9e4066Sahrens 
1078fa9e4066Sahrens #ifdef ZFS_DEBUG
1079fa9e4066Sahrens 	for (i = 0; i < zap->zap_m.zap_num_chunks; i++) {
1080c1379625SJustin T. Gibbs 		mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i];
1081b24ab676SJeff Bonwick 		ASSERT(strcmp(zn->zn_key_orig, mze->mze_name) != 0);
1082fa9e4066Sahrens 	}
1083fa9e4066Sahrens #endif
1084fa9e4066Sahrens 
1085da6c28aaSamw 	cd = mze_find_unused_cd(zap, zn->zn_hash);
1086fa9e4066Sahrens 	/* given the limited size of the microzap, this can't happen */
1087b24ab676SJeff Bonwick 	ASSERT(cd < zap_maxcd(zap));
1088fa9e4066Sahrens 
1089fa9e4066Sahrens again:
1090fa9e4066Sahrens 	for (i = start; i < zap->zap_m.zap_num_chunks; i++) {
1091c1379625SJustin T. Gibbs 		mzap_ent_phys_t *mze = &zap_m_phys(zap)->mz_chunk[i];
1092fa9e4066Sahrens 		if (mze->mze_name[0] == 0) {
1093fa9e4066Sahrens 			mze->mze_value = value;
1094fa9e4066Sahrens 			mze->mze_cd = cd;
1095b24ab676SJeff Bonwick 			(void) strcpy(mze->mze_name, zn->zn_key_orig);
1096fa9e4066Sahrens 			zap->zap_m.zap_num_entries++;
1097fa9e4066Sahrens 			zap->zap_m.zap_alloc_next = i+1;
1098fa9e4066Sahrens 			if (zap->zap_m.zap_alloc_next ==
1099fa9e4066Sahrens 			    zap->zap_m.zap_num_chunks)
1100fa9e4066Sahrens 				zap->zap_m.zap_alloc_next = 0;
11013f9d6ad7SLin Ling 			mze_insert(zap, i, zn->zn_hash);
1102fa9e4066Sahrens 			return;
1103fa9e4066Sahrens 		}
1104fa9e4066Sahrens 	}
1105fa9e4066Sahrens 	if (start != 0) {
1106fa9e4066Sahrens 		start = 0;
1107fa9e4066Sahrens 		goto again;
1108fa9e4066Sahrens 	}
1109fa9e4066Sahrens 	ASSERT(!"out of entries!");
1110fa9e4066Sahrens }
1111fa9e4066Sahrens 
1112fa9e4066Sahrens int
1113b24ab676SJeff Bonwick zap_add(objset_t *os, uint64_t zapobj, const char *key,
1114fa9e4066Sahrens     int integer_size, uint64_t num_integers,
1115fa9e4066Sahrens     const void *val, dmu_tx_t *tx)
1116fa9e4066Sahrens {
1117fa9e4066Sahrens 	zap_t *zap;
1118fa9e4066Sahrens 	int err;
1119fa9e4066Sahrens 	mzap_ent_t *mze;
1120fa9e4066Sahrens 	const uint64_t *intval = val;
1121da6c28aaSamw 	zap_name_t *zn;
1122fa9e4066Sahrens 
1123ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
1124fa9e4066Sahrens 	if (err)
1125fa9e4066Sahrens 		return (err);
1126*1c17160aSKevin Crowe 	zn = zap_name_alloc(zap, key, 0);
1127da6c28aaSamw 	if (zn == NULL) {
1128ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1129be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
1130da6c28aaSamw 	}
1131fa9e4066Sahrens 	if (!zap->zap_ismicro) {
1132ae972795SMatthew Ahrens 		err = fzap_add(zn, integer_size, num_integers, val, FTAG, tx);
1133ad860c82Sbonwick 		zap = zn->zn_zap;	/* fzap_add() may change zap */
1134fa9e4066Sahrens 	} else if (integer_size != 8 || num_integers != 1 ||
1135b24ab676SJeff Bonwick 	    strlen(key) >= MZAP_NAME_LEN) {
1136ae972795SMatthew Ahrens 		err = mzap_upgrade(&zn->zn_zap, FTAG, tx, 0);
1137ae972795SMatthew Ahrens 		if (err == 0) {
1138ae972795SMatthew Ahrens 			err = fzap_add(zn, integer_size, num_integers, val,
1139ae972795SMatthew Ahrens 			    FTAG, tx);
1140ae972795SMatthew Ahrens 		}
1141ad860c82Sbonwick 		zap = zn->zn_zap;	/* fzap_add() may change zap */
1142fa9e4066Sahrens 	} else {
1143da6c28aaSamw 		mze = mze_find(zn);
1144fa9e4066Sahrens 		if (mze != NULL) {
1145be6fd75aSMatthew Ahrens 			err = SET_ERROR(EEXIST);
1146fa9e4066Sahrens 		} else {
1147da6c28aaSamw 			mzap_addent(zn, *intval);
1148fa9e4066Sahrens 		}
1149fa9e4066Sahrens 	}
1150ad860c82Sbonwick 	ASSERT(zap == zn->zn_zap);
1151da6c28aaSamw 	zap_name_free(zn);
1152ad860c82Sbonwick 	if (zap != NULL)	/* may be NULL if fzap_add() failed */
1153ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1154fa9e4066Sahrens 	return (err);
1155fa9e4066Sahrens }
1156fa9e4066Sahrens 
1157b24ab676SJeff Bonwick int
1158b24ab676SJeff Bonwick zap_add_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
1159b24ab676SJeff Bonwick     int key_numints, int integer_size, uint64_t num_integers,
1160b24ab676SJeff Bonwick     const void *val, dmu_tx_t *tx)
1161b24ab676SJeff Bonwick {
1162b24ab676SJeff Bonwick 	zap_t *zap;
1163b24ab676SJeff Bonwick 	int err;
1164b24ab676SJeff Bonwick 	zap_name_t *zn;
1165b24ab676SJeff Bonwick 
1166ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
1167b24ab676SJeff Bonwick 	if (err)
1168b24ab676SJeff Bonwick 		return (err);
1169b24ab676SJeff Bonwick 	zn = zap_name_alloc_uint64(zap, key, key_numints);
1170b24ab676SJeff Bonwick 	if (zn == NULL) {
1171ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1172be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
1173b24ab676SJeff Bonwick 	}
1174ae972795SMatthew Ahrens 	err = fzap_add(zn, integer_size, num_integers, val, FTAG, tx);
1175b24ab676SJeff Bonwick 	zap = zn->zn_zap;	/* fzap_add() may change zap */
1176b24ab676SJeff Bonwick 	zap_name_free(zn);
1177b24ab676SJeff Bonwick 	if (zap != NULL)	/* may be NULL if fzap_add() failed */
1178ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1179b24ab676SJeff Bonwick 	return (err);
1180b24ab676SJeff Bonwick }
1181b24ab676SJeff Bonwick 
1182fa9e4066Sahrens int
1183fa9e4066Sahrens zap_update(objset_t *os, uint64_t zapobj, const char *name,
1184fa9e4066Sahrens     int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx)
1185fa9e4066Sahrens {
1186fa9e4066Sahrens 	zap_t *zap;
1187fa9e4066Sahrens 	mzap_ent_t *mze;
11883f9d6ad7SLin Ling 	uint64_t oldval;
1189fa9e4066Sahrens 	const uint64_t *intval = val;
1190da6c28aaSamw 	zap_name_t *zn;
1191fa9e4066Sahrens 	int err;
1192fa9e4066Sahrens 
11933f9d6ad7SLin Ling #ifdef ZFS_DEBUG
11943f9d6ad7SLin Ling 	/*
11953f9d6ad7SLin Ling 	 * If there is an old value, it shouldn't change across the
11963f9d6ad7SLin Ling 	 * lockdir (eg, due to bprewrite's xlation).
11973f9d6ad7SLin Ling 	 */
11983f9d6ad7SLin Ling 	if (integer_size == 8 && num_integers == 1)
11993f9d6ad7SLin Ling 		(void) zap_lookup(os, zapobj, name, 8, 1, &oldval);
12003f9d6ad7SLin Ling #endif
12013f9d6ad7SLin Ling 
1202ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
1203fa9e4066Sahrens 	if (err)
1204fa9e4066Sahrens 		return (err);
1205*1c17160aSKevin Crowe 	zn = zap_name_alloc(zap, name, 0);
1206da6c28aaSamw 	if (zn == NULL) {
1207ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1208be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
1209da6c28aaSamw 	}
1210fa9e4066Sahrens 	if (!zap->zap_ismicro) {
1211ae972795SMatthew Ahrens 		err = fzap_update(zn, integer_size, num_integers, val,
1212ae972795SMatthew Ahrens 		    FTAG, tx);
1213ad860c82Sbonwick 		zap = zn->zn_zap;	/* fzap_update() may change zap */
1214fa9e4066Sahrens 	} else if (integer_size != 8 || num_integers != 1 ||
1215fa9e4066Sahrens 	    strlen(name) >= MZAP_NAME_LEN) {
1216fa9e4066Sahrens 		dprintf("upgrading obj %llu: intsz=%u numint=%llu name=%s\n",
1217fa9e4066Sahrens 		    zapobj, integer_size, num_integers, name);
1218ae972795SMatthew Ahrens 		err = mzap_upgrade(&zn->zn_zap, FTAG, tx, 0);
1219ae972795SMatthew Ahrens 		if (err == 0) {
1220ad860c82Sbonwick 			err = fzap_update(zn, integer_size, num_integers,
1221ae972795SMatthew Ahrens 			    val, FTAG, tx);
1222ae972795SMatthew Ahrens 		}
1223ad860c82Sbonwick 		zap = zn->zn_zap;	/* fzap_update() may change zap */
1224fa9e4066Sahrens 	} else {
1225da6c28aaSamw 		mze = mze_find(zn);
1226fa9e4066Sahrens 		if (mze != NULL) {
12273f9d6ad7SLin Ling 			ASSERT3U(MZE_PHYS(zap, mze)->mze_value, ==, oldval);
12283f9d6ad7SLin Ling 			MZE_PHYS(zap, mze)->mze_value = *intval;
1229fa9e4066Sahrens 		} else {
1230da6c28aaSamw 			mzap_addent(zn, *intval);
1231fa9e4066Sahrens 		}
1232fa9e4066Sahrens 	}
1233ad860c82Sbonwick 	ASSERT(zap == zn->zn_zap);
1234da6c28aaSamw 	zap_name_free(zn);
1235ad860c82Sbonwick 	if (zap != NULL)	/* may be NULL if fzap_upgrade() failed */
1236ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1237455d5089Sahrens 	return (err);
1238fa9e4066Sahrens }
1239fa9e4066Sahrens 
1240b24ab676SJeff Bonwick int
1241b24ab676SJeff Bonwick zap_update_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
1242b24ab676SJeff Bonwick     int key_numints,
1243b24ab676SJeff Bonwick     int integer_size, uint64_t num_integers, const void *val, dmu_tx_t *tx)
1244b24ab676SJeff Bonwick {
1245b24ab676SJeff Bonwick 	zap_t *zap;
1246b24ab676SJeff Bonwick 	zap_name_t *zn;
1247b24ab676SJeff Bonwick 	int err;
1248b24ab676SJeff Bonwick 
1249ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, TRUE, FTAG, &zap);
1250b24ab676SJeff Bonwick 	if (err)
1251b24ab676SJeff Bonwick 		return (err);
1252b24ab676SJeff Bonwick 	zn = zap_name_alloc_uint64(zap, key, key_numints);
1253b24ab676SJeff Bonwick 	if (zn == NULL) {
1254ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1255be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
1256b24ab676SJeff Bonwick 	}
1257ae972795SMatthew Ahrens 	err = fzap_update(zn, integer_size, num_integers, val, FTAG, tx);
1258b24ab676SJeff Bonwick 	zap = zn->zn_zap;	/* fzap_update() may change zap */
1259b24ab676SJeff Bonwick 	zap_name_free(zn);
1260b24ab676SJeff Bonwick 	if (zap != NULL)	/* may be NULL if fzap_upgrade() failed */
1261ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1262b24ab676SJeff Bonwick 	return (err);
1263b24ab676SJeff Bonwick }
1264b24ab676SJeff Bonwick 
1265fa9e4066Sahrens int
1266fa9e4066Sahrens zap_remove(objset_t *os, uint64_t zapobj, const char *name, dmu_tx_t *tx)
1267da6c28aaSamw {
1268*1c17160aSKevin Crowe 	return (zap_remove_norm(os, zapobj, name, 0, tx));
1269da6c28aaSamw }
1270da6c28aaSamw 
1271da6c28aaSamw int
1272da6c28aaSamw zap_remove_norm(objset_t *os, uint64_t zapobj, const char *name,
1273da6c28aaSamw     matchtype_t mt, dmu_tx_t *tx)
1274fa9e4066Sahrens {
1275fa9e4066Sahrens 	zap_t *zap;
1276fa9e4066Sahrens 	int err;
1277fa9e4066Sahrens 	mzap_ent_t *mze;
1278da6c28aaSamw 	zap_name_t *zn;
1279fa9e4066Sahrens 
1280ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap);
1281fa9e4066Sahrens 	if (err)
1282fa9e4066Sahrens 		return (err);
1283da6c28aaSamw 	zn = zap_name_alloc(zap, name, mt);
1284da6c28aaSamw 	if (zn == NULL) {
1285ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1286be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
1287da6c28aaSamw 	}
1288fa9e4066Sahrens 	if (!zap->zap_ismicro) {
1289da6c28aaSamw 		err = fzap_remove(zn, tx);
1290fa9e4066Sahrens 	} else {
1291da6c28aaSamw 		mze = mze_find(zn);
1292fa9e4066Sahrens 		if (mze == NULL) {
1293be6fd75aSMatthew Ahrens 			err = SET_ERROR(ENOENT);
1294fa9e4066Sahrens 		} else {
1295fa9e4066Sahrens 			zap->zap_m.zap_num_entries--;
1296c1379625SJustin T. Gibbs 			bzero(&zap_m_phys(zap)->mz_chunk[mze->mze_chunkid],
1297fa9e4066Sahrens 			    sizeof (mzap_ent_phys_t));
1298fa9e4066Sahrens 			mze_remove(zap, mze);
1299fa9e4066Sahrens 		}
1300fa9e4066Sahrens 	}
1301da6c28aaSamw 	zap_name_free(zn);
1302ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
1303fa9e4066Sahrens 	return (err);
1304fa9e4066Sahrens }
1305fa9e4066Sahrens 
1306b24ab676SJeff Bonwick int
1307b24ab676SJeff Bonwick zap_remove_uint64(objset_t *os, uint64_t zapobj, const uint64_t *key,
1308b24ab676SJeff Bonwick     int key_numints, dmu_tx_t *tx)
1309b24ab676SJeff Bonwick {
1310b24ab676SJeff Bonwick 	zap_t *zap;
1311b24ab676SJeff Bonwick 	int err;
1312b24ab676SJeff Bonwick 	zap_name_t *zn;
1313b24ab676SJeff Bonwick 
1314ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, tx, RW_WRITER, TRUE, FALSE, FTAG, &zap);
1315b24ab676SJeff Bonwick 	if (err)
1316b24ab676SJeff Bonwick 		return (err);
1317b24ab676SJeff Bonwick 	zn = zap_name_alloc_uint64(zap, key, key_numints);
1318b24ab676SJeff Bonwick 	if (zn == NULL) {
1319ae972795SMatthew Ahrens 		zap_unlockdir(zap, FTAG);
1320be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOTSUP));
1321b24ab676SJeff Bonwick 	}
1322b24ab676SJeff Bonwick 	err = fzap_remove(zn, tx);
1323b24ab676SJeff Bonwick 	zap_name_free(zn);
1324ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
1325b24ab676SJeff Bonwick 	return (err);
1326b24ab676SJeff Bonwick }
1327b24ab676SJeff Bonwick 
1328fa9e4066Sahrens /*
1329fa9e4066Sahrens  * Routines for iterating over the attributes.
1330fa9e4066Sahrens  */
1331fa9e4066Sahrens 
1332fa9e4066Sahrens void
1333fa9e4066Sahrens zap_cursor_init_serialized(zap_cursor_t *zc, objset_t *os, uint64_t zapobj,
1334fa9e4066Sahrens     uint64_t serialized)
1335fa9e4066Sahrens {
1336fa9e4066Sahrens 	zc->zc_objset = os;
133787e5029aSahrens 	zc->zc_zap = NULL;
133887e5029aSahrens 	zc->zc_leaf = NULL;
1339fa9e4066Sahrens 	zc->zc_zapobj = zapobj;
1340b24ab676SJeff Bonwick 	zc->zc_serialized = serialized;
1341b24ab676SJeff Bonwick 	zc->zc_hash = 0;
1342b24ab676SJeff Bonwick 	zc->zc_cd = 0;
1343fa9e4066Sahrens }
1344fa9e4066Sahrens 
134587e5029aSahrens void
134687e5029aSahrens zap_cursor_init(zap_cursor_t *zc, objset_t *os, uint64_t zapobj)
134787e5029aSahrens {
134887e5029aSahrens 	zap_cursor_init_serialized(zc, os, zapobj, 0);
134987e5029aSahrens }
135087e5029aSahrens 
135187e5029aSahrens void
135287e5029aSahrens zap_cursor_fini(zap_cursor_t *zc)
135387e5029aSahrens {
135487e5029aSahrens 	if (zc->zc_zap) {
135587e5029aSahrens 		rw_enter(&zc->zc_zap->zap_rwlock, RW_READER);
1356ae972795SMatthew Ahrens 		zap_unlockdir(zc->zc_zap, NULL);
135787e5029aSahrens 		zc->zc_zap = NULL;
135887e5029aSahrens 	}
135987e5029aSahrens 	if (zc->zc_leaf) {
136087e5029aSahrens 		rw_enter(&zc->zc_leaf->l_rwlock, RW_READER);
136187e5029aSahrens 		zap_put_leaf(zc->zc_leaf);
136287e5029aSahrens 		zc->zc_leaf = NULL;
136387e5029aSahrens 	}
136487e5029aSahrens 	zc->zc_objset = NULL;
136587e5029aSahrens }
136687e5029aSahrens 
1367fa9e4066Sahrens uint64_t
1368fa9e4066Sahrens zap_cursor_serialize(zap_cursor_t *zc)
1369fa9e4066Sahrens {
1370fa9e4066Sahrens 	if (zc->zc_hash == -1ULL)
1371fa9e4066Sahrens 		return (-1ULL);
1372b24ab676SJeff Bonwick 	if (zc->zc_zap == NULL)
1373b24ab676SJeff Bonwick 		return (zc->zc_serialized);
1374b24ab676SJeff Bonwick 	ASSERT((zc->zc_hash & zap_maxcd(zc->zc_zap)) == 0);
1375b24ab676SJeff Bonwick 	ASSERT(zc->zc_cd < zap_maxcd(zc->zc_zap));
1376b24ab676SJeff Bonwick 
1377b24ab676SJeff Bonwick 	/*
1378b24ab676SJeff Bonwick 	 * We want to keep the high 32 bits of the cursor zero if we can, so
1379b24ab676SJeff Bonwick 	 * that 32-bit programs can access this.  So usually use a small
1380b24ab676SJeff Bonwick 	 * (28-bit) hash value so we can fit 4 bits of cd into the low 32-bits
1381b24ab676SJeff Bonwick 	 * of the cursor.
1382b24ab676SJeff Bonwick 	 *
1383b24ab676SJeff Bonwick 	 * [ collision differentiator | zap_hashbits()-bit hash value ]
1384b24ab676SJeff Bonwick 	 */
1385b24ab676SJeff Bonwick 	return ((zc->zc_hash >> (64 - zap_hashbits(zc->zc_zap))) |
1386b24ab676SJeff Bonwick 	    ((uint64_t)zc->zc_cd << zap_hashbits(zc->zc_zap)));
1387fa9e4066Sahrens }
1388fa9e4066Sahrens 
1389fa9e4066Sahrens int
1390fa9e4066Sahrens zap_cursor_retrieve(zap_cursor_t *zc, zap_attribute_t *za)
1391fa9e4066Sahrens {
1392fa9e4066Sahrens 	int err;
1393fa9e4066Sahrens 	avl_index_t idx;
1394fa9e4066Sahrens 	mzap_ent_t mze_tofind;
1395fa9e4066Sahrens 	mzap_ent_t *mze;
1396fa9e4066Sahrens 
1397fa9e4066Sahrens 	if (zc->zc_hash == -1ULL)
1398be6fd75aSMatthew Ahrens 		return (SET_ERROR(ENOENT));
1399fa9e4066Sahrens 
140087e5029aSahrens 	if (zc->zc_zap == NULL) {
1401b24ab676SJeff Bonwick 		int hb;
140287e5029aSahrens 		err = zap_lockdir(zc->zc_objset, zc->zc_zapobj, NULL,
1403ae972795SMatthew Ahrens 		    RW_READER, TRUE, FALSE, NULL, &zc->zc_zap);
140487e5029aSahrens 		if (err)
140587e5029aSahrens 			return (err);
1406b24ab676SJeff Bonwick 
1407b24ab676SJeff Bonwick 		/*
1408b24ab676SJeff Bonwick 		 * To support zap_cursor_init_serialized, advance, retrieve,
1409b24ab676SJeff Bonwick 		 * we must add to the existing zc_cd, which may already
1410b24ab676SJeff Bonwick 		 * be 1 due to the zap_cursor_advance.
1411b24ab676SJeff Bonwick 		 */
1412b24ab676SJeff Bonwick 		ASSERT(zc->zc_hash == 0);
1413b24ab676SJeff Bonwick 		hb = zap_hashbits(zc->zc_zap);
1414b24ab676SJeff Bonwick 		zc->zc_hash = zc->zc_serialized << (64 - hb);
1415b24ab676SJeff Bonwick 		zc->zc_cd += zc->zc_serialized >> hb;
1416b24ab676SJeff Bonwick 		if (zc->zc_cd >= zap_maxcd(zc->zc_zap)) /* corrupt serialized */
1417b24ab676SJeff Bonwick 			zc->zc_cd = 0;
141887e5029aSahrens 	} else {
141987e5029aSahrens 		rw_enter(&zc->zc_zap->zap_rwlock, RW_READER);
142087e5029aSahrens 	}
142187e5029aSahrens 	if (!zc->zc_zap->zap_ismicro) {
142287e5029aSahrens 		err = fzap_cursor_retrieve(zc->zc_zap, zc, za);
1423fa9e4066Sahrens 	} else {
1424fa9e4066Sahrens 		mze_tofind.mze_hash = zc->zc_hash;
14253f9d6ad7SLin Ling 		mze_tofind.mze_cd = zc->zc_cd;
1426fa9e4066Sahrens 
142787e5029aSahrens 		mze = avl_find(&zc->zc_zap->zap_m.zap_avl, &mze_tofind, &idx);
142887e5029aSahrens 		if (mze == NULL) {
142987e5029aSahrens 			mze = avl_nearest(&zc->zc_zap->zap_m.zap_avl,
143087e5029aSahrens 			    idx, AVL_AFTER);
143187e5029aSahrens 		}
1432fa9e4066Sahrens 		if (mze) {
14333f9d6ad7SLin Ling 			mzap_ent_phys_t *mzep = MZE_PHYS(zc->zc_zap, mze);
14343f9d6ad7SLin Ling 			ASSERT3U(mze->mze_cd, ==, mzep->mze_cd);
1435da6c28aaSamw 			za->za_normalization_conflict =
1436da6c28aaSamw 			    mzap_normalization_conflict(zc->zc_zap, NULL, mze);
1437fa9e4066Sahrens 			za->za_integer_length = 8;
1438fa9e4066Sahrens 			za->za_num_integers = 1;
14393f9d6ad7SLin Ling 			za->za_first_integer = mzep->mze_value;
14403f9d6ad7SLin Ling 			(void) strcpy(za->za_name, mzep->mze_name);
1441fa9e4066Sahrens 			zc->zc_hash = mze->mze_hash;
14423f9d6ad7SLin Ling 			zc->zc_cd = mze->mze_cd;
1443fa9e4066Sahrens 			err = 0;
1444fa9e4066Sahrens 		} else {
1445fa9e4066Sahrens 			zc->zc_hash = -1ULL;
1446be6fd75aSMatthew Ahrens 			err = SET_ERROR(ENOENT);
1447fa9e4066Sahrens 		}
1448fa9e4066Sahrens 	}
144987e5029aSahrens 	rw_exit(&zc->zc_zap->zap_rwlock);
1450fa9e4066Sahrens 	return (err);
1451fa9e4066Sahrens }
1452fa9e4066Sahrens 
1453fa9e4066Sahrens void
1454fa9e4066Sahrens zap_cursor_advance(zap_cursor_t *zc)
1455fa9e4066Sahrens {
1456fa9e4066Sahrens 	if (zc->zc_hash == -1ULL)
1457fa9e4066Sahrens 		return;
1458fa9e4066Sahrens 	zc->zc_cd++;
1459fa9e4066Sahrens }
1460fa9e4066Sahrens 
1461fa9e4066Sahrens int
1462fa9e4066Sahrens zap_get_stats(objset_t *os, uint64_t zapobj, zap_stats_t *zs)
1463fa9e4066Sahrens {
1464fa9e4066Sahrens 	int err;
1465fa9e4066Sahrens 	zap_t *zap;
1466fa9e4066Sahrens 
1467ae972795SMatthew Ahrens 	err = zap_lockdir(os, zapobj, NULL, RW_READER, TRUE, FALSE, FTAG, &zap);
1468fa9e4066Sahrens 	if (err)
1469fa9e4066Sahrens 		return (err);
1470fa9e4066Sahrens 
1471fa9e4066Sahrens 	bzero(zs, sizeof (zap_stats_t));
1472fa9e4066Sahrens 
1473fa9e4066Sahrens 	if (zap->zap_ismicro) {
1474fa9e4066Sahrens 		zs->zs_blocksize = zap->zap_dbuf->db_size;
1475fa9e4066Sahrens 		zs->zs_num_entries = zap->zap_m.zap_num_entries;
1476fa9e4066Sahrens 		zs->zs_num_blocks = 1;
1477fa9e4066Sahrens 	} else {
1478fa9e4066Sahrens 		fzap_get_stats(zap, zs);
1479fa9e4066Sahrens 	}
1480ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
1481fa9e4066Sahrens 	return (0);
1482fa9e4066Sahrens }
14833d692628SSanjeev Bagewadi 
14843d692628SSanjeev Bagewadi int
148579d72832SMatthew Ahrens zap_count_write_by_dnode(dnode_t *dn, const char *name, int add,
14860c779ad4SMatthew Ahrens     refcount_t *towrite, refcount_t *tooverwrite)
14873d692628SSanjeev Bagewadi {
14883d692628SSanjeev Bagewadi 	zap_t *zap;
14893d692628SSanjeev Bagewadi 	int err = 0;
14903d692628SSanjeev Bagewadi 
14913d692628SSanjeev Bagewadi 	/*
14923d692628SSanjeev Bagewadi 	 * Since, we don't have a name, we cannot figure out which blocks will
14933d692628SSanjeev Bagewadi 	 * be affected in this operation. So, account for the worst case :
14943d692628SSanjeev Bagewadi 	 * - 3 blocks overwritten: target leaf, ptrtbl block, header block
14953d692628SSanjeev Bagewadi 	 * - 4 new blocks written if adding:
14960c779ad4SMatthew Ahrens 	 *    - 2 blocks for possibly split leaves,
14970c779ad4SMatthew Ahrens 	 *    - 2 grown ptrtbl blocks
14983d692628SSanjeev Bagewadi 	 *
1499ae972795SMatthew Ahrens 	 * This also accommodates the case where an add operation to a fairly
15003d692628SSanjeev Bagewadi 	 * large microzap results in a promotion to fatzap.
15013d692628SSanjeev Bagewadi 	 */
15023d692628SSanjeev Bagewadi 	if (name == NULL) {
15030c779ad4SMatthew Ahrens 		(void) refcount_add_many(towrite,
15040c779ad4SMatthew Ahrens 		    (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE, FTAG);
15053d692628SSanjeev Bagewadi 		return (err);
15063d692628SSanjeev Bagewadi 	}
15073d692628SSanjeev Bagewadi 
15083d692628SSanjeev Bagewadi 	/*
150919b94df9SMatthew Ahrens 	 * We lock the zap with adding == FALSE. Because, if we pass
15103d692628SSanjeev Bagewadi 	 * the actual value of add, it could trigger a mzap_upgrade().
15113d692628SSanjeev Bagewadi 	 * At present we are just evaluating the possibility of this operation
1512ae972795SMatthew Ahrens 	 * and hence we do not want to trigger an upgrade.
15133d692628SSanjeev Bagewadi 	 */
151479d72832SMatthew Ahrens 	err = zap_lockdir_by_dnode(dn, NULL, RW_READER, TRUE, FALSE,
1515ae972795SMatthew Ahrens 	    FTAG, &zap);
1516ae972795SMatthew Ahrens 	if (err != 0)
15173d692628SSanjeev Bagewadi 		return (err);
15183d692628SSanjeev Bagewadi 
15193d692628SSanjeev Bagewadi 	if (!zap->zap_ismicro) {
1520*1c17160aSKevin Crowe 		zap_name_t *zn = zap_name_alloc(zap, name, 0);
15213d692628SSanjeev Bagewadi 		if (zn) {
15223d692628SSanjeev Bagewadi 			err = fzap_count_write(zn, add, towrite,
15233d692628SSanjeev Bagewadi 			    tooverwrite);
15243d692628SSanjeev Bagewadi 			zap_name_free(zn);
15253d692628SSanjeev Bagewadi 		} else {
15263d692628SSanjeev Bagewadi 			/*
15273d692628SSanjeev Bagewadi 			 * We treat this case as similar to (name == NULL)
15283d692628SSanjeev Bagewadi 			 */
15290c779ad4SMatthew Ahrens 			(void) refcount_add_many(towrite,
15300c779ad4SMatthew Ahrens 			    (3 + (add ? 4 : 0)) * SPA_OLD_MAXBLOCKSIZE, FTAG);
15313d692628SSanjeev Bagewadi 		}
15323d692628SSanjeev Bagewadi 	} else {
1533720d1aa1SSanjeev Bagewadi 		/*
1534720d1aa1SSanjeev Bagewadi 		 * We are here if (name != NULL) and this is a micro-zap.
1535720d1aa1SSanjeev Bagewadi 		 * We account for the header block depending on whether it
1536720d1aa1SSanjeev Bagewadi 		 * is freeable.
1537720d1aa1SSanjeev Bagewadi 		 *
1538720d1aa1SSanjeev Bagewadi 		 * Incase of an add-operation it is hard to find out
1539720d1aa1SSanjeev Bagewadi 		 * if this add will promote this microzap to fatzap.
1540720d1aa1SSanjeev Bagewadi 		 * Hence, we consider the worst case and account for the
1541720d1aa1SSanjeev Bagewadi 		 * blocks assuming this microzap would be promoted to a
1542720d1aa1SSanjeev Bagewadi 		 * fatzap.
1543720d1aa1SSanjeev Bagewadi 		 *
1544720d1aa1SSanjeev Bagewadi 		 * 1 block overwritten  : header block
1545720d1aa1SSanjeev Bagewadi 		 * 4 new blocks written : 2 new split leaf, 2 grown
1546720d1aa1SSanjeev Bagewadi 		 *			ptrtbl blocks
1547720d1aa1SSanjeev Bagewadi 		 */
15480c779ad4SMatthew Ahrens 		if (dmu_buf_freeable(zap->zap_dbuf)) {
15490c779ad4SMatthew Ahrens 			(void) refcount_add_many(tooverwrite,
15500c779ad4SMatthew Ahrens 			    MZAP_MAX_BLKSZ, FTAG);
15510c779ad4SMatthew Ahrens 		} else {
15520c779ad4SMatthew Ahrens 			(void) refcount_add_many(towrite,
15530c779ad4SMatthew Ahrens 			    MZAP_MAX_BLKSZ, FTAG);
15540c779ad4SMatthew Ahrens 		}
1555720d1aa1SSanjeev Bagewadi 
1556720d1aa1SSanjeev Bagewadi 		if (add) {
15570c779ad4SMatthew Ahrens 			(void) refcount_add_many(towrite,
15580c779ad4SMatthew Ahrens 			    4 * MZAP_MAX_BLKSZ, FTAG);
15593d692628SSanjeev Bagewadi 		}
15603d692628SSanjeev Bagewadi 	}
15613d692628SSanjeev Bagewadi 
1562ae972795SMatthew Ahrens 	zap_unlockdir(zap, FTAG);
15633d692628SSanjeev Bagewadi 	return (err);
15643d692628SSanjeev Bagewadi }
1565