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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/sa.c
          +++ new/usr/src/uts/common/fs/zfs/sa.c
↓ open down ↓ 15 lines elided ↑ open up ↑
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Portions Copyright 2011 iXsystems, Inc
  25   25   * Copyright (c) 2013 by Delphix. All rights reserved.
       26 + * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
  26   27   */
  27   28  
  28   29  #include <sys/zfs_context.h>
  29   30  #include <sys/types.h>
  30   31  #include <sys/param.h>
  31   32  #include <sys/systm.h>
  32   33  #include <sys/sysmacros.h>
  33   34  #include <sys/dmu.h>
  34   35  #include <sys/dmu_impl.h>
  35   36  #include <sys/dmu_objset.h>
↓ open down ↓ 167 lines elided ↑ open up ↑
 203  204  
 204  205  static int sa_legacy_attr_count = 16;
 205  206  static kmem_cache_t *sa_cache = NULL;
 206  207  
 207  208  /*ARGSUSED*/
 208  209  static int
 209  210  sa_cache_constructor(void *buf, void *unused, int kmflag)
 210  211  {
 211  212          sa_handle_t *hdl = buf;
 212  213  
      214 +        hdl->sa_dbu.dbu_evict_func = NULL;
 213  215          hdl->sa_bonus_tab = NULL;
 214  216          hdl->sa_spill_tab = NULL;
 215  217          hdl->sa_os = NULL;
 216  218          hdl->sa_userp = NULL;
 217  219          hdl->sa_bonus = NULL;
 218  220          hdl->sa_spill = NULL;
 219  221          mutex_init(&hdl->sa_lock, NULL, MUTEX_DEFAULT, NULL);
 220  222          return (0);
 221  223  }
 222  224  
 223  225  /*ARGSUSED*/
 224  226  static void
 225  227  sa_cache_destructor(void *buf, void *unused)
 226  228  {
 227  229          sa_handle_t *hdl = buf;
      230 +        hdl->sa_dbu.dbu_evict_func = NULL;
 228  231          mutex_destroy(&hdl->sa_lock);
 229  232  }
 230  233  
 231  234  void
 232  235  sa_cache_init(void)
 233  236  {
 234  237          sa_cache = kmem_cache_create("sa_cache",
 235  238              sizeof (sa_handle_t), 0, sa_cache_constructor,
 236  239              sa_cache_destructor, NULL, NULL, NULL, 0);
 237  240  }
↓ open down ↓ 1056 lines elided ↑ open up ↑
1294 1297          if (buftype == SA_BONUS)
1295 1298                  hdl->sa_bonus_tab = idx_tab;
1296 1299          else
1297 1300                  hdl->sa_spill_tab = idx_tab;
1298 1301  
1299 1302          mutex_exit(&sa->sa_lock);
1300 1303          return (0);
1301 1304  }
1302 1305  
1303 1306  /*ARGSUSED*/
1304      -void
1305      -sa_evict(dmu_buf_t *db, void *sap)
     1307 +static void
     1308 +sa_evict(void *dbu)
