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  */
  27 
  28 #include <sys/zfs_context.h>
  29 #include <sys/types.h>
  30 #include <sys/param.h>
  31 #include <sys/systm.h>
  32 #include <sys/sysmacros.h>
  33 #include <sys/dmu.h>
  34 #include <sys/dmu_impl.h>
  35 #include <sys/dmu_objset.h>
  36 #include <sys/dbuf.h>
  37 #include <sys/dnode.h>
  38 #include <sys/zap.h>
  39 #include <sys/sa.h>
  40 #include <sys/sunddi.h>
  41 #include <sys/sa_impl.h>
  42 #include <sys/dnode.h>
  43 #include <sys/errno.h>
  44 #include <sys/zfs_context.h>
  45 
 
 
 193  * This is only used for objects of type DMU_OT_ZNODE
 194  */
 195 sa_attr_type_t sa_legacy_zpl_layout[] = {
 196     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
 197 };
 198 
 199 /*
 200  * Special dummy layout used for buffers with no attributes.
 201  */
 202 sa_attr_type_t sa_dummy_zpl_layout[] = { 0 };
 203 
 204 static int sa_legacy_attr_count = 16;
 205 static kmem_cache_t *sa_cache = NULL;
 206 
 207 /*ARGSUSED*/
 208 static int
 209 sa_cache_constructor(void *buf, void *unused, int kmflag)
 210 {
 211         sa_handle_t *hdl = buf;
 212 
 213         hdl->sa_bonus_tab = NULL;
 214         hdl->sa_spill_tab = NULL;
 215         hdl->sa_os = NULL;
 216         hdl->sa_userp = NULL;
 217         hdl->sa_bonus = NULL;
 218         hdl->sa_spill = NULL;
 219         mutex_init(&hdl->sa_lock, NULL, MUTEX_DEFAULT, NULL);
 220         return (0);
 221 }
 222 
 223 /*ARGSUSED*/
 224 static void
 225 sa_cache_destructor(void *buf, void *unused)
 226 {
 227         sa_handle_t *hdl = buf;
 228         mutex_destroy(&hdl->sa_lock);
 229 }
 230 
 231 void
 232 sa_cache_init(void)
 233 {
 234         sa_cache = kmem_cache_create("sa_cache",
 235             sizeof (sa_handle_t), 0, sa_cache_constructor,
 236             sa_cache_destructor, NULL, NULL, NULL, 0);
 237 }
 238 
 239 void
 240 sa_cache_fini(void)
 241 {
 242         if (sa_cache)
 243                 kmem_cache_destroy(sa_cache);
 244 }
 245 
 246 static int
 247 layout_num_compare(const void *arg1, const void *arg2)
 
