/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <sys/zfs_context.h>
* location.
*
* Byteswap implications:
+ *
* Since the SA attributes are not entirely self describing we can't do
* the normal byteswap processing. The special ZAP layout attribute and
* attribute registration attributes define the byteswap function and the
sa_data_op_t action, sa_data_locator_t *locator, void *datastart,
uint16_t buflen, dmu_tx_t *tx);
-arc_byteswap_func_t *sa_bswap_table[] = {
+arc_byteswap_func_t sa_bswap_table[] = {
byteswap_uint64_array,
byteswap_uint32_array,
byteswap_uint16_array,
};
/*
- * ZPL legacy layout
* This is only used for objects of type DMU_OT_ZNODE
*/
sa_attr_type_t sa_legacy_zpl_layout[] = {
/*
* Special dummy layout used for buffers with no attributes.
*/
-
sa_attr_type_t sa_dummy_zpl_layout[] = { 0 };
static int sa_legacy_attr_count = 16;
void *
sa_spill_alloc(int flags)
{
- return kmem_cache_alloc(spill_cache, flags);
+ return (kmem_cache_alloc(spill_cache, flags));
}
void
switch (data_op) {
case SA_LOOKUP:
if (bulk[i].sa_addr == NULL)
- return (ENOENT);
+ return (SET_ERROR(ENOENT));
if (bulk[i].sa_data) {
SA_COPY_DATA(bulk[i].sa_data_func,
bulk[i].sa_addr, bulk[i].sa_data,
blocksize = SPA_MINBLOCKSIZE;
} else if (size > SPA_MAXBLOCKSIZE) {
ASSERT(0);
- return (EFBIG);
+ return (SET_ERROR(EFBIG));
} else {
blocksize = P2ROUNDUP_TYPED(size, SPA_MINBLOCKSIZE, uint32_t);
}
{
int var_size = 0;
int i;
- int j = -1;
int full_space;
int hdrsize;
- boolean_t done = B_FALSE;
+ int extra_hdrsize;
if (buftype == SA_BONUS && sa->sa_force_spill) {
*total = 0;
*index = -1;
*total = 0;
+ *will_spill = B_FALSE;
- if (buftype == SA_BONUS)
- *will_spill = B_FALSE;
-
+ extra_hdrsize = 0;
hdrsize = (SA_BONUSTYPE_FROM_DB(db) == DMU_OT_ZNODE) ? 0 :
sizeof (sa_hdr_phys_t);
*total = P2ROUNDUP(*total, 8);
*total += attr_desc[i].sa_length;
- if (done)
- goto next;
+ if (*will_spill)
+ continue;
is_var_sz = (SA_REGISTERED_LEN(sa, attr_desc[i].sa_attr) == 0);
if (is_var_sz) {
}
if (is_var_sz && var_size > 1) {
- if (P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
+ /*
+ * Don't worry that the spill block might overflow.
+ * It will be resized if needed in sa_build_layouts().
+ */
+ if (buftype == SA_SPILL ||
+ P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
*total < full_space) {
/*
* Account for header space used by array of
* optional sizes of variable-length attributes.
- * Record the index in case this increase needs
- * to be reversed due to spill-over.
+ * Record the extra header size in case this
+ * increase needs to be reversed due to
+ * spill-over.
*/
hdrsize += sizeof (uint16_t);
- j = i;
+ if (*index != -1)
+ extra_hdrsize += sizeof (uint16_t);
} else {
- done = B_TRUE;
- *index = i;
- if (buftype == SA_BONUS)
- *will_spill = B_TRUE;
+ ASSERT(buftype == SA_BONUS);
+ if (*index == -1)
+ *index = i;
+ *will_spill = B_TRUE;
continue;
}
}
(*total + P2ROUNDUP(hdrsize, 8)) >
(full_space - sizeof (blkptr_t))) {
*index = i;
- done = B_TRUE;
}
-next:
if ((*total + P2ROUNDUP(hdrsize, 8)) > full_space &&
buftype == SA_BONUS)
*will_spill = B_TRUE;
}
- /*
- * j holds the index of the last variable-sized attribute for
- * which hdrsize was increased. Reverse the increase if that
- * attribute will be relocated to the spill block.
- */
- if (*will_spill && j == *index)
- hdrsize -= sizeof (uint16_t);
+ if (*will_spill)
+ hdrsize -= extra_hdrsize;
hdrsize = P2ROUNDUP(hdrsize, 8);
return (hdrsize);
int buf_space;
sa_attr_type_t *attrs, *attrs_start;
int i, lot_count;
- int hdrsize, spillhdrsize = 0;
+ int hdrsize;
+ int spillhdrsize = 0;
int used;
dmu_object_type_t bonustype;
sa_lot_t *lot;
SA_BONUS, &i, &used, &spilling);
if (used > SPA_MAXBLOCKSIZE)
- return (EFBIG);
+ return (SET_ERROR(EFBIG));
VERIFY(0 == dmu_set_bonus(hdl->sa_bonus, spilling ?
MIN(DN_MAX_BONUSLEN - sizeof (blkptr_t), used + hdrsize) :
&spill_used, &dummy);
if (spill_used > SPA_MAXBLOCKSIZE)
- return (EFBIG);
+ return (SET_ERROR(EFBIG));
buf_space = hdl->sa_spill->db_size - spillhdrsize;
if (BUF_SPACE_NEEDED(spill_used, spillhdrsize) >
*/
if (error || (error == 0 && sa_attr_count == 0)) {
if (error == 0)
- error = EINVAL;
+ error = SET_ERROR(EINVAL);
goto bail;
}
sa_reg_count = sa_attr_count;
error = zap_lookup(os, sa->sa_reg_attr_obj,
reg_attrs[i].sa_name, 8, 1, &attr_value);
else
- error = ENOENT;
+ error = SET_ERROR(ENOENT);
switch (error) {
case ENOENT:
sa->sa_user_table[i] = (sa_attr_type_t)sa_attr_count;
sa_attr_type_t *tb;
int error;
- mutex_enter(&os->os_lock);
+ mutex_enter(&os->os_user_ptr_lock);
if (os->os_sa) {
mutex_enter(&os->os_sa->sa_lock);
- mutex_exit(&os->os_lock);
+ mutex_exit(&os->os_user_ptr_lock);
tb = os->os_sa->sa_user_table;
mutex_exit(&os->os_sa->sa_lock);
*user_table = tb;
os->os_sa = sa;
mutex_enter(&sa->sa_lock);
- mutex_exit(&os->os_lock);
+ mutex_exit(&os->os_user_ptr_lock);
avl_create(&sa->sa_layout_num_tree, layout_num_compare,
sizeof (sa_lot_t), offsetof(sa_lot_t, lot_num_node));
avl_create(&sa->sa_layout_hash_tree, layout_hash_compare,
*/
if (error || (error == 0 && layout_count == 0)) {
if (error == 0)
- error = EINVAL;
+ error = SET_ERROR(EINVAL);
goto fail;
}
sa_free_attr_table(sa);
cookie = NULL;
- while ((layout = avl_destroy_nodes(&sa->sa_layout_hash_tree, &cookie))){
+ while ((layout =
+ avl_destroy_nodes(&sa->sa_layout_hash_tree, &cookie))) {
sa_idx_tab_t *tab;
while ((tab = list_head(&layout->lot_idx_tab))) {
ASSERT(refcount_count(&tab->sa_refcount));
}
cookie = NULL;
- while ((layout = avl_destroy_nodes(&sa->sa_layout_num_tree, &cookie))){
+ while ((layout = avl_destroy_nodes(&sa->sa_layout_num_tree, &cookie))) {
kmem_free(layout->lot_attrs,
sizeof (sa_attr_type_t) * layout->lot_attr_count);
kmem_free(layout, sizeof (sa_lot_t));