mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-26 04:07:45 +03:00
Illumos 6267 - dn_bonus evicted too early
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> References: https://www.illumos.org/issues/6267 https://github.com/illumos/illumos-gate/commit/d205810 Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Ported-by: Ned Bass bass6@llnl.gov Issue #3865 Issue #3443
This commit is contained in:
committed by
Brian Behlendorf
parent
33df62d052
commit
bc4501f75a
+12
-35
@@ -303,7 +303,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);
|
||||
@@ -1880,8 +1880,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);
|
||||
@@ -2318,12 +2319,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
|
||||
@@ -2338,7 +2340,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);
|
||||
|
||||
@@ -2348,35 +2350,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
|
||||
@@ -2423,7 +2400,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 {
|
||||
@@ -2471,7 +2448,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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user