Print this page
5981 Deadlock in dmu_objset_find_dp

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dmu_objset.c
          +++ new/usr/src/uts/common/fs/zfs/dmu_objset.c
↓ open down ↓ 1738 lines elided ↑ open up ↑
1739 1739  
1740 1740          kmem_free(dcp, sizeof(*dcp));
1741 1741  }
1742 1742  
1743 1743  static void
1744 1744  dmu_objset_find_dp_cb(void *arg)
1745 1745  {
1746 1746          dmu_objset_find_ctx_t *dcp = arg;
1747 1747          dsl_pool_t *dp = dcp->dc_dp;
1748 1748  
1749      -        dsl_pool_config_enter(dp, FTAG);
     1749 +        /*
     1750 +         * We need to get a pool_config_lock here, as there are several
     1751 +         * asssert(pool_config_held) down the stack. Getting a lock via
     1752 +         * dsl_pool_config_enter is risky, as it might be stalled by a
     1753 +         * pending writer. This would deadlock, as the write lock can
     1754 +         * only be granted when our parent thread gives up the lock.
     1755 +         * The _prio interface gives us priority over a pending writer.
     1756 +         * On the other hand, we don't risk to stall any pending writers,
     1757 +         * as the parent thread already holds a config lock. We give up
     1758 +         * our lock before the parent does, so in effect we do not prolong
     1759 +         * the waiting time for the writer.
     1760 +         */
     1761 +        dsl_pool_config_enter_prio(dp, FTAG);
1750 1762  
1751 1763          dmu_objset_find_dp_impl(dcp);
1752 1764  
1753 1765          dsl_pool_config_exit(dp, FTAG);
1754 1766  }
1755 1767  
1756 1768  /*
1757 1769   * Find objsets under and including ddobj, call func(ds) on each.
1758 1770   * The order for the enumeration is completely undefined.
1759 1771   * func is called with dsl_pool_config held.
↓ open down ↓ 230 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX