Print this page
3752 want more verifiable dbuf user eviction
Submitted by:   Justin Gibbs <justing@spectralogic.com>
Submitted by:   Will Andrews <willa@spectralogic.com>


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 }