1306 1309  {
1307      -        panic("evicting sa dbuf %p\n", (void *)db);
     1310 +        panic("evicting sa dbuf\n");
1308 1311  }
1309 1312  
1310 1313  static void
1311 1314  sa_idx_tab_rele(objset_t *os, void *arg)
1312 1315  {
1313 1316          sa_os_t *sa = os->os_sa;
1314 1317          sa_idx_tab_t *idx_tab = arg;
1315 1318  
1316 1319          if (idx_tab == NULL)
1317 1320                  return;
↓ open down ↓ 18 lines elided ↑ open up ↑
1336 1339  {
1337 1340          sa_os_t *sa = os->os_sa;
1338 1341  
1339 1342          ASSERT(MUTEX_HELD(&sa->sa_lock));
1340 1343          (void) refcount_add(&idx_tab->sa_refcount, NULL);
1341 1344  }
1342 1345  
1343 1346  void
1344 1347  sa_handle_destroy(sa_handle_t *hdl)
1345 1348  {
     1349 +        dmu_buf_t *db = hdl->sa_bonus;
     1350 +
1346 1351          mutex_enter(&hdl->sa_lock);
1347      -        (void) dmu_buf_update_user((dmu_buf_t *)hdl->sa_bonus, hdl,
1348      -            NULL, NULL);
     1352 +        (void) dmu_buf_remove_user(db, &hdl->sa_dbu);
1349 1353  
1350 1354          if (hdl->sa_bonus_tab) {
1351 1355                  sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab);
1352 1356                  hdl->sa_bonus_tab = NULL;
1353 1357          }
1354 1358          if (hdl->sa_spill_tab) {
1355 1359                  sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab);
1356 1360                  hdl->sa_spill_tab = NULL;
1357 1361          }
1358 1362  
↓ open down ↓ 5 lines elided ↑ open up ↑
1364 1368  
1365 1369          kmem_cache_free(sa_cache, hdl);
1366 1370  }
1367 1371  
1368 1372  int
1369 1373  sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
1370 1374      sa_handle_type_t hdl_type, sa_handle_t **handlepp)
1371 1375  {
1372 1376          int error = 0;
1373 1377          dmu_object_info_t doi;
1374      -        sa_handle_t *handle;
     1378 +        sa_handle_t *handle = NULL;
1375 1379  
1376 1380  #ifdef ZFS_DEBUG
1377 1381          dmu_object_info_from_db(db, &doi);
1378 1382          ASSERT(doi.doi_bonus_type == DMU_OT_SA ||
1379 1383              doi.doi_bonus_type == DMU_OT_ZNODE);
1380 1384  #endif
1381 1385          /* find handle, if it exists */
1382 1386          /* if one doesn't exist then create a new one, and initialize it */
1383 1387  
1384      -        handle = (hdl_type == SA_HDL_SHARED) ? dmu_buf_get_user(db) : NULL;
     1388 +        if (hdl_type == SA_HDL_SHARED)
     1389 +                handle = dmu_buf_get_user(db);
     1390 +
1385 1391          if (handle == NULL) {
1386      -                sa_handle_t *newhandle;
     1392 +                sa_handle_t *winner = NULL;
     1393 +
1387 1394                  handle = kmem_cache_alloc(sa_cache, KM_SLEEP);
1388 1395                  handle->sa_userp = userp;
1389 1396                  handle->sa_bonus = db;
1390 1397                  handle->sa_os = os;
1391 1398                  handle->sa_spill = NULL;
1392 1399  
1393 1400                  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 1401  
1397      -                if (newhandle != NULL) {
     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) {
1398 1408                          kmem_cache_free(sa_cache, handle);
1399      -                        handle = newhandle;
     1409 +                        handle = winner;
1400 1410                  }
1401 1411          }
1402 1412          *handlepp = handle;
1403 1413  
1404 1414          return (error);
1405 1415  }
1406 1416  
1407 1417  int
1408 1418  sa_handle_get(objset_t *objset, uint64_t objid, void *userp,
1409 1419      sa_handle_type_t hdl_type, sa_handle_t **handlepp)
↓ open down ↓ 489 lines elided ↑ open up ↑
1899 1909          dmu_object_info_from_db((dmu_buf_t *)hdl->sa_bonus, doi);
1900 1910  }
1901 1911  
1902 1912  void
1903 1913  sa_object_size(sa_handle_t *hdl, uint32_t *blksize, u_longlong_t *nblocks)
1904 1914  {
1905 1915          dmu_object_size_from_db((dmu_buf_t *)hdl->sa_bonus,
1906 1916              blksize, nblocks);
1907 1917  }
1908 1918  
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 1919  void
1918 1920  sa_set_userp(sa_handle_t *hdl, void *ptr)
1919 1921  {
1920 1922          hdl->sa_userp = ptr;
1921 1923  }
1922 1924  
1923 1925  dmu_buf_t *
1924 1926  sa_get_db(sa_handle_t *hdl)
1925 1927  {
1926 1928          return ((dmu_buf_t *)hdl->sa_bonus);
↓ open down ↓ 70 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX