1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5789Sahrens * Common Development and Distribution License, Version 1.0 only 6789Sahrens * (the "License"). You may not use this file except in compliance 7789Sahrens * with the License. 8789Sahrens * 9789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10789Sahrens * or http://www.opensolaris.org/os/licensing. 11789Sahrens * See the License for the specific language governing permissions 12789Sahrens * and limitations under the License. 13789Sahrens * 14789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 15789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16789Sahrens * If applicable, add the following below this CDDL HEADER, with the 17789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 18789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 19789Sahrens * 20789Sahrens * CDDL HEADER END 21789Sahrens */ 22789Sahrens /* 23789Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24789Sahrens * Use is subject to license terms. 25789Sahrens */ 26789Sahrens 27789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 28789Sahrens 29789Sahrens /* 30789Sahrens * The 512-byte leaf is broken into 32 16-byte chunks. 31789Sahrens * chunk number n means l_chunk[n], even though the header precedes it. 32789Sahrens * the names are stored null-terminated. 33789Sahrens */ 34789Sahrens 35789Sahrens #include <sys/zfs_context.h> 36789Sahrens #include <sys/zap.h> 37789Sahrens #include <sys/zap_impl.h> 38789Sahrens #include <sys/zap_leaf.h> 39789Sahrens #include <sys/spa.h> 40789Sahrens #include <sys/dmu.h> 41789Sahrens 42789Sahrens #define CHAIN_END 0xffff /* end of the chunk chain */ 43789Sahrens 44789Sahrens /* somewhat arbitrary, could go up to around 100k ... */ 45789Sahrens #define MAX_ARRAY_BYTES (8<<10) 46789Sahrens 47789Sahrens #define NCHUNKS(bytes) (((bytes)+ZAP_LEAF_ARRAY_BYTES-1)/ZAP_LEAF_ARRAY_BYTES) 48789Sahrens 49789Sahrens /* 50789Sahrens * XXX This will >> by a negative number when 51789Sahrens * lh_prefix_len > 64-ZAP_LEAF_HASH_SHIFT. 52789Sahrens */ 53789Sahrens #define LEAF_HASH(l, h) \ 54789Sahrens ((ZAP_LEAF_HASH_NUMENTRIES-1) & \ 55789Sahrens ((h) >> (64 - ZAP_LEAF_HASH_SHIFT-(l)->lh_prefix_len))) 56789Sahrens 57789Sahrens #define LEAF_HASH_ENTPTR(l, h) (&(l)->l_phys->l_hash[LEAF_HASH(l, h)]) 58789Sahrens 59789Sahrens /* #define MEMCHECK */ 60789Sahrens 61789Sahrens 62789Sahrens static void 63789Sahrens zap_memset(void *a, int c, size_t n) 64789Sahrens { 65789Sahrens char *cp = a; 66789Sahrens char *cpend = cp + n; 67789Sahrens 68789Sahrens while (cp < cpend) 69789Sahrens *cp++ = c; 70789Sahrens } 71789Sahrens 72789Sahrens static void 73789Sahrens stv(int len, void *addr, uint64_t value) 74789Sahrens { 75789Sahrens switch (len) { 76789Sahrens case 1: 77789Sahrens *(uint8_t *)addr = value; 78789Sahrens return; 79789Sahrens case 2: 80789Sahrens *(uint16_t *)addr = value; 81789Sahrens return; 82789Sahrens case 4: 83789Sahrens *(uint32_t *)addr = value; 84789Sahrens return; 85789Sahrens case 8: 86789Sahrens *(uint64_t *)addr = value; 87789Sahrens return; 88789Sahrens } 89789Sahrens ASSERT(!"bad int len"); 90789Sahrens } 91789Sahrens 92789Sahrens static uint64_t 93789Sahrens ldv(int len, const void *addr) 94789Sahrens { 95789Sahrens switch (len) { 96789Sahrens case 1: 97789Sahrens return (*(uint8_t *)addr); 98789Sahrens case 2: 99789Sahrens return (*(uint16_t *)addr); 100789Sahrens case 4: 101789Sahrens return (*(uint32_t *)addr); 102789Sahrens case 8: 103789Sahrens return (*(uint64_t *)addr); 104789Sahrens } 105789Sahrens ASSERT(!"bad int len"); 106789Sahrens return (0xFEEDFACEDEADBEEF); 107789Sahrens } 108789Sahrens 109789Sahrens void 110789Sahrens zap_leaf_byteswap(zap_leaf_phys_t *buf) 111789Sahrens { 112789Sahrens int i; 113789Sahrens 114789Sahrens buf->l_hdr.lhr_block_type = BSWAP_64(buf->l_hdr.lhr_block_type); 115789Sahrens buf->l_hdr.lhr_next = BSWAP_64(buf->l_hdr.lhr_next); 116789Sahrens buf->l_hdr.lhr_prefix = BSWAP_64(buf->l_hdr.lhr_prefix); 117789Sahrens buf->l_hdr.lhr_magic = BSWAP_32(buf->l_hdr.lhr_magic); 118789Sahrens buf->l_hdr.lhr_nfree = BSWAP_16(buf->l_hdr.lhr_nfree); 119789Sahrens buf->l_hdr.lhr_nentries = BSWAP_16(buf->l_hdr.lhr_nentries); 120789Sahrens buf->l_hdr.lhr_prefix_len = BSWAP_16(buf->l_hdr.lhr_prefix_len); 121789Sahrens buf->l_hdr.lh_freelist = BSWAP_16(buf->l_hdr.lh_freelist); 122789Sahrens 123789Sahrens for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES; i++) 124789Sahrens buf->l_hash[i] = BSWAP_16(buf->l_hash[i]); 125789Sahrens 126789Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS; i++) { 127789Sahrens struct zap_leaf_entry *le; 128789Sahrens 129789Sahrens switch (buf->l_chunk[i].l_free.lf_type) { 130789Sahrens case ZAP_LEAF_ENTRY: 131789Sahrens le = &buf->l_chunk[i].l_entry; 132789Sahrens 133789Sahrens le->le_type = BSWAP_8(le->le_type); 134789Sahrens le->le_int_size = BSWAP_8(le->le_int_size); 135789Sahrens le->le_next = BSWAP_16(le->le_next); 136789Sahrens le->le_name_chunk = BSWAP_16(le->le_name_chunk); 137789Sahrens le->le_name_length = BSWAP_16(le->le_name_length); 138789Sahrens le->le_value_chunk = BSWAP_16(le->le_value_chunk); 139789Sahrens le->le_value_length = BSWAP_16(le->le_value_length); 140789Sahrens le->le_cd = BSWAP_32(le->le_cd); 141789Sahrens le->le_hash = BSWAP_64(le->le_hash); 142789Sahrens break; 143789Sahrens case ZAP_LEAF_FREE: 144789Sahrens buf->l_chunk[i].l_free.lf_type = 145789Sahrens BSWAP_8(buf->l_chunk[i].l_free.lf_type); 146789Sahrens buf->l_chunk[i].l_free.lf_next = 147789Sahrens BSWAP_16(buf->l_chunk[i].l_free.lf_next); 148789Sahrens break; 149789Sahrens case ZAP_LEAF_ARRAY: 150789Sahrens /* zap_leaf_array */ 151789Sahrens buf->l_chunk[i].l_array.la_type = 152789Sahrens BSWAP_8(buf->l_chunk[i].l_array.la_type); 153789Sahrens buf->l_chunk[i].l_array.la_next = 154789Sahrens BSWAP_16(buf->l_chunk[i].l_array.la_next); 155789Sahrens /* la_array doesn't need swapping */ 156789Sahrens break; 157789Sahrens default: 158789Sahrens ASSERT(!"bad leaf type"); 159789Sahrens } 160789Sahrens } 161789Sahrens } 162789Sahrens 163789Sahrens void 164789Sahrens zap_leaf_init(zap_leaf_t *l) 165789Sahrens { 166789Sahrens int i; 167789Sahrens 168789Sahrens ASSERT3U(sizeof (zap_leaf_phys_t), ==, l->l_dbuf->db_size); 169789Sahrens zap_memset(&l->l_phys->l_hdr, 0, sizeof (struct zap_leaf_header)); 170789Sahrens zap_memset(&l->l_phys->l_hash, CHAIN_END, sizeof (l->l_phys->l_hash)); 171789Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS; i++) { 172789Sahrens l->l_phys->l_chunk[i].l_free.lf_type = ZAP_LEAF_FREE; 173789Sahrens l->l_phys->l_chunk[i].l_free.lf_next = i+1; 174789Sahrens } 175789Sahrens l->l_phys->l_chunk[ZAP_LEAF_NUMCHUNKS-1].l_free.lf_next = CHAIN_END; 176789Sahrens l->lh_block_type = ZBT_LEAF; 177789Sahrens l->lh_magic = ZAP_LEAF_MAGIC; 178789Sahrens l->lh_nfree = ZAP_LEAF_NUMCHUNKS; 179789Sahrens } 180789Sahrens 181789Sahrens zap_leaf_t * 182789Sahrens zap_leaf_chainmore(zap_leaf_t *l, zap_leaf_t *nl) 183789Sahrens { 184789Sahrens nl->lh_prefix = l->lh_prefix; 185789Sahrens nl->lh_prefix_len = l->lh_prefix_len; 186789Sahrens nl->l_next = l->l_next; 187789Sahrens l->l_next = nl; 188789Sahrens nl->lh_next = l->lh_next; 189789Sahrens l->lh_next = nl->l_blkid; 190789Sahrens return (nl); 191789Sahrens } 192789Sahrens 193789Sahrens /* 194789Sahrens * Routines which manipulate leaf chunks (l_chunk[]). 195789Sahrens */ 196789Sahrens 197789Sahrens static uint16_t 198789Sahrens zap_leaf_chunk_alloc(zap_leaf_t *l) 199789Sahrens { 200789Sahrens int chunk; 201789Sahrens 202789Sahrens ASSERT(l->lh_nfree > 0); 203789Sahrens 204789Sahrens chunk = l->l_phys->l_hdr.lh_freelist; 205789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 206789Sahrens ASSERT3U(l->l_phys->l_chunk[chunk].l_free.lf_type, ==, ZAP_LEAF_FREE); 207789Sahrens 208789Sahrens l->l_phys->l_hdr.lh_freelist = l->l_phys->l_chunk[chunk].l_free.lf_next; 209789Sahrens 210789Sahrens #ifdef MEMCHECK 211789Sahrens zap_memset(&l->l_phys->l_chunk[chunk], 0xa1, 212789Sahrens sizeof (l->l_phys->l_chunk[chunk])); 213789Sahrens #endif 214789Sahrens 215789Sahrens l->lh_nfree--; 216789Sahrens 217789Sahrens return (chunk); 218789Sahrens } 219789Sahrens 220789Sahrens static void 221789Sahrens zap_leaf_chunk_free(zap_leaf_t *l, uint16_t chunk) 222789Sahrens { 223789Sahrens struct zap_leaf_free *zlf = &l->l_phys->l_chunk[chunk].l_free; 224789Sahrens ASSERT3U(l->lh_nfree, <, ZAP_LEAF_NUMCHUNKS); 225789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 226789Sahrens ASSERT(zlf->lf_type != ZAP_LEAF_FREE); 227789Sahrens 228789Sahrens #ifdef MEMCHECK 229789Sahrens zap_memset(&l->l_phys->l_chunk[chunk], 0xf4, 230789Sahrens sizeof (l->l_phys->l_chunk[chunk])); 231789Sahrens #endif 232789Sahrens 233789Sahrens zlf->lf_type = ZAP_LEAF_FREE; 234789Sahrens zlf->lf_next = l->l_phys->l_hdr.lh_freelist; 235789Sahrens bzero(zlf->lf_pad, sizeof (zlf->lf_pad)); /* help it to compress */ 236789Sahrens l->l_phys->l_hdr.lh_freelist = chunk; 237789Sahrens 238789Sahrens l->lh_nfree++; 239789Sahrens } 240789Sahrens 241789Sahrens 242789Sahrens /* 243789Sahrens * Routines which manipulate leaf arrays (zap_leaf_array type chunks). 244789Sahrens */ 245789Sahrens 246789Sahrens static uint16_t 247789Sahrens zap_leaf_array_create(const zap_entry_handle_t *zeh, const char *buf, 248789Sahrens int integer_size, int num_integers) 249789Sahrens { 250789Sahrens uint16_t chunk_head; 251789Sahrens uint16_t *chunkp = &chunk_head; 252789Sahrens int byten = 0; 253789Sahrens uint64_t value; 254789Sahrens int shift = (integer_size-1)*8; 255789Sahrens int len = num_integers; 256789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 257789Sahrens 258789Sahrens ASSERT3U(num_integers * integer_size, <, MAX_ARRAY_BYTES); 259789Sahrens 260789Sahrens while (len > 0) { 261789Sahrens uint16_t chunk = zap_leaf_chunk_alloc(l); 262789Sahrens struct zap_leaf_array *la = &l->l_phys->l_chunk[chunk].l_array; 263789Sahrens int i; 264789Sahrens 265789Sahrens la->la_type = ZAP_LEAF_ARRAY; 266789Sahrens for (i = 0; i < ZAP_LEAF_ARRAY_BYTES; i++) { 267789Sahrens if (byten == 0) 268789Sahrens value = ldv(integer_size, buf); 269789Sahrens la->la_array[i] = (value & (0xff << shift)) >> shift; 270789Sahrens value <<= 8; 271789Sahrens if (++byten == integer_size) { 272789Sahrens byten = 0; 273789Sahrens buf += integer_size; 274789Sahrens if (--len == 0) 275789Sahrens break; 276789Sahrens } 277789Sahrens } 278789Sahrens 279789Sahrens *chunkp = chunk; 280789Sahrens chunkp = &la->la_next; 281789Sahrens } 282789Sahrens *chunkp = CHAIN_END; 283789Sahrens 284789Sahrens return (chunk_head); 285789Sahrens } 286789Sahrens 287789Sahrens static void 288789Sahrens zap_leaf_array_free(zap_entry_handle_t *zeh, uint16_t *chunkp) 289789Sahrens { 290789Sahrens uint16_t chunk = *chunkp; 291789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 292789Sahrens 293789Sahrens *chunkp = CHAIN_END; 294789Sahrens 295789Sahrens while (chunk != CHAIN_END) { 296789Sahrens int nextchunk = l->l_phys->l_chunk[chunk].l_array.la_next; 297789Sahrens ASSERT3U(l->l_phys->l_chunk[chunk].l_array.la_type, ==, 298789Sahrens ZAP_LEAF_ARRAY); 299789Sahrens zap_leaf_chunk_free(l, chunk); 300789Sahrens chunk = nextchunk; 301789Sahrens } 302789Sahrens } 303789Sahrens 304789Sahrens /* array_len and buf_len are in integers, not bytes */ 305789Sahrens static void 306789Sahrens zap_leaf_array_read(const zap_entry_handle_t *zeh, uint16_t chunk, 307789Sahrens int array_int_len, int array_len, int buf_int_len, uint64_t buf_len, 308789Sahrens char *buf) 309789Sahrens { 310789Sahrens int len = MIN(array_len, buf_len); 311789Sahrens int byten = 0; 312789Sahrens uint64_t value = 0; 313789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 314789Sahrens 315789Sahrens ASSERT3U(array_int_len, <=, buf_int_len); 316789Sahrens 317885Sahrens /* Fast path for one 8-byte integer */ 318885Sahrens if (array_int_len == 8 && buf_int_len == 8 && len == 1) { 319885Sahrens struct zap_leaf_array *la = &l->l_phys->l_chunk[chunk].l_array; 320*899Sbonwick uint8_t *ip = la->la_array; 321885Sahrens uint64_t *buf64 = (uint64_t *)buf; 322*899Sbonwick 323*899Sbonwick *buf64 = (uint64_t)ip[0] << 56 | (uint64_t)ip[1] << 48 | 324*899Sbonwick (uint64_t)ip[2] << 40 | (uint64_t)ip[3] << 32 | 325*899Sbonwick (uint64_t)ip[4] << 24 | (uint64_t)ip[5] << 16 | 326*899Sbonwick (uint64_t)ip[6] << 8 | (uint64_t)ip[7]; 327885Sahrens return; 328885Sahrens } 329885Sahrens 330885Sahrens /* Fast path for an array of 1-byte integers (eg. the entry name) */ 331885Sahrens if (array_int_len == 1 && buf_int_len == 1 && 332885Sahrens buf_len > array_len + ZAP_LEAF_ARRAY_BYTES) { 333885Sahrens while (chunk != CHAIN_END) { 334885Sahrens struct zap_leaf_array *la = 335885Sahrens &l->l_phys->l_chunk[chunk].l_array; 336885Sahrens bcopy(la->la_array, buf, ZAP_LEAF_ARRAY_BYTES); 337885Sahrens buf += ZAP_LEAF_ARRAY_BYTES; 338885Sahrens chunk = la->la_next; 339885Sahrens } 340885Sahrens return; 341885Sahrens } 342885Sahrens 343789Sahrens while (len > 0) { 344789Sahrens struct zap_leaf_array *la = &l->l_phys->l_chunk[chunk].l_array; 345789Sahrens int i; 346789Sahrens 347789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 348789Sahrens for (i = 0; i < ZAP_LEAF_ARRAY_BYTES && len > 0; i++) { 349789Sahrens value = (value << 8) | la->la_array[i]; 350789Sahrens byten++; 351789Sahrens if (byten == array_int_len) { 352789Sahrens stv(buf_int_len, buf, value); 353789Sahrens byten = 0; 354789Sahrens len--; 355789Sahrens if (len == 0) 356789Sahrens return; 357789Sahrens buf += buf_int_len; 358789Sahrens } 359789Sahrens } 360789Sahrens chunk = la->la_next; 361789Sahrens } 362789Sahrens } 363789Sahrens 364789Sahrens /* 365789Sahrens * Only to be used on 8-bit arrays. 366789Sahrens * array_len is actual len in bytes (not encoded le_value_length). 367789Sahrens * buf is null-terminated. 368789Sahrens */ 369789Sahrens static int 370789Sahrens zap_leaf_array_equal(const zap_entry_handle_t *zeh, int chunk, 371789Sahrens int array_len, const char *buf) 372789Sahrens { 373789Sahrens int bseen = 0; 374789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 375789Sahrens 376789Sahrens while (bseen < array_len) { 377789Sahrens struct zap_leaf_array *la = &l->l_phys->l_chunk[chunk].l_array; 378789Sahrens int toread = MIN(array_len - bseen, ZAP_LEAF_ARRAY_BYTES); 379789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 380789Sahrens if (bcmp(la->la_array, buf + bseen, toread)) 381789Sahrens break; 382789Sahrens chunk = la->la_next; 383789Sahrens bseen += toread; 384789Sahrens } 385789Sahrens return (bseen == array_len); 386789Sahrens } 387789Sahrens 388789Sahrens /* 389789Sahrens * Routines which manipulate leaf entries. 390789Sahrens */ 391789Sahrens 392789Sahrens int 393789Sahrens zap_leaf_lookup(zap_leaf_t *l, 394789Sahrens const char *name, uint64_t h, zap_entry_handle_t *zeh) 395789Sahrens { 396789Sahrens uint16_t *chunkp; 397789Sahrens struct zap_leaf_entry *le; 398789Sahrens 399789Sahrens zeh->zeh_head_leaf = l; 400789Sahrens 401789Sahrens again: 402789Sahrens ASSERT3U(l->lh_magic, ==, ZAP_LEAF_MAGIC); 403789Sahrens 404789Sahrens for (chunkp = LEAF_HASH_ENTPTR(l, h); 405789Sahrens *chunkp != CHAIN_END; chunkp = &le->le_next) { 406789Sahrens uint16_t chunk = *chunkp; 407789Sahrens le = &l->l_phys->l_chunk[chunk].l_entry; 408789Sahrens 409789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 410789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 411789Sahrens 412789Sahrens if (le->le_hash != h) 413789Sahrens continue; 414789Sahrens 415789Sahrens zeh->zeh_found_leaf = l; 416789Sahrens if (zap_leaf_array_equal(zeh, le->le_name_chunk, 417789Sahrens le->le_name_length, name)) { 418789Sahrens zeh->zeh_num_integers = le->le_value_length; 419789Sahrens zeh->zeh_integer_size = le->le_int_size; 420789Sahrens zeh->zeh_cd = le->le_cd; 421789Sahrens zeh->zeh_hash = le->le_hash; 422789Sahrens zeh->zeh_chunkp = chunkp; 423789Sahrens zeh->zeh_found_leaf = l; 424789Sahrens return (0); 425789Sahrens } 426789Sahrens } 427789Sahrens 428789Sahrens if (l->l_next) { 429789Sahrens l = l->l_next; 430789Sahrens goto again; 431789Sahrens } 432789Sahrens 433789Sahrens return (ENOENT); 434789Sahrens } 435789Sahrens 436789Sahrens /* Return (h1,cd1 >= h2,cd2) */ 437885Sahrens #define HCD_GTEQ(h1, cd1, h2, cd2) \ 438885Sahrens ((h1 > h2) ? TRUE : ((h1 == h2 && cd1 >= cd2) ? TRUE : FALSE)) 439789Sahrens 440789Sahrens int 441789Sahrens zap_leaf_lookup_closest(zap_leaf_t *l, 442789Sahrens uint64_t h, uint32_t cd, zap_entry_handle_t *zeh) 443789Sahrens { 444789Sahrens uint16_t chunk; 445789Sahrens uint64_t besth = -1ULL; 446789Sahrens uint32_t bestcd = ZAP_MAXCD; 447789Sahrens uint16_t bestlh = ZAP_LEAF_HASH_NUMENTRIES-1; 448789Sahrens uint16_t lh; 449789Sahrens struct zap_leaf_entry *le; 450789Sahrens 451789Sahrens zeh->zeh_head_leaf = l; 452789Sahrens 453789Sahrens again: 454789Sahrens ASSERT3U(l->lh_magic, ==, ZAP_LEAF_MAGIC); 455789Sahrens 456789Sahrens for (lh = LEAF_HASH(l, h); lh <= bestlh; lh++) { 457789Sahrens for (chunk = l->l_phys->l_hash[lh]; 458789Sahrens chunk != CHAIN_END; chunk = le->le_next) { 459789Sahrens le = &l->l_phys->l_chunk[chunk].l_entry; 460789Sahrens 461789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 462789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 463789Sahrens 464885Sahrens if (HCD_GTEQ(le->le_hash, le->le_cd, h, cd) && 465885Sahrens HCD_GTEQ(besth, bestcd, le->le_hash, le->le_cd)) { 466789Sahrens ASSERT3U(bestlh, >=, lh); 467789Sahrens bestlh = lh; 468789Sahrens besth = le->le_hash; 469789Sahrens bestcd = le->le_cd; 470789Sahrens 471789Sahrens zeh->zeh_num_integers = le->le_value_length; 472789Sahrens zeh->zeh_integer_size = le->le_int_size; 473789Sahrens zeh->zeh_cd = le->le_cd; 474789Sahrens zeh->zeh_hash = le->le_hash; 475789Sahrens zeh->zeh_fakechunk = chunk; 476789Sahrens zeh->zeh_chunkp = &zeh->zeh_fakechunk; 477789Sahrens zeh->zeh_found_leaf = l; 478789Sahrens } 479789Sahrens } 480789Sahrens } 481789Sahrens 482789Sahrens if (l->l_next) { 483789Sahrens l = l->l_next; 484789Sahrens goto again; 485789Sahrens } 486789Sahrens 487789Sahrens return (bestcd == ZAP_MAXCD ? ENOENT : 0); 488789Sahrens } 489789Sahrens 490789Sahrens int 491789Sahrens zap_entry_read(const zap_entry_handle_t *zeh, 492789Sahrens uint8_t integer_size, uint64_t num_integers, void *buf) 493789Sahrens { 494789Sahrens struct zap_leaf_entry *le; 495789Sahrens 496789Sahrens le = &zeh->zeh_found_leaf->l_phys->l_chunk[*zeh->zeh_chunkp].l_entry; 497789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 498789Sahrens 499789Sahrens if (le->le_int_size > integer_size) 500789Sahrens return (EINVAL); 501789Sahrens 502789Sahrens zap_leaf_array_read(zeh, le->le_value_chunk, le->le_int_size, 503789Sahrens le->le_value_length, integer_size, num_integers, buf); 504789Sahrens 505789Sahrens if (zeh->zeh_num_integers > num_integers) 506789Sahrens return (EOVERFLOW); 507789Sahrens return (0); 508789Sahrens 509789Sahrens } 510789Sahrens 511789Sahrens int 512789Sahrens zap_entry_read_name(const zap_entry_handle_t *zeh, uint16_t buflen, char *buf) 513789Sahrens { 514789Sahrens struct zap_leaf_entry *le; 515789Sahrens 516789Sahrens le = &zeh->zeh_found_leaf->l_phys->l_chunk[*zeh->zeh_chunkp].l_entry; 517789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 518789Sahrens 519789Sahrens zap_leaf_array_read(zeh, le->le_name_chunk, 1, 520789Sahrens le->le_name_length, 1, buflen, buf); 521789Sahrens if (le->le_name_length > buflen) 522789Sahrens return (EOVERFLOW); 523789Sahrens return (0); 524789Sahrens } 525789Sahrens 526789Sahrens int 527789Sahrens zap_entry_update(zap_entry_handle_t *zeh, 528789Sahrens uint8_t integer_size, uint64_t num_integers, const void *buf) 529789Sahrens { 530789Sahrens int delta_chunks; 531789Sahrens struct zap_leaf_entry *le; 532789Sahrens le = &zeh->zeh_found_leaf->l_phys->l_chunk[*zeh->zeh_chunkp].l_entry; 533789Sahrens 534789Sahrens delta_chunks = NCHUNKS(num_integers * integer_size) - 535789Sahrens NCHUNKS(le->le_value_length * le->le_int_size); 536789Sahrens 537789Sahrens if (zeh->zeh_found_leaf->lh_nfree < delta_chunks) 538789Sahrens return (EAGAIN); 539789Sahrens 540789Sahrens /* 541789Sahrens * We should search other chained leaves (via 542789Sahrens * zap_entry_remove,create?) otherwise returning EAGAIN will 543789Sahrens * just send us into an infinite loop if we have to chain 544789Sahrens * another leaf block, rather than being able to split this 545789Sahrens * block. 546789Sahrens */ 547789Sahrens 548789Sahrens zap_leaf_array_free(zeh, &le->le_value_chunk); 549789Sahrens le->le_value_chunk = 550789Sahrens zap_leaf_array_create(zeh, buf, integer_size, num_integers); 551789Sahrens le->le_value_length = (num_integers*integer_size > MAX_ARRAY_BYTES) ? 552789Sahrens (MAX_ARRAY_BYTES + 1) : (num_integers); 553789Sahrens le->le_int_size = integer_size; 554789Sahrens return (0); 555789Sahrens } 556789Sahrens 557789Sahrens void 558789Sahrens zap_entry_remove(zap_entry_handle_t *zeh) 559789Sahrens { 560789Sahrens uint16_t entry_chunk; 561789Sahrens struct zap_leaf_entry *le; 562789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 563789Sahrens 564789Sahrens ASSERT3P(zeh->zeh_chunkp, !=, &zeh->zeh_fakechunk); 565789Sahrens 566789Sahrens entry_chunk = *zeh->zeh_chunkp; 567789Sahrens le = &l->l_phys->l_chunk[entry_chunk].l_entry; 568789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 569789Sahrens 570789Sahrens zap_leaf_array_free(zeh, &le->le_name_chunk); 571789Sahrens zap_leaf_array_free(zeh, &le->le_value_chunk); 572789Sahrens 573789Sahrens *zeh->zeh_chunkp = le->le_next; 574789Sahrens zap_leaf_chunk_free(l, entry_chunk); 575789Sahrens 576789Sahrens l->lh_nentries--; 577789Sahrens } 578789Sahrens 579789Sahrens int 580789Sahrens zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd, 581789Sahrens uint8_t integer_size, uint64_t num_integers, const void *buf, 582789Sahrens zap_entry_handle_t *zeh) 583789Sahrens { 584789Sahrens uint16_t chunk; 585789Sahrens uint16_t *chunkp; 586789Sahrens struct zap_leaf_entry *le; 587789Sahrens uint64_t namelen, valuelen; 588789Sahrens int numchunks; 589789Sahrens 590789Sahrens valuelen = integer_size * num_integers; 591789Sahrens namelen = strlen(name) + 1; 592789Sahrens ASSERT(namelen >= 2); 593789Sahrens 594789Sahrens zeh->zeh_head_leaf = l; 595789Sahrens 596789Sahrens if (namelen > MAXNAMELEN) 597789Sahrens return (ENAMETOOLONG); 598789Sahrens /* find the first leaf in the chain that has sufficient free space */ 599789Sahrens numchunks = 1 + NCHUNKS(namelen) + NCHUNKS(valuelen); 600789Sahrens if (numchunks > ZAP_LEAF_NUMCHUNKS) 601789Sahrens return (E2BIG); 602789Sahrens 603789Sahrens if (cd == ZAP_MAXCD) { 604789Sahrens for (cd = 0; cd < ZAP_MAXCD; cd++) { 605789Sahrens zap_leaf_t *ll; 606789Sahrens for (ll = l; ll; ll = ll->l_next) { 607789Sahrens for (chunk = *LEAF_HASH_ENTPTR(ll, h); 608789Sahrens chunk != CHAIN_END; chunk = le->le_next) { 609789Sahrens le = &ll->l_phys->l_chunk 610789Sahrens [chunk].l_entry; 611789Sahrens if (le->le_hash == h && 612789Sahrens le->le_cd == cd) { 613789Sahrens break; 614789Sahrens } 615789Sahrens } 616789Sahrens /* 617789Sahrens * if this cd is in use, no need to 618789Sahrens * check more chained leafs 619789Sahrens */ 620789Sahrens if (chunk != CHAIN_END) 621789Sahrens break; 622789Sahrens } 623789Sahrens /* If this cd is not in use, we are good. */ 624789Sahrens if (chunk == CHAIN_END) 625789Sahrens break; 626789Sahrens } 627789Sahrens /* If we tried all the cd's, we lose. */ 628789Sahrens if (cd == ZAP_MAXCD) 629789Sahrens return (ENOSPC); 630789Sahrens } 631789Sahrens 632789Sahrens for (; l; l = l->l_next) 633789Sahrens if (l->lh_nfree >= numchunks) 634789Sahrens break; 635789Sahrens if (l == NULL) 636789Sahrens return (EAGAIN); 637789Sahrens 638789Sahrens zeh->zeh_found_leaf = l; 639789Sahrens 640789Sahrens /* make the entry */ 641789Sahrens chunk = zap_leaf_chunk_alloc(l); 642789Sahrens le = &l->l_phys->l_chunk[chunk].l_entry; 643789Sahrens le->le_type = ZAP_LEAF_ENTRY; 644789Sahrens le->le_name_chunk = zap_leaf_array_create(zeh, name, 1, namelen); 645789Sahrens le->le_name_length = namelen; 646789Sahrens le->le_value_chunk = 647789Sahrens zap_leaf_array_create(zeh, buf, integer_size, num_integers); 648789Sahrens le->le_value_length = (num_integers*integer_size > MAX_ARRAY_BYTES) ? 649789Sahrens (MAX_ARRAY_BYTES + 1) : (num_integers); 650789Sahrens le->le_int_size = integer_size; 651789Sahrens le->le_hash = h; 652789Sahrens le->le_cd = cd; 653789Sahrens 654789Sahrens /* link it into the hash chain */ 655789Sahrens chunkp = LEAF_HASH_ENTPTR(l, h); 656789Sahrens le->le_next = *chunkp; 657789Sahrens *chunkp = chunk; 658789Sahrens 659789Sahrens l->lh_nentries++; 660789Sahrens 661789Sahrens zeh->zeh_num_integers = num_integers; 662789Sahrens zeh->zeh_integer_size = le->le_int_size; 663789Sahrens zeh->zeh_cd = le->le_cd; 664789Sahrens zeh->zeh_hash = le->le_hash; 665789Sahrens zeh->zeh_chunkp = chunkp; 666789Sahrens 667789Sahrens return (0); 668789Sahrens } 669789Sahrens 670789Sahrens /* 671789Sahrens * Routines for transferring entries between leafs. 672789Sahrens */ 673789Sahrens 674789Sahrens static void 675789Sahrens zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry) 676789Sahrens { 677789Sahrens struct zap_leaf_entry *le = &l->l_phys->l_chunk[entry].l_entry; 678789Sahrens uint16_t *ptr = LEAF_HASH_ENTPTR(l, le->le_hash); 679789Sahrens le->le_next = *ptr; 680789Sahrens *ptr = entry; 681789Sahrens } 682789Sahrens 683789Sahrens static void 684789Sahrens zap_leaf_rehash_entries(zap_leaf_t *l) 685789Sahrens { 686789Sahrens int i; 687789Sahrens 688789Sahrens if (l->lh_nentries == 0) 689789Sahrens return; 690789Sahrens 691789Sahrens /* break existing hash chains */ 692789Sahrens zap_memset(l->l_phys->l_hash, CHAIN_END, sizeof (l->l_phys->l_hash)); 693789Sahrens 694789Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS; i++) { 695789Sahrens struct zap_leaf_entry *le = &l->l_phys->l_chunk[i].l_entry; 696789Sahrens if (le->le_type != ZAP_LEAF_ENTRY) 697789Sahrens continue; 698789Sahrens zap_leaf_rehash_entry(l, i); 699789Sahrens } 700789Sahrens } 701789Sahrens 702789Sahrens static uint16_t 703789Sahrens zap_leaf_transfer_array(zap_leaf_t *l, uint16_t chunk, zap_leaf_t *nl) 704789Sahrens { 705789Sahrens uint16_t new_chunk; 706789Sahrens uint16_t *nchunkp = &new_chunk; 707789Sahrens 708789Sahrens while (chunk != CHAIN_END) { 709789Sahrens uint16_t nchunk = zap_leaf_chunk_alloc(nl); 710789Sahrens struct zap_leaf_array *nla = 711789Sahrens &nl->l_phys->l_chunk[nchunk].l_array; 712789Sahrens struct zap_leaf_array *la = 713789Sahrens &l->l_phys->l_chunk[chunk].l_array; 714789Sahrens int nextchunk = la->la_next; 715789Sahrens 716789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 717789Sahrens ASSERT3U(nchunk, <, ZAP_LEAF_NUMCHUNKS); 718789Sahrens 719789Sahrens *nla = *la; 720789Sahrens 721789Sahrens zap_leaf_chunk_free(l, chunk); 722789Sahrens chunk = nextchunk; 723789Sahrens *nchunkp = nchunk; 724789Sahrens nchunkp = &nla->la_next; 725789Sahrens } 726789Sahrens *nchunkp = CHAIN_END; 727789Sahrens return (new_chunk); 728789Sahrens } 729789Sahrens 730789Sahrens static void 731789Sahrens zap_leaf_transfer_entry(zap_t *zap, zap_leaf_t *l, int entry, zap_leaf_t *nhl, 732789Sahrens dmu_tx_t *tx) 733789Sahrens { 734789Sahrens zap_leaf_t *nl; 735789Sahrens struct zap_leaf_entry *le, *nle; 736789Sahrens uint16_t chunk, nchunks; 737789Sahrens 738789Sahrens le = &l->l_phys->l_chunk[entry].l_entry; 739789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 740789Sahrens 741789Sahrens /* find a leaf in the destination leaf chain with enough free space */ 742789Sahrens nchunks = 1 + NCHUNKS(le->le_name_length) + 743789Sahrens NCHUNKS(le->le_value_length * le->le_int_size); 744789Sahrens for (nl = nhl; nl; nl = nl->l_next) 745789Sahrens if (nl->lh_nfree >= nchunks) 746789Sahrens break; 747789Sahrens if (nl == NULL) { 748789Sahrens nl = zap_leaf_chainmore(nhl, zap_create_leaf(zap, tx)); 749789Sahrens dprintf("transfer_entry: chaining leaf %x/%d\n", 750789Sahrens nl->lh_prefix, nl->lh_prefix_len); 751789Sahrens } 752789Sahrens 753789Sahrens chunk = zap_leaf_chunk_alloc(nl); 754789Sahrens nle = &nl->l_phys->l_chunk[chunk].l_entry; 755789Sahrens *nle = *le; 756789Sahrens 757789Sahrens zap_leaf_rehash_entry(nl, chunk); 758789Sahrens 759789Sahrens nle->le_name_chunk = zap_leaf_transfer_array(l, le->le_name_chunk, nl); 760789Sahrens nle->le_value_chunk = 761789Sahrens zap_leaf_transfer_array(l, le->le_value_chunk, nl); 762789Sahrens 763789Sahrens zap_leaf_chunk_free(l, entry); 764789Sahrens 765789Sahrens l->lh_nentries--; 766789Sahrens nl->lh_nentries++; 767789Sahrens } 768789Sahrens 769789Sahrens /* 770789Sahrens * Transfer entries whose hash bit 'bit' is 1 to nl1, and 0 to nl0. 771789Sahrens * Ignore leaf chaining in source (l), but chain in destinations. 772789Sahrens * We'll re-chain all the entries in l as we go along. 773789Sahrens */ 774789Sahrens static void 775789Sahrens zap_leaf_transfer_entries(zap_t *zap, zap_leaf_t *l, 776789Sahrens zap_leaf_t *nl0, zap_leaf_t *nl1, int bit, dmu_tx_t *tx) 777789Sahrens { 778789Sahrens int i; 779789Sahrens 780789Sahrens ASSERT(bit < 64 && bit >= 0); 781789Sahrens /* break existing hash chains */ 782789Sahrens zap_memset(l->l_phys->l_hash, CHAIN_END, sizeof (l->l_phys->l_hash)); 783789Sahrens 784789Sahrens if (nl0 != l) 785789Sahrens zap_leaf_rehash_entries(nl0); 786789Sahrens if (nl1 != nl0) 787789Sahrens zap_leaf_rehash_entries(nl1); 788789Sahrens 789789Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS; i++) { 790789Sahrens struct zap_leaf_entry *le = &l->l_phys->l_chunk[i].l_entry; 791789Sahrens if (le->le_type != ZAP_LEAF_ENTRY) 792789Sahrens continue; 793789Sahrens 794789Sahrens /* 795789Sahrens * We could find entries via hashtable instead. That 796789Sahrens * would be O(hashents+numents) rather than 797789Sahrens * O(numblks+numents), but this accesses memory more 798789Sahrens * sequentially, and when we're called, the block is 799789Sahrens * usually pretty full. 800789Sahrens */ 801789Sahrens 802789Sahrens if (le->le_hash & (1ULL << bit)) { 803789Sahrens zap_leaf_transfer_entry(zap, l, i, nl1, tx); 804789Sahrens } else { 805789Sahrens if (nl0 == l) 806789Sahrens zap_leaf_rehash_entry(l, i); 807789Sahrens else 808789Sahrens zap_leaf_transfer_entry(zap, l, i, nl0, tx); 809789Sahrens } 810789Sahrens } 811789Sahrens 812789Sahrens } 813789Sahrens 814789Sahrens /* 815789Sahrens * nl will contain the entries whose hash prefix ends in 1 816789Sahrens * handles leaf chaining 817789Sahrens */ 818789Sahrens zap_leaf_t * 819789Sahrens zap_leaf_split(zap_t *zap, zap_leaf_t *hl, dmu_tx_t *tx) 820789Sahrens { 821789Sahrens zap_leaf_t *l = hl; 822789Sahrens int bit = 64 - 1 - hl->lh_prefix_len; 823789Sahrens zap_leaf_t *nl = zap_create_leaf(zap, tx); 824789Sahrens 825789Sahrens /* set new prefix and prefix_len */ 826789Sahrens hl->lh_prefix <<= 1; 827789Sahrens hl->lh_prefix_len++; 828789Sahrens nl->lh_prefix = hl->lh_prefix | 1; 829789Sahrens nl->lh_prefix_len = hl->lh_prefix_len; 830789Sahrens 831789Sahrens /* transfer odd entries from first leaf in hl chain to nl */ 832789Sahrens zap_leaf_transfer_entries(zap, hl, hl, nl, bit, tx); 833789Sahrens 834789Sahrens /* take rest of chain off hl */ 835789Sahrens l = hl->l_next; 836789Sahrens hl->l_next = NULL; 837789Sahrens hl->lh_next = 0; 838789Sahrens 839789Sahrens /* transfer even entries from hl chain back to hl, odd entries to nl */ 840789Sahrens while (l) { 841789Sahrens zap_leaf_t *next = l->l_next; 842789Sahrens zap_leaf_transfer_entries(zap, l, hl, nl, bit, tx); 843789Sahrens zap_destroy_leaf(zap, l, tx); 844789Sahrens l = next; 845789Sahrens } 846789Sahrens 847789Sahrens return (nl); 848789Sahrens } 849789Sahrens 850789Sahrens void 851789Sahrens zap_stats_leaf(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs) 852789Sahrens { 853789Sahrens int n, nchained = 0; 854789Sahrens 855789Sahrens n = zap->zap_f.zap_phys->zap_ptrtbl.zt_shift - l->lh_prefix_len; 856789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 857789Sahrens zs->zs_leafs_with_2n_pointers[n]++; 858789Sahrens 859789Sahrens do { 860789Sahrens int i; 861789Sahrens 862789Sahrens n = l->lh_nentries/5; 863789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 864789Sahrens zs->zs_blocks_with_n5_entries[n]++; 865789Sahrens 866789Sahrens n = ((1<<ZAP_BLOCK_SHIFT) - 867789Sahrens l->lh_nfree * (ZAP_LEAF_ARRAY_BYTES+1))*10 / 868789Sahrens (1<<ZAP_BLOCK_SHIFT); 869789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 870789Sahrens zs->zs_blocks_n_tenths_full[n]++; 871789Sahrens 872789Sahrens for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES; i++) { 873789Sahrens int nentries = 0; 874789Sahrens int chunk = l->l_phys->l_hash[i]; 875789Sahrens 876789Sahrens while (chunk != CHAIN_END) { 877789Sahrens struct zap_leaf_entry *le = 878789Sahrens &l->l_phys->l_chunk[chunk].l_entry; 879789Sahrens 880789Sahrens n = 1 + NCHUNKS(le->le_name_length) + 881789Sahrens NCHUNKS(le->le_value_length * 882789Sahrens le->le_int_size); 883789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 884789Sahrens zs->zs_entries_using_n_chunks[n]++; 885789Sahrens 886789Sahrens chunk = le->le_next; 887789Sahrens nentries++; 888789Sahrens } 889789Sahrens 890789Sahrens n = nentries; 891789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 892789Sahrens zs->zs_buckets_with_n_entries[n]++; 893789Sahrens } 894789Sahrens 895789Sahrens nchained++; 896789Sahrens l = l->l_next; 897789Sahrens } while (l); 898789Sahrens 899789Sahrens n = nchained-1; 900789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 901789Sahrens zs->zs_leafs_with_n_chained[n]++; 902789Sahrens } 903