mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 19:04:45 +03:00
Illumos 5056 - ZFS deadlock on db_mtx and dn_holds
5056 ZFS deadlock on db_mtx and dn_holds Author: Justin Gibbs <justing@spectralogic.com> 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> References: https://www.illumos.org/issues/5056 https://github.com/illumos/illumos-gate/commit/bc9014e Porting Notes: sa_handle_get_from_db(): - the original patch includes an otherwise unmentioned fix for a possible usage of an uninitialised variable dmu_objset_open_impl(): - Under Illumos list_link_init() is the same as filling a list_node_t with NULLs, so they don't notice if they miss doing list_link_init() on a zero'd containing structure (e.g. allocated with kmem_zalloc as here). Under Linux, not so much: an uninitialised list_node_t goes "Boom!" some time later when it's used or destroyed. dmu_objset_evict_dbufs(): - reduce stack usage using kmem_alloc() Ported-by: Chris Dunlop <chris@onthe.net.au> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
committed by
Brian Behlendorf
parent
d683ddbb72
commit
0c66c32d1d
+22
-21
@@ -22,6 +22,7 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
@@ -209,6 +210,7 @@ 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;
|
||||
@@ -224,6 +226,7 @@ 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);
|
||||
}
|
||||
|
||||
@@ -1306,10 +1309,10 @@ sa_build_index(sa_handle_t *hdl, sa_buf_type_t buftype)
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
sa_evict(dmu_buf_t *db, void *sap)
|
||||
static void
|
||||
sa_evict(void *dbu)
|
||||
{
|
||||
panic("evicting sa dbuf %p\n", (void *)db);
|
||||
panic("evicting sa dbuf\n");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1361,9 +1364,10 @@ sa_spill_rele(sa_handle_t *hdl)
|
||||
void
|
||||
sa_handle_destroy(sa_handle_t *hdl)
|
||||
{
|
||||
dmu_buf_t *db = hdl->sa_bonus;
|
||||
|
||||
mutex_enter(&hdl->sa_lock);
|
||||
(void) dmu_buf_update_user((dmu_buf_t *)hdl->sa_bonus, hdl,
|
||||
NULL, NULL);
|
||||
(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);
|
||||
@@ -1388,7 +1392,7 @@ 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;
|
||||
sa_handle_t *handle;
|
||||
sa_handle_t *handle = NULL;
|
||||
#ifdef ZFS_DEBUG
|
||||
dmu_object_info_t doi;
|
||||
|
||||
@@ -1399,9 +1403,12 @@ sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
|
||||
/* 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 (hdl_type == SA_HDL_SHARED)
|
||||
handle = dmu_buf_get_user(db);
|
||||
|
||||
if (handle == NULL) {
|
||||
sa_handle_t *newhandle;
|
||||
sa_handle_t *winner = NULL;
|
||||
|
||||
handle = kmem_cache_alloc(sa_cache, KM_SLEEP);
|
||||
handle->sa_userp = userp;
|
||||
handle->sa_bonus = db;
|
||||
@@ -1409,12 +1416,15 @@ sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
|
||||
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) {
|
||||
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 = newhandle;
|
||||
handle = winner;
|
||||
}
|
||||
}
|
||||
*handlepp = handle;
|
||||
@@ -1946,14 +1956,6 @@ sa_object_size(sa_handle_t *hdl, uint32_t *blksize, u_longlong_t *nblocks)
|
||||
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)
|
||||
{
|
||||
@@ -2052,7 +2054,6 @@ EXPORT_SYMBOL(sa_size);
|
||||
EXPORT_SYMBOL(sa_update_from_cb);
|
||||
EXPORT_SYMBOL(sa_object_info);
|
||||
EXPORT_SYMBOL(sa_object_size);
|
||||
EXPORT_SYMBOL(sa_update_user);
|
||||
EXPORT_SYMBOL(sa_get_userdata);
|
||||
EXPORT_SYMBOL(sa_set_userp);
|
||||
EXPORT_SYMBOL(sa_get_db);
|
||||
|
||||
Reference in New Issue
Block a user