summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-11-13 09:23:48 +0000
committermav <mav@FreeBSD.org>2015-11-13 09:23:48 +0000
commit23798dd760a273ed2b72d6e4a324d8b6e383829f (patch)
tree813bf1f49e784e28394f1627cde5d2fb41cbbc98 /sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
parentdbcbfaf0f164dbb9913f9d6c2a2fc956749d1729 (diff)
downloadFreeBSD-src-23798dd760a273ed2b72d6e4a324d8b6e383829f.zip
FreeBSD-src-23798dd760a273ed2b72d6e4a324d8b6e383829f.tar.gz
MFC r289309: 6267 dn_bonus evicted too early
Reviewed by: Richard Yao <ryao@gentoo.org> Reviewed by: Xin LI <delphij@freebsd.org> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net> Author: Justin T. Gibbs <gibbs@FreeBSD.org> illumos/illumos-gate@d2058105c61ec61df3a2dd3f839fed8c3fe7bfd6
Diffstat (limited to 'sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c47
1 files changed, 12 insertions, 35 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
index ba630a5..f39a353 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
@@ -267,7 +267,7 @@ dbuf_verify_user(dmu_buf_impl_t *db, dbvu_verify_type_t verify_type)
*/
ASSERT3U(holds, >=, db->db_dirtycnt);
} else {
- if (db->db_immediate_evict == TRUE)
+ if (db->db_user_immediate_evict == TRUE)
ASSERT3U(holds, >=, db->db_dirtycnt);
else
ASSERT3U(holds, >, 0);
@@ -1870,8 +1870,9 @@ dbuf_create(dnode_t *dn, uint8_t level, uint64_t blkid,
db->db_blkptr = blkptr;
db->db_user = NULL;
- db->db_immediate_evict = 0;
- db->db_freed_in_flight = 0;
+ db->db_user_immediate_evict = FALSE;
+ db->db_freed_in_flight = FALSE;
+ db->db_pending_evict = FALSE;
if (blkid == DMU_BONUS_BLKID) {
ASSERT3P(parent, ==, dn->dn_dbuf);
@@ -2427,12 +2428,13 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag)
arc_buf_freeze(db->db_buf);
if (holds == db->db_dirtycnt &&
- db->db_level == 0 && db->db_immediate_evict)
+ db->db_level == 0 && db->db_user_immediate_evict)
dbuf_evict_user(db);
if (holds == 0) {
if (db->db_blkid == DMU_BONUS_BLKID) {
dnode_t *dn;
+ boolean_t evict_dbuf = db->db_pending_evict;
/*
* If the dnode moves here, we cannot cross this
@@ -2447,7 +2449,7 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag)
* Decrementing the dbuf count means that the bonus
* buffer's dnode hold is no longer discounted in
* dnode_move(). The dnode cannot move until after
- * the dnode_rele_and_unlock() below.
+ * the dnode_rele() below.
*/
DB_DNODE_EXIT(db);
@@ -2457,35 +2459,10 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag)
*/
mutex_exit(&db->db_mtx);
- /*
- * If the dnode has been freed, evict the bonus
- * buffer immediately. The data in the bonus
- * buffer is no longer relevant and this prevents
- * a stale bonus buffer from being associated
- * with this dnode_t should the dnode_t be reused
- * prior to being destroyed.
- */
- mutex_enter(&dn->dn_mtx);
- if (dn->dn_type == DMU_OT_NONE ||
- dn->dn_free_txg != 0) {
- /*
- * Drop dn_mtx. It is a leaf lock and
- * cannot be held when dnode_evict_bonus()
- * acquires other locks in order to
- * perform the eviction.
- *
- * Freed dnodes cannot be reused until the
- * last hold is released. Since this bonus
- * buffer has a hold, the dnode will remain
- * in the free state, even without dn_mtx
- * held, until the dnode_rele_and_unlock()
- * below.
- */
- mutex_exit(&dn->dn_mtx);
+ if (evict_dbuf)
dnode_evict_bonus(dn);
- mutex_enter(&dn->dn_mtx);
- }
- dnode_rele_and_unlock(dn, db);
+
+ dnode_rele(dn, db);
} else if (db->db_buf == NULL) {
/*
* This is a special case: we never associated this
@@ -2532,7 +2509,7 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag)
} else {
dbuf_clear(db);
}
- } else if (db->db_objset->os_evicting ||
+ } else if (db->db_pending_evict ||
arc_buf_eviction_needed(db->db_buf)) {
dbuf_clear(db);
} else {
@@ -2580,7 +2557,7 @@ dmu_buf_set_user_ie(dmu_buf_t *db_fake, dmu_buf_user_t *user)
{
dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake;
- db->db_immediate_evict = TRUE;
+ db->db_user_immediate_evict = TRUE;
return (dmu_buf_set_user(db_fake, user));
}
OpenPOWER on IntegriCloud