Print this page
5056 ZFS deadlock on db_mtx and dn_holds
Reviewed by: Will Andrews <willa@spectralogic.com>
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>

*** 21,30 **** --- 21,31 ---- /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Portions Copyright 2011 iXsystems, Inc * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. */ #include <sys/zfs_context.h> #include <sys/types.h> #include <sys/param.h>
*** 208,217 **** --- 209,219 ---- static int sa_cache_constructor(void *buf, void *unused, int kmflag) { sa_handle_t *hdl = buf; + hdl->sa_dbu.dbu_evict_func = NULL; hdl->sa_bonus_tab = NULL; hdl->sa_spill_tab = NULL; hdl->sa_os = NULL; hdl->sa_userp = NULL; hdl->sa_bonus = NULL;
*** 223,232 **** --- 225,235 ---- /*ARGSUSED*/ static void sa_cache_destructor(void *buf, void *unused) { sa_handle_t *hdl = buf; + hdl->sa_dbu.dbu_evict_func = NULL; mutex_destroy(&hdl->sa_lock); } void sa_cache_init(void)
*** 1299,1312 **** mutex_exit(&sa->sa_lock); return (0); } /*ARGSUSED*/ ! void ! sa_evict(dmu_buf_t *db, void *sap) { ! panic("evicting sa dbuf %p\n", (void *)db); } static void sa_idx_tab_rele(objset_t *os, void *arg) { --- 1302,1315 ---- mutex_exit(&sa->sa_lock); return (0); } /*ARGSUSED*/ ! static void ! sa_evict(void *dbu) { ! panic("evicting sa dbuf\n"); } static void sa_idx_tab_rele(objset_t *os, void *arg) {
*** 1341,1353 **** } void sa_handle_destroy(sa_handle_t *hdl) { mutex_enter(&hdl->sa_lock); ! (void) dmu_buf_update_user((dmu_buf_t *)hdl->sa_bonus, hdl, ! NULL, NULL); if (hdl->sa_bonus_tab) { sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab); hdl->sa_bonus_tab = NULL; } --- 1344,1357 ---- } void sa_handle_destroy(sa_handle_t *hdl) { + dmu_buf_t *db = hdl->sa_bonus; + mutex_enter(&hdl->sa_lock); ! (void) dmu_buf_remove_user(db, &hdl->sa_dbu); if (hdl->sa_bonus_tab) { sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab); hdl->sa_bonus_tab = NULL; }
*** 1369,1404 **** sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp, sa_handle_type_t hdl_type, sa_handle_t **handlepp) { int error = 0; dmu_object_info_t doi; ! sa_handle_t *handle; #ifdef ZFS_DEBUG dmu_object_info_from_db(db, &doi); ASSERT(doi.doi_bonus_type == DMU_OT_SA || doi.doi_bonus_type == DMU_OT_ZNODE); #endif /* find handle, if it exists */ /* if one doesn't exist then create a new one, and initialize it */ ! handle = (hdl_type == SA_HDL_SHARED) ? dmu_buf_get_user(db) : NULL; if (handle == NULL) { ! sa_handle_t *newhandle; handle = kmem_cache_alloc(sa_cache, KM_SLEEP); handle->sa_userp = userp; handle->sa_bonus = db; handle->sa_os = os; handle->sa_spill = NULL; error = sa_build_index(handle, SA_BONUS); - newhandle = (hdl_type == SA_HDL_SHARED) ? - dmu_buf_set_user_ie(db, handle, sa_evict) : NULL; ! if (newhandle != NULL) { kmem_cache_free(sa_cache, handle); ! handle = newhandle; } } *handlepp = handle; return (error); --- 1373,1414 ---- sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp, sa_handle_type_t hdl_type, sa_handle_t **handlepp) { int error = 0; dmu_object_info_t doi; ! sa_handle_t *handle = NULL; #ifdef ZFS_DEBUG dmu_object_info_from_db(db, &doi); ASSERT(doi.doi_bonus_type == DMU_OT_SA || doi.doi_bonus_type == DMU_OT_ZNODE); #endif /* find handle, if it exists */ /* if one doesn't exist then create a new one, and initialize it */ ! if (hdl_type == SA_HDL_SHARED) ! handle = dmu_buf_get_user(db); ! if (handle == NULL) { ! sa_handle_t *winner = NULL; ! handle = kmem_cache_alloc(sa_cache, KM_SLEEP); handle->sa_userp = userp; handle->sa_bonus = db; handle->sa_os = os; handle->sa_spill = NULL; error = sa_build_index(handle, SA_BONUS); ! if (hdl_type == SA_HDL_SHARED) { ! dmu_buf_init_user(&handle->sa_dbu, sa_evict, NULL); ! winner = dmu_buf_set_user_ie(db, &handle->sa_dbu); ! } ! ! if (winner != NULL) { kmem_cache_free(sa_cache, handle); ! handle = winner; } } *handlepp = handle; return (error);
*** 1904,1921 **** { dmu_object_size_from_db((dmu_buf_t *)hdl->sa_bonus, blksize, nblocks); } - void - sa_update_user(sa_handle_t *newhdl, sa_handle_t *oldhdl) - { - (void) dmu_buf_update_user((dmu_buf_t *)newhdl->sa_bonus, - oldhdl, newhdl, sa_evict); - oldhdl->sa_bonus = NULL; - } - void sa_set_userp(sa_handle_t *hdl, void *ptr) { hdl->sa_userp = ptr; } --- 1914,1923 ----