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