Home | History | Annotate | Line # | Download | only in zfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
     24  * Portions Copyright 2011 iXsystems, Inc
     25  * Copyright (c) 2013, 2016 by Delphix. All rights reserved.
     26  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
     27  * Copyright (c) 2014 Integros [integros.com]
     28  */
     29 
     30 #include <sys/zfs_context.h>
     31 #include <sys/types.h>
     32 #include <sys/param.h>
     33 #include <sys/systm.h>
     34 #include <sys/sysmacros.h>
     35 #include <sys/dmu.h>
     36 #include <sys/dmu_impl.h>
     37 #include <sys/dmu_objset.h>
     38 #include <sys/dbuf.h>
     39 #include <sys/dnode.h>
     40 #include <sys/zap.h>
     41 #include <sys/sa.h>
     42 #include <sys/sunddi.h>
     43 #include <sys/sa_impl.h>
     44 #include <sys/dnode.h>
     45 #include <sys/errno.h>
     46 #include <sys/zfs_context.h>
     47 
     48 /*
     49  * ZFS System attributes:
     50  *
     51  * A generic mechanism to allow for arbitrary attributes
     52  * to be stored in a dnode.  The data will be stored in the bonus buffer of
     53  * the dnode and if necessary a special "spill" block will be used to handle
     54  * overflow situations.  The spill block will be sized to fit the data
     55  * from 512 - 128K.  When a spill block is used the BP (blkptr_t) for the
     56  * spill block is stored at the end of the current bonus buffer.  Any
     57  * attributes that would be in the way of the blkptr_t will be relocated
     58  * into the spill block.
     59  *
     60  * Attribute registration:
     61  *
     62  * Stored persistently on a per dataset basis
     63  * a mapping between attribute "string" names and their actual attribute
     64  * numeric values, length, and byteswap function.  The names are only used
     65  * during registration.  All  attributes are known by their unique attribute
     66  * id value.  If an attribute can have a variable size then the value
     67  * 0 will be used to indicate this.
     68  *
     69  * Attribute Layout:
     70  *
     71  * Attribute layouts are a way to compactly store multiple attributes, but
     72  * without taking the overhead associated with managing each attribute
     73  * individually.  Since you will typically have the same set of attributes
     74  * stored in the same order a single table will be used to represent that
     75  * layout.  The ZPL for example will usually have only about 10 different
     76  * layouts (regular files, device files, symlinks,
     77  * regular files + scanstamp, files/dir with extended attributes, and then
     78  * you have the possibility of all of those minus ACL, because it would
     79  * be kicked out into the spill block)
     80  *
     81  * Layouts are simply an array of the attributes and their
     82  * ordering i.e. [0, 1, 4, 5, 2]
     83  *
     84  * Each distinct layout is given a unique layout number and that is whats
     85  * stored in the header at the beginning of the SA data buffer.
     86  *
     87  * A layout only covers a single dbuf (bonus or spill).  If a set of
     88  * attributes is split up between the bonus buffer and a spill buffer then
     89  * two different layouts will be used.  This allows us to byteswap the
     90  * spill without looking at the bonus buffer and keeps the on disk format of
     91  * the bonus and spill buffer the same.
     92  *
     93  * Adding a single attribute will cause the entire set of attributes to
     94  * be rewritten and could result in a new layout number being constructed
     95  * as part of the rewrite if no such layout exists for the new set of
     96  * attribues.  The new attribute will be appended to the end of the already
     97  * existing attributes.
     98  *
     99  * Both the attribute registration and attribute layout information are
    100  * stored in normal ZAP attributes.  Their should be a small number of
    101  * known layouts and the set of attributes is assumed to typically be quite
    102  * small.
    103  *
    104  * The registered attributes and layout "table" information is maintained
    105  * in core and a special "sa_os_t" is attached to the objset_t.
    106  *
    107  * A special interface is provided to allow for quickly applying
    108  * a large set of attributes at once.  sa_replace_all_by_template() is
    109  * used to set an array of attributes.  This is used by the ZPL when
    110  * creating a brand new file.  The template that is passed into the function
    111  * specifies the attribute, size for variable length attributes, location of
    112  * data and special "data locator" function if the data isn't in a contiguous
    113  * location.
    114  *
    115  * Byteswap implications:
    116  *
    117  * Since the SA attributes are not entirely self describing we can't do
    118  * the normal byteswap processing.  The special ZAP layout attribute and
    119  * attribute registration attributes define the byteswap function and the
    120  * size of the attributes, unless it is variable sized.
    121  * The normal ZFS byteswapping infrastructure assumes you don't need
    122  * to read any objects in order to do the necessary byteswapping.  Whereas
    123  * SA attributes can only be properly byteswapped if the dataset is opened
    124  * and the layout/attribute ZAP attributes are available.  Because of this
    125  * the SA attributes will be byteswapped when they are first accessed by
    126  * the SA code that will read the SA data.
    127  */
    128 
    129 typedef void (sa_iterfunc_t)(void *hdr, void *addr, sa_attr_type_t,
    130     uint16_t length, int length_idx, boolean_t, void *userp);
    131 
    132 static int sa_build_index(sa_handle_t *hdl, sa_buf_type_t buftype);
    133 static void sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab);
    134 static void *sa_find_idx_tab(objset_t *os, dmu_object_type_t bonustype,
    135     void *data);
    136 static void sa_idx_tab_rele(objset_t *os, void *arg);
    137 static void sa_copy_data(sa_data_locator_t *func, void *start, void *target,
    138     int buflen);
    139 static int sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
    140     sa_data_op_t action, sa_data_locator_t *locator, void *datastart,
    141     uint16_t buflen, dmu_tx_t *tx);
    142 
    143 arc_byteswap_func_t *sa_bswap_table[] = {
    144 	byteswap_uint64_array,
    145 	byteswap_uint32_array,
    146 	byteswap_uint16_array,
    147 	byteswap_uint8_array,
    148 	zfs_acl_byteswap,
    149 };
    150 
    151 #define	SA_COPY_DATA(f, s, t, l) \
    152 	{ \
    153 		if (f == NULL) { \
    154 			if (l == 8) { \
    155 				*(uint64_t *)t = *(uint64_t *)s; \
    156 			} else if (l == 16) { \
    157 				*(uint64_t *)t = *(uint64_t *)s; \
    158 				*(uint64_t *)((uintptr_t)t + 8) = \
    159 				    *(uint64_t *)((uintptr_t)s + 8); \
    160 			} else { \
    161 				bcopy(s, t, l); \
    162 			} \
    163 		} else \
    164 			sa_copy_data(f, s, t, l); \
    165 	}
    166 
    167 /*
    168  * This table is fixed and cannot be changed.  Its purpose is to
    169  * allow the SA code to work with both old/new ZPL file systems.
    170  * It contains the list of legacy attributes.  These attributes aren't
    171  * stored in the "attribute" registry zap objects, since older ZPL file systems
    172  * won't have the registry.  Only objsets of type ZFS_TYPE_FILESYSTEM will
    173  * use this static table.
    174  */
    175 sa_attr_reg_t sa_legacy_attrs[] = {
    176 	{"ZPL_ATIME", sizeof (uint64_t) * 2, SA_UINT64_ARRAY, 0},
    177 	{"ZPL_MTIME", sizeof (uint64_t) * 2, SA_UINT64_ARRAY, 1},
    178 	{"ZPL_CTIME", sizeof (uint64_t) * 2, SA_UINT64_ARRAY, 2},
    179 	{"ZPL_CRTIME", sizeof (uint64_t) * 2, SA_UINT64_ARRAY, 3},
    180 	{"ZPL_GEN", sizeof (uint64_t), SA_UINT64_ARRAY, 4},
    181 	{"ZPL_MODE", sizeof (uint64_t), SA_UINT64_ARRAY, 5},
    182 	{"ZPL_SIZE", sizeof (uint64_t), SA_UINT64_ARRAY, 6},
    183 	{"ZPL_PARENT", sizeof (uint64_t), SA_UINT64_ARRAY, 7},
    184 	{"ZPL_LINKS", sizeof (uint64_t), SA_UINT64_ARRAY, 8},
    185 	{"ZPL_XATTR", sizeof (uint64_t), SA_UINT64_ARRAY, 9},
    186 	{"ZPL_RDEV", sizeof (uint64_t), SA_UINT64_ARRAY, 10},
    187 	{"ZPL_FLAGS", sizeof (uint64_t), SA_UINT64_ARRAY, 11},
    188 	{"ZPL_UID", sizeof (uint64_t), SA_UINT64_ARRAY, 12},
    189 	{"ZPL_GID", sizeof (uint64_t), SA_UINT64_ARRAY, 13},
    190 	{"ZPL_PAD", sizeof (uint64_t) * 4, SA_UINT64_ARRAY, 14},
    191 	{"ZPL_ZNODE_ACL", 88, SA_UINT8_ARRAY, 15},
    192 };
    193 
    194 /*
    195  * This is only used for objects of type DMU_OT_ZNODE
    196  */
    197 sa_attr_type_t sa_legacy_zpl_layout[] = {
    198     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
    199 };
    200 
    201 /*
    202  * Special dummy layout used for buffers with no attributes.
    203  */
    204 sa_attr_type_t sa_dummy_zpl_layout[] = { 0 };
    205 
    206 static int sa_legacy_attr_count = 16;
    207 static kmem_cache_t *sa_cache = NULL;
    208 
    209 /*ARGSUSED*/
    210 static int
    211 sa_cache_constructor(void *buf, void *unused, int kmflag)
    212 {
    213 	sa_handle_t *hdl = buf;
    214 
    215 	mutex_init(&hdl->sa_lock, NULL, MUTEX_DEFAULT, NULL);
    216 	return (0);
    217 }
    218 
    219 /*ARGSUSED*/
    220 static void
    221 sa_cache_destructor(void *buf, void *unused)
    222 {
    223 	sa_handle_t *hdl = buf;
    224 
    225 	mutex_destroy(&hdl->sa_lock);
    226 }
    227 
    228 void
    229 sa_cache_init(void)
    230 {
    231 	sa_cache = kmem_cache_create("sa_cache",
    232 	    sizeof (sa_handle_t), 0, sa_cache_constructor,
    233 	    sa_cache_destructor, NULL, NULL, NULL, 0);
    234 }
    235 
    236 void
    237 sa_cache_fini(void)
    238 {
    239 	if (sa_cache)
    240 		kmem_cache_destroy(sa_cache);
    241 }
    242 
    243 static int
    244 layout_num_compare(const void *arg1, const void *arg2)
    245 {
    246 	const sa_lot_t *node1 = arg1;
    247 	const sa_lot_t *node2 = arg2;
    248 
    249 	if (node1->lot_num > node2->lot_num)
    250 		return (1);
    251 	else if (node1->lot_num < node2->lot_num)
    252 		return (-1);
    253 	return (0);
    254 }
    255 
    256 static int
    257 layout_hash_compare(const void *arg1, const void *arg2)
    258 {
    259 	const sa_lot_t *node1 = arg1;
    260 	const sa_lot_t *node2 = arg2;
    261 
    262 	if (node1->lot_hash > node2->lot_hash)
    263 		return (1);
    264 	if (node1->lot_hash < node2->lot_hash)
    265 		return (-1);
    266 	if (node1->lot_instance > node2->lot_instance)
    267 		return (1);
    268 	if (node1->lot_instance < node2->lot_instance)
    269 		return (-1);
    270 	return (0);
    271 }
    272 
    273 boolean_t
    274 sa_layout_equal(sa_lot_t *tbf, sa_attr_type_t *attrs, int count)
    275 {
    276 	int i;
    277 
    278 	if (count != tbf->lot_attr_count)
    279 		return (1);
    280 
    281 	for (i = 0; i != count; i++) {
    282 		if (attrs[i] != tbf->lot_attrs[i])
    283 			return (1);
    284 	}
    285 	return (0);
    286 }
    287 
    288 #define	SA_ATTR_HASH(attr) (zfs_crc64_table[(-1ULL ^ attr) & 0xFF])
    289 
    290 static uint64_t
    291 sa_layout_info_hash(sa_attr_type_t *attrs, int attr_count)
    292 {
    293 	int i;
    294 	uint64_t crc = -1ULL;
    295 
    296 	for (i = 0; i != attr_count; i++)
    297 		crc ^= SA_ATTR_HASH(attrs[i]);
    298 
    299 	return (crc);
    300 }
    301 
    302 static int
    303 sa_get_spill(sa_handle_t *hdl)
    304 {
    305 	int rc;
    306 	if (hdl->sa_spill == NULL) {
    307 		if ((rc = dmu_spill_hold_existing(hdl->sa_bonus, NULL,
    308 		    &hdl->sa_spill)) == 0)
    309 			VERIFY(0 == sa_build_index(hdl, SA_SPILL));
    310 	} else {
    311 		rc = 0;
    312 	}
    313 
    314 	return (rc);
    315 }
    316 
    317 /*
    318  * Main attribute lookup/update function
    319  * returns 0 for success or non zero for failures
    320  *
    321  * Operates on bulk array, first failure will abort further processing
    322  */
    323 int
    324 sa_attr_op(sa_handle_t *hdl, sa_bulk_attr_t *bulk, int count,
    325     sa_data_op_t data_op, dmu_tx_t *tx)
    326 {
    327 	sa_os_t *sa = hdl->sa_os->os_sa;
    328 	int i;
    329 	int error = 0;
    330 	sa_buf_type_t buftypes;
    331 
    332 	buftypes = 0;
    333 
    334 	ASSERT(count > 0);
    335 	for (i = 0; i != count; i++) {
    336 		ASSERT(bulk[i].sa_attr <= hdl->sa_os->os_sa->sa_num_attrs);
    337 
    338 		bulk[i].sa_addr = NULL;
    339 		/* First check the bonus buffer */
    340 
    341 		if (hdl->sa_bonus_tab && TOC_ATTR_PRESENT(
    342 		    hdl->sa_bonus_tab->sa_idx_tab[bulk[i].sa_attr])) {
    343 			SA_ATTR_INFO(sa, hdl->sa_bonus_tab,
    344 			    SA_GET_HDR(hdl, SA_BONUS),
    345 			    bulk[i].sa_attr, bulk[i], SA_BONUS, hdl);
    346 			if (tx && !(buftypes & SA_BONUS)) {
    347 				dmu_buf_will_dirty(hdl->sa_bonus, tx);
    348 				buftypes |= SA_BONUS;
    349 			}
    350 		}
    351 		if (bulk[i].sa_addr == NULL &&
    352 		    ((error = sa_get_spill(hdl)) == 0)) {
    353 			if (TOC_ATTR_PRESENT(
    354 			    hdl->sa_spill_tab->sa_idx_tab[bulk[i].sa_attr])) {
    355 				SA_ATTR_INFO(sa, hdl->sa_spill_tab,
    356 				    SA_GET_HDR(hdl, SA_SPILL),
    357 				    bulk[i].sa_attr, bulk[i], SA_SPILL, hdl);
    358 				if (tx && !(buftypes & SA_SPILL) &&
    359 				    bulk[i].sa_size == bulk[i].sa_length) {
    360 					dmu_buf_will_dirty(hdl->sa_spill, tx);
    361 					buftypes |= SA_SPILL;
    362 				}
    363 			}
    364 		}
    365 		if (error && error != ENOENT) {
    366 			return ((error == ECKSUM) ? EIO : error);
    367 		}
    368 
    369 		switch (data_op) {
    370 		case SA_LOOKUP:
    371 			if (bulk[i].sa_addr == NULL)
    372 				return (SET_ERROR(ENOENT));
    373 			if (bulk[i].sa_data) {
    374 				SA_COPY_DATA(bulk[i].sa_data_func,
    375 				    bulk[i].sa_addr, bulk[i].sa_data,
    376 				    bulk[i].sa_size);
    377 			}
    378 			continue;
    379 
    380 		case SA_UPDATE:
    381 			/* existing rewrite of attr */
    382 			if (bulk[i].sa_addr &&
    383 			    bulk[i].sa_size == bulk[i].sa_length) {
    384 				SA_COPY_DATA(bulk[i].sa_data_func,
    385 				    bulk[i].sa_data, bulk[i].sa_addr,
    386 				    bulk[i].sa_length);
    387 				continue;
    388 			} else if (bulk[i].sa_addr) { /* attr size change */
    389 				error = sa_modify_attrs(hdl, bulk[i].sa_attr,
    390 				    SA_REPLACE, bulk[i].sa_data_func,
    391 				    bulk[i].sa_data, bulk[i].sa_length, tx);
    392 			} else { /* adding new attribute */
    393 				error = sa_modify_attrs(hdl, bulk[i].sa_attr,
    394 				    SA_ADD, bulk[i].sa_data_func,
    395 				    bulk[i].sa_data, bulk[i].sa_length, tx);
    396 			}
    397 			if (error)
    398 				return (error);
    399 			break;
    400 		}
    401 	}
    402 	return (error);
    403 }
    404 
    405 static sa_lot_t *
    406 sa_add_layout_entry(objset_t *os, sa_attr_type_t *attrs, int attr_count,
    407     uint64_t lot_num, uint64_t hash, boolean_t zapadd, dmu_tx_t *tx)
    408 {
    409 	sa_os_t *sa = os->os_sa;
    410 	sa_lot_t *tb, *findtb;
    411 	int i;
    412 	avl_index_t loc;
    413 
    414 	ASSERT(MUTEX_HELD(&sa->sa_lock));
    415 	tb = kmem_zalloc(sizeof (sa_lot_t), KM_SLEEP);
    416 	tb->lot_attr_count = attr_count;
    417 #ifdef __NetBSD__
    418 	if (attr_count != 0)
    419 #endif
    420 	tb->lot_attrs = kmem_alloc(sizeof (sa_attr_type_t) * attr_count,
    421 	    KM_SLEEP);
    422 	bcopy(attrs, tb->lot_attrs, sizeof (sa_attr_type_t) * attr_count);
    423 	tb->lot_num = lot_num;
    424 	tb->lot_hash = hash;
    425 	tb->lot_instance = 0;
    426 
    427 	if (zapadd) {
    428 		char attr_name[8];
    429 
    430 		if (sa->sa_layout_attr_obj == 0) {
    431 			sa->sa_layout_attr_obj = zap_create_link(os,
    432 			    DMU_OT_SA_ATTR_LAYOUTS,
    433 			    sa->sa_master_obj, SA_LAYOUTS, tx);
    434 		}
    435 
    436 		(void) snprintf(attr_name, sizeof (attr_name),
    437 		    "%d", (int)lot_num);
    438 		VERIFY(0 == zap_update(os, os->os_sa->sa_layout_attr_obj,
    439 		    attr_name, 2, attr_count, attrs, tx));
    440 	}
    441 
    442 	list_create(&tb->lot_idx_tab, sizeof (sa_idx_tab_t),
    443 	    offsetof(sa_idx_tab_t, sa_next));
    444 
    445 	for (i = 0; i != attr_count; i++) {
    446 		if (sa->sa_attr_table[tb->lot_attrs[i]].sa_length == 0)
    447 			tb->lot_var_sizes++;
    448 	}
    449 
    450 	avl_add(&sa->sa_layout_num_tree, tb);
    451 
    452 	/* verify we don't have a hash collision */
    453 	if ((findtb = avl_find(&sa->sa_layout_hash_tree, tb, &loc)) != NULL) {
    454 		for (; findtb && findtb->lot_hash == hash;
    455 		    findtb = AVL_NEXT(&sa->sa_layout_hash_tree, findtb)) {
    456 			if (findtb->lot_instance != tb->lot_instance)
    457 				break;
    458 			tb->lot_instance++;
    459 		}
    460 	}
    461 	avl_add(&sa->sa_layout_hash_tree, tb);
    462 	return (tb);
    463 }
    464 
    465 static void
    466 sa_find_layout(objset_t *os, uint64_t hash, sa_attr_type_t *attrs,
    467     int count, dmu_tx_t *tx, sa_lot_t **lot)
    468 {
    469 	sa_lot_t *tb, tbsearch;
    470 	avl_index_t loc;
    471 	sa_os_t *sa = os->os_sa;
    472 	boolean_t found = B_FALSE;
    473 
    474 	mutex_enter(&sa->sa_lock);
    475 	tbsearch.lot_hash = hash;
    476 	tbsearch.lot_instance = 0;
    477 	tb = avl_find(&sa->sa_layout_hash_tree, &tbsearch, &loc);
    478 	if (tb) {
    479 		for (; tb && tb->lot_hash == hash;
    480 		    tb = AVL_NEXT(&sa->sa_layout_hash_tree, tb)) {
    481 			if (sa_layout_equal(tb, attrs, count) == 0) {
    482 				found = B_TRUE;
    483 				break;
    484 			}
    485 		}
    486 	}
    487 	if (!found) {
    488 		tb = sa_add_layout_entry(os, attrs, count,
    489 		    avl_numnodes(&sa->sa_layout_num_tree), hash, B_TRUE, tx);
    490 	}
    491 	mutex_exit(&sa->sa_lock);
    492 	*lot = tb;
    493 }
    494 
    495 static int
    496 sa_resize_spill(sa_handle_t *hdl, uint32_t size, dmu_tx_t *tx)
    497 {
    498 	int error;
    499 	uint32_t blocksize;
    500 
    501 	if (size == 0) {
    502 		blocksize = SPA_MINBLOCKSIZE;
    503 	} else if (size > SPA_OLD_MAXBLOCKSIZE) {
    504 		ASSERT(0);
    505 		return (SET_ERROR(EFBIG));
    506 	} else {
    507 		blocksize = P2ROUNDUP_TYPED(size, SPA_MINBLOCKSIZE, uint32_t);
    508 	}
    509 
    510 	error = dbuf_spill_set_blksz(hdl->sa_spill, blocksize, tx);
    511 	ASSERT(error == 0);
    512 	return (error);
    513 }
    514 
    515 static void
    516 sa_copy_data(sa_data_locator_t *func, void *datastart, void *target, int buflen)
    517 {
    518 	if (func == NULL) {
    519 		bcopy(datastart, target, buflen);
    520 	} else {
    521 		boolean_t start;
    522 		int bytes;
    523 		void *dataptr;
    524 		void *saptr = target;
    525 		uint32_t length;
    526 
    527 		start = B_TRUE;
    528 		bytes = 0;
    529 		while (bytes < buflen) {
    530 			func(&dataptr, &length, buflen, start, datastart);
    531 			bcopy(dataptr, saptr, length);
    532 			saptr = (void *)((caddr_t)saptr + length);
    533 			bytes += length;
    534 			start = B_FALSE;
    535 		}
    536 	}
    537 }
    538 
    539 /*
    540  * Determine several different sizes
    541  * first the sa header size
    542  * the number of bytes to be stored
    543  * if spill would occur the index in the attribute array is returned
    544  *
    545  * the boolean will_spill will be set when spilling is necessary.  It
    546  * is only set when the buftype is SA_BONUS
    547  */
    548 static int
    549 sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
    550     dmu_buf_t *db, sa_buf_type_t buftype, int *index, int *total,
    551     boolean_t *will_spill)
    552 {
    553 	int var_size = 0;
    554 	int i;
    555 	int full_space;
    556 	int hdrsize;
    557 	int extra_hdrsize;
    558 
    559 	if (buftype == SA_BONUS && sa->sa_force_spill) {
    560 		*total = 0;
    561 		*index = 0;
    562 		*will_spill = B_TRUE;
    563 		return (0);
    564 	}
    565 
    566 	*index = -1;
    567 	*total = 0;
    568 	*will_spill = B_FALSE;
    569 
    570 	extra_hdrsize = 0;
    571 	hdrsize = (SA_BONUSTYPE_FROM_DB(db) == DMU_OT_ZNODE) ? 0 :
    572 	    sizeof (sa_hdr_phys_t);
    573 
    574 	full_space = (buftype == SA_BONUS) ? DN_MAX_BONUSLEN : db->db_size;
    575 	ASSERT(IS_P2ALIGNED(full_space, 8));
    576 
    577 	for (i = 0; i != attr_count; i++) {
    578 		boolean_t is_var_sz;
    579 
    580 		*total = P2ROUNDUP(*total, 8);
    581 		*total += attr_desc[i].sa_length;
    582 		if (*will_spill)
    583 			continue;
    584 
    585 		is_var_sz = (SA_REGISTERED_LEN(sa, attr_desc[i].sa_attr) == 0);
    586 		if (is_var_sz) {
    587 			var_size++;
    588 		}
    589 
    590 		if (is_var_sz && var_size > 1) {
    591 			/*
    592 			 * Don't worry that the spill block might overflow.
    593 			 * It will be resized if needed in sa_build_layouts().
    594 			 */
    595 			if (buftype == SA_SPILL ||
    596 			    P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
    597 			    *total < full_space) {
    598 				/*
    599 				 * Account for header space used by array of
    600 				 * optional sizes of variable-length attributes.
    601 				 * Record the extra header size in case this
    602 				 * increase needs to be reversed due to
    603 				 * spill-over.
    604 				 */
    605 				hdrsize += sizeof (uint16_t);
    606 				if (*index != -1)
    607 					extra_hdrsize += sizeof (uint16_t);
    608 			} else {
    609 				ASSERT(buftype == SA_BONUS);
    610 				if (*index == -1)
    611 					*index = i;
    612 				*will_spill = B_TRUE;
    613 				continue;
    614 			}
    615 		}
    616 
    617 		/*
    618 		 * find index of where spill *could* occur.
    619 		 * Then continue to count of remainder attribute
    620 		 * space.  The sum is used later for sizing bonus
    621 		 * and spill buffer.
    622 		 */
    623 		if (buftype == SA_BONUS && *index == -1 &&
    624 		    (*total + P2ROUNDUP(hdrsize, 8)) >
    625 		    (full_space - sizeof (blkptr_t))) {
    626 			*index = i;
    627 		}
    628 
    629 		if ((*total + P2ROUNDUP(hdrsize, 8)) > full_space &&
    630 		    buftype == SA_BONUS)
    631 			*will_spill = B_TRUE;
    632 	}
    633 
    634 	if (*will_spill)
    635 		hdrsize -= extra_hdrsize;
    636 
    637 	hdrsize = P2ROUNDUP(hdrsize, 8);
    638 	return (hdrsize);
    639 }
    640 
    641 #define	BUF_SPACE_NEEDED(total, header) (total + header)
    642 
    643 /*
    644  * Find layout that corresponds to ordering of attributes
    645  * If not found a new layout number is created and added to
    646  * persistent layout tables.
    647  */
    648 static int
    649 sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
    650     dmu_tx_t *tx)
    651 {
    652 	sa_os_t *sa = hdl->sa_os->os_sa;
    653 	uint64_t hash;
    654 	sa_buf_type_t buftype;
    655 	sa_hdr_phys_t *sahdr;
    656 	void *data_start;
    657 	int buf_space;
    658 	sa_attr_type_t *attrs, *attrs_start;
    659 	int i, lot_count;
    660 	int hdrsize;
    661 	int spillhdrsize = 0;
    662 	int used;
    663 	dmu_object_type_t bonustype;
    664 	sa_lot_t *lot;
    665 	int len_idx;
    666 	int spill_used;
    667 	boolean_t spilling;
    668 
    669 	dmu_buf_will_dirty(hdl->sa_bonus, tx);
    670 	bonustype = SA_BONUSTYPE_FROM_DB(hdl->sa_bonus);
    671 
    672 	/* first determine bonus header size and sum of all attributes */
    673 	hdrsize = sa_find_sizes(sa, attr_desc, attr_count, hdl->sa_bonus,
    674 	    SA_BONUS, &i, &used, &spilling);
    675 
    676 	if (used > SPA_OLD_MAXBLOCKSIZE)
    677 		return (SET_ERROR(EFBIG));
    678 
    679 	VERIFY(0 == dmu_set_bonus(hdl->sa_bonus, spilling ?
    680 	    MIN(DN_MAX_BONUSLEN - sizeof (blkptr_t), used + hdrsize) :
    681 	    used + hdrsize, tx));
    682 
    683 	ASSERT((bonustype == DMU_OT_ZNODE && spilling == 0) ||
    684 	    bonustype == DMU_OT_SA);
    685 
    686 	/* setup and size spill buffer when needed */
    687 	if (spilling) {
    688 		boolean_t dummy;
    689 
    690 		if (hdl->sa_spill == NULL) {
    691 			VERIFY(dmu_spill_hold_by_bonus(hdl->sa_bonus, NULL,
    692 			    &hdl->sa_spill) == 0);
    693 		}
    694 		dmu_buf_will_dirty(hdl->sa_spill, tx);
    695 
    696 		spillhdrsize = sa_find_sizes(sa, &attr_desc[i],
    697 		    attr_count - i, hdl->sa_spill, SA_SPILL, &i,
    698 		    &spill_used, &dummy);
    699 
    700 		if (spill_used > SPA_OLD_MAXBLOCKSIZE)
    701 			return (SET_ERROR(EFBIG));
    702 
    703 		buf_space = hdl->sa_spill->db_size - spillhdrsize;
    704 		if (BUF_SPACE_NEEDED(spill_used, spillhdrsize) >
    705 		    hdl->sa_spill->db_size)
    706 			VERIFY(0 == sa_resize_spill(hdl,
    707 			    BUF_SPACE_NEEDED(spill_used, spillhdrsize), tx));
    708 	}
    709 
    710 	/* setup starting pointers to lay down data */
    711 	data_start = (void *)((uintptr_t)hdl->sa_bonus->db_data + hdrsize);
    712 	sahdr = (sa_hdr_phys_t *)hdl->sa_bonus->db_data;
    713 	buftype = SA_BONUS;
    714 
    715 	if (spilling)
    716 		buf_space = (sa->sa_force_spill) ?
    717 		    0 : SA_BLKPTR_SPACE - hdrsize;
    718 	else
    719 		buf_space = hdl->sa_bonus->db_size - hdrsize;
    720 
    721 	attrs_start = attrs = kmem_alloc(sizeof (sa_attr_type_t) * attr_count,
    722 	    KM_SLEEP);
    723 	lot_count = 0;
    724 
    725 	for (i = 0, len_idx = 0, hash = -1ULL; i != attr_count; i++) {
    726 		uint16_t length;
    727 
    728 		ASSERT(IS_P2ALIGNED(data_start, 8));
    729 		ASSERT(IS_P2ALIGNED(buf_space, 8));
    730 		attrs[i] = attr_desc[i].sa_attr;
    731 		length = SA_REGISTERED_LEN(sa, attrs[i]);
    732 		if (length == 0)
    733 			length = attr_desc[i].sa_length;
    734 		else
    735 			VERIFY(length == attr_desc[i].sa_length);
    736 
    737 		if (buf_space < length) {  /* switch to spill buffer */
    738 			VERIFY(spilling);
    739 			VERIFY(bonustype == DMU_OT_SA);
    740 			if (buftype == SA_BONUS && !sa->sa_force_spill) {
    741 				sa_find_layout(hdl->sa_os, hash, attrs_start,
    742 				    lot_count, tx, &lot);
    743 				SA_SET_HDR(sahdr, lot->lot_num, hdrsize);
    744 			}
    745 
    746 			buftype = SA_SPILL;
    747 			hash = -1ULL;
    748 			len_idx = 0;
    749 
    750 			sahdr = (sa_hdr_phys_t *)hdl->sa_spill->db_data;
    751 			sahdr->sa_magic = SA_MAGIC;
    752 			data_start = (void *)((uintptr_t)sahdr +
    753 			    spillhdrsize);
    754 			attrs_start = &attrs[i];
    755 			buf_space = hdl->sa_spill->db_size - spillhdrsize;
    756 			lot_count = 0;
    757 		}
    758 		hash ^= SA_ATTR_HASH(attrs[i]);
    759 		attr_desc[i].sa_addr = data_start;
    760 		attr_desc[i].sa_size = length;
    761 		SA_COPY_DATA(attr_desc[i].sa_data_func, attr_desc[i].sa_data,
    762 		    data_start, length);
    763 		if (sa->sa_attr_table[attrs[i]].sa_length == 0) {
    764 			sahdr->sa_lengths[len_idx++] = length;
    765 		}
    766 		VERIFY((uintptr_t)data_start % 8 == 0);
    767 		data_start = (void *)P2ROUNDUP(((uintptr_t)data_start +
    768 		    length), 8);
    769 		buf_space -= P2ROUNDUP(length, 8);
    770 		lot_count++;
    771 	}
    772 
    773 	sa_find_layout(hdl->sa_os, hash, attrs_start, lot_count, tx, &lot);
    774 
    775 	/*
    776 	 * Verify that old znodes always have layout number 0.
    777 	 * Must be DMU_OT_SA for arbitrary layouts
    778 	 */
    779 	VERIFY((bonustype == DMU_OT_ZNODE && lot->lot_num == 0) ||
    780 	    (bonustype == DMU_OT_SA && lot->lot_num > 1));
    781 
    782 	if (bonustype == DMU_OT_SA) {
    783 		SA_SET_HDR(sahdr, lot->lot_num,
    784 		    buftype == SA_BONUS ? hdrsize : spillhdrsize);
    785 	}
    786 
    787 	kmem_free(attrs, sizeof (sa_attr_type_t) * attr_count);
    788 	if (hdl->sa_bonus_tab) {
    789 		sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab);
    790 		hdl->sa_bonus_tab = NULL;
    791 	}
    792 	if (!sa->sa_force_spill)
    793 		VERIFY(0 == sa_build_index(hdl, SA_BONUS));
    794 	if (hdl->sa_spill) {
    795 		sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab);
    796 		if (!spilling) {
    797 			/*
    798 			 * remove spill block that is no longer needed.
    799 			 */
    800 			dmu_buf_rele(hdl->sa_spill, NULL);
    801 			hdl->sa_spill = NULL;
    802 			hdl->sa_spill_tab = NULL;
    803 			VERIFY(0 == dmu_rm_spill(hdl->sa_os,
    804 			    sa_handle_object(hdl), tx));
    805 		} else {
    806 			VERIFY(0 == sa_build_index(hdl, SA_SPILL));
    807 		}
    808 	}
    809 
    810 	return (0);
    811 }
    812 
    813 static void
    814 sa_free_attr_table(sa_os_t *sa)
    815 {
    816 	int i;
    817 
    818 	if (sa->sa_attr_table == NULL)
    819 		return;
    820 
    821 	for (i = 0; i != sa->sa_num_attrs; i++) {
    822 		if (sa->sa_attr_table[i].sa_name)
    823 			kmem_free(sa->sa_attr_table[i].sa_name,
    824 			    strlen(sa->sa_attr_table[i].sa_name) + 1);
    825 	}
    826 
    827 	kmem_free(sa->sa_attr_table,
    828 	    sizeof (sa_attr_table_t) * sa->sa_num_attrs);
    829 
    830 	sa->sa_attr_table = NULL;
    831 }
    832 
    833 static int
    834 sa_attr_table_setup(objset_t *os, sa_attr_reg_t *reg_attrs, int count)
    835 {
    836 	sa_os_t *sa = os->os_sa;
    837 	uint64_t sa_attr_count = 0;
    838 	uint64_t sa_reg_count = 0;
    839 	int error = 0;
    840 	uint64_t attr_value;
    841 	sa_attr_table_t *tb;
    842 	zap_cursor_t zc;
    843 	zap_attribute_t za;
    844 	int registered_count = 0;
    845 	int i;
    846 	dmu_objset_type_t ostype = dmu_objset_type(os);
    847 
    848 	sa->sa_user_table =
    849 	    kmem_zalloc(count * sizeof (sa_attr_type_t), KM_SLEEP);
    850 	sa->sa_user_table_sz = count * sizeof (sa_attr_type_t);
    851 
    852 	if (sa->sa_reg_attr_obj != 0) {
    853 		error = zap_count(os, sa->sa_reg_attr_obj,
    854 		    &sa_attr_count);
    855 
    856 		/*
    857 		 * Make sure we retrieved a count and that it isn't zero
    858 		 */
    859 		if (error || (error == 0 && sa_attr_count == 0)) {
    860 			if (error == 0)
    861 				error = SET_ERROR(EINVAL);
    862 			goto bail;
    863 		}
    864 		sa_reg_count = sa_attr_count;
    865 	}
    866 
    867 	if (ostype == DMU_OST_ZFS && sa_attr_count == 0)
    868 		sa_attr_count += sa_legacy_attr_count;
    869 
    870 	/* Allocate attribute numbers for attributes that aren't registered */
    871 	for (i = 0; i != count; i++) {
    872 		boolean_t found = B_FALSE;
    873 		int j;
    874 
    875 		if (ostype == DMU_OST_ZFS) {
    876 			for (j = 0; j != sa_legacy_attr_count; j++) {
    877 				if (strcmp(reg_attrs[i].sa_name,
    878 				    sa_legacy_attrs[j].sa_name) == 0) {
    879 					sa->sa_user_table[i] =
    880 					    sa_legacy_attrs[j].sa_attr;
    881 					found = B_TRUE;
    882 				}
    883 			}
    884 		}
    885 		if (found)
    886 			continue;
    887 
    888 		if (sa->sa_reg_attr_obj)
    889 			error = zap_lookup(os, sa->sa_reg_attr_obj,
    890 			    reg_attrs[i].sa_name, 8, 1, &attr_value);
    891 		else
    892 			error = SET_ERROR(ENOENT);
    893 		switch (error) {
    894 		case ENOENT:
    895 			sa->sa_user_table[i] = (sa_attr_type_t)sa_attr_count;
    896 			sa_attr_count++;
    897 			break;
    898 		case 0:
    899 			sa->sa_user_table[i] = ATTR_NUM(attr_value);
    900 			break;
    901 		default:
    902 			goto bail;
    903 		}
    904 	}
    905 
    906 	sa->sa_num_attrs = sa_attr_count;
    907 	tb = sa->sa_attr_table =
    908 	    kmem_zalloc(sizeof (sa_attr_table_t) * sa_attr_count, KM_SLEEP);
    909 
    910 	/*
    911 	 * Attribute table is constructed from requested attribute list,
    912 	 * previously foreign registered attributes, and also the legacy
    913 	 * ZPL set of attributes.
    914 	 */
    915 
    916 	if (sa->sa_reg_attr_obj) {
    917 		for (zap_cursor_init(&zc, os, sa->sa_reg_attr_obj);
    918 		    (error = zap_cursor_retrieve(&zc, &za)) == 0;
    919 		    zap_cursor_advance(&zc)) {
    920 			uint64_t value;
    921 			value  = za.za_first_integer;
    922 
    923 			registered_count++;
    924 			tb[ATTR_NUM(value)].sa_attr = ATTR_NUM(value);
    925 			tb[ATTR_NUM(value)].sa_length = ATTR_LENGTH(value);
    926 			tb[ATTR_NUM(value)].sa_byteswap = ATTR_BSWAP(value);
    927 			tb[ATTR_NUM(value)].sa_registered = B_TRUE;
    928 
    929 			if (tb[ATTR_NUM(value)].sa_name) {
    930 				continue;
    931 			}
    932 			tb[ATTR_NUM(value)].sa_name =
    933 			    kmem_zalloc(strlen(za.za_name) +1, KM_SLEEP);
    934 			(void) strlcpy(tb[ATTR_NUM(value)].sa_name, za.za_name,
    935 			    strlen(za.za_name) +1);
    936 		}
    937 		zap_cursor_fini(&zc);
    938 		/*
    939 		 * Make sure we processed the correct number of registered
    940 		 * attributes
    941 		 */
    942 		if (registered_count != sa_reg_count) {
    943 			ASSERT(error != 0);
    944 			goto bail;
    945 		}
    946 
    947 	}
    948 
    949 	if (ostype == DMU_OST_ZFS) {
    950 		for (i = 0; i != sa_legacy_attr_count; i++) {
    951 			if (tb[i].sa_name)
    952 				continue;
    953 			tb[i].sa_attr = sa_legacy_attrs[i].sa_attr;
    954 			tb[i].sa_length = sa_legacy_attrs[i].sa_length;
    955 			tb[i].sa_byteswap = sa_legacy_attrs[i].sa_byteswap;
    956 			tb[i].sa_registered = B_FALSE;
    957 			tb[i].sa_name =
    958 			    kmem_zalloc(strlen(sa_legacy_attrs[i].sa_name) +1,
    959 			    KM_SLEEP);
    960 			(void) strlcpy(tb[i].sa_name,
    961 			    sa_legacy_attrs[i].sa_name,
    962 			    strlen(sa_legacy_attrs[i].sa_name) + 1);
    963 		}
    964 	}
    965 
    966 	for (i = 0; i != count; i++) {
    967 		sa_attr_type_t attr_id;
    968 
    969 		attr_id = sa->sa_user_table[i];
    970 		if (tb[attr_id].sa_name)
    971 			continue;
    972 
    973 		tb[attr_id].sa_length = reg_attrs[i].sa_length;
    974 		tb[attr_id].sa_byteswap = reg_attrs[i].sa_byteswap;
    975 		tb[attr_id].sa_attr = attr_id;
    976 		tb[attr_id].sa_name =
    977 		    kmem_zalloc(strlen(reg_attrs[i].sa_name) + 1, KM_SLEEP);
    978 		(void) strlcpy(tb[attr_id].sa_name, reg_attrs[i].sa_name,
    979 		    strlen(reg_attrs[i].sa_name) + 1);
    980 	}
    981 
    982 	sa->sa_need_attr_registration =
    983 	    (sa_attr_count != registered_count);
    984 
    985 	return (0);
    986 bail:
    987 	kmem_free(sa->sa_user_table, count * sizeof (sa_attr_type_t));
    988 	sa->sa_user_table = NULL;
    989 	sa_free_attr_table(sa);
    990 	return ((error != 0) ? error : EINVAL);
    991 }
    992 
    993 int
    994 sa_setup(objset_t *os, uint64_t sa_obj, sa_attr_reg_t *reg_attrs, int count,
    995     sa_attr_type_t **user_table)
    996 {
    997 	zap_cursor_t zc;
    998 	zap_attribute_t za;
    999 	sa_os_t *sa;
   1000 	dmu_objset_type_t ostype = dmu_objset_type(os);
   1001 	sa_attr_type_t *tb;
   1002 	int error;
   1003 
   1004 	mutex_enter(&os->os_user_ptr_lock);
   1005 	if (os->os_sa) {
   1006 		mutex_enter(&os->os_sa->sa_lock);
   1007 		mutex_exit(&os->os_user_ptr_lock);
   1008 		tb = os->os_sa->sa_user_table;
   1009 		mutex_exit(&os->os_sa->sa_lock);
   1010 		*user_table = tb;
   1011 		return (0);
   1012 	}
   1013 
   1014 	sa = kmem_zalloc(sizeof (sa_os_t), KM_SLEEP);
   1015 	mutex_init(&sa->sa_lock, NULL, MUTEX_DEFAULT, NULL);
   1016 	sa->sa_master_obj = sa_obj;
   1017 
   1018 	os->os_sa = sa;
   1019 	mutex_enter(&sa->sa_lock);
   1020 	mutex_exit(&os->os_user_ptr_lock);
   1021 	avl_create(&sa->sa_layout_num_tree, layout_num_compare,
   1022 	    sizeof (sa_lot_t), offsetof(sa_lot_t, lot_num_node));
   1023 	avl_create(&sa->sa_layout_hash_tree, layout_hash_compare,
   1024 	    sizeof (sa_lot_t), offsetof(sa_lot_t, lot_hash_node));
   1025 
   1026 	if (sa_obj) {
   1027 		error = zap_lookup(os, sa_obj, SA_LAYOUTS,
   1028 		    8, 1, &sa->sa_layout_attr_obj);
   1029 		if (error != 0 && error != ENOENT)
   1030 			goto fail;
   1031 		error = zap_lookup(os, sa_obj, SA_REGISTRY,
   1032 		    8, 1, &sa->sa_reg_attr_obj);
   1033 		if (error != 0 && error != ENOENT)
   1034 			goto fail;
   1035 	}
   1036 
   1037 	if ((error = sa_attr_table_setup(os, reg_attrs, count)) != 0)
   1038 		goto fail;
   1039 
   1040 	if (sa->sa_layout_attr_obj != 0) {
   1041 		uint64_t layout_count;
   1042 
   1043 		error = zap_count(os, sa->sa_layout_attr_obj,
   1044 		    &layout_count);
   1045 
   1046 		/*
   1047 		 * Layout number count should be > 0
   1048 		 */
   1049 		if (error || (error == 0 && layout_count == 0)) {
   1050 			if (error == 0)
   1051 				error = SET_ERROR(EINVAL);
   1052 			goto fail;
   1053 		}
   1054 
   1055 		for (zap_cursor_init(&zc, os, sa->sa_layout_attr_obj);
   1056 		    (error = zap_cursor_retrieve(&zc, &za)) == 0;
   1057 		    zap_cursor_advance(&zc)) {
   1058 			sa_attr_type_t *lot_attrs;
   1059 			uint64_t lot_num;
   1060 
   1061 			lot_attrs = kmem_zalloc(sizeof (sa_attr_type_t) *
   1062 			    za.za_num_integers, KM_SLEEP);
   1063 
   1064 			if ((error = (zap_lookup(os, sa->sa_layout_attr_obj,
   1065 			    za.za_name, 2, za.za_num_integers,
   1066 			    lot_attrs))) != 0) {
   1067 				kmem_free(lot_attrs, sizeof (sa_attr_type_t) *
   1068 				    za.za_num_integers);
   1069 				break;
   1070 			}
   1071 			VERIFY(ddi_strtoull(za.za_name, NULL, 10,
   1072 			    (unsigned long long *)&lot_num) == 0);
   1073 
   1074 			(void) sa_add_layout_entry(os, lot_attrs,
   1075 			    za.za_num_integers, lot_num,
   1076 			    sa_layout_info_hash(lot_attrs,
   1077 			    za.za_num_integers), B_FALSE, NULL);
   1078 			kmem_free(lot_attrs, sizeof (sa_attr_type_t) *
   1079 			    za.za_num_integers);
   1080 		}
   1081 		zap_cursor_fini(&zc);
   1082 
   1083 		/*
   1084 		 * Make sure layout count matches number of entries added
   1085 		 * to AVL tree
   1086 		 */
   1087 		if (avl_numnodes(&sa->sa_layout_num_tree) != layout_count) {
   1088 			ASSERT(error != 0);
   1089 			goto fail;
   1090 		}
   1091 	}
   1092 
   1093 	/* Add special layout number for old ZNODES */
   1094 	if (ostype == DMU_OST_ZFS) {
   1095 		(void) sa_add_layout_entry(os, sa_legacy_zpl_layout,
   1096 		    sa_legacy_attr_count, 0,
   1097 		    sa_layout_info_hash(sa_legacy_zpl_layout,
   1098 		    sa_legacy_attr_count), B_FALSE, NULL);
   1099 
   1100 		(void) sa_add_layout_entry(os, sa_dummy_zpl_layout, 0, 1,
   1101 		    0, B_FALSE, NULL);
   1102 	}
   1103 	*user_table = os->os_sa->sa_user_table;
   1104 	mutex_exit(&sa->sa_lock);
   1105 	return (0);
   1106 fail:
   1107 	os->os_sa = NULL;
   1108 	sa_free_attr_table(sa);
   1109 	if (sa->sa_user_table)
   1110 		kmem_free(sa->sa_user_table, sa->sa_user_table_sz);
   1111 	mutex_exit(&sa->sa_lock);
   1112 	avl_destroy(&sa->sa_layout_hash_tree);
   1113 	avl_destroy(&sa->sa_layout_num_tree);
   1114 	mutex_destroy(&sa->sa_lock);
   1115 	kmem_free(sa, sizeof (sa_os_t));
   1116 	return ((error == ECKSUM) ? EIO : error);
   1117 }
   1118 
   1119 void
   1120 sa_tear_down(objset_t *os)
   1121 {
   1122 	sa_os_t *sa = os->os_sa;
   1123 	sa_lot_t *layout;
   1124 	void *cookie;
   1125 
   1126 	kmem_free(sa->sa_user_table, sa->sa_user_table_sz);
   1127 
   1128 	/* Free up attr table */
   1129 
   1130 	sa_free_attr_table(sa);
   1131 
   1132 	cookie = NULL;
   1133 	while (layout = avl_destroy_nodes(&sa->sa_layout_hash_tree, &cookie)) {
   1134 		sa_idx_tab_t *tab;
   1135 		while (tab = list_head(&layout->lot_idx_tab)) {
   1136 			ASSERT(refcount_count(&tab->sa_refcount));
   1137 			sa_idx_tab_rele(os, tab);
   1138 		}
   1139 	}
   1140 
   1141 	cookie = NULL;
   1142 	while (layout = avl_destroy_nodes(&sa->sa_layout_num_tree, &cookie)) {
   1143 #ifdef __NetBSD__
   1144 		if (layout->lot_attr_count != 0)
   1145 #endif
   1146 		kmem_free(layout->lot_attrs,
   1147 		    sizeof (sa_attr_type_t) * layout->lot_attr_count);
   1148 		kmem_free(layout, sizeof (sa_lot_t));
   1149 	}
   1150 
   1151 	avl_destroy(&sa->sa_layout_hash_tree);
   1152 	avl_destroy(&sa->sa_layout_num_tree);
   1153 	mutex_destroy(&sa->sa_lock);
   1154 
   1155 	kmem_free(sa, sizeof (sa_os_t));
   1156 	os->os_sa = NULL;
   1157 }
   1158 
   1159 void
   1160 sa_build_idx_tab(void *hdr, void *attr_addr, sa_attr_type_t attr,
   1161     uint16_t length, int length_idx, boolean_t var_length, void *userp)
   1162 {
   1163 	sa_idx_tab_t *idx_tab = userp;
   1164 
   1165 	if (var_length) {
   1166 		ASSERT(idx_tab->sa_variable_lengths);
   1167 		idx_tab->sa_variable_lengths[length_idx] = length;
   1168 	}
   1169 	TOC_ATTR_ENCODE(idx_tab->sa_idx_tab[attr], length_idx,
   1170 	    (uint32_t)((uintptr_t)attr_addr - (uintptr_t)hdr));
   1171 }
   1172 
   1173 static void
   1174 sa_attr_iter(objset_t *os, sa_hdr_phys_t *hdr, dmu_object_type_t type,
   1175     sa_iterfunc_t func, sa_lot_t *tab, void *userp)
   1176 {
   1177 	void *data_start;
   1178 	sa_lot_t *tb = tab;
   1179 	sa_lot_t search;
   1180 	avl_index_t loc;
   1181 	sa_os_t *sa = os->os_sa;
   1182 	int i;
   1183 	uint16_t *length_start = NULL;
   1184 	uint8_t length_idx = 0;
   1185 
   1186 	if (tab == NULL) {
   1187 		search.lot_num = SA_LAYOUT_NUM(hdr, type);
   1188 		tb = avl_find(&sa->sa_layout_num_tree, &search, &loc);
   1189 		ASSERT(tb);
   1190 	}
   1191 
   1192 	if (IS_SA_BONUSTYPE(type)) {
   1193 		data_start = (void *)P2ROUNDUP(((uintptr_t)hdr +
   1194 		    offsetof(sa_hdr_phys_t, sa_lengths) +
   1195 		    (sizeof (uint16_t) * tb->lot_var_sizes)), 8);
   1196 		length_start = hdr->sa_lengths;
   1197 	} else {
   1198 		data_start = hdr;
   1199 	}
   1200 
   1201 	for (i = 0; i != tb->lot_attr_count; i++) {
   1202 		int attr_length, reg_length;
   1203 		uint8_t idx_len;
   1204 
   1205 		reg_length = sa->sa_attr_table[tb->lot_attrs[i]].sa_length;
   1206 		if (reg_length) {
   1207 			attr_length = reg_length;
   1208 			idx_len = 0;
   1209 		} else {
   1210 			attr_length = length_start[length_idx];
   1211 			idx_len = length_idx++;
   1212 		}
   1213 
   1214 		func(hdr, data_start, tb->lot_attrs[i], attr_length,
   1215 		    idx_len, reg_length == 0 ? B_TRUE : B_FALSE, userp);
   1216 
   1217 		data_start = (void *)P2ROUNDUP(((uintptr_t)data_start +
   1218 		    attr_length), 8);
   1219 	}
   1220 }
   1221 
   1222 /*ARGSUSED*/
   1223 void
   1224 sa_byteswap_cb(void *hdr, void *attr_addr, sa_attr_type_t attr,
   1225     uint16_t length, int length_idx, boolean_t variable_length, void *userp)
   1226 {
   1227 	sa_handle_t *hdl = userp;
   1228 	sa_os_t *sa = hdl->sa_os->os_sa;
   1229 
   1230 	sa_bswap_table[sa->sa_attr_table[attr].sa_byteswap](attr_addr, length);
   1231 }
   1232 
   1233 void
   1234 sa_byteswap(sa_handle_t *hdl, sa_buf_type_t buftype)
   1235 {
   1236 	sa_hdr_phys_t *sa_hdr_phys = SA_GET_HDR(hdl, buftype);
   1237 	dmu_buf_impl_t *db;
   1238 	sa_os_t *sa = hdl->sa_os->os_sa;
   1239 	int num_lengths = 1;
   1240 	int i;
   1241 
   1242 	ASSERT(MUTEX_HELD(&sa->sa_lock));
   1243 	if (sa_hdr_phys->sa_magic == SA_MAGIC)
   1244 		return;
   1245 
   1246 	db = SA_GET_DB(hdl, buftype);
   1247 
   1248 	if (buftype == SA_SPILL) {
   1249 		arc_release(db->db_buf, NULL);
   1250 		arc_buf_thaw(db->db_buf);
   1251 	}
   1252 
   1253 	sa_hdr_phys->sa_magic = BSWAP_32(sa_hdr_phys->sa_magic);
   1254 	sa_hdr_phys->sa_layout_info = BSWAP_16(sa_hdr_phys->sa_layout_info);
   1255 
   1256 	/*
   1257 	 * Determine number of variable lenghts in header
   1258 	 * The standard 8 byte header has one for free and a
   1259 	 * 16 byte header would have 4 + 1;
   1260 	 */
   1261 	if (SA_HDR_SIZE(sa_hdr_phys) > 8)
   1262 		num_lengths += (SA_HDR_SIZE(sa_hdr_phys) - 8) >> 1;
   1263 	for (i = 0; i != num_lengths; i++)
   1264 		sa_hdr_phys->sa_lengths[i] =
   1265 		    BSWAP_16(sa_hdr_phys->sa_lengths[i]);
   1266 
   1267 	sa_attr_iter(hdl->sa_os, sa_hdr_phys, DMU_OT_SA,
   1268 	    sa_byteswap_cb, NULL, hdl);
   1269 
   1270 	if (buftype == SA_SPILL)
   1271 		arc_buf_freeze(((dmu_buf_impl_t *)hdl->sa_spill)->db_buf);
   1272 }
   1273 
   1274 static int
   1275 sa_build_index(sa_handle_t *hdl, sa_buf_type_t buftype)
   1276 {
   1277 	sa_hdr_phys_t *sa_hdr_phys;
   1278 	dmu_buf_impl_t *db = SA_GET_DB(hdl, buftype);
   1279 	dmu_object_type_t bonustype = SA_BONUSTYPE_FROM_DB(db);
   1280 	sa_os_t *sa = hdl->sa_os->os_sa;
   1281 	sa_idx_tab_t *idx_tab;
   1282 
   1283 	sa_hdr_phys = SA_GET_HDR(hdl, buftype);
   1284 
   1285 	mutex_enter(&sa->sa_lock);
   1286 
   1287 	/* Do we need to byteswap? */
   1288 
   1289 	/* only check if not old znode */
   1290 	if (IS_SA_BONUSTYPE(bonustype) && sa_hdr_phys->sa_magic != SA_MAGIC &&
   1291 	    sa_hdr_phys->sa_magic != 0) {
   1292 		VERIFY(BSWAP_32(sa_hdr_phys->sa_magic) == SA_MAGIC);
   1293 		sa_byteswap(hdl, buftype);
   1294 	}
   1295 
   1296 	idx_tab = sa_find_idx_tab(hdl->sa_os, bonustype, sa_hdr_phys);
   1297 
   1298 	if (buftype == SA_BONUS)
   1299 		hdl->sa_bonus_tab = idx_tab;
   1300 	else
   1301 		hdl->sa_spill_tab = idx_tab;
   1302 
   1303 	mutex_exit(&sa->sa_lock);
   1304 	return (0);
   1305 }
   1306 
   1307 /*ARGSUSED*/
   1308 static void
   1309 sa_evict_sync(void *dbu)
   1310 {
   1311 	panic("evicting sa dbuf\n");
   1312 }
   1313 
   1314 static void
   1315 sa_idx_tab_rele(objset_t *os, void *arg)
   1316 {
   1317 	sa_os_t *sa = os->os_sa;
   1318 	sa_idx_tab_t *idx_tab = arg;
   1319 
   1320 	if (idx_tab == NULL)
   1321 		return;
   1322 
   1323 	mutex_enter(&sa->sa_lock);
   1324 	if (refcount_remove(&idx_tab->sa_refcount, NULL) == 0) {
   1325 		list_remove(&idx_tab->sa_layout->lot_idx_tab, idx_tab);
   1326 		if (idx_tab->sa_variable_lengths)
   1327 			kmem_free(idx_tab->sa_variable_lengths,
   1328 			    sizeof (uint16_t) *
   1329 			    idx_tab->sa_layout->lot_var_sizes);
   1330 		refcount_destroy(&idx_tab->sa_refcount);
   1331 		kmem_free(idx_tab->sa_idx_tab,
   1332 		    sizeof (uint32_t) * sa->sa_num_attrs);
   1333 		kmem_free(idx_tab, sizeof (sa_idx_tab_t));
   1334 	}
   1335 	mutex_exit(&sa->sa_lock);
   1336 }
   1337 
   1338 static void
   1339 sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab)
   1340 {
   1341 	sa_os_t *sa = os->os_sa;
   1342 
   1343 	ASSERT(MUTEX_HELD(&sa->sa_lock));
   1344 	(void) refcount_add(&idx_tab->sa_refcount, NULL);
   1345 }
   1346 
   1347 void
   1348 sa_handle_destroy(sa_handle_t *hdl)
   1349 {
   1350 	dmu_buf_t *db = hdl->sa_bonus;
   1351 
   1352 	mutex_enter(&hdl->sa_lock);
   1353 	(void) dmu_buf_remove_user(db, &hdl->sa_dbu);
   1354 
   1355 	if (hdl->sa_bonus_tab)
   1356 		sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab);
   1357 
   1358 	if (hdl->sa_spill_tab)
   1359 		sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab);
   1360 
   1361 	dmu_buf_rele(hdl->sa_bonus, NULL);
   1362 
   1363 	if (hdl->sa_spill)
   1364 		dmu_buf_rele((dmu_buf_t *)hdl->sa_spill, NULL);
   1365 	mutex_exit(&hdl->sa_lock);
   1366 
   1367 	kmem_cache_free(sa_cache, hdl);
   1368 }
   1369 
   1370 int
   1371 sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
   1372     sa_handle_type_t hdl_type, sa_handle_t **handlepp)
   1373 {
   1374 	int error = 0;
   1375 	dmu_object_info_t doi;
   1376 	sa_handle_t *handle = NULL;
   1377 
   1378 #ifdef ZFS_DEBUG
   1379 	dmu_object_info_from_db(db, &doi);
   1380 	ASSERT(doi.doi_bonus_type == DMU_OT_SA ||
   1381 	    doi.doi_bonus_type == DMU_OT_ZNODE);
   1382 #endif
   1383 	/* find handle, if it exists */
   1384 	/* if one doesn't exist then create a new one, and initialize it */
   1385 
   1386 	if (hdl_type == SA_HDL_SHARED)
   1387 		handle = dmu_buf_get_user(db);
   1388 
   1389 	if (handle == NULL) {
   1390 		sa_handle_t *winner = NULL;
   1391 
   1392 		handle = kmem_cache_alloc(sa_cache, KM_SLEEP);
   1393 		handle->sa_dbu.dbu_evict_func_sync = NULL;
   1394 		handle->sa_dbu.dbu_evict_func_async = NULL;
   1395 		handle->sa_userp = userp;
   1396 		handle->sa_bonus = db;
   1397 		handle->sa_os = os;
   1398 		handle->sa_spill = NULL;
   1399 		handle->sa_bonus_tab = NULL;
   1400 		handle->sa_spill_tab = NULL;
   1401 
   1402 		error = sa_build_index(handle, SA_BONUS);
   1403 
   1404 		if (hdl_type == SA_HDL_SHARED) {
   1405 			dmu_buf_init_user(&handle->sa_dbu, sa_evict_sync, NULL,
   1406 			    NULL);
   1407 			winner = dmu_buf_set_user_ie(db, &handle->sa_dbu);
   1408 		}
   1409 
   1410 		if (winner != NULL) {
   1411 			kmem_cache_free(sa_cache, handle);
   1412 			handle = winner;
   1413 		}
   1414 	}
   1415 	*handlepp = handle;
   1416 
   1417 	return (error);
   1418 }
   1419 
   1420 int
   1421 sa_handle_get(objset_t *objset, uint64_t objid, void *userp,
   1422     sa_handle_type_t hdl_type, sa_handle_t **handlepp)
   1423 {
   1424 	dmu_buf_t *db;
   1425 	int error;
   1426 
   1427 	if (error = dmu_bonus_hold(objset, objid, NULL, &db))
   1428 		return (error);
   1429 
   1430 	return (sa_handle_get_from_db(objset, db, userp, hdl_type,
   1431 	    handlepp));
   1432 }
   1433 
   1434 int
   1435 sa_buf_hold(objset_t *objset, uint64_t obj_num, void *tag, dmu_buf_t **db)
   1436 {
   1437 	return (dmu_bonus_hold(objset, obj_num, tag, db));
   1438 }
   1439 
   1440 void
   1441 sa_buf_rele(dmu_buf_t *db, void *tag)
   1442 {
   1443 	dmu_buf_rele(db, tag);
   1444 }
   1445 
   1446 int
   1447 sa_lookup_impl(sa_handle_t *hdl, sa_bulk_attr_t *bulk, int count)
   1448 {
   1449 	ASSERT(hdl);
   1450 	ASSERT(MUTEX_HELD(&hdl->sa_lock));
   1451 	return (sa_attr_op(hdl, bulk, count, SA_LOOKUP, NULL));
   1452 }
   1453 
   1454 int
   1455 sa_lookup(sa_handle_t *hdl, sa_attr_type_t attr, void *buf, uint32_t buflen)
   1456 {
   1457 	int error;
   1458 	sa_bulk_attr_t bulk;
   1459 
   1460 	bulk.sa_attr = attr;
   1461 	bulk.sa_data = buf;
   1462 	bulk.sa_length = buflen;
   1463 	bulk.sa_data_func = NULL;
   1464 
   1465 	ASSERT(hdl);
   1466 	mutex_enter(&hdl->sa_lock);
   1467 	error = sa_lookup_impl(hdl, &bulk, 1);
   1468 	mutex_exit(&hdl->sa_lock);
   1469 	return (error);
   1470 }
   1471 
   1472 #ifdef _KERNEL
   1473 int
   1474 sa_lookup_uio(sa_handle_t *hdl, sa_attr_type_t attr, uio_t *uio)
   1475 {
   1476 	int error;
   1477 	sa_bulk_attr_t bulk;
   1478 
   1479 	bulk.sa_data = NULL;
   1480 	bulk.sa_attr = attr;
   1481 	bulk.sa_data_func = NULL;
   1482 
   1483 	ASSERT(hdl);
   1484 
   1485 	mutex_enter(&hdl->sa_lock);
   1486 	if ((error = sa_attr_op(hdl, &bulk, 1, SA_LOOKUP, NULL)) == 0) {
   1487 		error = uiomove((void *)bulk.sa_addr, MIN(bulk.sa_size,
   1488 		    uio->uio_resid), UIO_READ, uio);
   1489 	}
   1490 	mutex_exit(&hdl->sa_lock);
   1491 	return (error);
   1492 
   1493 }
   1494 #endif
   1495 
   1496 void *
   1497 sa_find_idx_tab(objset_t *os, dmu_object_type_t bonustype, void *data)
   1498 {
   1499 	sa_idx_tab_t *idx_tab;
   1500 	sa_hdr_phys_t *hdr = (sa_hdr_phys_t *)data;
   1501 	sa_os_t *sa = os->os_sa;
   1502 	sa_lot_t *tb, search;
   1503 	avl_index_t loc;
   1504 
   1505 	/*
   1506 	 * Deterimine layout number.  If SA node and header == 0 then
   1507 	 * force the index table to the dummy "1" empty layout.
   1508 	 *
   1509 	 * The layout number would only be zero for a newly created file
   1510 	 * that has not added any attributes yet, or with crypto enabled which
   1511 	 * doesn't write any attributes to the bonus buffer.
   1512 	 */
   1513 
   1514 	search.lot_num = SA_LAYOUT_NUM(hdr, bonustype);
   1515 
   1516 	tb = avl_find(&sa->sa_layout_num_tree, &search, &loc);
   1517 
   1518 	/* Verify header size is consistent with layout information */
   1519 	ASSERT(tb);
   1520 	ASSERT(IS_SA_BONUSTYPE(bonustype) &&
   1521 	    SA_HDR_SIZE_MATCH_LAYOUT(hdr, tb) || !IS_SA_BONUSTYPE(bonustype) ||
   1522 	    (IS_SA_BONUSTYPE(bonustype) && hdr->sa_layout_info == 0));
   1523 
   1524 	/*
   1525 	 * See if any of the already existing TOC entries can be reused?
   1526 	 */
   1527 
   1528 	for (idx_tab = list_head(&tb->lot_idx_tab); idx_tab;
   1529 	    idx_tab = list_next(&tb->lot_idx_tab, idx_tab)) {
   1530 		boolean_t valid_idx = B_TRUE;
   1531 		int i;
   1532 
   1533 		if (tb->lot_var_sizes != 0 &&
   1534 		    idx_tab->sa_variable_lengths != NULL) {
   1535 			for (i = 0; i != tb->lot_var_sizes; i++) {
   1536 				if (hdr->sa_lengths[i] !=
   1537 				    idx_tab->sa_variable_lengths[i]) {
   1538 					valid_idx = B_FALSE;
   1539 					break;
   1540 				}
   1541 			}
   1542 		}
   1543 		if (valid_idx) {
   1544 			sa_idx_tab_hold(os, idx_tab);
   1545 			return (idx_tab);
   1546 		}
   1547 	}
   1548 
   1549 	/* No such luck, create a new entry */
   1550 	idx_tab = kmem_zalloc(sizeof (sa_idx_tab_t), KM_SLEEP);
   1551 	idx_tab->sa_idx_tab =
   1552 	    kmem_zalloc(sizeof (uint32_t) * sa->sa_num_attrs, KM_SLEEP);
   1553 	idx_tab->sa_layout = tb;
   1554 	refcount_create(&idx_tab->sa_refcount);
   1555 	if (tb->lot_var_sizes)
   1556 		idx_tab->sa_variable_lengths = kmem_alloc(sizeof (uint16_t) *
   1557 		    tb->lot_var_sizes, KM_SLEEP);
   1558 
   1559 	sa_attr_iter(os, hdr, bonustype, sa_build_idx_tab,
   1560 	    tb, idx_tab);
   1561 	sa_idx_tab_hold(os, idx_tab);   /* one hold for consumer */
   1562 	sa_idx_tab_hold(os, idx_tab);	/* one for layout */
   1563 	list_insert_tail(&tb->lot_idx_tab, idx_tab);
   1564 	return (idx_tab);
   1565 }
   1566 
   1567 void
   1568 sa_default_locator(void **dataptr, uint32_t *len, uint32_t total_len,
   1569     boolean_t start, void *userdata)
   1570 {
   1571 	ASSERT(start);
   1572 
   1573 	*dataptr = userdata;
   1574 	*len = total_len;
   1575 }
   1576 
   1577 static void
   1578 sa_attr_register_sync(sa_handle_t *hdl, dmu_tx_t *tx)
   1579 {
   1580 	uint64_t attr_value = 0;
   1581 	sa_os_t *sa = hdl->sa_os->os_sa;
   1582 	sa_attr_table_t *tb = sa->sa_attr_table;
   1583 	int i;
   1584 
   1585 	mutex_enter(&sa->sa_lock);
   1586 
   1587 	if (!sa->sa_need_attr_registration || sa->sa_master_obj == 0) {
   1588 		mutex_exit(&sa->sa_lock);
   1589 		return;
   1590 	}
   1591 
   1592 	if (sa->sa_reg_attr_obj == 0) {
   1593 		sa->sa_reg_attr_obj = zap_create_link(hdl->sa_os,
   1594 		    DMU_OT_SA_ATTR_REGISTRATION,
   1595 		    sa->sa_master_obj, SA_REGISTRY, tx);
   1596 	}
   1597 	for (i = 0; i != sa->sa_num_attrs; i++) {
   1598 		if (sa->sa_attr_table[i].sa_registered)
   1599 			continue;
   1600 		ATTR_ENCODE(attr_value, tb[i].sa_attr, tb[i].sa_length,
   1601 		    tb[i].sa_byteswap);
   1602 		VERIFY(0 == zap_update(hdl->sa_os, sa->sa_reg_attr_obj,
   1603 		    tb[i].sa_name, 8, 1, &attr_value, tx));
   1604 		tb[i].sa_registered = B_TRUE;
   1605 	}
   1606 	sa->sa_need_attr_registration = B_FALSE;
   1607 	mutex_exit(&sa->sa_lock);
   1608 }
   1609 
   1610 /*
   1611  * Replace all attributes with attributes specified in template.
   1612  * If dnode had a spill buffer then those attributes will be
   1613  * also be replaced, possibly with just an empty spill block
   1614  *
   1615  * This interface is intended to only be used for bulk adding of
   1616  * attributes for a new file.  It will also be used by the ZPL
   1617  * when converting and old formatted znode to native SA support.
   1618  */
   1619 int
   1620 sa_replace_all_by_template_locked(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc,
   1621     int attr_count, dmu_tx_t *tx)
   1622 {
   1623 	sa_os_t *sa = hdl->sa_os->os_sa;
   1624 
   1625 	if (sa->sa_need_attr_registration)
   1626 		sa_attr_register_sync(hdl, tx);
   1627 	return (sa_build_layouts(hdl, attr_desc, attr_count, tx));
   1628 }
   1629 
   1630 int
   1631 sa_replace_all_by_template(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc,
   1632     int attr_count, dmu_tx_t *tx)
   1633 {
   1634 	int error;
   1635 
   1636 	mutex_enter(&hdl->sa_lock);
   1637 	error = sa_replace_all_by_template_locked(hdl, attr_desc,
   1638 	    attr_count, tx);
   1639 	mutex_exit(&hdl->sa_lock);
   1640 	return (error);
   1641 }
   1642 
   1643 /*
   1644  * Add/remove a single attribute or replace a variable-sized attribute value
   1645  * with a value of a different size, and then rewrite the entire set
   1646  * of attributes.
   1647  * Same-length attribute value replacement (including fixed-length attributes)
   1648  * is handled more efficiently by the upper layers.
   1649  */
   1650 static int
   1651 sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
   1652     sa_data_op_t action, sa_data_locator_t *locator, void *datastart,
   1653     uint16_t buflen, dmu_tx_t *tx)
   1654 {
   1655 	sa_os_t *sa = hdl->sa_os->os_sa;
   1656 	dmu_buf_impl_t *db = (dmu_buf_impl_t *)hdl->sa_bonus;
   1657 	dnode_t *dn;
   1658 	sa_bulk_attr_t *attr_desc;
   1659 	void *old_data[2];
   1660 	int bonus_attr_count = 0;
   1661 	int bonus_data_size = 0;
   1662 	int spill_data_size = 0;
   1663 	int spill_attr_count = 0;
   1664 	int error;
   1665 	uint16_t length, reg_length;
   1666 	int i, j, k, length_idx;
   1667 	sa_hdr_phys_t *hdr;
   1668 	sa_idx_tab_t *idx_tab;
   1669 	int attr_count;
   1670 	int count;
   1671 
   1672 	ASSERT(MUTEX_HELD(&hdl->sa_lock));
   1673 
   1674 	/* First make of copy of the old data */
   1675 
   1676 	DB_DNODE_ENTER(db);
   1677 	dn = DB_DNODE(db);
   1678 	if (dn->dn_bonuslen != 0) {
   1679 		bonus_data_size = hdl->sa_bonus->db_size;
   1680 		old_data[0] = kmem_alloc(bonus_data_size, KM_SLEEP);
   1681 		bcopy(hdl->sa_bonus->db_data, old_data[0],
   1682 		    hdl->sa_bonus->db_size);
   1683 		bonus_attr_count = hdl->sa_bonus_tab->sa_layout->lot_attr_count;
   1684 	} else {
   1685 		old_data[0] = NULL;
   1686 	}
   1687 	DB_DNODE_EXIT(db);
   1688 
   1689 	/* Bring spill buffer online if it isn't currently */
   1690 
   1691 	if ((error = sa_get_spill(hdl)) == 0) {
   1692 		spill_data_size = hdl->sa_spill->db_size;
   1693 		old_data[1] = kmem_alloc(spill_data_size, KM_SLEEP);
   1694 		bcopy(hdl->sa_spill->db_data, old_data[1],
   1695 		    hdl->sa_spill->db_size);
   1696 		spill_attr_count =
   1697 		    hdl->sa_spill_tab->sa_layout->lot_attr_count;
   1698 	} else if (error && error != ENOENT) {
   1699 		if (old_data[0])
   1700 			kmem_free(old_data[0], bonus_data_size);
   1701 		return (error);
   1702 	} else {
   1703 		old_data[1] = NULL;
   1704 	}
   1705 
   1706 	/* build descriptor of all attributes */
   1707 
   1708 	attr_count = bonus_attr_count + spill_attr_count;
   1709 	if (action == SA_ADD)
   1710 		attr_count++;
   1711 	else if (action == SA_REMOVE)
   1712 		attr_count--;
   1713 
   1714 	attr_desc = kmem_zalloc(sizeof (sa_bulk_attr_t) * attr_count, KM_SLEEP);
   1715 
   1716 	/*
   1717 	 * loop through bonus and spill buffer if it exists, and
   1718 	 * build up new attr_descriptor to reset the attributes
   1719 	 */
   1720 	k = j = 0;
   1721 	count = bonus_attr_count;
   1722 	hdr = SA_GET_HDR(hdl, SA_BONUS);
   1723 	idx_tab = SA_IDX_TAB_GET(hdl, SA_BONUS);
   1724 	for (; k != 2; k++) {
   1725 		/*
   1726 		 * Iterate over each attribute in layout.  Fetch the
   1727 		 * size of variable-length attributes needing rewrite
   1728 		 * from sa_lengths[].
   1729 		 */
   1730 		for (i = 0, length_idx = 0; i != count; i++) {
   1731 			sa_attr_type_t attr;
   1732 
   1733 			attr = idx_tab->sa_layout->lot_attrs[i];
   1734 			reg_length = SA_REGISTERED_LEN(sa, attr);
   1735 			if (reg_length == 0) {
   1736 				length = hdr->sa_lengths[length_idx];
   1737 				length_idx++;
   1738 			} else {
   1739 				length = reg_length;
   1740 			}
   1741 			if (attr == newattr) {
   1742 				/*
   1743 				 * There is nothing to do for SA_REMOVE,
   1744 				 * so it is just skipped.
   1745 				 */
   1746 				if (action == SA_REMOVE)
   1747 					continue;
   1748 
   1749 				/*
   1750 				 * Duplicate attributes are not allowed, so the
   1751 				 * action can not be SA_ADD here.
   1752 				 */
   1753 				ASSERT3S(action, ==, SA_REPLACE);
   1754 
   1755 				/*
   1756 				 * Only a variable-sized attribute can be
   1757 				 * replaced here, and its size must be changing.
   1758 				 */
   1759 				ASSERT3U(reg_length, ==, 0);
   1760 				ASSERT3U(length, !=, buflen);
   1761 				SA_ADD_BULK_ATTR(attr_desc, j, attr,
   1762 				    locator, datastart, buflen);
   1763 			} else {
   1764 				SA_ADD_BULK_ATTR(attr_desc, j, attr,
   1765 				    NULL, (void *)
   1766 				    (TOC_OFF(idx_tab->sa_idx_tab[attr]) +
   1767 				    (uintptr_t)old_data[k]), length);
   1768 			}
   1769 		}
   1770 		if (k == 0 && hdl->sa_spill) {
   1771 			hdr = SA_GET_HDR(hdl, SA_SPILL);
   1772 			idx_tab = SA_IDX_TAB_GET(hdl, SA_SPILL);
   1773 			count = spill_attr_count;
   1774 		} else {
   1775 			break;
   1776 		}
   1777 	}
   1778 	if (action == SA_ADD) {
   1779 		reg_length = SA_REGISTERED_LEN(sa, newattr);
   1780 		IMPLY(reg_length != 0, reg_length == buflen);
   1781 		SA_ADD_BULK_ATTR(attr_desc, j, newattr, locator,
   1782 		    datastart, buflen);
   1783 	}
   1784 	ASSERT3U(j, ==, attr_count);
   1785 
   1786 	error = sa_build_layouts(hdl, attr_desc, attr_count, tx);
   1787 
   1788 	if (old_data[0])
   1789 		kmem_free(old_data[0], bonus_data_size);
   1790 	if (old_data[1])
   1791 		kmem_free(old_data[1], spill_data_size);
   1792 	kmem_free(attr_desc, sizeof (sa_bulk_attr_t) * attr_count);
   1793 
   1794 	return (error);
   1795 }
   1796 
   1797 static int
   1798 sa_bulk_update_impl(sa_handle_t *hdl, sa_bulk_attr_t *bulk, int count,
   1799     dmu_tx_t *tx)
   1800 {
   1801 	int error;
   1802 	sa_os_t *sa = hdl->sa_os->os_sa;
   1803 	dmu_object_type_t bonustype;
   1804 
   1805 	bonustype = SA_BONUSTYPE_FROM_DB(SA_GET_DB(hdl, SA_BONUS));
   1806 
   1807 	ASSERT(hdl);
   1808 	ASSERT(MUTEX_HELD(&hdl->sa_lock));
   1809 
   1810 	/* sync out registration table if necessary */
   1811 	if (sa->sa_need_attr_registration)
   1812 		sa_attr_register_sync(hdl, tx);
   1813 
   1814 	error = sa_attr_op(hdl, bulk, count, SA_UPDATE, tx);
   1815 	if (error == 0 && !IS_SA_BONUSTYPE(bonustype) && sa->sa_update_cb)
   1816 		sa->sa_update_cb(hdl, tx);
   1817 
   1818 	return (error);
   1819 }
   1820 
   1821 /*
   1822  * update or add new attribute
   1823  */
   1824 int
   1825 sa_update(sa_handle_t *hdl, sa_attr_type_t type,
   1826     void *buf, uint32_t buflen, dmu_tx_t *tx)
   1827 {
   1828 	int error;
   1829 	sa_bulk_attr_t bulk;
   1830 
   1831 	bulk.sa_attr = type;
   1832 	bulk.sa_data_func = NULL;
   1833 	bulk.sa_length = buflen;
   1834 	bulk.sa_data = buf;
   1835 
   1836 	mutex_enter(&hdl->sa_lock);
   1837 	error = sa_bulk_update_impl(hdl, &bulk, 1, tx);
   1838 	mutex_exit(&hdl->sa_lock);
   1839 	return (error);
   1840 }
   1841 
   1842 int
   1843 sa_update_from_cb(sa_handle_t *hdl, sa_attr_type_t attr,
   1844     uint32_t buflen, sa_data_locator_t *locator, void *userdata, dmu_tx_t *tx)
   1845 {
   1846 	int error;
   1847 	sa_bulk_attr_t bulk;
   1848 
   1849 	bulk.sa_attr = attr;
   1850 	bulk.sa_data = userdata;
   1851 	bulk.sa_data_func = locator;
   1852 	bulk.sa_length = buflen;
   1853 
   1854 	mutex_enter(&hdl->sa_lock);
   1855 	error = sa_bulk_update_impl(hdl, &bulk, 1, tx);
   1856 	mutex_exit(&hdl->sa_lock);
   1857 	return (error);
   1858 }
   1859 
   1860 /*
   1861  * Return size of an attribute
   1862  */
   1863 
   1864 int
   1865 sa_size(sa_handle_t *hdl, sa_attr_type_t attr, int *size)
   1866 {
   1867 	sa_bulk_attr_t bulk;
   1868 	int error;
   1869 
   1870 	bulk.sa_data = NULL;
   1871 	bulk.sa_attr = attr;
   1872 	bulk.sa_data_func = NULL;
   1873 
   1874 	ASSERT(hdl);
   1875 	mutex_enter(&hdl->sa_lock);
   1876 	if ((error = sa_attr_op(hdl, &bulk, 1, SA_LOOKUP, NULL)) != 0) {
   1877 		mutex_exit(&hdl->sa_lock);
   1878 		return (error);
   1879 	}
   1880 	*size = bulk.sa_size;
   1881 
   1882 	mutex_exit(&hdl->sa_lock);
   1883 	return (0);
   1884 }
   1885 
   1886 int
   1887 sa_bulk_lookup_locked(sa_handle_t *hdl, sa_bulk_attr_t *attrs, int count)
   1888 {
   1889 	ASSERT(hdl);
   1890 	ASSERT(MUTEX_HELD(&hdl->sa_lock));
   1891 	return (sa_lookup_impl(hdl, attrs, count));
   1892 }
   1893 
   1894 int
   1895 sa_bulk_lookup(sa_handle_t *hdl, sa_bulk_attr_t *attrs, int count)
   1896 {
   1897 	int error;
   1898 
   1899 	ASSERT(hdl);
   1900 	mutex_enter(&hdl->sa_lock);
   1901 	error = sa_bulk_lookup_locked(hdl, attrs, count);
   1902 	mutex_exit(&hdl->sa_lock);
   1903 	return (error);
   1904 }
   1905 
   1906 int
   1907 sa_bulk_update(sa_handle_t *hdl, sa_bulk_attr_t *attrs, int count, dmu_tx_t *tx)
   1908 {
   1909 	int error;
   1910 
   1911 	ASSERT(hdl);
   1912 	mutex_enter(&hdl->sa_lock);
   1913 	error = sa_bulk_update_impl(hdl, attrs, count, tx);
   1914 	mutex_exit(&hdl->sa_lock);
   1915 	return (error);
   1916 }
   1917 
   1918 int
   1919 sa_remove(sa_handle_t *hdl, sa_attr_type_t attr, dmu_tx_t *tx)
   1920 {
   1921 	int error;
   1922 
   1923 	mutex_enter(&hdl->sa_lock);
   1924 	error = sa_modify_attrs(hdl, attr, SA_REMOVE, NULL,
   1925 	    NULL, 0, tx);
   1926 	mutex_exit(&hdl->sa_lock);
   1927 	return (error);
   1928 }
   1929 
   1930 void
   1931 sa_object_info(sa_handle_t *hdl, dmu_object_info_t *doi)
   1932 {
   1933 	dmu_object_info_from_db((dmu_buf_t *)hdl->sa_bonus, doi);
   1934 }
   1935 
   1936 void
   1937 sa_object_size(sa_handle_t *hdl, uint32_t *blksize, u_longlong_t *nblocks)
   1938 {
   1939 	dmu_object_size_from_db((dmu_buf_t *)hdl->sa_bonus,
   1940 	    blksize, nblocks);
   1941 }
   1942 
   1943 void
   1944 sa_set_userp(sa_handle_t *hdl, void *ptr)
   1945 {
   1946 	hdl->sa_userp = ptr;
   1947 }
   1948 
   1949 dmu_buf_t *
   1950 sa_get_db(sa_handle_t *hdl)
   1951 {
   1952 	return ((dmu_buf_t *)hdl->sa_bonus);
   1953 }
   1954 
   1955 void *
   1956 sa_get_userdata(sa_handle_t *hdl)
   1957 {
   1958 	return (hdl->sa_userp);
   1959 }
   1960 
   1961 void
   1962 sa_register_update_callback_locked(objset_t *os, sa_update_cb_t *func)
   1963 {
   1964 	ASSERT(MUTEX_HELD(&os->os_sa->sa_lock));
   1965 	os->os_sa->sa_update_cb = func;
   1966 }
   1967 
   1968 void
   1969 sa_register_update_callback(objset_t *os, sa_update_cb_t *func)
   1970 {
   1971 
   1972 	mutex_enter(&os->os_sa->sa_lock);
   1973 	sa_register_update_callback_locked(os, func);
   1974 	mutex_exit(&os->os_sa->sa_lock);
   1975 }
   1976 
   1977 uint64_t
   1978 sa_handle_object(sa_handle_t *hdl)
   1979 {
   1980 	return (hdl->sa_bonus->db_object);
   1981 }
   1982 
   1983 boolean_t
   1984 sa_enabled(objset_t *os)
   1985 {
   1986 	return (os->os_sa == NULL);
   1987 }
   1988 
   1989 int
   1990 sa_set_sa_object(objset_t *os, uint64_t sa_object)
   1991 {
   1992 	sa_os_t *sa = os->os_sa;
   1993 
   1994 	if (sa->sa_master_obj)
   1995 		return (1);
   1996 
   1997 	sa->sa_master_obj = sa_object;
   1998 
   1999 	return (0);
   2000 }
   2001 
   2002 int
   2003 sa_hdrsize(void *arg)
   2004 {
   2005 	sa_hdr_phys_t *hdr = arg;
   2006 
   2007 	return (SA_HDR_SIZE(hdr));
   2008 }
   2009 
   2010 void
   2011 sa_handle_lock(sa_handle_t *hdl)
   2012 {
   2013 	ASSERT(hdl);
   2014 	mutex_enter(&hdl->sa_lock);
   2015 }
   2016 
   2017 void
   2018 sa_handle_unlock(sa_handle_t *hdl)
   2019 {
   2020 	ASSERT(hdl);
   2021 	mutex_exit(&hdl->sa_lock);
   2022 }
   2023