mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-25 03:37:45 +03:00
Update core ZFS code from build 121 to build 141.
This commit is contained in:
+94
-74
@@ -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]++;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user