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 317*885Sahrens /* Fast path for one 8-byte integer */ 318*885Sahrens if (array_int_len == 8 && buf_int_len == 8 && len == 1) { 319*885Sahrens struct zap_leaf_array *la = &l->l_phys->l_chunk[chunk].l_array; 320*885Sahrens uint64_t *buf64 = (uint64_t *)buf; 321*885Sahrens uint64_t val = *(uint64_t *)la->la_array; 322*885Sahrens *buf64 = BE_64(val); 323*885Sahrens return; 324*885Sahrens } 325*885Sahrens 326*885Sahrens /* Fast path for an array of 1-byte integers (eg. the entry name) */ 327*885Sahrens if (array_int_len == 1 && buf_int_len == 1 && 328*885Sahrens buf_len > array_len + ZAP_LEAF_ARRAY_BYTES) { 329*885Sahrens while (chunk != CHAIN_END) { 330*885Sahrens struct zap_leaf_array *la = 331*885Sahrens &l->l_phys->l_chunk[chunk].l_array; 332*885Sahrens bcopy(la->la_array, buf, ZAP_LEAF_ARRAY_BYTES); 333*885Sahrens buf += ZAP_LEAF_ARRAY_BYTES; 334*885Sahrens chunk = la->la_next; 335*885Sahrens } 336*885Sahrens return; 337*885Sahrens } 338*885Sahrens 339789Sahrens while (len > 0) { 340789Sahrens struct zap_leaf_array *la = &l->l_phys->l_chunk[chunk].l_array; 341789Sahrens int i; 342789Sahrens 343789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 344789Sahrens for (i = 0; i < ZAP_LEAF_ARRAY_BYTES && len > 0; i++) { 345789Sahrens value = (value << 8) | la->la_array[i]; 346789Sahrens byten++; 347789Sahrens if (byten == array_int_len) { 348789Sahrens stv(buf_int_len, buf, value); 349789Sahrens byten = 0; 350789Sahrens len--; 351789Sahrens if (len == 0) 352789Sahrens return; 353789Sahrens buf += buf_int_len; 354789Sahrens } 355789Sahrens } 356789Sahrens chunk = la->la_next; 357789Sahrens } 358789Sahrens } 359789Sahrens 360789Sahrens /* 361789Sahrens * Only to be used on 8-bit arrays. 362789Sahrens * array_len is actual len in bytes (not encoded le_value_length). 363789Sahrens * buf is null-terminated. 364789Sahrens */ 365789Sahrens static int 366789Sahrens zap_leaf_array_equal(const zap_entry_handle_t *zeh, int chunk, 367789Sahrens int array_len, const char *buf) 368789Sahrens { 369789Sahrens int bseen = 0; 370789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 371789Sahrens 372789Sahrens while (bseen < array_len) { 373789Sahrens struct zap_leaf_array *la = &l->l_phys->l_chunk[chunk].l_array; 374789Sahrens int toread = MIN(array_len - bseen, ZAP_LEAF_ARRAY_BYTES); 375789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 376789Sahrens if (bcmp(la->la_array, buf + bseen, toread)) 377789Sahrens break; 378789Sahrens chunk = la->la_next; 379789Sahrens bseen += toread; 380789Sahrens } 381789Sahrens return (bseen == array_len); 382789Sahrens } 383789Sahrens 384789Sahrens /* 385789Sahrens * Routines which manipulate leaf entries. 386789Sahrens */ 387789Sahrens 388789Sahrens int 389789Sahrens zap_leaf_lookup(zap_leaf_t *l, 390789Sahrens const char *name, uint64_t h, zap_entry_handle_t *zeh) 391789Sahrens { 392789Sahrens uint16_t *chunkp; 393789Sahrens struct zap_leaf_entry *le; 394789Sahrens 395789Sahrens zeh->zeh_head_leaf = l; 396789Sahrens 397789Sahrens again: 398789Sahrens ASSERT3U(l->lh_magic, ==, ZAP_LEAF_MAGIC); 399789Sahrens 400789Sahrens for (chunkp = LEAF_HASH_ENTPTR(l, h); 401789Sahrens *chunkp != CHAIN_END; chunkp = &le->le_next) { 402789Sahrens uint16_t chunk = *chunkp; 403789Sahrens le = &l->l_phys->l_chunk[chunk].l_entry; 404789Sahrens 405789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 406789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 407789Sahrens 408789Sahrens if (le->le_hash != h) 409789Sahrens continue; 410789Sahrens 411789Sahrens zeh->zeh_found_leaf = l; 412789Sahrens if (zap_leaf_array_equal(zeh, le->le_name_chunk, 413789Sahrens le->le_name_length, name)) { 414789Sahrens zeh->zeh_num_integers = le->le_value_length; 415789Sahrens zeh->zeh_integer_size = le->le_int_size; 416789Sahrens zeh->zeh_cd = le->le_cd; 417789Sahrens zeh->zeh_hash = le->le_hash; 418789Sahrens zeh->zeh_chunkp = chunkp; 419789Sahrens zeh->zeh_found_leaf = l; 420789Sahrens return (0); 421789Sahrens } 422789Sahrens } 423789Sahrens 424789Sahrens if (l->l_next) { 425789Sahrens l = l->l_next; 426789Sahrens goto again; 427789Sahrens } 428789Sahrens 429789Sahrens return (ENOENT); 430789Sahrens } 431789Sahrens 432789Sahrens /* Return (h1,cd1 >= h2,cd2) */ 433*885Sahrens #define HCD_GTEQ(h1, cd1, h2, cd2) \ 434*885Sahrens ((h1 > h2) ? TRUE : ((h1 == h2 && cd1 >= cd2) ? TRUE : FALSE)) 435789Sahrens 436789Sahrens int 437789Sahrens zap_leaf_lookup_closest(zap_leaf_t *l, 438789Sahrens uint64_t h, uint32_t cd, zap_entry_handle_t *zeh) 439789Sahrens { 440789Sahrens uint16_t chunk; 441789Sahrens uint64_t besth = -1ULL; 442789Sahrens uint32_t bestcd = ZAP_MAXCD; 443789Sahrens uint16_t bestlh = ZAP_LEAF_HASH_NUMENTRIES-1; 444789Sahrens uint16_t lh; 445789Sahrens struct zap_leaf_entry *le; 446789Sahrens 447789Sahrens zeh->zeh_head_leaf = l; 448789Sahrens 449789Sahrens again: 450789Sahrens ASSERT3U(l->lh_magic, ==, ZAP_LEAF_MAGIC); 451789Sahrens 452789Sahrens for (lh = LEAF_HASH(l, h); lh <= bestlh; lh++) { 453789Sahrens for (chunk = l->l_phys->l_hash[lh]; 454789Sahrens chunk != CHAIN_END; chunk = le->le_next) { 455789Sahrens le = &l->l_phys->l_chunk[chunk].l_entry; 456789Sahrens 457789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 458789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 459789Sahrens 460*885Sahrens if (HCD_GTEQ(le->le_hash, le->le_cd, h, cd) && 461*885Sahrens HCD_GTEQ(besth, bestcd, le->le_hash, le->le_cd)) { 462789Sahrens ASSERT3U(bestlh, >=, lh); 463789Sahrens bestlh = lh; 464789Sahrens besth = le->le_hash; 465789Sahrens bestcd = le->le_cd; 466789Sahrens 467789Sahrens zeh->zeh_num_integers = le->le_value_length; 468789Sahrens zeh->zeh_integer_size = le->le_int_size; 469789Sahrens zeh->zeh_cd = le->le_cd; 470789Sahrens zeh->zeh_hash = le->le_hash; 471789Sahrens zeh->zeh_fakechunk = chunk; 472789Sahrens zeh->zeh_chunkp = &zeh->zeh_fakechunk; 473789Sahrens zeh->zeh_found_leaf = l; 474789Sahrens } 475789Sahrens } 476789Sahrens } 477789Sahrens 478789Sahrens if (l->l_next) { 479789Sahrens l = l->l_next; 480789Sahrens goto again; 481789Sahrens } 482789Sahrens 483789Sahrens return (bestcd == ZAP_MAXCD ? ENOENT : 0); 484789Sahrens } 485789Sahrens 486789Sahrens int 487789Sahrens zap_entry_read(const zap_entry_handle_t *zeh, 488789Sahrens uint8_t integer_size, uint64_t num_integers, void *buf) 489789Sahrens { 490789Sahrens struct zap_leaf_entry *le; 491789Sahrens 492789Sahrens le = &zeh->zeh_found_leaf->l_phys->l_chunk[*zeh->zeh_chunkp].l_entry; 493789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 494789Sahrens 495789Sahrens if (le->le_int_size > integer_size) 496789Sahrens return (EINVAL); 497789Sahrens 498789Sahrens zap_leaf_array_read(zeh, le->le_value_chunk, le->le_int_size, 499789Sahrens le->le_value_length, integer_size, num_integers, buf); 500789Sahrens 501789Sahrens if (zeh->zeh_num_integers > num_integers) 502789Sahrens return (EOVERFLOW); 503789Sahrens return (0); 504789Sahrens 505789Sahrens } 506789Sahrens 507789Sahrens int 508789Sahrens zap_entry_read_name(const zap_entry_handle_t *zeh, uint16_t buflen, char *buf) 509789Sahrens { 510789Sahrens struct zap_leaf_entry *le; 511789Sahrens 512789Sahrens le = &zeh->zeh_found_leaf->l_phys->l_chunk[*zeh->zeh_chunkp].l_entry; 513789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 514789Sahrens 515789Sahrens zap_leaf_array_read(zeh, le->le_name_chunk, 1, 516789Sahrens le->le_name_length, 1, buflen, buf); 517789Sahrens if (le->le_name_length > buflen) 518789Sahrens return (EOVERFLOW); 519789Sahrens return (0); 520789Sahrens } 521789Sahrens 522789Sahrens int 523789Sahrens zap_entry_update(zap_entry_handle_t *zeh, 524789Sahrens uint8_t integer_size, uint64_t num_integers, const void *buf) 525789Sahrens { 526789Sahrens int delta_chunks; 527789Sahrens struct zap_leaf_entry *le; 528789Sahrens le = &zeh->zeh_found_leaf->l_phys->l_chunk[*zeh->zeh_chunkp].l_entry; 529789Sahrens 530789Sahrens delta_chunks = NCHUNKS(num_integers * integer_size) - 531789Sahrens NCHUNKS(le->le_value_length * le->le_int_size); 532789Sahrens 533789Sahrens if (zeh->zeh_found_leaf->lh_nfree < delta_chunks) 534789Sahrens return (EAGAIN); 535789Sahrens 536789Sahrens /* 537789Sahrens * We should search other chained leaves (via 538789Sahrens * zap_entry_remove,create?) otherwise returning EAGAIN will 539789Sahrens * just send us into an infinite loop if we have to chain 540789Sahrens * another leaf block, rather than being able to split this 541789Sahrens * block. 542789Sahrens */ 543789Sahrens 544789Sahrens zap_leaf_array_free(zeh, &le->le_value_chunk); 545789Sahrens le->le_value_chunk = 546789Sahrens zap_leaf_array_create(zeh, buf, integer_size, num_integers); 547789Sahrens le->le_value_length = (num_integers*integer_size > MAX_ARRAY_BYTES) ? 548789Sahrens (MAX_ARRAY_BYTES + 1) : (num_integers); 549789Sahrens le->le_int_size = integer_size; 550789Sahrens return (0); 551789Sahrens } 552789Sahrens 553789Sahrens void 554789Sahrens zap_entry_remove(zap_entry_handle_t *zeh) 555789Sahrens { 556789Sahrens uint16_t entry_chunk; 557789Sahrens struct zap_leaf_entry *le; 558789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 559789Sahrens 560789Sahrens ASSERT3P(zeh->zeh_chunkp, !=, &zeh->zeh_fakechunk); 561789Sahrens 562789Sahrens entry_chunk = *zeh->zeh_chunkp; 563789Sahrens le = &l->l_phys->l_chunk[entry_chunk].l_entry; 564789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 565789Sahrens 566789Sahrens zap_leaf_array_free(zeh, &le->le_name_chunk); 567789Sahrens zap_leaf_array_free(zeh, &le->le_value_chunk); 568789Sahrens 569789Sahrens *zeh->zeh_chunkp = le->le_next; 570789Sahrens zap_leaf_chunk_free(l, entry_chunk); 571789Sahrens 572789Sahrens l->lh_nentries--; 573789Sahrens } 574789Sahrens 575789Sahrens int 576789Sahrens zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd, 577789Sahrens uint8_t integer_size, uint64_t num_integers, const void *buf, 578789Sahrens zap_entry_handle_t *zeh) 579789Sahrens { 580789Sahrens uint16_t chunk; 581789Sahrens uint16_t *chunkp; 582789Sahrens struct zap_leaf_entry *le; 583789Sahrens uint64_t namelen, valuelen; 584789Sahrens int numchunks; 585789Sahrens 586789Sahrens valuelen = integer_size * num_integers; 587789Sahrens namelen = strlen(name) + 1; 588789Sahrens ASSERT(namelen >= 2); 589789Sahrens 590789Sahrens zeh->zeh_head_leaf = l; 591789Sahrens 592789Sahrens if (namelen > MAXNAMELEN) 593789Sahrens return (ENAMETOOLONG); 594789Sahrens /* find the first leaf in the chain that has sufficient free space */ 595789Sahrens numchunks = 1 + NCHUNKS(namelen) + NCHUNKS(valuelen); 596789Sahrens if (numchunks > ZAP_LEAF_NUMCHUNKS) 597789Sahrens return (E2BIG); 598789Sahrens 599789Sahrens if (cd == ZAP_MAXCD) { 600789Sahrens for (cd = 0; cd < ZAP_MAXCD; cd++) { 601789Sahrens zap_leaf_t *ll; 602789Sahrens for (ll = l; ll; ll = ll->l_next) { 603789Sahrens for (chunk = *LEAF_HASH_ENTPTR(ll, h); 604789Sahrens chunk != CHAIN_END; chunk = le->le_next) { 605789Sahrens le = &ll->l_phys->l_chunk 606789Sahrens [chunk].l_entry; 607789Sahrens if (le->le_hash == h && 608789Sahrens le->le_cd == cd) { 609789Sahrens break; 610789Sahrens } 611789Sahrens } 612789Sahrens /* 613789Sahrens * if this cd is in use, no need to 614789Sahrens * check more chained leafs 615789Sahrens */ 616789Sahrens if (chunk != CHAIN_END) 617789Sahrens break; 618789Sahrens } 619789Sahrens /* If this cd is not in use, we are good. */ 620789Sahrens if (chunk == CHAIN_END) 621789Sahrens break; 622789Sahrens } 623789Sahrens /* If we tried all the cd's, we lose. */ 624789Sahrens if (cd == ZAP_MAXCD) 625789Sahrens return (ENOSPC); 626789Sahrens } 627789Sahrens 628789Sahrens for (; l; l = l->l_next) 629789Sahrens if (l->lh_nfree >= numchunks) 630789Sahrens break; 631789Sahrens if (l == NULL) 632789Sahrens return (EAGAIN); 633789Sahrens 634789Sahrens zeh->zeh_found_leaf = l; 635789Sahrens 636789Sahrens /* make the entry */ 637789Sahrens chunk = zap_leaf_chunk_alloc(l); 638789Sahrens le = &l->l_phys->l_chunk[chunk].l_entry; 639789Sahrens le->le_type = ZAP_LEAF_ENTRY; 640789Sahrens le->le_name_chunk = zap_leaf_array_create(zeh, name, 1, namelen); 641789Sahrens le->le_name_length = namelen; 642789Sahrens le->le_value_chunk = 643789Sahrens zap_leaf_array_create(zeh, buf, integer_size, num_integers); 644789Sahrens le->le_value_length = (num_integers*integer_size > MAX_ARRAY_BYTES) ? 645789Sahrens (MAX_ARRAY_BYTES + 1) : (num_integers); 646789Sahrens le->le_int_size = integer_size; 647789Sahrens le->le_hash = h; 648789Sahrens le->le_cd = cd; 649789Sahrens 650789Sahrens /* link it into the hash chain */ 651789Sahrens chunkp = LEAF_HASH_ENTPTR(l, h); 652789Sahrens le->le_next = *chunkp; 653789Sahrens *chunkp = chunk; 654789Sahrens 655789Sahrens l->lh_nentries++; 656789Sahrens 657789Sahrens zeh->zeh_num_integers = num_integers; 658789Sahrens zeh->zeh_integer_size = le->le_int_size; 659789Sahrens zeh->zeh_cd = le->le_cd; 660789Sahrens zeh->zeh_hash = le->le_hash; 661789Sahrens zeh->zeh_chunkp = chunkp; 662789Sahrens 663789Sahrens return (0); 664789Sahrens } 665789Sahrens 666789Sahrens /* 667789Sahrens * Routines for transferring entries between leafs. 668789Sahrens */ 669789Sahrens 670789Sahrens static void 671789Sahrens zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry) 672789Sahrens { 673789Sahrens struct zap_leaf_entry *le = &l->l_phys->l_chunk[entry].l_entry; 674789Sahrens uint16_t *ptr = LEAF_HASH_ENTPTR(l, le->le_hash); 675789Sahrens le->le_next = *ptr; 676789Sahrens *ptr = entry; 677789Sahrens } 678789Sahrens 679789Sahrens static void 680789Sahrens zap_leaf_rehash_entries(zap_leaf_t *l) 681789Sahrens { 682789Sahrens int i; 683789Sahrens 684789Sahrens if (l->lh_nentries == 0) 685789Sahrens return; 686789Sahrens 687789Sahrens /* break existing hash chains */ 688789Sahrens zap_memset(l->l_phys->l_hash, CHAIN_END, sizeof (l->l_phys->l_hash)); 689789Sahrens 690789Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS; i++) { 691789Sahrens struct zap_leaf_entry *le = &l->l_phys->l_chunk[i].l_entry; 692789Sahrens if (le->le_type != ZAP_LEAF_ENTRY) 693789Sahrens continue; 694789Sahrens zap_leaf_rehash_entry(l, i); 695789Sahrens } 696789Sahrens } 697789Sahrens 698789Sahrens static uint16_t 699789Sahrens zap_leaf_transfer_array(zap_leaf_t *l, uint16_t chunk, zap_leaf_t *nl) 700789Sahrens { 701789Sahrens uint16_t new_chunk; 702789Sahrens uint16_t *nchunkp = &new_chunk; 703789Sahrens 704789Sahrens while (chunk != CHAIN_END) { 705789Sahrens uint16_t nchunk = zap_leaf_chunk_alloc(nl); 706789Sahrens struct zap_leaf_array *nla = 707789Sahrens &nl->l_phys->l_chunk[nchunk].l_array; 708789Sahrens struct zap_leaf_array *la = 709789Sahrens &l->l_phys->l_chunk[chunk].l_array; 710789Sahrens int nextchunk = la->la_next; 711789Sahrens 712789Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS); 713789Sahrens ASSERT3U(nchunk, <, ZAP_LEAF_NUMCHUNKS); 714789Sahrens 715789Sahrens *nla = *la; 716789Sahrens 717789Sahrens zap_leaf_chunk_free(l, chunk); 718789Sahrens chunk = nextchunk; 719789Sahrens *nchunkp = nchunk; 720789Sahrens nchunkp = &nla->la_next; 721789Sahrens } 722789Sahrens *nchunkp = CHAIN_END; 723789Sahrens return (new_chunk); 724789Sahrens } 725789Sahrens 726789Sahrens static void 727789Sahrens zap_leaf_transfer_entry(zap_t *zap, zap_leaf_t *l, int entry, zap_leaf_t *nhl, 728789Sahrens dmu_tx_t *tx) 729789Sahrens { 730789Sahrens zap_leaf_t *nl; 731789Sahrens struct zap_leaf_entry *le, *nle; 732789Sahrens uint16_t chunk, nchunks; 733789Sahrens 734789Sahrens le = &l->l_phys->l_chunk[entry].l_entry; 735789Sahrens ASSERT3U(le->le_type, ==, ZAP_LEAF_ENTRY); 736789Sahrens 737789Sahrens /* find a leaf in the destination leaf chain with enough free space */ 738789Sahrens nchunks = 1 + NCHUNKS(le->le_name_length) + 739789Sahrens NCHUNKS(le->le_value_length * le->le_int_size); 740789Sahrens for (nl = nhl; nl; nl = nl->l_next) 741789Sahrens if (nl->lh_nfree >= nchunks) 742789Sahrens break; 743789Sahrens if (nl == NULL) { 744789Sahrens nl = zap_leaf_chainmore(nhl, zap_create_leaf(zap, tx)); 745789Sahrens dprintf("transfer_entry: chaining leaf %x/%d\n", 746789Sahrens nl->lh_prefix, nl->lh_prefix_len); 747789Sahrens } 748789Sahrens 749789Sahrens chunk = zap_leaf_chunk_alloc(nl); 750789Sahrens nle = &nl->l_phys->l_chunk[chunk].l_entry; 751789Sahrens *nle = *le; 752789Sahrens 753789Sahrens zap_leaf_rehash_entry(nl, chunk); 754789Sahrens 755789Sahrens nle->le_name_chunk = zap_leaf_transfer_array(l, le->le_name_chunk, nl); 756789Sahrens nle->le_value_chunk = 757789Sahrens zap_leaf_transfer_array(l, le->le_value_chunk, nl); 758789Sahrens 759789Sahrens zap_leaf_chunk_free(l, entry); 760789Sahrens 761789Sahrens l->lh_nentries--; 762789Sahrens nl->lh_nentries++; 763789Sahrens } 764789Sahrens 765789Sahrens /* 766789Sahrens * Transfer entries whose hash bit 'bit' is 1 to nl1, and 0 to nl0. 767789Sahrens * Ignore leaf chaining in source (l), but chain in destinations. 768789Sahrens * We'll re-chain all the entries in l as we go along. 769789Sahrens */ 770789Sahrens static void 771789Sahrens zap_leaf_transfer_entries(zap_t *zap, zap_leaf_t *l, 772789Sahrens zap_leaf_t *nl0, zap_leaf_t *nl1, int bit, dmu_tx_t *tx) 773789Sahrens { 774789Sahrens int i; 775789Sahrens 776789Sahrens ASSERT(bit < 64 && bit >= 0); 777789Sahrens /* break existing hash chains */ 778789Sahrens zap_memset(l->l_phys->l_hash, CHAIN_END, sizeof (l->l_phys->l_hash)); 779789Sahrens 780789Sahrens if (nl0 != l) 781789Sahrens zap_leaf_rehash_entries(nl0); 782789Sahrens if (nl1 != nl0) 783789Sahrens zap_leaf_rehash_entries(nl1); 784789Sahrens 785789Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS; i++) { 786789Sahrens struct zap_leaf_entry *le = &l->l_phys->l_chunk[i].l_entry; 787789Sahrens if (le->le_type != ZAP_LEAF_ENTRY) 788789Sahrens continue; 789789Sahrens 790789Sahrens /* 791789Sahrens * We could find entries via hashtable instead. That 792789Sahrens * would be O(hashents+numents) rather than 793789Sahrens * O(numblks+numents), but this accesses memory more 794789Sahrens * sequentially, and when we're called, the block is 795789Sahrens * usually pretty full. 796789Sahrens */ 797789Sahrens 798789Sahrens if (le->le_hash & (1ULL << bit)) { 799789Sahrens zap_leaf_transfer_entry(zap, l, i, nl1, tx); 800789Sahrens } else { 801789Sahrens if (nl0 == l) 802789Sahrens zap_leaf_rehash_entry(l, i); 803789Sahrens else 804789Sahrens zap_leaf_transfer_entry(zap, l, i, nl0, tx); 805789Sahrens } 806789Sahrens } 807789Sahrens 808789Sahrens } 809789Sahrens 810789Sahrens /* 811789Sahrens * nl will contain the entries whose hash prefix ends in 1 812789Sahrens * handles leaf chaining 813789Sahrens */ 814789Sahrens zap_leaf_t * 815789Sahrens zap_leaf_split(zap_t *zap, zap_leaf_t *hl, dmu_tx_t *tx) 816789Sahrens { 817789Sahrens zap_leaf_t *l = hl; 818789Sahrens int bit = 64 - 1 - hl->lh_prefix_len; 819789Sahrens zap_leaf_t *nl = zap_create_leaf(zap, tx); 820789Sahrens 821789Sahrens /* set new prefix and prefix_len */ 822789Sahrens hl->lh_prefix <<= 1; 823789Sahrens hl->lh_prefix_len++; 824789Sahrens nl->lh_prefix = hl->lh_prefix | 1; 825789Sahrens nl->lh_prefix_len = hl->lh_prefix_len; 826789Sahrens 827789Sahrens /* transfer odd entries from first leaf in hl chain to nl */ 828789Sahrens zap_leaf_transfer_entries(zap, hl, hl, nl, bit, tx); 829789Sahrens 830789Sahrens /* take rest of chain off hl */ 831789Sahrens l = hl->l_next; 832789Sahrens hl->l_next = NULL; 833789Sahrens hl->lh_next = 0; 834789Sahrens 835789Sahrens /* transfer even entries from hl chain back to hl, odd entries to nl */ 836789Sahrens while (l) { 837789Sahrens zap_leaf_t *next = l->l_next; 838789Sahrens zap_leaf_transfer_entries(zap, l, hl, nl, bit, tx); 839789Sahrens zap_destroy_leaf(zap, l, tx); 840789Sahrens l = next; 841789Sahrens } 842789Sahrens 843789Sahrens return (nl); 844789Sahrens } 845789Sahrens 846789Sahrens void 847789Sahrens zap_stats_leaf(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs) 848789Sahrens { 849789Sahrens int n, nchained = 0; 850789Sahrens 851789Sahrens n = zap->zap_f.zap_phys->zap_ptrtbl.zt_shift - l->lh_prefix_len; 852789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 853789Sahrens zs->zs_leafs_with_2n_pointers[n]++; 854789Sahrens 855789Sahrens do { 856789Sahrens int i; 857789Sahrens 858789Sahrens n = l->lh_nentries/5; 859789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 860789Sahrens zs->zs_blocks_with_n5_entries[n]++; 861789Sahrens 862789Sahrens n = ((1<<ZAP_BLOCK_SHIFT) - 863789Sahrens l->lh_nfree * (ZAP_LEAF_ARRAY_BYTES+1))*10 / 864789Sahrens (1<<ZAP_BLOCK_SHIFT); 865789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 866789Sahrens zs->zs_blocks_n_tenths_full[n]++; 867789Sahrens 868789Sahrens for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES; i++) { 869789Sahrens int nentries = 0; 870789Sahrens int chunk = l->l_phys->l_hash[i]; 871789Sahrens 872789Sahrens while (chunk != CHAIN_END) { 873789Sahrens struct zap_leaf_entry *le = 874789Sahrens &l->l_phys->l_chunk[chunk].l_entry; 875789Sahrens 876789Sahrens n = 1 + NCHUNKS(le->le_name_length) + 877789Sahrens NCHUNKS(le->le_value_length * 878789Sahrens le->le_int_size); 879789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 880789Sahrens zs->zs_entries_using_n_chunks[n]++; 881789Sahrens 882789Sahrens chunk = le->le_next; 883789Sahrens nentries++; 884789Sahrens } 885789Sahrens 886789Sahrens n = nentries; 887789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 888789Sahrens zs->zs_buckets_with_n_entries[n]++; 889789Sahrens } 890789Sahrens 891789Sahrens nchained++; 892789Sahrens l = l->l_next; 893789Sahrens } while (l); 894789Sahrens 895789Sahrens n = nchained-1; 896789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 897789Sahrens zs->zs_leafs_with_n_chained[n]++; 898789Sahrens } 899