1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5*1491Sahrens * Common Development and Distribution License (the "License"). 6*1491Sahrens * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 22*1491Sahrens * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens /* 29789Sahrens * The 512-byte leaf is broken into 32 16-byte chunks. 30789Sahrens * chunk number n means l_chunk[n], even though the header precedes it. 31789Sahrens * the names are stored null-terminated. 32789Sahrens */ 33789Sahrens 34789Sahrens #include <sys/zfs_context.h> 35789Sahrens #include <sys/zap.h> 36789Sahrens #include <sys/zap_impl.h> 37789Sahrens #include <sys/zap_leaf.h> 38789Sahrens #include <sys/spa.h> 39789Sahrens #include <sys/dmu.h> 40789Sahrens 41789Sahrens #define CHAIN_END 0xffff /* end of the chunk chain */ 42789Sahrens 43*1491Sahrens /* half the (current) minimum block size */ 44789Sahrens #define MAX_ARRAY_BYTES (8<<10) 45789Sahrens 46789Sahrens #define NCHUNKS(bytes) (((bytes)+ZAP_LEAF_ARRAY_BYTES-1)/ZAP_LEAF_ARRAY_BYTES) 47789Sahrens 48789Sahrens /* 49789Sahrens * XXX This will >> by a negative number when 50789Sahrens * lh_prefix_len > 64-ZAP_LEAF_HASH_SHIFT. 51789Sahrens */ 52789Sahrens #define LEAF_HASH(l, h) \ 53*1491Sahrens ((ZAP_LEAF_HASH_NUMENTRIES(l)-1) & \ 54*1491Sahrens ((h) >> (64 - ZAP_LEAF_HASH_SHIFT(l)-(l)->lh_prefix_len))) 55789Sahrens 56789Sahrens #define LEAF_HASH_ENTPTR(l, h) (&(l)->l_phys->l_hash[LEAF_HASH(l, h)]) 57789Sahrens 58789Sahrens /* #define MEMCHECK */ 59789Sahrens 60789Sahrens 61789Sahrens static void 62789Sahrens zap_memset(void *a, int c, size_t n) 63789Sahrens { 64789Sahrens char *cp = a; 65789Sahrens char *cpend = cp + n; 66789Sahrens 67789Sahrens while (cp < cpend) 68789Sahrens *cp++ = c; 69789Sahrens } 70789Sahrens 71789Sahrens static void 72789Sahrens stv(int len, void *addr, uint64_t value) 73789Sahrens { 74789Sahrens switch (len) { 75789Sahrens case 1: 76789Sahrens *(uint8_t *)addr = value; 77789Sahrens return; 78789Sahrens case 2: 79789Sahrens *(uint16_t *)addr = value; 80789Sahrens return; 81789Sahrens case 4: 82789Sahrens *(uint32_t *)addr = value; 83789Sahrens return; 84789Sahrens case 8: 85789Sahrens *(uint64_t *)addr = value; 86789Sahrens return; 87789Sahrens } 88789Sahrens ASSERT(!"bad int len"); 89789Sahrens } 90789Sahrens 91789Sahrens static uint64_t 92789Sahrens ldv(int len, const void *addr) 93789Sahrens { 94789Sahrens switch (len) { 95789Sahrens case 1: 96789Sahrens return (*(uint8_t *)addr); 97789Sahrens case 2: 98789Sahrens return (*(uint16_t *)addr); 99789Sahrens case 4: 100789Sahrens return (*(uint32_t *)addr); 101789Sahrens case 8: 102789Sahrens return (*(uint64_t *)addr); 103789Sahrens } 104789Sahrens ASSERT(!"bad int len"); 105789Sahrens return (0xFEEDFACEDEADBEEF); 106789Sahrens } 107789Sahrens 108789Sahrens void 109*1491Sahrens zap_leaf_byteswap(zap_leaf_phys_t *buf, int size) 110789Sahrens { 111789Sahrens int i; 112*1491Sahrens zap_leaf_t l; 113*1491Sahrens l.l_bs = highbit(size)-1; 114*1491Sahrens l.l_phys = buf; 115789Sahrens 116789Sahrens buf->l_hdr.lhr_block_type = BSWAP_64(buf->l_hdr.lhr_block_type); 117789Sahrens buf->l_hdr.lhr_next = BSWAP_64(buf->l_hdr.lhr_next); 118789Sahrens buf->l_hdr.lhr_prefix = BSWAP_64(buf->l_hdr.lhr_prefix); 119789Sahrens buf->l_hdr.lhr_magic = BSWAP_32(buf->l_hdr.lhr_magic); 120789Sahrens buf->l_hdr.lhr_nfree = BSWAP_16(buf->l_hdr.lhr_nfree); 121789Sahrens buf->l_hdr.lhr_nentries = BSWAP_16(buf->l_hdr.lhr_nentries); 122789Sahrens buf->l_hdr.lhr_prefix_len = BSWAP_16(buf->l_hdr.lhr_prefix_len); 123789Sahrens buf->l_hdr.lh_freelist = BSWAP_16(buf->l_hdr.lh_freelist); 124789Sahrens 125*1491Sahrens for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++) 126789Sahrens buf->l_hash[i] = BSWAP_16(buf->l_hash[i]); 127789Sahrens 128*1491Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) { 129*1491Sahrens zap_leaf_chunk_t *lc = &ZAP_LEAF_CHUNK(&l, i); 130789Sahrens struct zap_leaf_entry *le; 131789Sahrens 132*1491Sahrens switch (lc->l_free.lf_type) { 133*1491Sahrens case ZAP_CHUNK_ENTRY: 134*1491Sahrens le = &lc->l_entry; 135789Sahrens 136789Sahrens le->le_type = BSWAP_8(le->le_type); 137789Sahrens le->le_int_size = BSWAP_8(le->le_int_size); 138789Sahrens le->le_next = BSWAP_16(le->le_next); 139789Sahrens le->le_name_chunk = BSWAP_16(le->le_name_chunk); 140789Sahrens le->le_name_length = BSWAP_16(le->le_name_length); 141789Sahrens le->le_value_chunk = BSWAP_16(le->le_value_chunk); 142789Sahrens le->le_value_length = BSWAP_16(le->le_value_length); 143789Sahrens le->le_cd = BSWAP_32(le->le_cd); 144789Sahrens le->le_hash = BSWAP_64(le->le_hash); 145789Sahrens break; 146*1491Sahrens case ZAP_CHUNK_FREE: 147*1491Sahrens lc->l_free.lf_type = BSWAP_8(lc->l_free.lf_type); 148*1491Sahrens lc->l_free.lf_next = BSWAP_16(lc->l_free.lf_next); 149789Sahrens break; 150*1491Sahrens case ZAP_CHUNK_ARRAY: 151*1491Sahrens lc->l_array.la_type = BSWAP_8(lc->l_array.la_type); 152*1491Sahrens lc->l_array.la_next = BSWAP_16(lc->l_array.la_next); 153789Sahrens /* la_array doesn't need swapping */ 154789Sahrens break; 155789Sahrens default: 156789Sahrens ASSERT(!"bad leaf type"); 157789Sahrens } 158789Sahrens } 159789Sahrens } 160789Sahrens 161789Sahrens void 162789Sahrens zap_leaf_init(zap_leaf_t *l) 163789Sahrens { 164789Sahrens int i; 165789Sahrens 166*1491Sahrens l->l_bs = highbit(l->l_dbuf->db_size)-1; 167789Sahrens zap_memset(&l->l_phys->l_hdr, 0, sizeof (struct zap_leaf_header)); 168*1491Sahrens zap_memset(l->l_phys->l_hash, CHAIN_END, 2*ZAP_LEAF_HASH_NUMENTRIES(l)); 169*1491Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) { 170*1491Sahrens ZAP_LEAF_CHUNK(l, i).l_free.lf_type = ZAP_CHUNK_FREE; 171*1491Sahrens ZAP_LEAF_CHUNK(l, i).l_free.lf_next = i+1; 172789Sahrens } 173*1491Sahrens ZAP_LEAF_CHUNK(l, ZAP_LEAF_NUMCHUNKS(l)-1).l_free.lf_next = CHAIN_END; 174789Sahrens l->lh_block_type = ZBT_LEAF; 175789Sahrens l->lh_magic = ZAP_LEAF_MAGIC; 176*1491Sahrens l->lh_nfree = ZAP_LEAF_NUMCHUNKS(l); 177789Sahrens } 178789Sahrens 179789Sahrens zap_leaf_t * 180789Sahrens zap_leaf_chainmore(zap_leaf_t *l, zap_leaf_t *nl) 181789Sahrens { 182789Sahrens nl->lh_prefix = l->lh_prefix; 183789Sahrens nl->lh_prefix_len = l->lh_prefix_len; 184789Sahrens nl->l_next = l->l_next; 185789Sahrens l->l_next = nl; 186789Sahrens nl->lh_next = l->lh_next; 187789Sahrens l->lh_next = nl->l_blkid; 188789Sahrens return (nl); 189789Sahrens } 190789Sahrens 191789Sahrens /* 192789Sahrens * Routines which manipulate leaf chunks (l_chunk[]). 193789Sahrens */ 194789Sahrens 195789Sahrens static uint16_t 196789Sahrens zap_leaf_chunk_alloc(zap_leaf_t *l) 197789Sahrens { 198789Sahrens int chunk; 199789Sahrens 200789Sahrens ASSERT(l->lh_nfree > 0); 201789Sahrens 202789Sahrens chunk = l->l_phys->l_hdr.lh_freelist; 203*1491Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); 204*1491Sahrens ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_free.lf_type, ==, ZAP_CHUNK_FREE); 205789Sahrens 206*1491Sahrens l->l_phys->l_hdr.lh_freelist = ZAP_LEAF_CHUNK(l, chunk).l_free.lf_next; 207789Sahrens 208789Sahrens #ifdef MEMCHECK 209*1491Sahrens zap_memset(&ZAP_LEAF_CHUNK(l, chunk), 0xa1, sizeof (zap_leaf_chunk_t)); 210789Sahrens #endif 211789Sahrens 212789Sahrens l->lh_nfree--; 213789Sahrens 214789Sahrens return (chunk); 215789Sahrens } 216789Sahrens 217789Sahrens static void 218789Sahrens zap_leaf_chunk_free(zap_leaf_t *l, uint16_t chunk) 219789Sahrens { 220*1491Sahrens struct zap_leaf_free *zlf = &ZAP_LEAF_CHUNK(l, chunk).l_free; 221*1491Sahrens ASSERT3U(l->lh_nfree, <, ZAP_LEAF_NUMCHUNKS(l)); 222*1491Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); 223*1491Sahrens ASSERT(zlf->lf_type != ZAP_CHUNK_FREE); 224789Sahrens 225789Sahrens #ifdef MEMCHECK 226*1491Sahrens zap_memset(zlf, 0xf4, sizeof (zap_leaf_chunk_t)); 227789Sahrens #endif 228789Sahrens 229*1491Sahrens zlf->lf_type = ZAP_CHUNK_FREE; 230789Sahrens zlf->lf_next = l->l_phys->l_hdr.lh_freelist; 231789Sahrens bzero(zlf->lf_pad, sizeof (zlf->lf_pad)); /* help it to compress */ 232789Sahrens l->l_phys->l_hdr.lh_freelist = chunk; 233789Sahrens 234789Sahrens l->lh_nfree++; 235789Sahrens } 236789Sahrens 237789Sahrens 238789Sahrens /* 239789Sahrens * Routines which manipulate leaf arrays (zap_leaf_array type chunks). 240789Sahrens */ 241789Sahrens 242789Sahrens static uint16_t 243789Sahrens zap_leaf_array_create(const zap_entry_handle_t *zeh, const char *buf, 244789Sahrens int integer_size, int num_integers) 245789Sahrens { 246789Sahrens uint16_t chunk_head; 247789Sahrens uint16_t *chunkp = &chunk_head; 248789Sahrens int byten = 0; 249789Sahrens uint64_t value; 250789Sahrens int shift = (integer_size-1)*8; 251789Sahrens int len = num_integers; 252789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 253789Sahrens 254789Sahrens ASSERT3U(num_integers * integer_size, <, MAX_ARRAY_BYTES); 255789Sahrens 256789Sahrens while (len > 0) { 257789Sahrens uint16_t chunk = zap_leaf_chunk_alloc(l); 258*1491Sahrens struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array; 259789Sahrens int i; 260789Sahrens 261*1491Sahrens la->la_type = ZAP_CHUNK_ARRAY; 262789Sahrens for (i = 0; i < ZAP_LEAF_ARRAY_BYTES; i++) { 263789Sahrens if (byten == 0) 264789Sahrens value = ldv(integer_size, buf); 265789Sahrens la->la_array[i] = (value & (0xff << shift)) >> shift; 266789Sahrens value <<= 8; 267789Sahrens if (++byten == integer_size) { 268789Sahrens byten = 0; 269789Sahrens buf += integer_size; 270789Sahrens if (--len == 0) 271789Sahrens break; 272789Sahrens } 273789Sahrens } 274789Sahrens 275789Sahrens *chunkp = chunk; 276789Sahrens chunkp = &la->la_next; 277789Sahrens } 278789Sahrens *chunkp = CHAIN_END; 279789Sahrens 280789Sahrens return (chunk_head); 281789Sahrens } 282789Sahrens 283789Sahrens static void 284789Sahrens zap_leaf_array_free(zap_entry_handle_t *zeh, uint16_t *chunkp) 285789Sahrens { 286789Sahrens uint16_t chunk = *chunkp; 287789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 288789Sahrens 289789Sahrens *chunkp = CHAIN_END; 290789Sahrens 291789Sahrens while (chunk != CHAIN_END) { 292*1491Sahrens int nextchunk = ZAP_LEAF_CHUNK(l, chunk).l_array.la_next; 293*1491Sahrens ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_array.la_type, ==, 294*1491Sahrens ZAP_CHUNK_ARRAY); 295789Sahrens zap_leaf_chunk_free(l, chunk); 296789Sahrens chunk = nextchunk; 297789Sahrens } 298789Sahrens } 299789Sahrens 300789Sahrens /* array_len and buf_len are in integers, not bytes */ 301789Sahrens static void 302789Sahrens zap_leaf_array_read(const zap_entry_handle_t *zeh, uint16_t chunk, 303789Sahrens int array_int_len, int array_len, int buf_int_len, uint64_t buf_len, 304789Sahrens char *buf) 305789Sahrens { 306789Sahrens int len = MIN(array_len, buf_len); 307789Sahrens int byten = 0; 308789Sahrens uint64_t value = 0; 309789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 310789Sahrens 311789Sahrens ASSERT3U(array_int_len, <=, buf_int_len); 312789Sahrens 313885Sahrens /* Fast path for one 8-byte integer */ 314885Sahrens if (array_int_len == 8 && buf_int_len == 8 && len == 1) { 315*1491Sahrens struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array; 316899Sbonwick uint8_t *ip = la->la_array; 317885Sahrens uint64_t *buf64 = (uint64_t *)buf; 318899Sbonwick 319899Sbonwick *buf64 = (uint64_t)ip[0] << 56 | (uint64_t)ip[1] << 48 | 320899Sbonwick (uint64_t)ip[2] << 40 | (uint64_t)ip[3] << 32 | 321899Sbonwick (uint64_t)ip[4] << 24 | (uint64_t)ip[5] << 16 | 322899Sbonwick (uint64_t)ip[6] << 8 | (uint64_t)ip[7]; 323885Sahrens return; 324885Sahrens } 325885Sahrens 326885Sahrens /* Fast path for an array of 1-byte integers (eg. the entry name) */ 327885Sahrens if (array_int_len == 1 && buf_int_len == 1 && 328885Sahrens buf_len > array_len + ZAP_LEAF_ARRAY_BYTES) { 329885Sahrens while (chunk != CHAIN_END) { 330885Sahrens struct zap_leaf_array *la = 331*1491Sahrens &ZAP_LEAF_CHUNK(l, chunk).l_array; 332885Sahrens bcopy(la->la_array, buf, ZAP_LEAF_ARRAY_BYTES); 333885Sahrens buf += ZAP_LEAF_ARRAY_BYTES; 334885Sahrens chunk = la->la_next; 335885Sahrens } 336885Sahrens return; 337885Sahrens } 338885Sahrens 339789Sahrens while (len > 0) { 340*1491Sahrens struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array; 341789Sahrens int i; 342789Sahrens 343*1491Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); 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) { 373*1491Sahrens struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array; 374789Sahrens int toread = MIN(array_len - bseen, ZAP_LEAF_ARRAY_BYTES); 375*1491Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); 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; 403*1491Sahrens le = ZAP_LEAF_ENTRY(l, chunk); 404789Sahrens 405*1491Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); 406*1491Sahrens ASSERT3U(le->le_type, ==, ZAP_CHUNK_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) */ 433885Sahrens #define HCD_GTEQ(h1, cd1, h2, cd2) \ 434885Sahrens ((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; 443*1491Sahrens uint16_t bestlh = ZAP_LEAF_HASH_NUMENTRIES(l)-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) { 455*1491Sahrens le = ZAP_LEAF_ENTRY(l, chunk); 456789Sahrens 457*1491Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); 458*1491Sahrens ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY); 459789Sahrens 460885Sahrens if (HCD_GTEQ(le->le_hash, le->le_cd, h, cd) && 461885Sahrens 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 { 490*1491Sahrens struct zap_leaf_entry *le = 491*1491Sahrens ZAP_LEAF_ENTRY(zeh->zeh_found_leaf, *zeh->zeh_chunkp); 492*1491Sahrens ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY); 493789Sahrens 494789Sahrens if (le->le_int_size > integer_size) 495789Sahrens return (EINVAL); 496789Sahrens 497789Sahrens zap_leaf_array_read(zeh, le->le_value_chunk, le->le_int_size, 498789Sahrens le->le_value_length, integer_size, num_integers, buf); 499789Sahrens 500789Sahrens if (zeh->zeh_num_integers > num_integers) 501789Sahrens return (EOVERFLOW); 502789Sahrens return (0); 503789Sahrens 504789Sahrens } 505789Sahrens 506789Sahrens int 507789Sahrens zap_entry_read_name(const zap_entry_handle_t *zeh, uint16_t buflen, char *buf) 508789Sahrens { 509*1491Sahrens struct zap_leaf_entry *le = 510*1491Sahrens ZAP_LEAF_ENTRY(zeh->zeh_found_leaf, *zeh->zeh_chunkp); 511*1491Sahrens ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY); 512789Sahrens 513789Sahrens zap_leaf_array_read(zeh, le->le_name_chunk, 1, 514789Sahrens le->le_name_length, 1, buflen, buf); 515789Sahrens if (le->le_name_length > buflen) 516789Sahrens return (EOVERFLOW); 517789Sahrens return (0); 518789Sahrens } 519789Sahrens 520789Sahrens int 521789Sahrens zap_entry_update(zap_entry_handle_t *zeh, 522789Sahrens uint8_t integer_size, uint64_t num_integers, const void *buf) 523789Sahrens { 524789Sahrens int delta_chunks; 525*1491Sahrens struct zap_leaf_entry *le = 526*1491Sahrens ZAP_LEAF_ENTRY(zeh->zeh_found_leaf, *zeh->zeh_chunkp); 527789Sahrens 528789Sahrens delta_chunks = NCHUNKS(num_integers * integer_size) - 529789Sahrens NCHUNKS(le->le_value_length * le->le_int_size); 530789Sahrens 531789Sahrens if (zeh->zeh_found_leaf->lh_nfree < delta_chunks) 532789Sahrens return (EAGAIN); 533789Sahrens 534789Sahrens /* 535789Sahrens * We should search other chained leaves (via 536789Sahrens * zap_entry_remove,create?) otherwise returning EAGAIN will 537789Sahrens * just send us into an infinite loop if we have to chain 538789Sahrens * another leaf block, rather than being able to split this 539789Sahrens * block. 540789Sahrens */ 541789Sahrens 542789Sahrens zap_leaf_array_free(zeh, &le->le_value_chunk); 543789Sahrens le->le_value_chunk = 544789Sahrens zap_leaf_array_create(zeh, buf, integer_size, num_integers); 545*1491Sahrens le->le_value_length = num_integers; 546789Sahrens le->le_int_size = integer_size; 547789Sahrens return (0); 548789Sahrens } 549789Sahrens 550789Sahrens void 551789Sahrens zap_entry_remove(zap_entry_handle_t *zeh) 552789Sahrens { 553789Sahrens uint16_t entry_chunk; 554789Sahrens struct zap_leaf_entry *le; 555789Sahrens zap_leaf_t *l = zeh->zeh_found_leaf; 556789Sahrens 557789Sahrens ASSERT3P(zeh->zeh_chunkp, !=, &zeh->zeh_fakechunk); 558789Sahrens 559789Sahrens entry_chunk = *zeh->zeh_chunkp; 560*1491Sahrens le = ZAP_LEAF_ENTRY(l, entry_chunk); 561*1491Sahrens ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY); 562789Sahrens 563789Sahrens zap_leaf_array_free(zeh, &le->le_name_chunk); 564789Sahrens zap_leaf_array_free(zeh, &le->le_value_chunk); 565789Sahrens 566789Sahrens *zeh->zeh_chunkp = le->le_next; 567789Sahrens zap_leaf_chunk_free(l, entry_chunk); 568789Sahrens 569789Sahrens l->lh_nentries--; 570789Sahrens } 571789Sahrens 572789Sahrens int 573789Sahrens zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd, 574789Sahrens uint8_t integer_size, uint64_t num_integers, const void *buf, 575789Sahrens zap_entry_handle_t *zeh) 576789Sahrens { 577789Sahrens uint16_t chunk; 578789Sahrens uint16_t *chunkp; 579789Sahrens struct zap_leaf_entry *le; 580789Sahrens uint64_t namelen, valuelen; 581789Sahrens int numchunks; 582789Sahrens 583789Sahrens valuelen = integer_size * num_integers; 584789Sahrens namelen = strlen(name) + 1; 585789Sahrens ASSERT(namelen >= 2); 586789Sahrens 587789Sahrens zeh->zeh_head_leaf = l; 588789Sahrens 589789Sahrens if (namelen > MAXNAMELEN) 590789Sahrens return (ENAMETOOLONG); 591789Sahrens /* find the first leaf in the chain that has sufficient free space */ 592789Sahrens numchunks = 1 + NCHUNKS(namelen) + NCHUNKS(valuelen); 593*1491Sahrens if (numchunks > ZAP_LEAF_NUMCHUNKS(l)) 594789Sahrens return (E2BIG); 595789Sahrens 596789Sahrens if (cd == ZAP_MAXCD) { 597789Sahrens for (cd = 0; cd < ZAP_MAXCD; cd++) { 598789Sahrens zap_leaf_t *ll; 599789Sahrens for (ll = l; ll; ll = ll->l_next) { 600789Sahrens for (chunk = *LEAF_HASH_ENTPTR(ll, h); 601789Sahrens chunk != CHAIN_END; chunk = le->le_next) { 602*1491Sahrens le = ZAP_LEAF_ENTRY(ll, chunk); 603789Sahrens if (le->le_hash == h && 604789Sahrens le->le_cd == cd) { 605789Sahrens break; 606789Sahrens } 607789Sahrens } 608789Sahrens /* 609789Sahrens * if this cd is in use, no need to 610789Sahrens * check more chained leafs 611789Sahrens */ 612789Sahrens if (chunk != CHAIN_END) 613789Sahrens break; 614789Sahrens } 615789Sahrens /* If this cd is not in use, we are good. */ 616789Sahrens if (chunk == CHAIN_END) 617789Sahrens break; 618789Sahrens } 619789Sahrens /* If we tried all the cd's, we lose. */ 620789Sahrens if (cd == ZAP_MAXCD) 621789Sahrens return (ENOSPC); 622789Sahrens } 623789Sahrens 624789Sahrens for (; l; l = l->l_next) 625789Sahrens if (l->lh_nfree >= numchunks) 626789Sahrens break; 627789Sahrens if (l == NULL) 628789Sahrens return (EAGAIN); 629789Sahrens 630789Sahrens zeh->zeh_found_leaf = l; 631789Sahrens 632789Sahrens /* make the entry */ 633789Sahrens chunk = zap_leaf_chunk_alloc(l); 634*1491Sahrens le = ZAP_LEAF_ENTRY(l, chunk); 635*1491Sahrens le->le_type = ZAP_CHUNK_ENTRY; 636789Sahrens le->le_name_chunk = zap_leaf_array_create(zeh, name, 1, namelen); 637789Sahrens le->le_name_length = namelen; 638789Sahrens le->le_value_chunk = 639789Sahrens zap_leaf_array_create(zeh, buf, integer_size, num_integers); 640*1491Sahrens le->le_value_length = num_integers; 641789Sahrens le->le_int_size = integer_size; 642789Sahrens le->le_hash = h; 643789Sahrens le->le_cd = cd; 644789Sahrens 645789Sahrens /* link it into the hash chain */ 646789Sahrens chunkp = LEAF_HASH_ENTPTR(l, h); 647789Sahrens le->le_next = *chunkp; 648789Sahrens *chunkp = chunk; 649789Sahrens 650789Sahrens l->lh_nentries++; 651789Sahrens 652789Sahrens zeh->zeh_num_integers = num_integers; 653789Sahrens zeh->zeh_integer_size = le->le_int_size; 654789Sahrens zeh->zeh_cd = le->le_cd; 655789Sahrens zeh->zeh_hash = le->le_hash; 656789Sahrens zeh->zeh_chunkp = chunkp; 657789Sahrens 658789Sahrens return (0); 659789Sahrens } 660789Sahrens 661789Sahrens /* 662789Sahrens * Routines for transferring entries between leafs. 663789Sahrens */ 664789Sahrens 665789Sahrens static void 666789Sahrens zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry) 667789Sahrens { 668*1491Sahrens struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, entry); 669789Sahrens uint16_t *ptr = LEAF_HASH_ENTPTR(l, le->le_hash); 670789Sahrens le->le_next = *ptr; 671789Sahrens *ptr = entry; 672789Sahrens } 673789Sahrens 674789Sahrens static void 675789Sahrens zap_leaf_rehash_entries(zap_leaf_t *l) 676789Sahrens { 677789Sahrens int i; 678789Sahrens 679789Sahrens if (l->lh_nentries == 0) 680789Sahrens return; 681789Sahrens 682789Sahrens /* break existing hash chains */ 683*1491Sahrens zap_memset(l->l_phys->l_hash, CHAIN_END, 2*ZAP_LEAF_HASH_NUMENTRIES(l)); 684789Sahrens 685*1491Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) { 686*1491Sahrens struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, i); 687*1491Sahrens if (le->le_type != ZAP_CHUNK_ENTRY) 688789Sahrens continue; 689789Sahrens zap_leaf_rehash_entry(l, i); 690789Sahrens } 691789Sahrens } 692789Sahrens 693789Sahrens static uint16_t 694789Sahrens zap_leaf_transfer_array(zap_leaf_t *l, uint16_t chunk, zap_leaf_t *nl) 695789Sahrens { 696789Sahrens uint16_t new_chunk; 697789Sahrens uint16_t *nchunkp = &new_chunk; 698789Sahrens 699789Sahrens while (chunk != CHAIN_END) { 700789Sahrens uint16_t nchunk = zap_leaf_chunk_alloc(nl); 701789Sahrens struct zap_leaf_array *nla = 702*1491Sahrens &ZAP_LEAF_CHUNK(nl, nchunk).l_array; 703789Sahrens struct zap_leaf_array *la = 704*1491Sahrens &ZAP_LEAF_CHUNK(l, chunk).l_array; 705789Sahrens int nextchunk = la->la_next; 706789Sahrens 707*1491Sahrens ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l)); 708*1491Sahrens ASSERT3U(nchunk, <, ZAP_LEAF_NUMCHUNKS(l)); 709789Sahrens 710789Sahrens *nla = *la; 711789Sahrens 712789Sahrens zap_leaf_chunk_free(l, chunk); 713789Sahrens chunk = nextchunk; 714789Sahrens *nchunkp = nchunk; 715789Sahrens nchunkp = &nla->la_next; 716789Sahrens } 717789Sahrens *nchunkp = CHAIN_END; 718789Sahrens return (new_chunk); 719789Sahrens } 720789Sahrens 721789Sahrens static void 722789Sahrens zap_leaf_transfer_entry(zap_t *zap, zap_leaf_t *l, int entry, zap_leaf_t *nhl, 723789Sahrens dmu_tx_t *tx) 724789Sahrens { 725789Sahrens zap_leaf_t *nl; 726789Sahrens struct zap_leaf_entry *le, *nle; 727789Sahrens uint16_t chunk, nchunks; 728789Sahrens 729*1491Sahrens le = ZAP_LEAF_ENTRY(l, entry); 730*1491Sahrens ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY); 731789Sahrens 732789Sahrens /* find a leaf in the destination leaf chain with enough free space */ 733789Sahrens nchunks = 1 + NCHUNKS(le->le_name_length) + 734789Sahrens NCHUNKS(le->le_value_length * le->le_int_size); 735789Sahrens for (nl = nhl; nl; nl = nl->l_next) 736789Sahrens if (nl->lh_nfree >= nchunks) 737789Sahrens break; 738789Sahrens if (nl == NULL) { 739789Sahrens nl = zap_leaf_chainmore(nhl, zap_create_leaf(zap, tx)); 740789Sahrens dprintf("transfer_entry: chaining leaf %x/%d\n", 741789Sahrens nl->lh_prefix, nl->lh_prefix_len); 742789Sahrens } 743789Sahrens 744789Sahrens chunk = zap_leaf_chunk_alloc(nl); 745*1491Sahrens nle = ZAP_LEAF_ENTRY(nl, chunk); 746789Sahrens *nle = *le; 747789Sahrens 748789Sahrens zap_leaf_rehash_entry(nl, chunk); 749789Sahrens 750789Sahrens nle->le_name_chunk = zap_leaf_transfer_array(l, le->le_name_chunk, nl); 751789Sahrens nle->le_value_chunk = 752789Sahrens zap_leaf_transfer_array(l, le->le_value_chunk, nl); 753789Sahrens 754789Sahrens zap_leaf_chunk_free(l, entry); 755789Sahrens 756789Sahrens l->lh_nentries--; 757789Sahrens nl->lh_nentries++; 758789Sahrens } 759789Sahrens 760789Sahrens /* 761789Sahrens * Transfer entries whose hash bit 'bit' is 1 to nl1, and 0 to nl0. 762789Sahrens * Ignore leaf chaining in source (l), but chain in destinations. 763789Sahrens * We'll re-chain all the entries in l as we go along. 764789Sahrens */ 765789Sahrens static void 766789Sahrens zap_leaf_transfer_entries(zap_t *zap, zap_leaf_t *l, 767789Sahrens zap_leaf_t *nl0, zap_leaf_t *nl1, int bit, dmu_tx_t *tx) 768789Sahrens { 769789Sahrens int i; 770789Sahrens 771789Sahrens ASSERT(bit < 64 && bit >= 0); 772789Sahrens /* break existing hash chains */ 773*1491Sahrens zap_memset(l->l_phys->l_hash, CHAIN_END, 2*ZAP_LEAF_HASH_NUMENTRIES(l)); 774789Sahrens 775789Sahrens if (nl0 != l) 776789Sahrens zap_leaf_rehash_entries(nl0); 777789Sahrens if (nl1 != nl0) 778789Sahrens zap_leaf_rehash_entries(nl1); 779789Sahrens 780*1491Sahrens for (i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) { 781*1491Sahrens struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, i); 782*1491Sahrens if (le->le_type != ZAP_CHUNK_ENTRY) 783789Sahrens continue; 784789Sahrens 785789Sahrens /* 786789Sahrens * We could find entries via hashtable instead. That 787789Sahrens * would be O(hashents+numents) rather than 788789Sahrens * O(numblks+numents), but this accesses memory more 789789Sahrens * sequentially, and when we're called, the block is 790789Sahrens * usually pretty full. 791789Sahrens */ 792789Sahrens 793789Sahrens if (le->le_hash & (1ULL << bit)) { 794789Sahrens zap_leaf_transfer_entry(zap, l, i, nl1, tx); 795789Sahrens } else { 796789Sahrens if (nl0 == l) 797789Sahrens zap_leaf_rehash_entry(l, i); 798789Sahrens else 799789Sahrens zap_leaf_transfer_entry(zap, l, i, nl0, tx); 800789Sahrens } 801789Sahrens } 802789Sahrens 803789Sahrens } 804789Sahrens 805789Sahrens /* 806789Sahrens * nl will contain the entries whose hash prefix ends in 1 807789Sahrens * handles leaf chaining 808789Sahrens */ 809789Sahrens zap_leaf_t * 810789Sahrens zap_leaf_split(zap_t *zap, zap_leaf_t *hl, dmu_tx_t *tx) 811789Sahrens { 812789Sahrens zap_leaf_t *l = hl; 813789Sahrens int bit = 64 - 1 - hl->lh_prefix_len; 814789Sahrens zap_leaf_t *nl = zap_create_leaf(zap, tx); 815789Sahrens 816789Sahrens /* set new prefix and prefix_len */ 817789Sahrens hl->lh_prefix <<= 1; 818789Sahrens hl->lh_prefix_len++; 819789Sahrens nl->lh_prefix = hl->lh_prefix | 1; 820789Sahrens nl->lh_prefix_len = hl->lh_prefix_len; 821789Sahrens 822789Sahrens /* transfer odd entries from first leaf in hl chain to nl */ 823789Sahrens zap_leaf_transfer_entries(zap, hl, hl, nl, bit, tx); 824789Sahrens 825789Sahrens /* take rest of chain off hl */ 826789Sahrens l = hl->l_next; 827789Sahrens hl->l_next = NULL; 828789Sahrens hl->lh_next = 0; 829789Sahrens 830789Sahrens /* transfer even entries from hl chain back to hl, odd entries to nl */ 831789Sahrens while (l) { 832789Sahrens zap_leaf_t *next = l->l_next; 833789Sahrens zap_leaf_transfer_entries(zap, l, hl, nl, bit, tx); 834789Sahrens zap_destroy_leaf(zap, l, tx); 835789Sahrens l = next; 836789Sahrens } 837789Sahrens 838789Sahrens return (nl); 839789Sahrens } 840789Sahrens 841789Sahrens void 842789Sahrens zap_stats_leaf(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs) 843789Sahrens { 844789Sahrens int n, nchained = 0; 845789Sahrens 846789Sahrens n = zap->zap_f.zap_phys->zap_ptrtbl.zt_shift - l->lh_prefix_len; 847789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 848789Sahrens zs->zs_leafs_with_2n_pointers[n]++; 849789Sahrens 850789Sahrens do { 851789Sahrens int i; 852789Sahrens 853789Sahrens n = l->lh_nentries/5; 854789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 855789Sahrens zs->zs_blocks_with_n5_entries[n]++; 856789Sahrens 857*1491Sahrens n = ((1<<FZAP_BLOCK_SHIFT(zap)) - 858789Sahrens l->lh_nfree * (ZAP_LEAF_ARRAY_BYTES+1))*10 / 859*1491Sahrens (1<<FZAP_BLOCK_SHIFT(zap)); 860789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 861789Sahrens zs->zs_blocks_n_tenths_full[n]++; 862789Sahrens 863*1491Sahrens for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(l); i++) { 864789Sahrens int nentries = 0; 865789Sahrens int chunk = l->l_phys->l_hash[i]; 866789Sahrens 867789Sahrens while (chunk != CHAIN_END) { 868789Sahrens struct zap_leaf_entry *le = 869*1491Sahrens ZAP_LEAF_ENTRY(l, chunk); 870789Sahrens 871789Sahrens n = 1 + NCHUNKS(le->le_name_length) + 872789Sahrens NCHUNKS(le->le_value_length * 873789Sahrens le->le_int_size); 874789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 875789Sahrens zs->zs_entries_using_n_chunks[n]++; 876789Sahrens 877789Sahrens chunk = le->le_next; 878789Sahrens nentries++; 879789Sahrens } 880789Sahrens 881789Sahrens n = nentries; 882789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 883789Sahrens zs->zs_buckets_with_n_entries[n]++; 884789Sahrens } 885789Sahrens 886789Sahrens nchained++; 887789Sahrens l = l->l_next; 888789Sahrens } while (l); 889789Sahrens 890789Sahrens n = nchained-1; 891789Sahrens n = MIN(n, ZAP_HISTOGRAM_SIZE-1); 892789Sahrens zs->zs_leafs_with_n_chained[n]++; 893789Sahrens } 894