Update core ZFS code from build 121 to build 141.

This commit is contained in:
Brian Behlendorf
2010-05-28 13:45:14 -07:00
parent 6119cb885a
commit 428870ff73
174 changed files with 35763 additions and 14592 deletions
+94 -74
View File
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -29,6 +28,7 @@
* the names are stored null-terminated.
*/
#include <sys/zio.h>
#include <sys/spa.h>
#include <sys/dmu.h>
#include <sys/zfs_context.h>
@@ -36,6 +36,7 @@
#include <sys/zap.h>
#include <sys/zap_impl.h>
#include <sys/zap_leaf.h>
#include <sys/arc.h>
static uint16_t *zap_leaf_rehash_entry(zap_leaf_t *l, uint16_t entry);
@@ -126,12 +127,12 @@ zap_leaf_byteswap(zap_leaf_phys_t *buf, int size)
le = &lc->l_entry;
le->le_type = BSWAP_8(le->le_type);
le->le_int_size = BSWAP_8(le->le_int_size);
le->le_value_intlen = BSWAP_8(le->le_value_intlen);
le->le_next = BSWAP_16(le->le_next);
le->le_name_chunk = BSWAP_16(le->le_name_chunk);
le->le_name_length = BSWAP_16(le->le_name_length);
le->le_name_numints = BSWAP_16(le->le_name_numints);
le->le_value_chunk = BSWAP_16(le->le_value_chunk);
le->le_value_length = BSWAP_16(le->le_value_length);
le->le_value_numints = BSWAP_16(le->le_value_numints);
le->le_cd = BSWAP_32(le->le_cd);
le->le_hash = BSWAP_64(le->le_hash);
break;
@@ -214,7 +215,7 @@ zap_leaf_chunk_free(zap_leaf_t *l, uint16_t chunk)
static uint16_t
zap_leaf_array_create(zap_leaf_t *l, const char *buf,
int integer_size, int num_integers)
int integer_size, int num_integers)
{
uint16_t chunk_head;
uint16_t *chunkp = &chunk_head;
@@ -272,11 +273,12 @@ zap_leaf_array_free(zap_leaf_t *l, uint16_t *chunkp)
static void
zap_leaf_array_read(zap_leaf_t *l, uint16_t chunk,
int array_int_len, int array_len, int buf_int_len, uint64_t buf_len,
char *buf)
void *buf)
{
int len = MIN(array_len, buf_len);
int byten = 0;
uint64_t value = 0;
char *p = buf;
ASSERT3U(array_int_len, <=, buf_int_len);
@@ -284,7 +286,7 @@ zap_leaf_array_read(zap_leaf_t *l, uint16_t chunk,
if (array_int_len == 8 && buf_int_len == 8 && len == 1) {
struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
uint8_t *ip = la->la_array;
uint64_t *buf64 = (uint64_t *)buf;
uint64_t *buf64 = buf;
*buf64 = (uint64_t)ip[0] << 56 | (uint64_t)ip[1] << 48 |
(uint64_t)ip[2] << 40 | (uint64_t)ip[3] << 32 |
@@ -299,8 +301,8 @@ zap_leaf_array_read(zap_leaf_t *l, uint16_t chunk,
while (chunk != CHAIN_END) {
struct zap_leaf_array *la =
&ZAP_LEAF_CHUNK(l, chunk).l_array;
bcopy(la->la_array, buf, ZAP_LEAF_ARRAY_BYTES);
buf += ZAP_LEAF_ARRAY_BYTES;
bcopy(la->la_array, p, ZAP_LEAF_ARRAY_BYTES);
p += ZAP_LEAF_ARRAY_BYTES;
chunk = la->la_next;
}
return;
@@ -315,50 +317,69 @@ zap_leaf_array_read(zap_leaf_t *l, uint16_t chunk,
value = (value << 8) | la->la_array[i];
byten++;
if (byten == array_int_len) {
stv(buf_int_len, buf, value);
stv(buf_int_len, p, value);
byten = 0;
len--;
if (len == 0)
return;
buf += buf_int_len;
p += buf_int_len;
}
}
chunk = la->la_next;
}
}
/*
* Only to be used on 8-bit arrays.
* array_len is actual len in bytes (not encoded le_value_length).
* namenorm is null-terminated.
*/
static boolean_t
zap_leaf_array_match(zap_leaf_t *l, zap_name_t *zn, int chunk, int array_len)
zap_leaf_array_match(zap_leaf_t *l, zap_name_t *zn,
int chunk, int array_numints)
{
int bseen = 0;
if (zn->zn_matchtype == MT_FIRST) {
char *thisname = kmem_alloc(array_len, KM_SLEEP);
if (zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY) {
uint64_t *thiskey;
boolean_t match;
zap_leaf_array_read(l, chunk, 1, array_len, 1,
array_len, thisname);
match = zap_match(zn, thisname);
kmem_free(thisname, array_len);
ASSERT(zn->zn_key_intlen == sizeof (*thiskey));
thiskey = kmem_alloc(array_numints * sizeof (*thiskey),
KM_SLEEP);
zap_leaf_array_read(l, chunk, sizeof (*thiskey), array_numints,
sizeof (*thiskey), array_numints, thiskey);
match = bcmp(thiskey, zn->zn_key_orig,
array_numints * sizeof (*thiskey)) == 0;
kmem_free(thiskey, array_numints * sizeof (*thiskey));
return (match);
}
/* Fast path for exact matching */
while (bseen < array_len) {
ASSERT(zn->zn_key_intlen == 1);
if (zn->zn_matchtype == MT_FIRST) {
char *thisname = kmem_alloc(array_numints, KM_SLEEP);
boolean_t match;
zap_leaf_array_read(l, chunk, sizeof (char), array_numints,
sizeof (char), array_numints, thisname);
match = zap_match(zn, thisname);
kmem_free(thisname, array_numints);
return (match);
}
/*
* Fast path for exact matching.
* First check that the lengths match, so that we don't read
* past the end of the zn_key_orig array.
*/
if (array_numints != zn->zn_key_orig_numints)
return (B_FALSE);
while (bseen < array_numints) {
struct zap_leaf_array *la = &ZAP_LEAF_CHUNK(l, chunk).l_array;
int toread = MIN(array_len - bseen, ZAP_LEAF_ARRAY_BYTES);
int toread = MIN(array_numints - bseen, ZAP_LEAF_ARRAY_BYTES);
ASSERT3U(chunk, <, ZAP_LEAF_NUMCHUNKS(l));
if (bcmp(la->la_array, zn->zn_name_orij + bseen, toread))
if (bcmp(la->la_array, (char *)zn->zn_key_orig + bseen, toread))
break;
chunk = la->la_next;
bseen += toread;
}
return (bseen == array_len);
return (bseen == array_numints);
}
/*
@@ -393,9 +414,9 @@ again:
ASSERT(zn->zn_matchtype == MT_EXACT ||
(l->l_phys->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED));
if (zap_leaf_array_match(l, zn, le->le_name_chunk,
le->le_name_length)) {
zeh->zeh_num_integers = le->le_value_length;
zeh->zeh_integer_size = le->le_int_size;
le->le_name_numints)) {
zeh->zeh_num_integers = le->le_value_numints;
zeh->zeh_integer_size = le->le_value_intlen;
zeh->zeh_cd = le->le_cd;
zeh->zeh_hash = le->le_hash;
zeh->zeh_chunkp = chunkp;
@@ -426,7 +447,7 @@ zap_leaf_lookup_closest(zap_leaf_t *l,
{
uint16_t chunk;
uint64_t besth = -1ULL;
uint32_t bestcd = ZAP_MAXCD;
uint32_t bestcd = -1U;
uint16_t bestlh = ZAP_LEAF_HASH_NUMENTRIES(l)-1;
uint16_t lh;
struct zap_leaf_entry *le;
@@ -448,8 +469,8 @@ zap_leaf_lookup_closest(zap_leaf_t *l,
besth = le->le_hash;
bestcd = le->le_cd;
zeh->zeh_num_integers = le->le_value_length;
zeh->zeh_integer_size = le->le_int_size;
zeh->zeh_num_integers = le->le_value_numints;
zeh->zeh_integer_size = le->le_value_intlen;
zeh->zeh_cd = le->le_cd;
zeh->zeh_hash = le->le_hash;
zeh->zeh_fakechunk = chunk;
@@ -459,7 +480,7 @@ zap_leaf_lookup_closest(zap_leaf_t *l,
}
}
return (bestcd == ZAP_MAXCD ? ENOENT : 0);
return (bestcd == -1U ? ENOENT : 0);
}
int
@@ -470,11 +491,12 @@ zap_entry_read(const zap_entry_handle_t *zeh,
ZAP_LEAF_ENTRY(zeh->zeh_leaf, *zeh->zeh_chunkp);
ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
if (le->le_int_size > integer_size)
if (le->le_value_intlen > integer_size)
return (EINVAL);
zap_leaf_array_read(zeh->zeh_leaf, le->le_value_chunk, le->le_int_size,
le->le_value_length, integer_size, num_integers, buf);
zap_leaf_array_read(zeh->zeh_leaf, le->le_value_chunk,
le->le_value_intlen, le->le_value_numints,
integer_size, num_integers, buf);
if (zeh->zeh_num_integers > num_integers)
return (EOVERFLOW);
@@ -483,15 +505,21 @@ zap_entry_read(const zap_entry_handle_t *zeh,
}
int
zap_entry_read_name(const zap_entry_handle_t *zeh, uint16_t buflen, char *buf)
zap_entry_read_name(zap_t *zap, const zap_entry_handle_t *zeh, uint16_t buflen,
char *buf)
{
struct zap_leaf_entry *le =
ZAP_LEAF_ENTRY(zeh->zeh_leaf, *zeh->zeh_chunkp);
ASSERT3U(le->le_type, ==, ZAP_CHUNK_ENTRY);
zap_leaf_array_read(zeh->zeh_leaf, le->le_name_chunk, 1,
le->le_name_length, 1, buflen, buf);
if (le->le_name_length > buflen)
if (zap_getflags(zap) & ZAP_FLAG_UINT64_KEY) {
zap_leaf_array_read(zeh->zeh_leaf, le->le_name_chunk, 8,
le->le_name_numints, 8, buflen / 8, buf);
} else {
zap_leaf_array_read(zeh->zeh_leaf, le->le_name_chunk, 1,
le->le_name_numints, 1, buflen, buf);
}
if (le->le_name_numints > buflen)
return (EOVERFLOW);
return (0);
}
@@ -505,24 +533,16 @@ zap_entry_update(zap_entry_handle_t *zeh,
struct zap_leaf_entry *le = ZAP_LEAF_ENTRY(l, *zeh->zeh_chunkp);
delta_chunks = ZAP_LEAF_ARRAY_NCHUNKS(num_integers * integer_size) -
ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_length * le->le_int_size);
ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_numints * le->le_value_intlen);
if ((int)l->l_phys->l_hdr.lh_nfree < delta_chunks)
return (EAGAIN);
/*
* We should search other chained leaves (via
* zap_entry_remove,create?) otherwise returning EAGAIN will
* just send us into an infinite loop if we have to chain
* another leaf block, rather than being able to split this
* block.
*/
zap_leaf_array_free(l, &le->le_value_chunk);
le->le_value_chunk =
zap_leaf_array_create(l, buf, integer_size, num_integers);
le->le_value_length = num_integers;
le->le_int_size = integer_size;
le->le_value_numints = num_integers;
le->le_value_intlen = integer_size;
return (0);
}
@@ -549,26 +569,25 @@ zap_entry_remove(zap_entry_handle_t *zeh)
}
int
zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd,
zap_entry_create(zap_leaf_t *l, zap_name_t *zn, uint32_t cd,
uint8_t integer_size, uint64_t num_integers, const void *buf,
zap_entry_handle_t *zeh)
{
uint16_t chunk;
uint16_t *chunkp;
struct zap_leaf_entry *le;
uint64_t namelen, valuelen;
uint64_t valuelen;
int numchunks;
uint64_t h = zn->zn_hash;
valuelen = integer_size * num_integers;
namelen = strlen(name) + 1;
ASSERT(namelen >= 2);
numchunks = 1 + ZAP_LEAF_ARRAY_NCHUNKS(namelen) +
ZAP_LEAF_ARRAY_NCHUNKS(valuelen);
numchunks = 1 + ZAP_LEAF_ARRAY_NCHUNKS(zn->zn_key_orig_numints *
zn->zn_key_intlen) + ZAP_LEAF_ARRAY_NCHUNKS(valuelen);
if (numchunks > ZAP_LEAF_NUMCHUNKS(l))
return (E2BIG);
if (cd == ZAP_MAXCD) {
if (cd == ZAP_NEED_CD) {
/* find the lowest unused cd */
if (l->l_phys->l_hdr.lh_flags & ZLF_ENTRIES_CDSORTED) {
cd = 0;
@@ -585,7 +604,7 @@ zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd,
}
} else {
/* old unsorted format; do it the O(n^2) way */
for (cd = 0; cd < ZAP_MAXCD; cd++) {
for (cd = 0; ; cd++) {
for (chunk = *LEAF_HASH_ENTPTR(l, h);
chunk != CHAIN_END; chunk = le->le_next) {
le = ZAP_LEAF_ENTRY(l, chunk);
@@ -600,10 +619,10 @@ zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd,
}
}
/*
* we would run out of space in a block before we could
* have ZAP_MAXCD entries
* We would run out of space in a block before we could
* store enough entries to run out of CD values.
*/
ASSERT3U(cd, <, ZAP_MAXCD);
ASSERT3U(cd, <, zap_maxcd(zn->zn_zap));
}
if (l->l_phys->l_hdr.lh_nfree < numchunks)
@@ -613,12 +632,13 @@ zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd,
chunk = zap_leaf_chunk_alloc(l);
le = ZAP_LEAF_ENTRY(l, chunk);
le->le_type = ZAP_CHUNK_ENTRY;
le->le_name_chunk = zap_leaf_array_create(l, name, 1, namelen);
le->le_name_length = namelen;
le->le_name_chunk = zap_leaf_array_create(l, zn->zn_key_orig,
zn->zn_key_intlen, zn->zn_key_orig_numints);
le->le_name_numints = zn->zn_key_orig_numints;
le->le_value_chunk =
zap_leaf_array_create(l, buf, integer_size, num_integers);
le->le_value_length = num_integers;
le->le_int_size = integer_size;
le->le_value_numints = num_integers;
le->le_value_intlen = integer_size;
le->le_hash = h;
le->le_cd = cd;
@@ -630,7 +650,7 @@ zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd,
zeh->zeh_leaf = l;
zeh->zeh_num_integers = num_integers;
zeh->zeh_integer_size = le->le_int_size;
zeh->zeh_integer_size = le->le_value_intlen;
zeh->zeh_cd = le->le_cd;
zeh->zeh_hash = le->le_hash;
zeh->zeh_chunkp = chunkp;
@@ -672,7 +692,7 @@ zap_entry_normalization_conflict(zap_entry_handle_t *zeh, zap_name_t *zn,
allocdzn = B_TRUE;
}
if (zap_leaf_array_match(zeh->zeh_leaf, zn,
le->le_name_chunk, le->le_name_length)) {
le->le_name_chunk, le->le_name_numints)) {
if (allocdzn)
zap_name_free(zn);
return (B_TRUE);
@@ -835,9 +855,9 @@ zap_leaf_stats(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs)
struct zap_leaf_entry *le =
ZAP_LEAF_ENTRY(l, chunk);
n = 1 + ZAP_LEAF_ARRAY_NCHUNKS(le->le_name_length) +
ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_length *
le->le_int_size);
n = 1 + ZAP_LEAF_ARRAY_NCHUNKS(le->le_name_numints) +
ZAP_LEAF_ARRAY_NCHUNKS(le->le_value_numints *
le->le_value_intlen);
n = MIN(n, ZAP_HISTOGRAM_SIZE-1);
zs->zs_entries_using_n_chunks[n]++;