1282 /* only check if not old znode */
1283 if (IS_SA_BONUSTYPE(bonustype) && sa_hdr_phys->sa_magic != SA_MAGIC &&
1284 sa_hdr_phys->sa_magic != 0) {
1285 VERIFY(BSWAP_32(sa_hdr_phys->sa_magic) == SA_MAGIC);
1286 sa_byteswap(hdl, buftype);
1287 }
1288
1289 idx_tab = sa_find_idx_tab(hdl->sa_os, bonustype, sa_hdr_phys);
1290
1291 if (buftype == SA_BONUS)
1292 hdl->sa_bonus_tab = idx_tab;
1293 else
1294 hdl->sa_spill_tab = idx_tab;
1295
1296 mutex_exit(&sa->sa_lock);
1297 return (0);
1298 }
1299
1300 /*ARGSUSED*/
1301 void
1302 sa_evict(dmu_buf_t *db, void *sap)
1303 {
1304 panic("evicting sa dbuf %p\n", (void *)db);
1305 }
1306
1307 static void
1308 sa_idx_tab_rele(objset_t *os, void *arg)
1309 {
1310 sa_os_t *sa = os->os_sa;
1311 sa_idx_tab_t *idx_tab = arg;
1312
1313 if (idx_tab == NULL)
1314 return;
1315
1316 mutex_enter(&sa->sa_lock);
1317 if (refcount_remove(&idx_tab->sa_refcount, NULL) == 0) {
1318 list_remove(&idx_tab->sa_layout->lot_idx_tab, idx_tab);
1319 if (idx_tab->sa_variable_lengths)
1320 kmem_free(idx_tab->sa_variable_lengths,
1321 sizeof (uint16_t) *
1322 idx_tab->sa_layout->lot_var_sizes);
1323 refcount_destroy(&idx_tab->sa_refcount);
1324 kmem_free(idx_tab->sa_idx_tab,
1325 sizeof (uint32_t) * sa->sa_num_attrs);
1326 kmem_free(idx_tab, sizeof (sa_idx_tab_t));
1327 }
1328 mutex_exit(&sa->sa_lock);
1329 }
1330
1331 static void
1332 sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab)
1333 {
1334 sa_os_t *sa = os->os_sa;
1335
1336 ASSERT(MUTEX_HELD(&sa->sa_lock));
1337 (void) refcount_add(&idx_tab->sa_refcount, NULL);
1338 }
1339
1340 void
1341 sa_handle_destroy(sa_handle_t *hdl)
1342 {
1343 mutex_enter(&hdl->sa_lock);
1344 (void) dmu_buf_update_user((dmu_buf_t *)hdl->sa_bonus, hdl,
1345 NULL, NULL, NULL);
1346
1347 if (hdl->sa_bonus_tab) {
1348 sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab);
1349 hdl->sa_bonus_tab = NULL;
1350 }
1351 if (hdl->sa_spill_tab) {
1352 sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab);
1353 hdl->sa_spill_tab = NULL;
1354 }
1355
1356 dmu_buf_rele(hdl->sa_bonus, NULL);
1357
1358 if (hdl->sa_spill)
1359 dmu_buf_rele((dmu_buf_t *)hdl->sa_spill, NULL);
1360 mutex_exit(&hdl->sa_lock);
1361
1362 kmem_cache_free(sa_cache, hdl);
1363 }
1364
1365 int
1366 sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
1367 sa_handle_type_t hdl_type, sa_handle_t **handlepp)
1368 {
1369 int error = 0;
1370 dmu_object_info_t doi;
1371 sa_handle_t *handle;
1372
1373 #ifdef ZFS_DEBUG
1374 dmu_object_info_from_db(db, &doi);
1375 ASSERT(doi.doi_bonus_type == DMU_OT_SA ||
1376 doi.doi_bonus_type == DMU_OT_ZNODE);
1377 #endif
1378 /* find handle, if it exists */
1379 /* if one doesn't exist then create a new one, and initialize it */
1380
1381 handle = (hdl_type == SA_HDL_SHARED) ? dmu_buf_get_user(db) : NULL;
1382 if (handle == NULL) {
1383 sa_handle_t *newhandle;
1384 handle = kmem_cache_alloc(sa_cache, KM_SLEEP);
1385 handle->sa_userp = userp;
1386 handle->sa_bonus = db;
1387 handle->sa_os = os;
1388 handle->sa_spill = NULL;
1389
1390 error = sa_build_index(handle, SA_BONUS);
1391 newhandle = (hdl_type == SA_HDL_SHARED) ?
1392 dmu_buf_set_user_ie(db, handle,
1393 NULL, sa_evict) : NULL;
1394
1395 if (newhandle != NULL) {
1396 kmem_cache_free(sa_cache, handle);
1397 handle = newhandle;
1398 }
1399 }
1400 *handlepp = handle;
1401
1402 return (error);
1403 }
1404
1405 int
1406 sa_handle_get(objset_t *objset, uint64_t objid, void *userp,
1407 sa_handle_type_t hdl_type, sa_handle_t **handlepp)
1408 {
1409 dmu_buf_t *db;
1410 int error;
1411
1412 if (error = dmu_bonus_hold(objset, objid, NULL, &db))
1413 return (error);
1414
1415 return (sa_handle_get_from_db(objset, db, userp, hdl_type,
1416 handlepp));
1417 }
1890 mutex_exit(&hdl->sa_lock);
1891 return (error);
1892 }
1893
1894 void
1895 sa_object_info(sa_handle_t *hdl, dmu_object_info_t *doi)
1896 {
1897 dmu_object_info_from_db((dmu_buf_t *)hdl->sa_bonus, doi);
1898 }
1899
1900 void
1901 sa_object_size(sa_handle_t *hdl, uint32_t *blksize, u_longlong_t *nblocks)
1902 {
1903 dmu_object_size_from_db((dmu_buf_t *)hdl->sa_bonus,
1904 blksize, nblocks);
1905 }
1906
1907 void
1908 sa_update_user(sa_handle_t *newhdl, sa_handle_t *oldhdl)
1909 {
1910 (void) dmu_buf_update_user((dmu_buf_t *)newhdl->sa_bonus,
1911 oldhdl, newhdl, NULL, sa_evict);
1912 oldhdl->sa_bonus = NULL;
1913 }
1914
1915 void
1916 sa_set_userp(sa_handle_t *hdl, void *ptr)
1917 {
1918 hdl->sa_userp = ptr;
1919 }
1920
1921 dmu_buf_t *
1922 sa_get_db(sa_handle_t *hdl)
1923 {
1924 return ((dmu_buf_t *)hdl->sa_bonus);
1925 }
1926
1927 void *
1928 sa_get_userdata(sa_handle_t *hdl)
1929 {
1930 return (hdl->sa_userp);
1931 }
|
1282 /* only check if not old znode */
1283 if (IS_SA_BONUSTYPE(bonustype) && sa_hdr_phys->sa_magic != SA_MAGIC &&
1284 sa_hdr_phys->sa_magic != 0) {
1285 VERIFY(BSWAP_32(sa_hdr_phys->sa_magic) == SA_MAGIC);
1286 sa_byteswap(hdl, buftype);
1287 }
1288
1289 idx_tab = sa_find_idx_tab(hdl->sa_os, bonustype, sa_hdr_phys);
1290
1291 if (buftype == SA_BONUS)
1292 hdl->sa_bonus_tab = idx_tab;
1293 else
1294 hdl->sa_spill_tab = idx_tab;
1295
1296 mutex_exit(&sa->sa_lock);
1297 return (0);
1298 }
1299
1300 /*ARGSUSED*/
1301 void
1302 sa_evict(dmu_buf_user_t *dbu)
1303 {
1304 panic("evicting sa dbuf\n");
1305 }
1306
1307 static void
1308 sa_idx_tab_rele(objset_t *os, void *arg)
1309 {
1310 sa_os_t *sa = os->os_sa;
1311 sa_idx_tab_t *idx_tab = arg;
1312
1313 if (idx_tab == NULL)
1314 return;
1315
1316 mutex_enter(&sa->sa_lock);
1317 if (refcount_remove(&idx_tab->sa_refcount, NULL) == 0) {
1318 list_remove(&idx_tab->sa_layout->lot_idx_tab, idx_tab);
1319 if (idx_tab->sa_variable_lengths)
1320 kmem_free(idx_tab->sa_variable_lengths,
1321 sizeof (uint16_t) *
1322 idx_tab->sa_layout->lot_var_sizes);
1323 refcount_destroy(&idx_tab->sa_refcount);
1324 kmem_free(idx_tab->sa_idx_tab,
1325 sizeof (uint32_t) * sa->sa_num_attrs);
1326 kmem_free(idx_tab, sizeof (sa_idx_tab_t));
1327 }
1328 mutex_exit(&sa->sa_lock);
1329 }
1330
1331 static void
1332 sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab)
1333 {
1334 sa_os_t *sa = os->os_sa;
1335
1336 ASSERT(MUTEX_HELD(&sa->sa_lock));
1337 (void) refcount_add(&idx_tab->sa_refcount, NULL);
1338 }
1339
1340 void
1341 sa_handle_destroy(sa_handle_t *hdl)
1342 {
1343 dmu_buf_t *db = hdl->sa_bonus;
1344
1345 mutex_enter(&hdl->sa_lock);
1346 (void) dmu_buf_remove_user(db, &hdl->db_evict);
1347
1348 if (hdl->sa_bonus_tab) {
1349 sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab);
1350 hdl->sa_bonus_tab = NULL;
1351 }
1352 if (hdl->sa_spill_tab) {
1353 sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab);
1354 hdl->sa_spill_tab = NULL;
1355 }
1356
1357 dmu_buf_rele(hdl->sa_bonus, NULL);
1358
1359 if (hdl->sa_spill)
1360 dmu_buf_rele((dmu_buf_t *)hdl->sa_spill, NULL);
1361 mutex_exit(&hdl->sa_lock);
1362
1363 kmem_cache_free(sa_cache, hdl);
1364 }
1365
1366 int
1367 sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
1368 sa_handle_type_t hdl_type, sa_handle_t **handlepp)
1369 {
1370 int error = 0;
1371 dmu_object_info_t doi;
1372 sa_handle_t *handle = NULL;
1373
1374 #ifdef ZFS_DEBUG
1375 dmu_object_info_from_db(db, &doi);
1376 ASSERT(doi.doi_bonus_type == DMU_OT_SA ||
1377 doi.doi_bonus_type == DMU_OT_ZNODE);
1378 #endif
1379 /* find handle, if it exists */
1380 /* if one doesn't exist then create a new one, and initialize it */
1381
1382 if (hdl_type == SA_HDL_SHARED)
1383 handle = (sa_handle_t *)dmu_buf_get_user(db);
1384
1385 if (handle == NULL) {
1386 sa_handle_t *winner = NULL;
1387
1388 bzero(&handle->db_evict, sizeof(dmu_buf_user_t));
1389 handle = kmem_cache_alloc(sa_cache, KM_SLEEP);
1390 handle->sa_userp = userp;
1391 handle->sa_bonus = db;
1392 handle->sa_os = os;
1393 handle->sa_spill = NULL;
1394
1395 error = sa_build_index(handle, SA_BONUS);
1396 if (hdl_type == SA_HDL_SHARED) {
1397 dmu_buf_init_user(&handle->db_evict, sa_evict);
1398 winner = (sa_handle_t *)
1399 dmu_buf_set_user_ie(db, &handle->db_evict);
1400 }
1401 if (winner != NULL) {
1402 kmem_cache_free(sa_cache, handle);
1403 handle = winner;
1404 }
1405 }
1406 *handlepp = handle;
1407
1408 return (error);
1409 }
1410
1411 int
1412 sa_handle_get(objset_t *objset, uint64_t objid, void *userp,
1413 sa_handle_type_t hdl_type, sa_handle_t **handlepp)
1414 {
1415 dmu_buf_t *db;
1416 int error;
1417
1418 if (error = dmu_bonus_hold(objset, objid, NULL, &db))
1419 return (error);
1420
1421 return (sa_handle_get_from_db(objset, db, userp, hdl_type,
1422 handlepp));
1423 }
1896 mutex_exit(&hdl->sa_lock);
1897 return (error);
1898 }
1899
1900 void
1901 sa_object_info(sa_handle_t *hdl, dmu_object_info_t *doi)
1902 {
1903 dmu_object_info_from_db((dmu_buf_t *)hdl->sa_bonus, doi);
1904 }
1905
1906 void
1907 sa_object_size(sa_handle_t *hdl, uint32_t *blksize, u_longlong_t *nblocks)
1908 {
1909 dmu_object_size_from_db((dmu_buf_t *)hdl->sa_bonus,
1910 blksize, nblocks);
1911 }
1912
1913 void
1914 sa_update_user(sa_handle_t *newhdl, sa_handle_t *oldhdl)
1915 {
1916 dmu_buf_user_t *new_user = &newhdl->db_evict;
1917 dmu_buf_user_t *old_user = &oldhdl->db_evict;
1918
1919 dmu_buf_init_user(new_user, sa_evict);
1920 VERIFY(dmu_buf_replace_user(newhdl->sa_bonus, old_user,
1921 new_user) == old_user);
1922 oldhdl->sa_bonus = NULL;
1923 }
1924
1925 void
1926 sa_set_userp(sa_handle_t *hdl, void *ptr)
1927 {
1928 hdl->sa_userp = ptr;
1929 }
1930
1931 dmu_buf_t *
1932 sa_get_db(sa_handle_t *hdl)
1933 {
1934 return ((dmu_buf_t *)hdl->sa_bonus);
1935 }
1936
1937 void *
1938 sa_get_userdata(sa_handle_t *hdl)
1939 {
1940 return (hdl->sa_userp);
1941 }
|