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)
|