Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/sys/dmu_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ extern "C" {
* dn_free_txg
* dn_assigned_txg
* dn_dirty_txg
* dn_dirtycnt
* dd_assigned_tx
* dn_notxholds
* dn_nodnholds
Expand Down
1 change: 1 addition & 0 deletions include/sys/dnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ struct dnode {
uint64_t dn_free_txg;
uint64_t dn_assigned_txg;
uint64_t dn_dirty_txg; /* txg dnode was last dirtied */
uint8_t dn_dirtycnt;
kcondvar_t dn_notxholds;
kcondvar_t dn_nodnholds;
enum dnode_dirtycontext dn_dirtyctx;
Expand Down
6 changes: 6 additions & 0 deletions module/zfs/dmu_objset.c
Original file line number Diff line number Diff line change
Expand Up @@ -2037,6 +2037,8 @@ userquota_updates_task(void *arg)
dn->dn_id_flags |= DN_ID_CHKED_BONUS;
}
dn->dn_id_flags &= ~(DN_ID_NEW_EXIST);
ASSERT3U(dn->dn_dirtycnt, >, 0);
dn->dn_dirtycnt--;
mutex_exit(&dn->dn_mtx);

multilist_sublist_remove(list, dn);
Expand Down Expand Up @@ -2070,6 +2072,10 @@ dnode_rele_task(void *arg)

dnode_t *dn;
while ((dn = multilist_sublist_head(list)) != NULL) {
mutex_enter(&dn->dn_mtx);
ASSERT3U(dn->dn_dirtycnt, >, 0);
dn->dn_dirtycnt--;
mutex_exit(&dn->dn_mtx);
multilist_sublist_remove(list, dn);
dnode_rele(dn, &os->os_synced_dnodes);
}
Expand Down
30 changes: 23 additions & 7 deletions module/zfs/dnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ dnode_cons(void *arg, void *unused, int kmflag)
dn->dn_dirty_txg = 0;
dn->dn_dirtyctx = 0;
dn->dn_dirtyctx_firstset = NULL;
dn->dn_dirtycnt = 0;
dn->dn_bonus = NULL;
dn->dn_have_spill = B_FALSE;
dn->dn_zio = NULL;
Expand Down Expand Up @@ -232,6 +233,7 @@ dnode_dest(void *arg, void *unused)
ASSERT0(dn->dn_dirty_txg);
ASSERT0(dn->dn_dirtyctx);
ASSERT0P(dn->dn_dirtyctx_firstset);
ASSERT0(dn->dn_dirtycnt);
ASSERT0P(dn->dn_bonus);
ASSERT(!dn->dn_have_spill);
ASSERT0P(dn->dn_zio);
Expand Down Expand Up @@ -693,6 +695,7 @@ dnode_destroy(dnode_t *dn)
dn->dn_free_txg = 0;
dn->dn_assigned_txg = 0;
dn->dn_dirty_txg = 0;
dn->dn_dirtycnt = 0;

dn->dn_dirtyctx = 0;
dn->dn_dirtyctx_firstset = NULL;
Expand Down Expand Up @@ -805,6 +808,7 @@ dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
dn->dn_free_txg = 0;
dn->dn_dirtyctx_firstset = NULL;
dn->dn_dirty_txg = 0;
dn->dn_dirtycnt = 0;

dn->dn_allocated_txg = tx->tx_txg;
dn->dn_id_flags = 0;
Expand Down Expand Up @@ -958,6 +962,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
ndn->dn_dirty_txg = odn->dn_dirty_txg;
ndn->dn_dirtyctx = odn->dn_dirtyctx;
ndn->dn_dirtyctx_firstset = odn->dn_dirtyctx_firstset;
ndn->dn_dirtycnt = odn->dn_dirtycnt;
ASSERT0(zfs_refcount_count(&odn->dn_tx_holds));
zfs_refcount_transfer(&ndn->dn_holds, &odn->dn_holds);
ASSERT(avl_is_empty(&ndn->dn_dbufs));
Expand Down Expand Up @@ -1023,6 +1028,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
odn->dn_dirty_txg = 0;
odn->dn_dirtyctx = 0;
odn->dn_dirtyctx_firstset = NULL;
odn->dn_dirtycnt = 0;
odn->dn_have_spill = B_FALSE;
odn->dn_zio = NULL;
odn->dn_oldused = 0;
Expand Down Expand Up @@ -1757,17 +1763,23 @@ dnode_hold(objset_t *os, uint64_t object, const void *tag, dnode_t **dnp)
* reference on the dnode. Returns FALSE if unable to add a
* new reference.
*/
static boolean_t
dnode_add_ref_locked(dnode_t *dn, const void *tag)
{
ASSERT(MUTEX_HELD(&dn->dn_mtx));
if (zfs_refcount_is_zero(&dn->dn_holds))
return (FALSE);
VERIFY(1 < zfs_refcount_add(&dn->dn_holds, tag));
return (TRUE);
}

boolean_t
dnode_add_ref(dnode_t *dn, const void *tag)
{
mutex_enter(&dn->dn_mtx);
if (zfs_refcount_is_zero(&dn->dn_holds)) {
mutex_exit(&dn->dn_mtx);
return (FALSE);
}
VERIFY(1 < zfs_refcount_add(&dn->dn_holds, tag));
boolean_t r = dnode_add_ref_locked(dn, tag);
mutex_exit(&dn->dn_mtx);
return (TRUE);
return (r);
}

void
Expand Down Expand Up @@ -1916,7 +1928,11 @@ dnode_setdirty(dnode_t *dn, dmu_tx_t *tx)
* dnode will hang around after we finish processing its
* children.
*/
VERIFY(dnode_add_ref(dn, (void *)(uintptr_t)tx->tx_txg));
mutex_enter(&dn->dn_mtx);
VERIFY(dnode_add_ref_locked(dn, (void *)(uintptr_t)tx->tx_txg));
dn->dn_dirtycnt++;
ASSERT3U(dn->dn_dirtycnt, <=, 3);
mutex_exit(&dn->dn_mtx);

(void) dbuf_dirty(dn->dn_dbuf, tx);

Expand Down