1284 
1285         /* only check if not old znode */
1286         if (IS_SA_BONUSTYPE(bonustype) && sa_hdr_phys->sa_magic != SA_MAGIC &&
1287             sa_hdr_phys->sa_magic != 0) {
1288                 VERIFY(BSWAP_32(sa_hdr_phys->sa_magic) == SA_MAGIC);
1289                 sa_byteswap(hdl, buftype);
1290         }
1291 
1292         idx_tab = sa_find_idx_tab(hdl->sa_os, bonustype, sa_hdr_phys);
1293 
1294         if (buftype == SA_BONUS)
1295                 hdl->sa_bonus_tab = idx_tab;
1296         else
1297                 hdl->sa_spill_tab = idx_tab;
1298 
1299         mutex_exit(&sa->sa_lock);
1300         return (0);
1301 }
1302 
1303 /*ARGSUSED*/
1304 void
1305 sa_evict(dmu_buf_t *db, void *sap)
1306 {
1307         panic("evicting sa dbuf %p\n", (void *)db);
1308 }
1309 
1310 static void
1311 sa_idx_tab_rele(objset_t *os, void *arg)
1312 {
1313         sa_os_t *sa = os->os_sa;
1314         sa_idx_tab_t *idx_tab = arg;
1315 
1316         if (idx_tab == NULL)
1317                 return;
1318 
1319         mutex_enter(&sa->sa_lock);
1320         if (refcount_remove(&idx_tab->sa_refcount, NULL) == 0) {
1321                 list_remove(&idx_tab->sa_layout->lot_idx_tab, idx_tab);
1322                 if (idx_tab->sa_variable_lengths)
1323                         kmem_free(idx_tab->sa_variable_lengths,
1324                             sizeof (uint16_t) *
1325                             idx_tab->sa_layout->lot_var_sizes);
1326                 refcount_destroy(&idx_tab->sa_refcount);
1327                 kmem_free(idx_tab->sa_idx_tab,
1328                     sizeof (uint32_t) * sa->sa_num_attrs);
1329                 kmem_free(idx_tab, sizeof (sa_idx_tab_t));
1330         }
1331         mutex_exit(&sa->sa_lock);
1332 }
1333 
1334 static void
1335 sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab)
1336 {
1337         sa_os_t *sa = os->os_sa;
1338 
1339         ASSERT(MUTEX_HELD(&sa->sa_lock));
1340         (void) refcount_add(&idx_tab->sa_refcount, NULL);
1341 }
1342 
1343 void
1344 sa_handle_destroy(sa_handle_t *hdl)
1345 {
1346         mutex_enter(&hdl->sa_lock);
1347         (void) dmu_buf_update_user((dmu_buf_t *)hdl->sa_bonus, hdl,
1348             NULL, NULL);
1349 
1350         if (hdl->sa_bonus_tab) {
1351                 sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab);
1352                 hdl->sa_bonus_tab = NULL;
1353         }
1354         if (hdl->sa_spill_tab) {
1355                 sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab);
1356                 hdl->sa_spill_tab = NULL;
1357         }
1358 
1359         dmu_buf_rele(hdl->sa_bonus, NULL);
1360 
1361         if (hdl->sa_spill)
1362                 dmu_buf_rele((dmu_buf_t *)hdl->sa_spill, NULL);
1363         mutex_exit(&hdl->sa_lock);
1364 
1365         kmem_cache_free(sa_cache, hdl);
1366 }
1367 
1368 int
1369 sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
1370     sa_handle_type_t hdl_type, sa_handle_t **handlepp)
1371 {
1372         int error = 0;
1373         dmu_object_info_t doi;
1374         sa_handle_t *handle;
1375 
1376 #ifdef ZFS_DEBUG
1377         dmu_object_info_from_db(db, &doi);
1378         ASSERT(doi.doi_bonus_type == DMU_OT_SA ||
1379             doi.doi_bonus_type == DMU_OT_ZNODE);
1380 #endif
1381         /* find handle, if it exists */
1382         /* if one doesn't exist then create a new one, and initialize it */
1383 
1384         handle = (hdl_type == SA_HDL_SHARED) ? dmu_buf_get_user(db) : NULL;
1385         if (handle == NULL) {
1386                 sa_handle_t *newhandle;
1387                 handle = kmem_cache_alloc(sa_cache, KM_SLEEP);
1388                 handle->sa_userp = userp;
1389                 handle->sa_bonus = db;
1390                 handle->sa_os = os;
1391                 handle->sa_spill = NULL;
1392 
1393                 error = sa_build_index(handle, SA_BONUS);
1394                 newhandle = (hdl_type == SA_HDL_SHARED) ?
1395                     dmu_buf_set_user_ie(db, handle, sa_evict) : NULL;
1396 
1397                 if (newhandle != NULL) {
1398                         kmem_cache_free(sa_cache, handle);
1399                         handle = newhandle;
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 }
 
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_update_user(sa_handle_t *newhdl, sa_handle_t *oldhdl)
1911 {
1912         (void) dmu_buf_update_user((dmu_buf_t *)newhdl->sa_bonus,
1913             oldhdl, newhdl, sa_evict);
1914         oldhdl->sa_bonus = NULL;
1915 }
1916 
1917 void
1918 sa_set_userp(sa_handle_t *hdl, void *ptr)
1919 {
1920         hdl->sa_userp = ptr;
1921 }
1922 
1923 dmu_buf_t *
1924 sa_get_db(sa_handle_t *hdl)
1925 {
1926         return ((dmu_buf_t *)hdl->sa_bonus);
1927 }
1928 
1929 void *
1930 sa_get_userdata(sa_handle_t *hdl)
1931 {
1932         return (hdl->sa_userp);
1933 }
1934 
1935 void
1936 sa_register_update_callback_locked(objset_t *os, sa_update_cb_t *func)
 
 | 
 
 
   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 
 
 
 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         hdl->sa_dbu.dbu_evict_func = NULL;
 215         hdl->sa_bonus_tab = NULL;
 216         hdl->sa_spill_tab = NULL;
 217         hdl->sa_os = NULL;
 218         hdl->sa_userp = NULL;
 219         hdl->sa_bonus = NULL;
 220         hdl->sa_spill = NULL;
 221         mutex_init(&hdl->sa_lock, NULL, MUTEX_DEFAULT, NULL);
 222         return (0);
 223 }
 224 
 225 /*ARGSUSED*/
 226 static void
 227 sa_cache_destructor(void *buf, void *unused)
 228 {
 229         sa_handle_t *hdl = buf;
 230         hdl->sa_dbu.dbu_evict_func = NULL;
 231         mutex_destroy(&hdl->sa_lock);
 232 }
 233 
 234 void
 235 sa_cache_init(void)
 236 {
 237         sa_cache = kmem_cache_create("sa_cache",
 238             sizeof (sa_handle_t), 0, sa_cache_constructor,
 239             sa_cache_destructor, NULL, NULL, NULL, 0);
 240 }
 241 
 242 void
 243 sa_cache_fini(void)
 244 {
 245         if (sa_cache)
 246                 kmem_cache_destroy(sa_cache);
 247 }
 248 
 249 static int
 250 layout_num_compare(const void *arg1, const void *arg2)
 
1287 
1288         /* only check if not old znode */
1289         if (IS_SA_BONUSTYPE(bonustype) && sa_hdr_phys->sa_magic != SA_MAGIC &&
1290             sa_hdr_phys->sa_magic != 0) {
1291                 VERIFY(BSWAP_32(sa_hdr_phys->sa_magic) == SA_MAGIC);
1292                 sa_byteswap(hdl, buftype);
1293         }
1294 
1295         idx_tab = sa_find_idx_tab(hdl->sa_os, bonustype, sa_hdr_phys);
1296 
1297         if (buftype == SA_BONUS)
1298                 hdl->sa_bonus_tab = idx_tab;
1299         else
1300                 hdl->sa_spill_tab = idx_tab;
1301 
1302         mutex_exit(&sa->sa_lock);
1303         return (0);
1304 }
1305 
1306 /*ARGSUSED*/
1307 static void
1308 sa_evict(void *dbu)
1309 {
1310         panic("evicting sa dbuf\n");
1311 }
1312 
1313 static void
1314 sa_idx_tab_rele(objset_t *os, void *arg)
1315 {
1316         sa_os_t *sa = os->os_sa;
1317         sa_idx_tab_t *idx_tab = arg;
1318 
1319         if (idx_tab == NULL)
1320                 return;
1321 
1322         mutex_enter(&sa->sa_lock);
1323         if (refcount_remove(&idx_tab->sa_refcount, NULL) == 0) {
1324                 list_remove(&idx_tab->sa_layout->lot_idx_tab, idx_tab);
1325                 if (idx_tab->sa_variable_lengths)
1326                         kmem_free(idx_tab->sa_variable_lengths,
1327                             sizeof (uint16_t) *
1328                             idx_tab->sa_layout->lot_var_sizes);
1329                 refcount_destroy(&idx_tab->sa_refcount);
1330                 kmem_free(idx_tab->sa_idx_tab,
1331                     sizeof (uint32_t) * sa->sa_num_attrs);
1332                 kmem_free(idx_tab, sizeof (sa_idx_tab_t));
1333         }
1334         mutex_exit(&sa->sa_lock);
1335 }
1336 
1337 static void
1338 sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab)
1339 {
1340         sa_os_t *sa = os->os_sa;
1341 
1342         ASSERT(MUTEX_HELD(&sa->sa_lock));
1343         (void) refcount_add(&idx_tab->sa_refcount, NULL);
1344 }
1345 
1346 void
1347 sa_handle_destroy(sa_handle_t *hdl)
1348 {
1349         dmu_buf_t *db = hdl->sa_bonus;
1350 
1351         mutex_enter(&hdl->sa_lock);
1352         (void) dmu_buf_remove_user(db, &hdl->sa_dbu);
1353 
1354         if (hdl->sa_bonus_tab) {
1355                 sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab);
1356                 hdl->sa_bonus_tab = NULL;
1357         }
1358         if (hdl->sa_spill_tab) {
1359                 sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab);
1360                 hdl->sa_spill_tab = NULL;
1361         }
1362 
1363         dmu_buf_rele(hdl->sa_bonus, NULL);
1364 
1365         if (hdl->sa_spill)
1366                 dmu_buf_rele((dmu_buf_t *)hdl->sa_spill, NULL);
1367         mutex_exit(&hdl->sa_lock);
1368 
1369         kmem_cache_free(sa_cache, hdl);
1370 }
1371 
1372 int
1373 sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
1374     sa_handle_type_t hdl_type, sa_handle_t **handlepp)
1375 {
1376         int error = 0;
1377         dmu_object_info_t doi;
1378         sa_handle_t *handle = NULL;
1379 
1380 #ifdef ZFS_DEBUG
1381         dmu_object_info_from_db(db, &doi);
1382         ASSERT(doi.doi_bonus_type == DMU_OT_SA ||
1383             doi.doi_bonus_type == DMU_OT_ZNODE);
1384 #endif
1385         /* find handle, if it exists */
1386         /* if one doesn't exist then create a new one, and initialize it */
1387 
1388         if (hdl_type == SA_HDL_SHARED)
1389                 handle = dmu_buf_get_user(db);
1390 
1391         if (handle == NULL) {
1392                 sa_handle_t *winner = NULL;
1393 
1394                 handle = kmem_cache_alloc(sa_cache, KM_SLEEP);
1395                 handle->sa_userp = userp;
1396                 handle->sa_bonus = db;
1397                 handle->sa_os = os;
1398                 handle->sa_spill = NULL;
1399 
1400                 error = sa_build_index(handle, SA_BONUS);
1401 
1402                 if (hdl_type == SA_HDL_SHARED) {
1403                         dmu_buf_init_user(&handle->sa_dbu, sa_evict, NULL);
1404                         winner = dmu_buf_set_user_ie(db, &handle->sa_dbu);
1405                 }
1406 
1407                 if (winner != NULL) {
1408                         kmem_cache_free(sa_cache, handle);
1409                         handle = winner;
1410                 }
1411         }
1412         *handlepp = handle;
1413 
1414         return (error);
1415 }
1416 
1417 int
1418 sa_handle_get(objset_t *objset, uint64_t objid, void *userp,
1419     sa_handle_type_t hdl_type, sa_handle_t **handlepp)
1420 {
1421         dmu_buf_t *db;
1422         int error;
1423 
1424         if (error = dmu_bonus_hold(objset, objid, NULL, &db))
1425                 return (error);
1426 
1427         return (sa_handle_get_from_db(objset, db, userp, hdl_type,
1428             handlepp));
1429 }
 
1899         mutex_enter(&hdl->sa_lock);
1900         error = sa_modify_attrs(hdl, attr, SA_REMOVE, NULL,
1901             NULL, 0, tx);
1902         mutex_exit(&hdl->sa_lock);
1903         return (error);
1904 }
1905 
1906 void
1907 sa_object_info(sa_handle_t *hdl, dmu_object_info_t *doi)
1908 {
1909         dmu_object_info_from_db((dmu_buf_t *)hdl->sa_bonus, doi);
1910 }
1911 
1912 void
1913 sa_object_size(sa_handle_t *hdl, uint32_t *blksize, u_longlong_t *nblocks)
1914 {
1915         dmu_object_size_from_db((dmu_buf_t *)hdl->sa_bonus,
1916             blksize, nblocks);
1917 }
1918 
1919 void
1920 sa_set_userp(sa_handle_t *hdl, void *ptr)
1921 {
1922         hdl->sa_userp = ptr;
1923 }
1924 
1925 dmu_buf_t *
1926 sa_get_db(sa_handle_t *hdl)
1927 {
1928         return ((dmu_buf_t *)hdl->sa_bonus);
1929 }
1930 
1931 void *
1932 sa_get_userdata(sa_handle_t *hdl)
1933 {
1934         return (hdl->sa_userp);
1935 }
1936 
1937 void
1938 sa_register_update_callback_locked(objset_t *os, sa_update_cb_t *func)
 
 |