FreeBSD ZFS
The Zettabyte File System

zap_leaf.c

Go to the documentation of this file.
00001 /*
00002  * CDDL HEADER START
00003  *
00004  * The contents of this file are subject to the terms of the
00005  * Common Development and Distribution License (the "License").
00006  * You may not use this file except in compliance with the License.
00007  *
00008  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
00009  * or http://www.opensolaris.org/os/licensing.
00010  * See the License for the specific language governing permissions
00011  * and limitations under the License.
00012  *
00013  * When distributing Covered Code, include this CDDL HEADER in each
00014  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
00015  * If applicable, add the following below this CDDL HEADER, with the
00016  * fields enclosed by brackets "[]" replaced with your own identifying
00017  * information: Portions Copyright [yyyy] [name of copyright owner]
00018  *
00019  * CDDL HEADER END
00020  */
00021 /*
00022  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
00023  */
00024 
00032 #include <sys/zio.h>
00033 #include <sys/spa.h>
00034 #include <sys/dmu.h>
00035 #include <sys/zfs_context.h>
00036 #include <sys/fs/zfs.h>
00037 #include <sys/zap.h>
00038 #include <sys/zap_impl.h>
00039 #include <sys/zap_leaf.h>
00040 #include <sys/arc.h>
00041 
00042 static uint16_t *zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry);
00043 
00044 #define CHAIN_END 0xffff /* end of the chunk chain */
00045 
00046 /* half the (current) minimum block size */
00047 #define MAX_ARRAY_BYTES (8<<10)
00048 
00049 #define LEAF_HASH(l, h) \
00050         ((ZAP_LEAF_HASH_NUMENTRIES(l)-1) & \
00051         ((h) >> (64 - ZAP_LEAF_HASH_SHIFT(l)-(l)->l_phys->l_hdr.lh_prefix_len)))
00052 
00053 #define LEAF_HASH_ENTPTR(l, h) (&(l)->l_phys->l_hash[LEAF_HASH(l, h)])
00054 
00055 
00056 static void
00057 zap_memset(void *a, int c, size_t n)
00058 {
00059         char *cp = a;
00060         char *cpend = cp + n;
00061 
00062         while (cp < cpend)
00063                 *cp++ = c;
00064 }
00065 
00066 static void
00067 stv(int len, void *addr, uint64_t value)
00068 {
00069         switch (len) {
00070         case 1:
00071                 *(uint8_t *)addr = value;
00072                 return;
00073         case 2:
00074                 *(uint16_t *)addr = value;
00075                 return;
00076         case 4:
00077                 *(uint32_t *)addr = value;
00078                 return;
00079         case 8:
00080                 *(uint64_t *)addr = value;
00081                 return;
00082         }
00083         ASSERT(!"bad int len");
00084 }
00085 
00086 static uint64_t
00087 ldv(int len, const void *addr)
00088 {
00089         switch (len) {
00090         case 1:
00091                 return (*(uint8_t *)addr);
00092         case 2:
00093                 return (*(uint16_t *)addr);
00094         case 4:
00095                 return (*(uint32_t *)addr);
00096         case 8:
00097                 return (*(uint64_t *)addr);
00098         }
00099         ASSERT(!"bad int len");
00100         return (0xFEEDFACEDEADBEEFULL);
00101 }
00102 
00103 void
00104 zap_leaf_byteswap(zap_leaf_phys_t *buf, int size)
00105 {
00106         int i;
00107         zap_leaf_t l;
00108         l.l_bs = highbit(size)-1;
00109         l.l_phys = buf;
00110 
00111         buf->l_hdr.lh_block_type =      BSWAP_64(buf->l_hdr.lh_block_type);
00112         buf->l_hdr.lh_prefix =          BSWAP_64(buf->l_hdr.lh_prefix);
00113         buf->l_hdr.lh_magic =           BSWAP_32(buf->l_hdr.lh_magic);
00114         buf->l_hdr.lh_nfree =           BSWAP_16(buf->l_hdr.lh_nfree);
00115         buf->l_hdr.lh_nentries =        BSWAP_16(buf->l_hdr.lh_nentries);
00116         buf->l_hdr.lh_prefix_len =      BSWAP_16(buf->l_hdr.lh_prefix_len);
00117         buf->l_hdr.lh_freelist =        BSWAP_16(buf->l_hdr.lh_freelist);
00118 
00119         for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(&l); i++)
00120                 buf->l_hash[i] = BSWAP_16(buf->l_hash[i]);
00121 
00122         for (i = 0; i < ZAP_LEAF_NUMCHUNKS(&l); i++) {
00123                 zap_leaf_chunk_t *lc = &ZAP_LEAF_CHUNK(&l, i);
00124                 struct zap_leaf_entry *le;
00125 
00126                 switch (lc->l_free.lf_type) {
00127                 case ZAP_CHUNK_ENTRY:
00128                         le = &lc->l_entry;
00129 
00130                         le->le_type =           BSWAP_8(le->le_type);
00131                         le->le_value_intlen =   BSWAP_8(le->le_value_intlen);
00132                         le->le_next =           BSWAP_16(le->le_next);
00133                         le->le_name_chunk =     BSWAP_16(le->le_name_chunk);
00134                         le->le_name_numints =   BSWAP_16(le->le_name_numints);
00135                         le->le_value_chunk =    BSWAP_16(le->le_value_chunk);
00136                         le->le_value_numints =  BSWAP_16(le->le_value_numints);
00137                         le->le_cd =             BSWAP_32(le->le_cd);
00138                         le->le_hash =           BSWAP_64(le->le_hash);
00139                         break;
00140                 case ZAP_CHUNK_FREE:
00141                         lc->l_free.lf_type =    BSWAP_8(lc->l_free.lf_type);
00142                         lc->l_free.lf_next =    BSWAP_16(lc->l_free.lf_next);
00143                         break;
00144                 case ZAP_CHUNK_ARRAY:
00145                         lc->l_array.la_type =   BSWAP_8(lc->l_array.la_type);
00146                         lc->l_array.la_next =   BSWAP_16(lc->l_array.la_next);
00147                         /* la_array doesn't need swapping */
00148                         break;
00149                 default:
00150                         ASSERT(!"bad leaf type");
00151                 }
00152         }
00153 }
00154 
00155 void
00156 zap_leaf_init(zap_leaf_t *l, boolean_t sort)
00157 {
00158         int i;
00159 
00160         l->l_bs = highbit(l->l_dbuf->db_size)-1;
00161         zap_memset(&l->l_phys->l_hdr, 0, sizeof (struct zap_leaf_header));
00162         zap_memset(l->l_phys->l_hash, CHAIN_END, 2*ZAP_LEAF_HASH_NUMENTRIES(l));
00163         for (i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
00164                 ZAP_LEAF_CHUNK(l, i).l_free.lf_type = ZAP_CHUNK_FREE;
00165                 ZAP_LEAF_CHUNK(l, i).l_free.lf_next = i+1;
00166         }
00167         ZAP_LEAF_CHUNK(l, ZAP_LEAF_NUMCHUNKS(l)-1).l_free.lf_next = CHAIN_END;
00168         l->l_phys->l_hdr.lh_block_type = ZBT_LEAF;
00169         l->l_phys->l_hdr.lh_magic = ZAP_LEAF_MAGIC;
00170         l->l_phys->l_hdr.lh_nfree = ZAP_LEAF_NUMCHUNKS(l);
00171         if (sort)
00172                 l->l_phys->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED;
00173 }
00174 
00175 /*
00176  * Routines which manipulate leaf chunks (l_chunk[]).
00177  */
00178 
00179 static uint16_t
00180 zap_leaf_chunk_alloc(zap_leaf_t *l)
00181 {
00182         int chunk;
00183 
00184         ASSERT(l->l_phys->l_hdr.lh_nfree > 0);
00185 
00186         chunk = l->l_phys->l_hdr.lh_freelist;
00187         ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
00188         ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_free.lf_type, ==, ZAP_CHUNK_FREE);
00189 
00190         l->l_phys->l_hdr.lh_freelist = ZAP_LEAF_CHUNK(l, chunk).l_free.lf_next;
00191 
00192         l->l_phys->l_hdr.lh_nfree--;
00193 
00194         return (chunk);
00195 }
00196 
00197 static void
00198 zap_leaf_chunk_free(zap_leaf_t *l, uint16_t chunk)
00199 {
00200         struct zap_leaf_free *zlf = &ZAP_LEAF_CHUNK(l, chunk).l_free;
00201         ASSERT3U(l->l_phys->l_hdr.lh_nfree, <, ZAP_LEAF_NUMCHUNKS(l));
00202         ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
00203         ASSERT(zlf->lf_type != ZAP_CHUNK_FREE);
00204 
00205         zlf->lf_type = ZAP_CHUNK_FREE;
00206         zlf->lf_next = l->l_phys->l_hdr.lh_freelist;
00207         bzero(zlf->lf_pad, sizeof (zlf->lf_pad)); /* help it to compress */
00208         l->l_phys->l_hdr.lh_freelist = chunk;
00209 
00210         l->l_phys->l_hdr.lh_nfree++;
00211 }
00212 
00213 /*
00214  * Routines which manipulate leaf arrays (zap_leaf_array type chunks).
00215  */
00216 
00217 static uint16_t
00218 zap_leaf_array_create(zap_leaf_t *l, const char *buf,
00219     int integer_size, int num_integers)
00220 {
00221         uint16_t chunk_head;
00222         uint16_t *chunkp = &chunk_head;
00223         int byten = 0;
00224         uint64_t value;
00225         int shift = (integer_size-1)*8;
00226         int len = num_integers;
00227 
00228         ASSERT3U(num_integers * integer_size, <, MAX_ARRAY_BYTES);
00229 
00230         while (len > 0) {
00231                 uint16_t chunk = zap_leaf_chunk_alloc(l);
00232                 struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
00233                 int i;
00234 
00235                 la->la_type = ZAP_CHUNK_ARRAY;
00236                 for (i = 0; i < ZAP_LEAF_ARRAY_BYTES; i++) {
00237                         if (byten == 0)
00238                                 value = ldv(integer_size, buf);
00239                         la->la_array[i] = value >> shift;
00240                         value <<= 8;
00241                         if (++byten == integer_size) {
00242                                 byten = 0;
00243                                 buf += integer_size;
00244                                 if (--len == 0)
00245                                         break;
00246                         }
00247                 }
00248 
00249                 *chunkp = chunk;
00250                 chunkp = &la->la_next;
00251         }
00252         *chunkp = CHAIN_END;
00253 
00254         return (chunk_head);
00255 }
00256 
00257 static void
00258 zap_leaf_array_free(zap_leaf_t *l, uint16_t *chunkp)
00259 {
00260         uint16_t chunk = *chunkp;
00261 
00262         *chunkp = CHAIN_END;
00263 
00264         while (chunk != CHAIN_END) {
00265                 int nextchunk = ZAP_LEAF_CHUNK(l, chunk).l_array.la_next;
00266                 ASSERT3U(ZAP_LEAF_CHUNK(l, chunk).l_array.la_type, ==,
00267                     ZAP_CHUNK_ARRAY);
00268                 zap_leaf_chunk_free(l, chunk);
00269                 chunk = nextchunk;
00270         }
00271 }
00272 
00277 static void
00278 zap_leaf_array_read(zap_leaf_t *l, uint16_t chunk,
00279     int array_int_len, int array_len, int buf_int_len, uint64_t buf_len,
00280     void *buf)
00281 {
00282         int len = MIN(array_len, buf_len);
00283         int byten = 0;
00284         uint64_t value = 0;
00285         char *p = buf;
00286 
00287         ASSERT3U(array_int_len, <=, buf_int_len);
00288 
00289         /* Fast path for one 8-byte integer */
00290         if (array_int_len == 8 && buf_int_len == 8 && len == 1) {
00291                 struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
00292                 uint8_t *ip = la->la_array;
00293                 uint64_t *buf64 = buf;
00294 
00295                 *buf64 = (uint64_t)ip[0] << 56 | (uint64_t)ip[1] << 48 |
00296                     (uint64_t)ip[2] << 40 | (uint64_t)ip[3] << 32 |
00297                     (uint64_t)ip[4] << 24 | (uint64_t)ip[5] << 16 |
00298                     (uint64_t)ip[6] << 8 | (uint64_t)ip[7];
00299                 return;
00300         }
00301 
00302         /* Fast path for an array of 1-byte integers (eg. the entry name) */
00303         if (array_int_len == 1 && buf_int_len == 1 &&
00304             buf_len > array_len + ZAP_LEAF_ARRAY_BYTES) {
00305                 while (chunk != CHAIN_END) {
00306                         struct zap_leaf_array *la =
00307                             &ZAP_LEAF_CHUNK(l, chunk).l_array;
00308                         bcopy(la->la_array, p, ZAP_LEAF_ARRAY_BYTES);
00309                         p += ZAP_LEAF_ARRAY_BYTES;
00310                         chunk = la->la_next;
00311                 }
00312                 return;
00313         }
00314 
00315         while (len > 0) {
00316                 struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
00317                 int i;
00318 
00319                 ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
00320                 for (i = 0; i < ZAP_LEAF_ARRAY_BYTES && len > 0; i++) {
00321                         value = (value << 8) | la->la_array[i];
00322                         byten++;
00323                         if (byten == array_int_len) {
00324                                 stv(buf_int_len, p, value);
00325                                 byten = 0;
00326                                 len--;
00327                                 if (len == 0)
00328                                         return;
00329                                 p += buf_int_len;
00330                         }
00331                 }
00332                 chunk = la->la_next;
00333         }
00334 }
00335 
00336 static boolean_t
00337 zap_leaf_array_match(zap_leaf_t *l, zap_name_t *zn,
00338     int chunk, int array_numints)
00339 {
00340         int bseen = 0;
00341 
00342         if (zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY) {
00343                 uint64_t *thiskey;
00344                 boolean_t match;
00345 
00346                 ASSERT(zn->zn_key_intlen == sizeof (*thiskey));
00347                 thiskey = kmem_alloc(array_numints * sizeof (*thiskey),
00348                     KM_SLEEP);
00349 
00350                 zap_leaf_array_read(l, chunk, sizeof (*thiskey), array_numints,
00351                     sizeof (*thiskey), array_numints, thiskey);
00352                 match = bcmp(thiskey, zn->zn_key_orig,
00353                     array_numints * sizeof (*thiskey)) == 0;
00354                 kmem_free(thiskey, array_numints * sizeof (*thiskey));
00355                 return (match);
00356         }
00357 
00358         ASSERT(zn->zn_key_intlen == 1);
00359         if (zn->zn_matchtype == MT_FIRST) {
00360                 char *thisname = kmem_alloc(array_numints, KM_SLEEP);
00361                 boolean_t match;
00362 
00363                 zap_leaf_array_read(l, chunk, sizeof (char), array_numints,
00364                     sizeof (char), array_numints, thisname);
00365                 match = zap_match(zn, thisname);
00366                 kmem_free(thisname, array_numints);
00367                 return (match);
00368         }
00369 
00370         /*
00371          * Fast path for exact matching.
00372          * First check that the lengths match, so that we don't read
00373          * past the end of the zn_key_orig array.
00374          */
00375         if (array_numints != zn->zn_key_orig_numints)
00376                 return (B_FALSE);
00377         while (bseen < array_numints) {
00378                 struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
00379                 int toread = MIN(array_numints - bseen, ZAP_LEAF_ARRAY_BYTES);
00380                 ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
00381                 if (bcmp(la->la_array, (char *)zn->zn_key_orig + bseen, toread))
00382                         break;
00383                 chunk = la->la_next;
00384                 bseen += toread;
00385         }
00386         return (bseen == array_numints);
00387 }
00388 
00389 /*
00390  * Routines which manipulate leaf entries.
00391  */
00392 
00393 int
00394 zap_leaf_lookup(zap_leaf_t *l, zap_name_t *zn, zap_entry_handle_t *zeh)
00395 {
00396         uint16_t *chunkp;
00397         struct zap_leaf_entry *le;
00398 
00399         ASSERT3U(l->l_phys->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);
00400 
00401 again:
00402         for (chunkp = LEAF_HASH_ENTPTR(l, zn->zn_hash);
00403             *chunkp != CHAIN_END; chunkp = &le->le_next) {
00404                 uint16_t chunk = *chunkp;
00405                 le = ZAP_LEAF_ENTRY(l, chunk);
00406 
00407                 ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
00408                 ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
00409 
00410                 if (le->le_hash != zn->zn_hash)
00411                         continue;
00412 
00413                 /*
00414                  * NB: the entry chain is always sorted by cd on
00415                  * normalized zap objects, so this will find the
00416                  * lowest-cd match for MT_FIRST.
00417                  */
00418                 ASSERT(zn->zn_matchtype == MT_EXACT ||
00419                     (l->l_phys->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED));
00420                 if (zap_leaf_array_match(l, zn, le->le_name_chunk,
00421                     le->le_name_numints)) {
00422                         zeh->zeh_num_integers = le->le_value_numints;
00423                         zeh->zeh_integer_size = le->le_value_intlen;
00424                         zeh->zeh_cd = le->le_cd;
00425                         zeh->zeh_hash = le->le_hash;
00426                         zeh->zeh_chunkp = chunkp;
00427                         zeh->zeh_leaf = l;
00428                         return (0);
00429                 }
00430         }
00431 
00432         /*
00433          * NB: we could of course do this in one pass, but that would be
00434          * a pain.  We'll see if MT_BEST is even used much.
00435          */
00436         if (zn->zn_matchtype == MT_BEST) {
00437                 zn->zn_matchtype = MT_FIRST;
00438                 goto again;
00439         }
00440 
00441         return (ENOENT);
00442 }
00443 
00444 /* Return (h1,cd1 >= h2,cd2) */
00445 #define HCD_GTEQ(h1, cd1, h2, cd2) \
00446         ((h1 > h2) ? TRUE : ((h1 == h2 && cd1 >= cd2) ? TRUE : FALSE))
00447 
00448 int
00449 zap_leaf_lookup_closest(zap_leaf_t *l,
00450     uint64_t h, uint32_t cd, zap_entry_handle_t *zeh)
00451 {
00452         uint16_t chunk;
00453         uint64_t besth = -1ULL;
00454         uint32_t bestcd = -1U;
00455         uint16_t bestlh = ZAP_LEAF_HASH_NUMENTRIES(l)-1;
00456         uint16_t lh;
00457         struct zap_leaf_entry *le;
00458 
00459         ASSERT3U(l->l_phys->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);
00460 
00461         for (lh = LEAF_HASH(l, h); lh <= bestlh; lh++) {
00462                 for (chunk = l->l_phys->l_hash[lh];
00463                     chunk != CHAIN_END; chunk = le->le_next) {
00464                         le = ZAP_LEAF_ENTRY(l, chunk);
00465 
00466                         ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
00467                         ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
00468 
00469                         if (HCD_GTEQ(le->le_hash, le->le_cd, h, cd) &&
00470                             HCD_GTEQ(besth, bestcd, le->le_hash, le->le_cd)) {
00471                                 ASSERT3U(bestlh, >=, lh);
00472                                 bestlh = lh;
00473                                 besth = le->le_hash;
00474                                 bestcd = le->le_cd;
00475 
00476                                 zeh->zeh_num_integers = le->le_value_numints;
00477                                 zeh->zeh_integer_size = le->le_value_intlen;
00478                                 zeh->zeh_cd = le->le_cd;
00479                                 zeh->zeh_hash = le->le_hash;
00480                                 zeh->zeh_fakechunk = chunk;
00481                                 zeh->zeh_chunkp = &zeh->zeh_fakechunk;
00482                                 zeh->zeh_leaf = l;
00483                         }
00484                 }
00485         }
00486 
00487         return (bestcd == -1U ? ENOENT : 0);
00488 }
00489 
00490 int
00491 zap_entry_read(const zap_entry_handle_t *zeh,
00492     uint8_t integer_size, uint64_t num_integers, void *buf)
00493 {
00494         struct zap_leaf_entry *le =
00495             ZAP_LEAF_ENTRY(zeh->zeh_leaf, *zeh->zeh_chunkp);
00496         ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
00497 
00498         if (le->le_value_intlen > integer_size)
00499                 return (EINVAL);
00500 
00501         zap_leaf_array_read(zeh->zeh_leaf, le->le_value_chunk,
00502             le->le_value_intlen, le->le_value_numints,
00503             integer_size, num_integers, buf);
00504 
00505         if (zeh->zeh_num_integers > num_integers)
00506                 return (EOVERFLOW);
00507         return (0);
00508 
00509 }
00510 
00511 int
00512 zap_entry_read_name(zap_t *zap, const zap_entry_handle_t *zeh, uint16_t buflen,
00513     char *buf)
00514 {
00515         struct zap_leaf_entry *le =
00516             ZAP_LEAF_ENTRY(zeh->zeh_leaf, *zeh->zeh_chunkp);
00517         ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
00518 
00519         if (zap_getflags(zap) & ZAP_FLAG_UINT64_KEY) {
00520                 zap_leaf_array_read(zeh->zeh_leaf, le->le_name_chunk, 8,
00521                     le->le_name_numints, 8, buflen / 8, buf);
00522         } else {
00523                 zap_leaf_array_read(zeh->zeh_leaf, le->le_name_chunk, 1,
00524                     le->le_name_numints, 1, buflen, buf);
00525         }
00526         if (le->le_name_numints > buflen)
00527                 return (EOVERFLOW);
00528         return (0);
00529 }
00530 
00531 int
00532 zap_entry_update(zap_entry_handle_t *zeh,
00533         uint8_t integer_size, uint64_t num_integers, const void *buf)
00534 {
00535         int delta_chunks;
00536         zap_leaf_t *l = zeh->zeh_leaf;
00537         struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, *zeh->zeh_chunkp);
00538 
00539         delta_chunks = ZAP_LEAF_ARRAY_NCHUNKS(num_integers * integer_size) -
00540             ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_numints * le->le_value_intlen);
00541 
00542         if ((int)l->l_phys->l_hdr.lh_nfree < delta_chunks)
00543                 return (EAGAIN);
00544 
00545         zap_leaf_array_free(l, &le->le_value_chunk);
00546         le->le_value_chunk =
00547             zap_leaf_array_create(l, buf, integer_size, num_integers);
00548         le->le_value_numints = num_integers;
00549         le->le_value_intlen = integer_size;
00550         return (0);
00551 }
00552 
00553 void
00554 zap_entry_remove(zap_entry_handle_t *zeh)
00555 {
00556         uint16_t entry_chunk;
00557         struct zap_leaf_entry *le;
00558         zap_leaf_t *l = zeh->zeh_leaf;
00559 
00560         ASSERT3P(zeh->zeh_chunkp, !=, &zeh->zeh_fakechunk);
00561 
00562         entry_chunk = *zeh->zeh_chunkp;
00563         le = ZAP_LEAF_ENTRY(l, entry_chunk);
00564         ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
00565 
00566         zap_leaf_array_free(l, &le->le_name_chunk);
00567         zap_leaf_array_free(l, &le->le_value_chunk);
00568 
00569         *zeh->zeh_chunkp = le->le_next;
00570         zap_leaf_chunk_free(l, entry_chunk);
00571 
00572         l->l_phys->l_hdr.lh_nentries--;
00573 }
00574 
00575 int
00576 zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd,
00577     uint8_t integer_size, uint64_t num_integers, const void *buf,
00578     zap_entry_handle_t *zeh)
00579 {
00580         uint16_t chunk;
00581         uint16_t *chunkp;
00582         struct zap_leaf_entry *le;
00583         uint64_t valuelen;
00584         int numchunks;
00585         uint64_t h = zn->zn_hash;
00586 
00587         valuelen = integer_size * num_integers;
00588 
00589         numchunks = 1 + ZAP_LEAF_ARRAY_NCHUNKS(zn->zn_key_orig_numints *
00590             zn->zn_key_intlen) + ZAP_LEAF_ARRAY_NCHUNKS(valuelen);
00591         if (numchunks > ZAP_LEAF_NUMCHUNKS(l))
00592                 return (E2BIG);
00593 
00594         if (cd == ZAP_NEED_CD) {
00595                 /* find the lowest unused cd */
00596                 if (l->l_phys->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED) {
00597                         cd = 0;
00598 
00599                         for (chunk = *LEAF_HASH_ENTPTR(l, h);
00600                             chunk != CHAIN_END; chunk = le->le_next) {
00601                                 le = ZAP_LEAF_ENTRY(l, chunk);
00602                                 if (le->le_cd > cd)
00603                                         break;
00604                                 if (le->le_hash == h) {
00605                                         ASSERT3U(cd, ==, le->le_cd);
00606                                         cd++;
00607                                 }
00608                         }
00609                 } else {
00610                         /* old unsorted format; do it the O(n^2) way */
00611                         for (cd = 0; ; cd++) {
00612                                 for (chunk = *LEAF_HASH_ENTPTR(l, h);
00613                                     chunk != CHAIN_END; chunk = le->le_next) {
00614                                         le = ZAP_LEAF_ENTRY(l, chunk);
00615                                         if (le->le_hash == h &&
00616                                             le->le_cd == cd) {
00617                                                 break;
00618                                         }
00619                                 }
00620                                 /* If this cd is not in use, we are good. */
00621                                 if (chunk == CHAIN_END)
00622                                         break;
00623                         }
00624                 }
00625                 /*
00626                  * We would run out of space in a block before we could
00627                  * store enough entries to run out of CD values.
00628                  */
00629                 ASSERT3U(cd, <, zap_maxcd(zn->zn_zap));
00630         }
00631 
00632         if (l->l_phys->l_hdr.lh_nfree < numchunks)
00633                 return (EAGAIN);
00634 
00635         /* make the entry */
00636         chunk = zap_leaf_chunk_alloc(l);
00637         le = ZAP_LEAF_ENTRY(l, chunk);
00638         le->le_type = ZAP_CHUNK_ENTRY;
00639         le->le_name_chunk = zap_leaf_array_create(l, zn->zn_key_orig,
00640             zn->zn_key_intlen, zn->zn_key_orig_numints);
00641         le->le_name_numints = zn->zn_key_orig_numints;
00642         le->le_value_chunk =
00643             zap_leaf_array_create(l, buf, integer_size, num_integers);
00644         le->le_value_numints = num_integers;
00645         le->le_value_intlen = integer_size;
00646         le->le_hash = h;
00647         le->le_cd = cd;
00648 
00649         /* link it into the hash chain */
00650         /* XXX if we did the search above, we could just use that */
00651         chunkp = zap_leaf_rehash_entry(l, chunk);
00652 
00653         l->l_phys->l_hdr.lh_nentries++;
00654 
00655         zeh->zeh_leaf = l;
00656         zeh->zeh_num_integers = num_integers;
00657         zeh->zeh_integer_size = le->le_value_intlen;
00658         zeh->zeh_cd = le->le_cd;
00659         zeh->zeh_hash = le->le_hash;
00660         zeh->zeh_chunkp = chunkp;
00661 
00662         return (0);
00663 }
00664 
00676 boolean_t
00677 zap_entry_normalization_conflict(zap_entry_handle_t *zeh, zap_name_t *zn,
00678     const char *name, zap_t *zap)
00679 {
00680         uint64_t chunk;
00681         struct zap_leaf_entry *le;
00682         boolean_t allocdzn = B_FALSE;
00683 
00684         if (zap->zap_normflags == 0)
00685                 return (B_FALSE);
00686 
00687         for (chunk = *LEAF_HASH_ENTPTR(zeh->zeh_leaf, zeh->zeh_hash);
00688             chunk != CHAIN_END; chunk = le->le_next) {
00689                 le = ZAP_LEAF_ENTRY(zeh->zeh_leaf, chunk);
00690                 if (le->le_hash != zeh->zeh_hash)
00691                         continue;
00692                 if (le->le_cd == zeh->zeh_cd)
00693                         continue;
00694 
00695                 if (zn == NULL) {
00696                         zn = zap_name_alloc(zap, name, MT_FIRST);
00697                         allocdzn = B_TRUE;
00698                 }
00699                 if (zap_leaf_array_match(zeh->zeh_leaf, zn,
00700                     le->le_name_chunk, le->le_name_numints)) {
00701                         if (allocdzn)
00702                                 zap_name_free(zn);
00703                         return (B_TRUE);
00704                 }
00705         }
00706         if (allocdzn)
00707                 zap_name_free(zn);
00708         return (B_FALSE);
00709 }
00710 
00711 /*
00712  * Routines for transferring entries between leafs.
00713  */
00714 
00715 static uint16_t *
00716 zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry)
00717 {
00718         struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, entry);
00719         struct zap_leaf_entry *le2;
00720         uint16_t *chunkp;
00721 
00722         /*
00723          * keep the entry chain sorted by cd
00724          * NB: this will not cause problems for unsorted leafs, though
00725          * it is unnecessary there.
00726          */
00727         for (chunkp = LEAF_HASH_ENTPTR(l, le->le_hash);
00728             *chunkp != CHAIN_END; chunkp = &le2->le_next) {
00729                 le2 = ZAP_LEAF_ENTRY(l, *chunkp);
00730                 if (le2->le_cd > le->le_cd)
00731                         break;
00732         }
00733 
00734         le->le_next = *chunkp;
00735         *chunkp = entry;
00736         return (chunkp);
00737 }
00738 
00739 static uint16_t
00740 zap_leaf_transfer_array(zap_leaf_t *l, uint16_t chunk, zap_leaf_t *nl)
00741 {
00742         uint16_t new_chunk;
00743         uint16_t *nchunkp = &new_chunk;
00744 
00745         while (chunk != CHAIN_END) {
00746                 uint16_t nchunk = zap_leaf_chunk_alloc(nl);
00747                 struct zap_leaf_array *nla =
00748                     &ZAP_LEAF_CHUNK(nl, nchunk).l_array;
00749                 struct zap_leaf_array *la =
00750                     &ZAP_LEAF_CHUNK(l, chunk).l_array;
00751                 int nextchunk = la->la_next;
00752 
00753                 ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
00754                 ASSERT3U(nchunk, <, ZAP_LEAF_NUMCHUNKS(l));
00755 
00756                 *nla = *la; /* structure assignment */
00757 
00758                 zap_leaf_chunk_free(l, chunk);
00759                 chunk = nextchunk;
00760                 *nchunkp = nchunk;
00761                 nchunkp = &nla->la_next;
00762         }
00763         *nchunkp = CHAIN_END;
00764         return (new_chunk);
00765 }
00766 
00767 static void
00768 zap_leaf_transfer_entry(zap_leaf_t *l, int entry, zap_leaf_t *nl)
00769 {
00770         struct zap_leaf_entry *le, *nle;
00771         uint16_t chunk;
00772 
00773         le = ZAP_LEAF_ENTRY(l, entry);
00774         ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
00775 
00776         chunk = zap_leaf_chunk_alloc(nl);
00777         nle = ZAP_LEAF_ENTRY(nl, chunk);
00778         *nle = *le; /* structure assignment */
00779 
00780         (void) zap_leaf_rehash_entry(nl, chunk);
00781 
00782         nle->le_name_chunk = zap_leaf_transfer_array(l, le->le_name_chunk, nl);
00783         nle->le_value_chunk =
00784             zap_leaf_transfer_array(l, le->le_value_chunk, nl);
00785 
00786         zap_leaf_chunk_free(l, entry);
00787 
00788         l->l_phys->l_hdr.lh_nentries--;
00789         nl->l_phys->l_hdr.lh_nentries++;
00790 }
00791 
00795 void
00796 zap_leaf_split(zap_leaf_t *l, zap_leaf_t *nl, boolean_t sort)
00797 {
00798         int i;
00799         int bit = 64 - 1 - l->l_phys->l_hdr.lh_prefix_len;
00800 
00801         /* set new prefix and prefix_len */
00802         l->l_phys->l_hdr.lh_prefix <<= 1;
00803         l->l_phys->l_hdr.lh_prefix_len++;
00804         nl->l_phys->l_hdr.lh_prefix = l->l_phys->l_hdr.lh_prefix | 1;
00805         nl->l_phys->l_hdr.lh_prefix_len = l->l_phys->l_hdr.lh_prefix_len;
00806 
00807         /* break existing hash chains */
00808         zap_memset(l->l_phys->l_hash, CHAIN_END, 2*ZAP_LEAF_HASH_NUMENTRIES(l));
00809 
00810         if (sort)
00811                 l->l_phys->l_hdr.lh_flags |= ZLF_ENTRIES_CDSORTED;
00812 
00813         /*
00814          * Transfer entries whose hash bit 'bit' is set to nl; rehash
00815          * the remaining entries
00816          *
00817          * NB: We could find entries via the hashtable instead. That
00818          * would be O(hashents+numents) rather than O(numblks+numents),
00819          * but this accesses memory more sequentially, and when we're
00820          * called, the block is usually pretty full.
00821          */
00822         for (i = 0; i < ZAP_LEAF_NUMCHUNKS(l); i++) {
00823                 struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, i);
00824                 if (le->le_type != ZAP_CHUNK_ENTRY)
00825                         continue;
00826 
00827                 if (le->le_hash & (1ULL << bit))
00828                         zap_leaf_transfer_entry(l, i, nl);
00829                 else
00830                         (void) zap_leaf_rehash_entry(l, i);
00831         }
00832 }
00833 
00834 void
00835 zap_leaf_stats(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs)
00836 {
00837         int i, n;
00838 
00839         n = zap->zap_f.zap_phys->zap_ptrtbl.zt_shift -
00840             l->l_phys->l_hdr.lh_prefix_len;
00841         n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
00842         zs->zs_leafs_with_2n_pointers[n]++;
00843 
00844 
00845         n = l->l_phys->l_hdr.lh_nentries/5;
00846         n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
00847         zs->zs_blocks_with_n5_entries[n]++;
00848 
00849         n = ((1<<FZAP_BLOCK_SHIFT(zap)) -
00850             l->l_phys->l_hdr.lh_nfree * (ZAP_LEAF_ARRAY_BYTES+1))*10 /
00851             (1<<FZAP_BLOCK_SHIFT(zap));
00852         n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
00853         zs->zs_blocks_n_tenths_full[n]++;
00854 
00855         for (i = 0; i < ZAP_LEAF_HASH_NUMENTRIES(l); i++) {
00856                 int nentries = 0;
00857                 int chunk = l->l_phys->l_hash[i];
00858 
00859                 while (chunk != CHAIN_END) {
00860                         struct zap_leaf_entry *le =
00861                             ZAP_LEAF_ENTRY(l, chunk);
00862 
00863                         n = 1 + ZAP_LEAF_ARRAY_NCHUNKS(le->le_name_numints) +
00864                             ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_numints *
00865                             le->le_value_intlen);
00866                         n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
00867                         zs->zs_entries_using_n_chunks[n]++;
00868 
00869                         chunk = le->le_next;
00870                         nentries++;
00871                 }
00872 
00873                 n = nentries;
00874                 n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
00875                 zs->zs_buckets_with_n_entries[n]++;
00876         }
00877 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines