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