1*61145dc2SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2eda14cbcSMatt Macy /*
3eda14cbcSMatt Macy * CDDL HEADER START
4eda14cbcSMatt Macy *
5eda14cbcSMatt Macy * The contents of this file are subject to the terms of the
6eda14cbcSMatt Macy * Common Development and Distribution License (the "License").
7eda14cbcSMatt Macy * You may not use this file except in compliance with the License.
8eda14cbcSMatt Macy *
9eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0.
11eda14cbcSMatt Macy * See the License for the specific language governing permissions
12eda14cbcSMatt Macy * and limitations under the License.
13eda14cbcSMatt Macy *
14eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each
15eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the
17eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying
18eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner]
19eda14cbcSMatt Macy *
20eda14cbcSMatt Macy * CDDL HEADER END
21eda14cbcSMatt Macy */
22eda14cbcSMatt Macy
23eda14cbcSMatt Macy /*
24eda14cbcSMatt Macy * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
25eda14cbcSMatt Macy * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
26eda14cbcSMatt Macy * Copyright 2017 Nexenta Systems, Inc.
27eda14cbcSMatt Macy */
28eda14cbcSMatt Macy
29eda14cbcSMatt Macy /*
30eda14cbcSMatt Macy * The 512-byte leaf is broken into 32 16-byte chunks.
31eda14cbcSMatt Macy * chunk number n means l_chunk[n], even though the header precedes it.
32eda14cbcSMatt Macy * the names are stored null-terminated.
33eda14cbcSMatt Macy */
34eda14cbcSMatt Macy
35eda14cbcSMatt Macy #include <sys/zio.h>
36eda14cbcSMatt Macy #include <sys/spa.h>
37eda14cbcSMatt Macy #include <sys/dmu.h>
38eda14cbcSMatt Macy #include <sys/zfs_context.h>
39eda14cbcSMatt Macy #include <sys/fs/zfs.h>
40eda14cbcSMatt Macy #include <sys/zap.h>
41eda14cbcSMatt Macy #include <sys/zap_impl.h>
42eda14cbcSMatt Macy #include <sys/zap_leaf.h>
43eda14cbcSMatt Macy #include <sys/arc.h>
44eda14cbcSMatt Macy
45783d3ff6SMartin Matuska static uint16_t *zap_leaf_rehash_entry(zap_leaf_t *l, struct zap_leaf_entry *le,
46783d3ff6SMartin Matuska uint16_t entry);
47eda14cbcSMatt Macy
48eda14cbcSMatt Macy #define CHAIN_END 0xffff /* end of the chunk chain */
49eda14cbcSMatt Macy
50eda14cbcSMatt Macy #define LEAF_HASH(l, h) \
51eda14cbcSMatt Macy ((ZAP_LEAF_HASH_NUMENTRIES(l)-1) & \
52eda14cbcSMatt Macy ((h) >> \
53eda14cbcSMatt Macy (64 - ZAP_LEAF_HASH_SHIFT(l) - zap_leaf_phys(l)->l_hdr.lh_prefix_len)))
54eda14cbcSMatt Macy
55eda14cbcSMatt Macy #define LEAF_HASH_ENTPTR(l, h) (&zap_leaf_phys(l)->l_hash[LEAF_HASH(l, h)])
56eda14cbcSMatt Macy
57eda14cbcSMatt Macy static void
stv(int len,void * addr,uint64_t value)58eda14cbcSMatt Macy stv(int len, void *addr, uint64_t value)
59eda14cbcSMatt Macy {
60eda14cbcSMatt Macy switch (len) {
61eda14cbcSMatt Macy case 1:
62eda14cbcSMatt Macy *(uint8_t *)addr = value;
63eda14cbcSMatt Macy return;
64eda14cbcSMatt Macy case 2:
65eda14cbcSMatt Macy *(uint16_t *)addr = value;
66eda14cbcSMatt Macy return;
67eda14cbcSMatt Macy case 4:
68eda14cbcSMatt Macy *(uint32_t *)addr = value;
69eda14cbcSMatt Macy return;
70eda14cbcSMatt Macy case 8:
71eda14cbcSMatt Macy *(uint64_t *)addr = value;
72eda14cbcSMatt Macy return;
73eda14cbcSMatt Macy default:
74783d3ff6SMartin Matuska PANIC("bad int len %d", len);
75eda14cbcSMatt Macy }
76eda14cbcSMatt Macy }
77eda14cbcSMatt Macy
78eda14cbcSMatt Macy static uint64_t
ldv(int len,const void * addr)79eda14cbcSMatt Macy ldv(int len, const void *addr)
80eda14cbcSMatt Macy {
81eda14cbcSMatt Macy switch (len) {
82eda14cbcSMatt Macy case 1:
83eda14cbcSMatt Macy return (*(uint8_t *)addr);
84eda14cbcSMatt Macy case 2:
85eda14cbcSMatt Macy return (*(uint16_t *)addr);
86eda14cbcSMatt Macy case 4:
87eda14cbcSMatt Macy return (*(uint32_t *)addr);
88eda14cbcSMatt Macy case 8:
89eda14cbcSMatt Macy return (*(uint64_t *)addr);
90eda14cbcSMatt Macy default:
91783d3ff6SMartin Matuska PANIC("bad int len %d", len);
92eda14cbcSMatt Macy }
93eda14cbcSMatt Macy return (0xFEEDFACEDEADBEEFULL);
94eda14cbcSMatt Macy }
95eda14cbcSMatt Macy
96eda14cbcSMatt Macy void
zap_leaf_byteswap(zap_leaf_phys_t * buf,size_t size)97783d3ff6SMartin Matuska zap_leaf_byteswap(zap_leaf_phys_t *buf, size_t size)
98eda14cbcSMatt Macy {
99eda14cbcSMatt Macy zap_leaf_t l;
100eda14cbcSMatt Macy dmu_buf_t l_dbuf;
101eda14cbcSMatt Macy
102eda14cbcSMatt Macy l_dbuf.db_data = buf;
103eda14cbcSMatt Macy l.l_bs = highbit64(size) - 1;
104eda14cbcSMatt Macy l.l_dbuf = &l_dbuf;
105eda14cbcSMatt Macy
106eda14cbcSMatt Macy buf->l_hdr.lh_block_type = BSWAP_64(buf->l_hdr.lh_block_type);
107eda14cbcSMatt Macy buf->l_hdr.lh_prefix = BSWAP_64(buf->l_hdr.lh_prefix);
108eda14cbcSMatt Macy buf->l_hdr.lh_magic = BSWAP_32(buf->l_hdr.lh_magic);
109eda14cbcSMatt Macy buf->l_hdr.lh_nfree = BSWAP_16(buf->l_hdr.lh_nfree);
110eda14cbcSMatt Macy buf->l_hdr.lh_nentries = BSWAP_16(buf->l_hdr.lh_nentries);
111eda14cbcSMatt Macy buf->l_hdr.lh_prefix_len = BSWAP_16(buf->l_hdr.lh_prefix_len);
112eda14cbcSMatt Macy buf->l_hdr.lh_freelist = BSWAP_16(buf->l_hdr.lh_freelist);
113eda14cbcSMatt Macy
114783d3ff6SMartin Matuska for (uint_t i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++)
115eda14cbcSMatt Macy buf->l_hash[i] = BSWAP_16(buf->l_hash[i]);
116eda14cbcSMatt Macy
117783d3ff6SMartin Matuska for (uint_t i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) {
118eda14cbcSMatt Macy zap_leaf_chunk_t *lc = &ZAP_LEAF_CHUNK(&l, i);
119eda14cbcSMatt Macy struct zap_leaf_entry *le;
120eda14cbcSMatt Macy
121eda14cbcSMatt Macy switch (lc->l_free.lf_type) {
122eda14cbcSMatt Macy case ZAP_CHUNK_ENTRY:
123eda14cbcSMatt Macy le = &lc->l_entry;
124eda14cbcSMatt Macy
125eda14cbcSMatt Macy le->le_type = BSWAP_8(le->le_type);
126eda14cbcSMatt Macy le->le_value_intlen = BSWAP_8(le->le_value_intlen);
127eda14cbcSMatt Macy le->le_next = BSWAP_16(le->le_next);
128eda14cbcSMatt Macy le->le_name_chunk = BSWAP_16(le->le_name_chunk);
129eda14cbcSMatt Macy le->le_name_numints = BSWAP_16(le->le_name_numints);
130eda14cbcSMatt Macy le->le_value_chunk = BSWAP_16(le->le_value_chunk);
131eda14cbcSMatt Macy le->le_value_numints = BSWAP_16(le->le_value_numints);
132eda14cbcSMatt Macy le->le_cd = BSWAP_32(le->le_cd);
133eda14cbcSMatt Macy le->le_hash = BSWAP_64(le->le_hash);
134eda14cbcSMatt Macy break;
135eda14cbcSMatt Macy case ZAP_CHUNK_FREE:
136eda14cbcSMatt Macy lc->l_free.lf_type = BSWAP_8(lc->l_free.lf_type);
137eda14cbcSMatt Macy lc->l_free.lf_next = BSWAP_16(lc->l_free.lf_next);
138eda14cbcSMatt Macy break;
139eda14cbcSMatt Macy case ZAP_CHUNK_ARRAY:
140eda14cbcSMatt Macy lc->l_array.la_type = BSWAP_8(lc->l_array.la_type);
141eda14cbcSMatt Macy lc->l_array.la_next = BSWAP_16(lc->l_array.la_next);
142eda14cbcSMatt Macy /* la_array doesn't need swapping */
143eda14cbcSMatt Macy break;
144eda14cbcSMatt Macy default:
145eda14cbcSMatt Macy cmn_err(CE_PANIC, "bad leaf type %d",
146eda14cbcSMatt Macy lc->l_free.lf_type);
147eda14cbcSMatt Macy }
148eda14cbcSMatt Macy }
149eda14cbcSMatt Macy }
150eda14cbcSMatt Macy
151eda14cbcSMatt Macy void
zap_leaf_init(zap_leaf_t * l,boolean_t sort)152eda14cbcSMatt Macy zap_leaf_init(zap_leaf_t *l, boolean_t sort)
153eda14cbcSMatt Macy {
154eda14cbcSMatt Macy l->l_bs = highbit64(l->l_dbuf->db_size) - 1;
155783d3ff6SMartin Matuska memset(&zap_leaf_phys(l)->l_hdr, 0,
156eda14cbcSMatt Macy sizeof (struct zap_leaf_header));
157783d3ff6SMartin Matuska memset(zap_leaf_phys(l)->l_hash, CHAIN_END,
158eda14cbcSMatt Macy 2*ZAP_LEAF_HASH_NUMENTRIES(l));
159783d3ff6SMartin Matuska for (uint_t i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
160eda14cbcSMatt Macy ZAP_LEAF_CHUNK(l, i).l_free.lf_type = ZAP_CHUNK_FREE;
161eda14cbcSMatt Macy ZAP_LEAF_CHUNK(l, i).l_free.lf_next = i+1;
162eda14cbcSMatt Macy }
163eda14cbcSMatt Macy ZAP_LEAF_CHUNK(l, ZAP_LEAF_NUMCHUNKS(l)-1).l_free.lf_next = CHAIN_END;
164eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_block_type = ZBT_LEAF;
165eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_magic = ZAP_LEAF_MAGIC;
166eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_nfree = ZAP_LEAF_NUMCHUNKS(l);
167eda14cbcSMatt Macy if (sort)
168eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED;
169eda14cbcSMatt Macy }
170eda14cbcSMatt Macy
171eda14cbcSMatt Macy /*
172eda14cbcSMatt Macy * Routines which manipulate leaf chunks (l_chunk[]).
173eda14cbcSMatt Macy */
174eda14cbcSMatt Macy
175eda14cbcSMatt Macy static uint16_t
zap_leaf_chunk_alloc(zap_leaf_t * l)176eda14cbcSMatt Macy zap_leaf_chunk_alloc(zap_leaf_t *l)
177eda14cbcSMatt Macy {
178eda14cbcSMatt Macy ASSERT(zap_leaf_phys(l)->l_hdr.lh_nfree > 0);
179eda14cbcSMatt Macy
180783d3ff6SMartin Matuska uint_t chunk = zap_leaf_phys(l)->l_hdr.lh_freelist;
181eda14cbcSMatt Macy ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
182eda14cbcSMatt Macy ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_free.lf_type, ==, ZAP_CHUNK_FREE);
183eda14cbcSMatt Macy
184eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_freelist =
185eda14cbcSMatt Macy ZAP_LEAF_CHUNK(l, chunk).l_free.lf_next;
186eda14cbcSMatt Macy
187eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_nfree--;
188eda14cbcSMatt Macy
189eda14cbcSMatt Macy return (chunk);
190eda14cbcSMatt Macy }
191eda14cbcSMatt Macy
192eda14cbcSMatt Macy static void
zap_leaf_chunk_free(zap_leaf_t * l,uint16_t chunk)193eda14cbcSMatt Macy zap_leaf_chunk_free(zap_leaf_t *l, uint16_t chunk)
194eda14cbcSMatt Macy {
195eda14cbcSMatt Macy struct zap_leaf_free *zlf = &ZAP_LEAF_CHUNK(l, chunk).l_free;
196eda14cbcSMatt Macy ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_nfree, <, ZAP_LEAF_NUMCHUNKS(l));
197eda14cbcSMatt Macy ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
198eda14cbcSMatt Macy ASSERT(zlf->lf_type != ZAP_CHUNK_FREE);
199eda14cbcSMatt Macy
200eda14cbcSMatt Macy zlf->lf_type = ZAP_CHUNK_FREE;
201eda14cbcSMatt Macy zlf->lf_next = zap_leaf_phys(l)->l_hdr.lh_freelist;
202da5137abSMartin Matuska memset(zlf->lf_pad, 0, sizeof (zlf->lf_pad)); /* help it to compress */
203eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_freelist = chunk;
204eda14cbcSMatt Macy
205eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_nfree++;
206eda14cbcSMatt Macy }
207eda14cbcSMatt Macy
208eda14cbcSMatt Macy /*
209eda14cbcSMatt Macy * Routines which manipulate leaf arrays (zap_leaf_array type chunks).
210eda14cbcSMatt Macy */
211eda14cbcSMatt Macy
212eda14cbcSMatt Macy static uint16_t
zap_leaf_array_create(zap_leaf_t * l,const char * buf,int integer_size,int num_integers)213eda14cbcSMatt Macy zap_leaf_array_create(zap_leaf_t *l, const char *buf,
214eda14cbcSMatt Macy int integer_size, int num_integers)
215eda14cbcSMatt Macy {
216eda14cbcSMatt Macy uint16_t chunk_head;
217eda14cbcSMatt Macy uint16_t *chunkp = &chunk_head;
218783d3ff6SMartin Matuska int byten = integer_size;
219eda14cbcSMatt Macy uint64_t value = 0;
220eda14cbcSMatt Macy int shift = (integer_size - 1) * 8;
221eda14cbcSMatt Macy int len = num_integers;
222eda14cbcSMatt Macy
223eda14cbcSMatt Macy ASSERT3U(num_integers * integer_size, <=, ZAP_MAXVALUELEN);
224eda14cbcSMatt Macy
225783d3ff6SMartin Matuska if (len > 0)
226783d3ff6SMartin Matuska value = ldv(integer_size, buf);
227eda14cbcSMatt Macy while (len > 0) {
228eda14cbcSMatt Macy uint16_t chunk = zap_leaf_chunk_alloc(l);
229eda14cbcSMatt Macy struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
230eda14cbcSMatt Macy
231eda14cbcSMatt Macy la->la_type = ZAP_CHUNK_ARRAY;
232eda14cbcSMatt Macy for (int i = 0; i < ZAP_LEAF_ARRAY_BYTES; i++) {
233eda14cbcSMatt Macy la->la_array[i] = value >> shift;
234eda14cbcSMatt Macy value <<= 8;
235783d3ff6SMartin Matuska if (--byten == 0) {
236eda14cbcSMatt Macy if (--len == 0)
237eda14cbcSMatt Macy break;
238783d3ff6SMartin Matuska byten = integer_size;
239783d3ff6SMartin Matuska buf += integer_size;
240783d3ff6SMartin Matuska value = ldv(integer_size, buf);
241eda14cbcSMatt Macy }
242eda14cbcSMatt Macy }
243eda14cbcSMatt Macy
244eda14cbcSMatt Macy *chunkp = chunk;
245eda14cbcSMatt Macy chunkp = &la->la_next;
246eda14cbcSMatt Macy }
247eda14cbcSMatt Macy *chunkp = CHAIN_END;
248eda14cbcSMatt Macy
249eda14cbcSMatt Macy return (chunk_head);
250eda14cbcSMatt Macy }
251eda14cbcSMatt Macy
252718519f4SMartin Matuska /*
253718519f4SMartin Matuska * Non-destructively copy array between leaves.
254718519f4SMartin Matuska */
255718519f4SMartin Matuska static uint16_t
zap_leaf_array_copy(zap_leaf_t * l,uint16_t chunk,zap_leaf_t * nl)256718519f4SMartin Matuska zap_leaf_array_copy(zap_leaf_t *l, uint16_t chunk, zap_leaf_t *nl)
257eda14cbcSMatt Macy {
258718519f4SMartin Matuska uint16_t new_chunk;
259718519f4SMartin Matuska uint16_t *nchunkp = &new_chunk;
260eda14cbcSMatt Macy
261eda14cbcSMatt Macy while (chunk != CHAIN_END) {
262718519f4SMartin Matuska ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
263718519f4SMartin Matuska uint16_t nchunk = zap_leaf_chunk_alloc(nl);
264718519f4SMartin Matuska
265718519f4SMartin Matuska struct zap_leaf_array *la =
266718519f4SMartin Matuska &ZAP_LEAF_CHUNK(l, chunk).l_array;
267718519f4SMartin Matuska struct zap_leaf_array *nla =
268718519f4SMartin Matuska &ZAP_LEAF_CHUNK(nl, nchunk).l_array;
269718519f4SMartin Matuska ASSERT3U(la->la_type, ==, ZAP_CHUNK_ARRAY);
270718519f4SMartin Matuska
271718519f4SMartin Matuska *nla = *la; /* structure assignment */
272718519f4SMartin Matuska
273718519f4SMartin Matuska chunk = la->la_next;
274718519f4SMartin Matuska *nchunkp = nchunk;
275718519f4SMartin Matuska nchunkp = &nla->la_next;
276eda14cbcSMatt Macy }
277718519f4SMartin Matuska *nchunkp = CHAIN_END;
278718519f4SMartin Matuska return (new_chunk);
279718519f4SMartin Matuska }
280718519f4SMartin Matuska
281718519f4SMartin Matuska /*
282718519f4SMartin Matuska * Free array. Unlike trivial loop of zap_leaf_chunk_free() this does
283718519f4SMartin Matuska * not reverse order of chunks in the free list, reducing fragmentation.
284718519f4SMartin Matuska */
285718519f4SMartin Matuska static void
zap_leaf_array_free(zap_leaf_t * l,uint16_t chunk)286718519f4SMartin Matuska zap_leaf_array_free(zap_leaf_t *l, uint16_t chunk)
287718519f4SMartin Matuska {
288718519f4SMartin Matuska struct zap_leaf_header *hdr = &zap_leaf_phys(l)->l_hdr;
289718519f4SMartin Matuska uint16_t *tailp = &hdr->lh_freelist;
290718519f4SMartin Matuska uint16_t oldfree = *tailp;
291718519f4SMartin Matuska
292718519f4SMartin Matuska while (chunk != CHAIN_END) {
293718519f4SMartin Matuska ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
294718519f4SMartin Matuska zap_leaf_chunk_t *c = &ZAP_LEAF_CHUNK(l, chunk);
295718519f4SMartin Matuska ASSERT3U(c->l_array.la_type, ==, ZAP_CHUNK_ARRAY);
296718519f4SMartin Matuska
297718519f4SMartin Matuska *tailp = chunk;
298718519f4SMartin Matuska chunk = c->l_array.la_next;
299718519f4SMartin Matuska
300718519f4SMartin Matuska c->l_free.lf_type = ZAP_CHUNK_FREE;
301718519f4SMartin Matuska memset(c->l_free.lf_pad, 0, sizeof (c->l_free.lf_pad));
302718519f4SMartin Matuska tailp = &c->l_free.lf_next;
303718519f4SMartin Matuska
304718519f4SMartin Matuska ASSERT3U(hdr->lh_nfree, <, ZAP_LEAF_NUMCHUNKS(l));
305718519f4SMartin Matuska hdr->lh_nfree++;
306718519f4SMartin Matuska }
307718519f4SMartin Matuska
308718519f4SMartin Matuska *tailp = oldfree;
309eda14cbcSMatt Macy }
310eda14cbcSMatt Macy
311eda14cbcSMatt Macy /* array_len and buf_len are in integers, not bytes */
312eda14cbcSMatt Macy static void
zap_leaf_array_read(zap_leaf_t * l,uint16_t chunk,int array_int_len,int array_len,int buf_int_len,uint64_t buf_len,void * buf)313eda14cbcSMatt Macy zap_leaf_array_read(zap_leaf_t *l, uint16_t chunk,
314eda14cbcSMatt Macy int array_int_len, int array_len, int buf_int_len, uint64_t buf_len,
315eda14cbcSMatt Macy void *buf)
316eda14cbcSMatt Macy {
317eda14cbcSMatt Macy int len = MIN(array_len, buf_len);
318eda14cbcSMatt Macy int byten = 0;
319eda14cbcSMatt Macy uint64_t value = 0;
320eda14cbcSMatt Macy char *p = buf;
321eda14cbcSMatt Macy
322eda14cbcSMatt Macy ASSERT3U(array_int_len, <=, buf_int_len);
323eda14cbcSMatt Macy
324eda14cbcSMatt Macy /* Fast path for one 8-byte integer */
325eda14cbcSMatt Macy if (array_int_len == 8 && buf_int_len == 8 && len == 1) {
326eda14cbcSMatt Macy struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
327eda14cbcSMatt Macy uint8_t *ip = la->la_array;
328eda14cbcSMatt Macy uint64_t *buf64 = buf;
329eda14cbcSMatt Macy
330eda14cbcSMatt Macy *buf64 = (uint64_t)ip[0] << 56 | (uint64_t)ip[1] << 48 |
331eda14cbcSMatt Macy (uint64_t)ip[2] << 40 | (uint64_t)ip[3] << 32 |
332eda14cbcSMatt Macy (uint64_t)ip[4] << 24 | (uint64_t)ip[5] << 16 |
333eda14cbcSMatt Macy (uint64_t)ip[6] << 8 | (uint64_t)ip[7];
334eda14cbcSMatt Macy return;
335eda14cbcSMatt Macy }
336eda14cbcSMatt Macy
337eda14cbcSMatt Macy /* Fast path for an array of 1-byte integers (eg. the entry name) */
338eda14cbcSMatt Macy if (array_int_len == 1 && buf_int_len == 1 &&
339eda14cbcSMatt Macy buf_len > array_len + ZAP_LEAF_ARRAY_BYTES) {
340eda14cbcSMatt Macy while (chunk != CHAIN_END) {
341eda14cbcSMatt Macy struct zap_leaf_array *la =
342eda14cbcSMatt Macy &ZAP_LEAF_CHUNK(l, chunk).l_array;
343da5137abSMartin Matuska memcpy(p, la->la_array, ZAP_LEAF_ARRAY_BYTES);
344eda14cbcSMatt Macy p += ZAP_LEAF_ARRAY_BYTES;
345eda14cbcSMatt Macy chunk = la->la_next;
346eda14cbcSMatt Macy }
347eda14cbcSMatt Macy return;
348eda14cbcSMatt Macy }
349eda14cbcSMatt Macy
350eda14cbcSMatt Macy while (len > 0) {
351eda14cbcSMatt Macy struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
352eda14cbcSMatt Macy
353eda14cbcSMatt Macy ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
3542a58b312SMartin Matuska for (int i = 0; i < ZAP_LEAF_ARRAY_BYTES; i++) {
355eda14cbcSMatt Macy value = (value << 8) | la->la_array[i];
356eda14cbcSMatt Macy byten++;
357eda14cbcSMatt Macy if (byten == array_int_len) {
358eda14cbcSMatt Macy stv(buf_int_len, p, value);
359eda14cbcSMatt Macy byten = 0;
360eda14cbcSMatt Macy len--;
361eda14cbcSMatt Macy if (len == 0)
362eda14cbcSMatt Macy return;
363eda14cbcSMatt Macy p += buf_int_len;
364eda14cbcSMatt Macy }
365eda14cbcSMatt Macy }
366eda14cbcSMatt Macy chunk = la->la_next;
367eda14cbcSMatt Macy }
368eda14cbcSMatt Macy }
369eda14cbcSMatt Macy
370eda14cbcSMatt Macy static boolean_t
zap_leaf_array_match(zap_leaf_t * l,zap_name_t * zn,uint_t chunk,int array_numints)371eda14cbcSMatt Macy zap_leaf_array_match(zap_leaf_t *l, zap_name_t *zn,
372783d3ff6SMartin Matuska uint_t chunk, int array_numints)
373eda14cbcSMatt Macy {
374eda14cbcSMatt Macy int bseen = 0;
375eda14cbcSMatt Macy
376eda14cbcSMatt Macy if (zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY) {
377eda14cbcSMatt Macy uint64_t *thiskey =
378eda14cbcSMatt Macy kmem_alloc(array_numints * sizeof (*thiskey), KM_SLEEP);
379eda14cbcSMatt Macy ASSERT(zn->zn_key_intlen == sizeof (*thiskey));
380eda14cbcSMatt Macy
381eda14cbcSMatt Macy zap_leaf_array_read(l, chunk, sizeof (*thiskey), array_numints,
382eda14cbcSMatt Macy sizeof (*thiskey), array_numints, thiskey);
383da5137abSMartin Matuska boolean_t match = memcmp(thiskey, zn->zn_key_orig,
384eda14cbcSMatt Macy array_numints * sizeof (*thiskey)) == 0;
385eda14cbcSMatt Macy kmem_free(thiskey, array_numints * sizeof (*thiskey));
386eda14cbcSMatt Macy return (match);
387eda14cbcSMatt Macy }
388eda14cbcSMatt Macy
389eda14cbcSMatt Macy ASSERT(zn->zn_key_intlen == 1);
390eda14cbcSMatt Macy if (zn->zn_matchtype & MT_NORMALIZE) {
391eda14cbcSMatt Macy char *thisname = kmem_alloc(array_numints, KM_SLEEP);
392eda14cbcSMatt Macy
393eda14cbcSMatt Macy zap_leaf_array_read(l, chunk, sizeof (char), array_numints,
394eda14cbcSMatt Macy sizeof (char), array_numints, thisname);
395eda14cbcSMatt Macy boolean_t match = zap_match(zn, thisname);
396eda14cbcSMatt Macy kmem_free(thisname, array_numints);
397eda14cbcSMatt Macy return (match);
398eda14cbcSMatt Macy }
399eda14cbcSMatt Macy
400eda14cbcSMatt Macy /*
401eda14cbcSMatt Macy * Fast path for exact matching.
402eda14cbcSMatt Macy * First check that the lengths match, so that we don't read
403eda14cbcSMatt Macy * past the end of the zn_key_orig array.
404eda14cbcSMatt Macy */
405eda14cbcSMatt Macy if (array_numints != zn->zn_key_orig_numints)
406eda14cbcSMatt Macy return (B_FALSE);
407eda14cbcSMatt Macy while (bseen < array_numints) {
408eda14cbcSMatt Macy struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
409eda14cbcSMatt Macy int toread = MIN(array_numints - bseen, ZAP_LEAF_ARRAY_BYTES);
410eda14cbcSMatt Macy ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
411da5137abSMartin Matuska if (memcmp(la->la_array, (char *)zn->zn_key_orig + bseen,
412da5137abSMartin Matuska toread))
413eda14cbcSMatt Macy break;
414eda14cbcSMatt Macy chunk = la->la_next;
415eda14cbcSMatt Macy bseen += toread;
416eda14cbcSMatt Macy }
417eda14cbcSMatt Macy return (bseen == array_numints);
418eda14cbcSMatt Macy }
419eda14cbcSMatt Macy
420eda14cbcSMatt Macy /*
421eda14cbcSMatt Macy * Routines which manipulate leaf entries.
422eda14cbcSMatt Macy */
423eda14cbcSMatt Macy
424eda14cbcSMatt Macy int
zap_leaf_lookup(zap_leaf_t * l,zap_name_t * zn,zap_entry_handle_t * zeh)425eda14cbcSMatt Macy zap_leaf_lookup(zap_leaf_t *l, zap_name_t *zn, zap_entry_handle_t *zeh)
426eda14cbcSMatt Macy {
427eda14cbcSMatt Macy struct zap_leaf_entry *le;
428eda14cbcSMatt Macy
429eda14cbcSMatt Macy ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);
430eda14cbcSMatt Macy
431eda14cbcSMatt Macy for (uint16_t *chunkp = LEAF_HASH_ENTPTR(l, zn->zn_hash);
432eda14cbcSMatt Macy *chunkp != CHAIN_END; chunkp = &le->le_next) {
433eda14cbcSMatt Macy uint16_t chunk = *chunkp;
434eda14cbcSMatt Macy le = ZAP_LEAF_ENTRY(l, chunk);
435eda14cbcSMatt Macy
436eda14cbcSMatt Macy ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
437eda14cbcSMatt Macy ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
438eda14cbcSMatt Macy
439eda14cbcSMatt Macy if (le->le_hash != zn->zn_hash)
440eda14cbcSMatt Macy continue;
441eda14cbcSMatt Macy
442eda14cbcSMatt Macy /*
443eda14cbcSMatt Macy * NB: the entry chain is always sorted by cd on
444eda14cbcSMatt Macy * normalized zap objects, so this will find the
445eda14cbcSMatt Macy * lowest-cd match for MT_NORMALIZE.
446eda14cbcSMatt Macy */
447eda14cbcSMatt Macy ASSERT((zn->zn_matchtype == 0) ||
448eda14cbcSMatt Macy (zap_leaf_phys(l)->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED));
449eda14cbcSMatt Macy if (zap_leaf_array_match(l, zn, le->le_name_chunk,
450eda14cbcSMatt Macy le->le_name_numints)) {
451eda14cbcSMatt Macy zeh->zeh_num_integers = le->le_value_numints;
452eda14cbcSMatt Macy zeh->zeh_integer_size = le->le_value_intlen;
453eda14cbcSMatt Macy zeh->zeh_cd = le->le_cd;
454eda14cbcSMatt Macy zeh->zeh_hash = le->le_hash;
455eda14cbcSMatt Macy zeh->zeh_chunkp = chunkp;
456eda14cbcSMatt Macy zeh->zeh_leaf = l;
457eda14cbcSMatt Macy return (0);
458eda14cbcSMatt Macy }
459eda14cbcSMatt Macy }
460eda14cbcSMatt Macy
461eda14cbcSMatt Macy return (SET_ERROR(ENOENT));
462eda14cbcSMatt Macy }
463eda14cbcSMatt Macy
464eda14cbcSMatt Macy /* Return (h1,cd1 >= h2,cd2) */
465eda14cbcSMatt Macy #define HCD_GTEQ(h1, cd1, h2, cd2) \
466eda14cbcSMatt Macy ((h1 > h2) ? TRUE : ((h1 == h2 && cd1 >= cd2) ? TRUE : FALSE))
467eda14cbcSMatt Macy
468eda14cbcSMatt Macy int
zap_leaf_lookup_closest(zap_leaf_t * l,uint64_t h,uint32_t cd,zap_entry_handle_t * zeh)469eda14cbcSMatt Macy zap_leaf_lookup_closest(zap_leaf_t *l,
470eda14cbcSMatt Macy uint64_t h, uint32_t cd, zap_entry_handle_t *zeh)
471eda14cbcSMatt Macy {
472eda14cbcSMatt Macy uint64_t besth = -1ULL;
473eda14cbcSMatt Macy uint32_t bestcd = -1U;
474eda14cbcSMatt Macy uint16_t bestlh = ZAP_LEAF_HASH_NUMENTRIES(l)-1;
475eda14cbcSMatt Macy struct zap_leaf_entry *le;
476eda14cbcSMatt Macy
477eda14cbcSMatt Macy ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);
478eda14cbcSMatt Macy
479eda14cbcSMatt Macy for (uint16_t lh = LEAF_HASH(l, h); lh <= bestlh; lh++) {
480eda14cbcSMatt Macy for (uint16_t chunk = zap_leaf_phys(l)->l_hash[lh];
481eda14cbcSMatt Macy chunk != CHAIN_END; chunk = le->le_next) {
482eda14cbcSMatt Macy le = ZAP_LEAF_ENTRY(l, chunk);
483eda14cbcSMatt Macy
484eda14cbcSMatt Macy ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
485eda14cbcSMatt Macy ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
486eda14cbcSMatt Macy
487eda14cbcSMatt Macy if (HCD_GTEQ(le->le_hash, le->le_cd, h, cd) &&
488eda14cbcSMatt Macy HCD_GTEQ(besth, bestcd, le->le_hash, le->le_cd)) {
489eda14cbcSMatt Macy ASSERT3U(bestlh, >=, lh);
490eda14cbcSMatt Macy bestlh = lh;
491eda14cbcSMatt Macy besth = le->le_hash;
492eda14cbcSMatt Macy bestcd = le->le_cd;
493eda14cbcSMatt Macy
494eda14cbcSMatt Macy zeh->zeh_num_integers = le->le_value_numints;
495eda14cbcSMatt Macy zeh->zeh_integer_size = le->le_value_intlen;
496eda14cbcSMatt Macy zeh->zeh_cd = le->le_cd;
497eda14cbcSMatt Macy zeh->zeh_hash = le->le_hash;
498eda14cbcSMatt Macy zeh->zeh_fakechunk = chunk;
499eda14cbcSMatt Macy zeh->zeh_chunkp = &zeh->zeh_fakechunk;
500eda14cbcSMatt Macy zeh->zeh_leaf = l;
501eda14cbcSMatt Macy }
502eda14cbcSMatt Macy }
503eda14cbcSMatt Macy }
504eda14cbcSMatt Macy
505eda14cbcSMatt Macy return (bestcd == -1U ? SET_ERROR(ENOENT) : 0);
506eda14cbcSMatt Macy }
507eda14cbcSMatt Macy
508eda14cbcSMatt Macy int
zap_entry_read(const zap_entry_handle_t * zeh,uint8_t integer_size,uint64_t num_integers,void * buf)509eda14cbcSMatt Macy zap_entry_read(const zap_entry_handle_t *zeh,
510eda14cbcSMatt Macy uint8_t integer_size, uint64_t num_integers, void *buf)
511eda14cbcSMatt Macy {
512eda14cbcSMatt Macy struct zap_leaf_entry *le =
513eda14cbcSMatt Macy ZAP_LEAF_ENTRY(zeh->zeh_leaf, *zeh->zeh_chunkp);
514eda14cbcSMatt Macy ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
515eda14cbcSMatt Macy
516eda14cbcSMatt Macy if (le->le_value_intlen > integer_size)
517eda14cbcSMatt Macy return (SET_ERROR(EINVAL));
518eda14cbcSMatt Macy
519eda14cbcSMatt Macy zap_leaf_array_read(zeh->zeh_leaf, le->le_value_chunk,
520eda14cbcSMatt Macy le->le_value_intlen, le->le_value_numints,
521eda14cbcSMatt Macy integer_size, num_integers, buf);
522eda14cbcSMatt Macy
523eda14cbcSMatt Macy if (zeh->zeh_num_integers > num_integers)
524eda14cbcSMatt Macy return (SET_ERROR(EOVERFLOW));
525eda14cbcSMatt Macy return (0);
526eda14cbcSMatt Macy
527eda14cbcSMatt Macy }
528eda14cbcSMatt Macy
529eda14cbcSMatt Macy int
zap_entry_read_name(zap_t * zap,const zap_entry_handle_t * zeh,uint16_t buflen,char * buf)530eda14cbcSMatt Macy zap_entry_read_name(zap_t *zap, const zap_entry_handle_t *zeh, uint16_t buflen,
531eda14cbcSMatt Macy char *buf)
532eda14cbcSMatt Macy {
533eda14cbcSMatt Macy struct zap_leaf_entry *le =
534eda14cbcSMatt Macy ZAP_LEAF_ENTRY(zeh->zeh_leaf, *zeh->zeh_chunkp);
535eda14cbcSMatt Macy ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
536eda14cbcSMatt Macy
537eda14cbcSMatt Macy if (zap_getflags(zap) & ZAP_FLAG_UINT64_KEY) {
538eda14cbcSMatt Macy zap_leaf_array_read(zeh->zeh_leaf, le->le_name_chunk, 8,
539eda14cbcSMatt Macy le->le_name_numints, 8, buflen / 8, buf);
540eda14cbcSMatt Macy } else {
541eda14cbcSMatt Macy zap_leaf_array_read(zeh->zeh_leaf, le->le_name_chunk, 1,
542eda14cbcSMatt Macy le->le_name_numints, 1, buflen, buf);
543eda14cbcSMatt Macy }
544eda14cbcSMatt Macy if (le->le_name_numints > buflen)
545eda14cbcSMatt Macy return (SET_ERROR(EOVERFLOW));
546eda14cbcSMatt Macy return (0);
547eda14cbcSMatt Macy }
548eda14cbcSMatt Macy
549eda14cbcSMatt Macy int
zap_entry_update(zap_entry_handle_t * zeh,uint8_t integer_size,uint64_t num_integers,const void * buf)550eda14cbcSMatt Macy zap_entry_update(zap_entry_handle_t *zeh,
551eda14cbcSMatt Macy uint8_t integer_size, uint64_t num_integers, const void *buf)
552eda14cbcSMatt Macy {
553eda14cbcSMatt Macy zap_leaf_t *l = zeh->zeh_leaf;
554eda14cbcSMatt Macy struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, *zeh->zeh_chunkp);
555eda14cbcSMatt Macy
556eda14cbcSMatt Macy int delta_chunks = ZAP_LEAF_ARRAY_NCHUNKS(num_integers * integer_size) -
557eda14cbcSMatt Macy ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_numints * le->le_value_intlen);
558eda14cbcSMatt Macy
559eda14cbcSMatt Macy if ((int)zap_leaf_phys(l)->l_hdr.lh_nfree < delta_chunks)
560eda14cbcSMatt Macy return (SET_ERROR(EAGAIN));
561eda14cbcSMatt Macy
562718519f4SMartin Matuska zap_leaf_array_free(l, le->le_value_chunk);
563eda14cbcSMatt Macy le->le_value_chunk =
564eda14cbcSMatt Macy zap_leaf_array_create(l, buf, integer_size, num_integers);
565eda14cbcSMatt Macy le->le_value_numints = num_integers;
566eda14cbcSMatt Macy le->le_value_intlen = integer_size;
567eda14cbcSMatt Macy return (0);
568eda14cbcSMatt Macy }
569eda14cbcSMatt Macy
570eda14cbcSMatt Macy void
zap_entry_remove(zap_entry_handle_t * zeh)571eda14cbcSMatt Macy zap_entry_remove(zap_entry_handle_t *zeh)
572eda14cbcSMatt Macy {
573eda14cbcSMatt Macy zap_leaf_t *l = zeh->zeh_leaf;
574eda14cbcSMatt Macy
575eda14cbcSMatt Macy ASSERT3P(zeh->zeh_chunkp, !=, &zeh->zeh_fakechunk);
576eda14cbcSMatt Macy
577eda14cbcSMatt Macy uint16_t entry_chunk = *zeh->zeh_chunkp;
578eda14cbcSMatt Macy struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, entry_chunk);
579eda14cbcSMatt Macy ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
580eda14cbcSMatt Macy
581eda14cbcSMatt Macy *zeh->zeh_chunkp = le->le_next;
582718519f4SMartin Matuska
583718519f4SMartin Matuska /* Free in opposite order to reduce fragmentation. */
584718519f4SMartin Matuska zap_leaf_array_free(l, le->le_value_chunk);
585718519f4SMartin Matuska zap_leaf_array_free(l, le->le_name_chunk);
586eda14cbcSMatt Macy zap_leaf_chunk_free(l, entry_chunk);
587eda14cbcSMatt Macy
588eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_nentries--;
589eda14cbcSMatt Macy }
590eda14cbcSMatt Macy
591eda14cbcSMatt Macy int
zap_entry_create(zap_leaf_t * l,zap_name_t * zn,uint32_t cd,uint8_t integer_size,uint64_t num_integers,const void * buf,zap_entry_handle_t * zeh)592eda14cbcSMatt Macy zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd,
593eda14cbcSMatt Macy uint8_t integer_size, uint64_t num_integers, const void *buf,
594eda14cbcSMatt Macy zap_entry_handle_t *zeh)
595eda14cbcSMatt Macy {
596eda14cbcSMatt Macy uint16_t chunk;
597eda14cbcSMatt Macy struct zap_leaf_entry *le;
598eda14cbcSMatt Macy uint64_t h = zn->zn_hash;
599eda14cbcSMatt Macy
600eda14cbcSMatt Macy uint64_t valuelen = integer_size * num_integers;
601eda14cbcSMatt Macy
602783d3ff6SMartin Matuska uint_t numchunks = 1 + ZAP_LEAF_ARRAY_NCHUNKS(zn->zn_key_orig_numints *
603eda14cbcSMatt Macy zn->zn_key_intlen) + ZAP_LEAF_ARRAY_NCHUNKS(valuelen);
604eda14cbcSMatt Macy if (numchunks > ZAP_LEAF_NUMCHUNKS(l))
605eda14cbcSMatt Macy return (SET_ERROR(E2BIG));
606eda14cbcSMatt Macy
607eda14cbcSMatt Macy if (cd == ZAP_NEED_CD) {
608eda14cbcSMatt Macy /* find the lowest unused cd */
609eda14cbcSMatt Macy if (zap_leaf_phys(l)->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED) {
610eda14cbcSMatt Macy cd = 0;
611eda14cbcSMatt Macy
612eda14cbcSMatt Macy for (chunk = *LEAF_HASH_ENTPTR(l, h);
613eda14cbcSMatt Macy chunk != CHAIN_END; chunk = le->le_next) {
614eda14cbcSMatt Macy le = ZAP_LEAF_ENTRY(l, chunk);
615eda14cbcSMatt Macy if (le->le_cd > cd)
616eda14cbcSMatt Macy break;
617eda14cbcSMatt Macy if (le->le_hash == h) {
618eda14cbcSMatt Macy ASSERT3U(cd, ==, le->le_cd);
619eda14cbcSMatt Macy cd++;
620eda14cbcSMatt Macy }
621eda14cbcSMatt Macy }
622eda14cbcSMatt Macy } else {
623eda14cbcSMatt Macy /* old unsorted format; do it the O(n^2) way */
624eda14cbcSMatt Macy for (cd = 0; ; cd++) {
625eda14cbcSMatt Macy for (chunk = *LEAF_HASH_ENTPTR(l, h);
626eda14cbcSMatt Macy chunk != CHAIN_END; chunk = le->le_next) {
627eda14cbcSMatt Macy le = ZAP_LEAF_ENTRY(l, chunk);
628eda14cbcSMatt Macy if (le->le_hash == h &&
629eda14cbcSMatt Macy le->le_cd == cd) {
630eda14cbcSMatt Macy break;
631eda14cbcSMatt Macy }
632eda14cbcSMatt Macy }
633eda14cbcSMatt Macy /* If this cd is not in use, we are good. */
634eda14cbcSMatt Macy if (chunk == CHAIN_END)
635eda14cbcSMatt Macy break;
636eda14cbcSMatt Macy }
637eda14cbcSMatt Macy }
638eda14cbcSMatt Macy /*
639eda14cbcSMatt Macy * We would run out of space in a block before we could
640eda14cbcSMatt Macy * store enough entries to run out of CD values.
641eda14cbcSMatt Macy */
642eda14cbcSMatt Macy ASSERT3U(cd, <, zap_maxcd(zn->zn_zap));
643eda14cbcSMatt Macy }
644eda14cbcSMatt Macy
645eda14cbcSMatt Macy if (zap_leaf_phys(l)->l_hdr.lh_nfree < numchunks)
646eda14cbcSMatt Macy return (SET_ERROR(EAGAIN));
647eda14cbcSMatt Macy
648eda14cbcSMatt Macy /* make the entry */
649eda14cbcSMatt Macy chunk = zap_leaf_chunk_alloc(l);
650eda14cbcSMatt Macy le = ZAP_LEAF_ENTRY(l, chunk);
651eda14cbcSMatt Macy le->le_type = ZAP_CHUNK_ENTRY;
652eda14cbcSMatt Macy le->le_name_chunk = zap_leaf_array_create(l, zn->zn_key_orig,
653eda14cbcSMatt Macy zn->zn_key_intlen, zn->zn_key_orig_numints);
654eda14cbcSMatt Macy le->le_name_numints = zn->zn_key_orig_numints;
655eda14cbcSMatt Macy le->le_value_chunk =
656eda14cbcSMatt Macy zap_leaf_array_create(l, buf, integer_size, num_integers);
657eda14cbcSMatt Macy le->le_value_numints = num_integers;
658eda14cbcSMatt Macy le->le_value_intlen = integer_size;
659eda14cbcSMatt Macy le->le_hash = h;
660eda14cbcSMatt Macy le->le_cd = cd;
661eda14cbcSMatt Macy
662eda14cbcSMatt Macy /* link it into the hash chain */
663eda14cbcSMatt Macy /* XXX if we did the search above, we could just use that */
664783d3ff6SMartin Matuska uint16_t *chunkp = zap_leaf_rehash_entry(l, le, chunk);
665eda14cbcSMatt Macy
666eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_nentries++;
667eda14cbcSMatt Macy
668eda14cbcSMatt Macy zeh->zeh_leaf = l;
669eda14cbcSMatt Macy zeh->zeh_num_integers = num_integers;
670eda14cbcSMatt Macy zeh->zeh_integer_size = le->le_value_intlen;
671eda14cbcSMatt Macy zeh->zeh_cd = le->le_cd;
672eda14cbcSMatt Macy zeh->zeh_hash = le->le_hash;
673eda14cbcSMatt Macy zeh->zeh_chunkp = chunkp;
674eda14cbcSMatt Macy
675eda14cbcSMatt Macy return (0);
676eda14cbcSMatt Macy }
677eda14cbcSMatt Macy
678eda14cbcSMatt Macy /*
679eda14cbcSMatt Macy * Determine if there is another entry with the same normalized form.
680eda14cbcSMatt Macy * For performance purposes, either zn or name must be provided (the
681eda14cbcSMatt Macy * other can be NULL). Note, there usually won't be any hash
682eda14cbcSMatt Macy * conflicts, in which case we don't need the concatenated/normalized
683eda14cbcSMatt Macy * form of the name. But all callers have one of these on hand anyway,
684eda14cbcSMatt Macy * so might as well take advantage. A cleaner but slower interface
685eda14cbcSMatt Macy * would accept neither argument, and compute the normalized name as
686dbd5678dSMartin Matuska * needed (using zap_name_alloc_str(zap_entry_read_name(zeh))).
687eda14cbcSMatt Macy */
688eda14cbcSMatt Macy boolean_t
zap_entry_normalization_conflict(zap_entry_handle_t * zeh,zap_name_t * zn,const char * name,zap_t * zap)689eda14cbcSMatt Macy zap_entry_normalization_conflict(zap_entry_handle_t *zeh, zap_name_t *zn,
690eda14cbcSMatt Macy const char *name, zap_t *zap)
691eda14cbcSMatt Macy {
692eda14cbcSMatt Macy struct zap_leaf_entry *le;
693eda14cbcSMatt Macy boolean_t allocdzn = B_FALSE;
694eda14cbcSMatt Macy
695eda14cbcSMatt Macy if (zap->zap_normflags == 0)
696eda14cbcSMatt Macy return (B_FALSE);
697eda14cbcSMatt Macy
698eda14cbcSMatt Macy for (uint16_t chunk = *LEAF_HASH_ENTPTR(zeh->zeh_leaf, zeh->zeh_hash);
699eda14cbcSMatt Macy chunk != CHAIN_END; chunk = le->le_next) {
700eda14cbcSMatt Macy le = ZAP_LEAF_ENTRY(zeh->zeh_leaf, chunk);
701eda14cbcSMatt Macy if (le->le_hash != zeh->zeh_hash)
702eda14cbcSMatt Macy continue;
703eda14cbcSMatt Macy if (le->le_cd == zeh->zeh_cd)
704eda14cbcSMatt Macy continue;
705eda14cbcSMatt Macy
706eda14cbcSMatt Macy if (zn == NULL) {
707dbd5678dSMartin Matuska zn = zap_name_alloc_str(zap, name, MT_NORMALIZE);
708eda14cbcSMatt Macy allocdzn = B_TRUE;
709eda14cbcSMatt Macy }
710eda14cbcSMatt Macy if (zap_leaf_array_match(zeh->zeh_leaf, zn,
711eda14cbcSMatt Macy le->le_name_chunk, le->le_name_numints)) {
712eda14cbcSMatt Macy if (allocdzn)
713eda14cbcSMatt Macy zap_name_free(zn);
714eda14cbcSMatt Macy return (B_TRUE);
715eda14cbcSMatt Macy }
716eda14cbcSMatt Macy }
717eda14cbcSMatt Macy if (allocdzn)
718eda14cbcSMatt Macy zap_name_free(zn);
719eda14cbcSMatt Macy return (B_FALSE);
720eda14cbcSMatt Macy }
721eda14cbcSMatt Macy
722eda14cbcSMatt Macy /*
723eda14cbcSMatt Macy * Routines for transferring entries between leafs.
724eda14cbcSMatt Macy */
725eda14cbcSMatt Macy
726eda14cbcSMatt Macy static uint16_t *
zap_leaf_rehash_entry(zap_leaf_t * l,struct zap_leaf_entry * le,uint16_t entry)727783d3ff6SMartin Matuska zap_leaf_rehash_entry(zap_leaf_t *l, struct zap_leaf_entry *le, uint16_t entry)
728eda14cbcSMatt Macy {
729eda14cbcSMatt Macy struct zap_leaf_entry *le2;
730eda14cbcSMatt Macy uint16_t *chunkp;
731eda14cbcSMatt Macy
732eda14cbcSMatt Macy /*
733eda14cbcSMatt Macy * keep the entry chain sorted by cd
734eda14cbcSMatt Macy * NB: this will not cause problems for unsorted leafs, though
735eda14cbcSMatt Macy * it is unnecessary there.
736eda14cbcSMatt Macy */
737eda14cbcSMatt Macy for (chunkp = LEAF_HASH_ENTPTR(l, le->le_hash);
738eda14cbcSMatt Macy *chunkp != CHAIN_END; chunkp = &le2->le_next) {
739eda14cbcSMatt Macy le2 = ZAP_LEAF_ENTRY(l, *chunkp);
740eda14cbcSMatt Macy if (le2->le_cd > le->le_cd)
741eda14cbcSMatt Macy break;
742eda14cbcSMatt Macy }
743eda14cbcSMatt Macy
744eda14cbcSMatt Macy le->le_next = *chunkp;
745eda14cbcSMatt Macy *chunkp = entry;
746eda14cbcSMatt Macy return (chunkp);
747eda14cbcSMatt Macy }
748eda14cbcSMatt Macy
749eda14cbcSMatt Macy static void
zap_leaf_transfer_entry(zap_leaf_t * l,uint_t entry,zap_leaf_t * nl)750783d3ff6SMartin Matuska zap_leaf_transfer_entry(zap_leaf_t *l, uint_t entry, zap_leaf_t *nl)
751eda14cbcSMatt Macy {
752eda14cbcSMatt Macy struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, entry);
753eda14cbcSMatt Macy ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
754eda14cbcSMatt Macy
755eda14cbcSMatt Macy uint16_t chunk = zap_leaf_chunk_alloc(nl);
756eda14cbcSMatt Macy struct zap_leaf_entry *nle = ZAP_LEAF_ENTRY(nl, chunk);
757eda14cbcSMatt Macy *nle = *le; /* structure assignment */
758eda14cbcSMatt Macy
759783d3ff6SMartin Matuska (void) zap_leaf_rehash_entry(nl, nle, chunk);
760eda14cbcSMatt Macy
761718519f4SMartin Matuska nle->le_name_chunk = zap_leaf_array_copy(l, le->le_name_chunk, nl);
762718519f4SMartin Matuska nle->le_value_chunk = zap_leaf_array_copy(l, le->le_value_chunk, nl);
763eda14cbcSMatt Macy
764718519f4SMartin Matuska /* Free in opposite order to reduce fragmentation. */
765718519f4SMartin Matuska zap_leaf_array_free(l, le->le_value_chunk);
766718519f4SMartin Matuska zap_leaf_array_free(l, le->le_name_chunk);
767eda14cbcSMatt Macy zap_leaf_chunk_free(l, entry);
768eda14cbcSMatt Macy
769eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_nentries--;
770eda14cbcSMatt Macy zap_leaf_phys(nl)->l_hdr.lh_nentries++;
771eda14cbcSMatt Macy }
772eda14cbcSMatt Macy
773eda14cbcSMatt Macy /*
774eda14cbcSMatt Macy * Transfer the entries whose hash prefix ends in 1 to the new leaf.
775eda14cbcSMatt Macy */
776eda14cbcSMatt Macy void
zap_leaf_split(zap_leaf_t * l,zap_leaf_t * nl,boolean_t sort)777eda14cbcSMatt Macy zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort)
778eda14cbcSMatt Macy {
779783d3ff6SMartin Matuska uint_t bit = 64 - 1 - zap_leaf_phys(l)->l_hdr.lh_prefix_len;
780eda14cbcSMatt Macy
781eda14cbcSMatt Macy /* set new prefix and prefix_len */
782eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_prefix <<= 1;
783eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_prefix_len++;
784eda14cbcSMatt Macy zap_leaf_phys(nl)->l_hdr.lh_prefix =
785eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_prefix | 1;
786eda14cbcSMatt Macy zap_leaf_phys(nl)->l_hdr.lh_prefix_len =
787eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_prefix_len;
788eda14cbcSMatt Macy
789eda14cbcSMatt Macy /* break existing hash chains */
790783d3ff6SMartin Matuska memset(zap_leaf_phys(l)->l_hash, CHAIN_END,
791eda14cbcSMatt Macy 2*ZAP_LEAF_HASH_NUMENTRIES(l));
792eda14cbcSMatt Macy
793eda14cbcSMatt Macy if (sort)
794eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED;
795eda14cbcSMatt Macy
796eda14cbcSMatt Macy /*
797eda14cbcSMatt Macy * Transfer entries whose hash bit 'bit' is set to nl; rehash
798eda14cbcSMatt Macy * the remaining entries
799eda14cbcSMatt Macy *
800eda14cbcSMatt Macy * NB: We could find entries via the hashtable instead. That
801eda14cbcSMatt Macy * would be O(hashents+numents) rather than O(numblks+numents),
802eda14cbcSMatt Macy * but this accesses memory more sequentially, and when we're
803eda14cbcSMatt Macy * called, the block is usually pretty full.
804eda14cbcSMatt Macy */
805783d3ff6SMartin Matuska for (uint_t i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
806eda14cbcSMatt Macy struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, i);
807eda14cbcSMatt Macy if (le->le_type != ZAP_CHUNK_ENTRY)
808eda14cbcSMatt Macy continue;
809eda14cbcSMatt Macy
810eda14cbcSMatt Macy if (le->le_hash & (1ULL << bit))
811eda14cbcSMatt Macy zap_leaf_transfer_entry(l, i, nl);
812eda14cbcSMatt Macy else
813783d3ff6SMartin Matuska (void) zap_leaf_rehash_entry(l, le, i);
814eda14cbcSMatt Macy }
815eda14cbcSMatt Macy }
816eda14cbcSMatt Macy
817eda14cbcSMatt Macy void
zap_leaf_stats(zap_t * zap,zap_leaf_t * l,zap_stats_t * zs)818eda14cbcSMatt Macy zap_leaf_stats(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs)
819eda14cbcSMatt Macy {
820783d3ff6SMartin Matuska uint_t n = zap_f_phys(zap)->zap_ptrtbl.zt_shift -
821eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_prefix_len;
822eda14cbcSMatt Macy n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
823eda14cbcSMatt Macy zs->zs_leafs_with_2n_pointers[n]++;
824eda14cbcSMatt Macy
825eda14cbcSMatt Macy
826eda14cbcSMatt Macy n = zap_leaf_phys(l)->l_hdr.lh_nentries/5;
827eda14cbcSMatt Macy n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
828eda14cbcSMatt Macy zs->zs_blocks_with_n5_entries[n]++;
829eda14cbcSMatt Macy
830eda14cbcSMatt Macy n = ((1<<FZAP_BLOCK_SHIFT(zap)) -
831eda14cbcSMatt Macy zap_leaf_phys(l)->l_hdr.lh_nfree * (ZAP_LEAF_ARRAY_BYTES+1))*10 /
832eda14cbcSMatt Macy (1<<FZAP_BLOCK_SHIFT(zap));
833eda14cbcSMatt Macy n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
834eda14cbcSMatt Macy zs->zs_blocks_n_tenths_full[n]++;
835eda14cbcSMatt Macy
836783d3ff6SMartin Matuska for (uint_t i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(l); i++) {
837783d3ff6SMartin Matuska uint_t nentries = 0;
838783d3ff6SMartin Matuska uint_t chunk = zap_leaf_phys(l)->l_hash[i];
839eda14cbcSMatt Macy
840eda14cbcSMatt Macy while (chunk != CHAIN_END) {
841eda14cbcSMatt Macy struct zap_leaf_entry *le =
842eda14cbcSMatt Macy ZAP_LEAF_ENTRY(l, chunk);
843eda14cbcSMatt Macy
844eda14cbcSMatt Macy n = 1 + ZAP_LEAF_ARRAY_NCHUNKS(le->le_name_numints) +
845eda14cbcSMatt Macy ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_numints *
846eda14cbcSMatt Macy le->le_value_intlen);
847eda14cbcSMatt Macy n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
848eda14cbcSMatt Macy zs->zs_entries_using_n_chunks[n]++;
849eda14cbcSMatt Macy
850eda14cbcSMatt Macy chunk = le->le_next;
851eda14cbcSMatt Macy nentries++;
852eda14cbcSMatt Macy }
853eda14cbcSMatt Macy
854eda14cbcSMatt Macy n = nentries;
855eda14cbcSMatt Macy n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
856eda14cbcSMatt Macy zs->zs_buckets_with_n_entries[n]++;
857eda14cbcSMatt Macy }
858eda14cbcSMatt Macy }
859