Skip to content

Commit

Permalink
Linux: dbuf_undirty should work with uint64_t txg
Browse files Browse the repository at this point in the history
RIP: 0010:dbuf_undirty+0x19/0x820 [zfs]
Call Trace:
 <TASK>
 ? __die+0x1f/0x60
 ? page_fault_oops+0x17d/0x550
 ? zfs_btree_add_idx+0xa4/0x340 [zfs]
 ? exc_page_fault+0x67/0x140
 ? asm_exc_page_fault+0x22/0x30
 ? dbuf_undirty+0x19/0x820 [zfs]
 ? kfree+0x27c/0x310
 ? spl_kmem_cache_free+0x12e/0x270 [spl]
 dmu_write_direct_done+0x126/0x310 [zfs]
 zio_done+0x2df/0x21e0 [zfs]
 zio_execute+0xd7/0x290 [zfs]
 taskq_thread+0x350/0x880 [spl]
 ? __pfx_default_wake_function+0x10/0x10
 ? __pfx_zio_execute+0x10/0x10 [zfs]
 ? __pfx_taskq_thread+0x10/0x10 [spl]
 kthread+0xc9/0x100
 ? __pfx_kthread+0x10/0x10
 ret_from_fork+0x2d/0x50
 ? __pfx_kthread+0x10/0x10
 ret_from_fork_asm+0x1a/0x30
 </TASK>

Signed-off-by: Pavel Snajdr <[email protected]>
  • Loading branch information
snajpa committed Nov 1, 2024
1 parent 035947a commit bacde33
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 16 deletions.
2 changes: 1 addition & 1 deletion include/sys/brt.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ extern void brt_init(void);
extern void brt_fini(void);

extern void brt_pending_add(spa_t *spa, const blkptr_t *bp, dmu_tx_t *tx);
extern void brt_pending_remove(spa_t *spa, const blkptr_t *bp, dmu_tx_t *tx);
extern void brt_pending_remove(spa_t *spa, const blkptr_t *bp, uint64_t txg);
extern void brt_pending_apply(spa_t *spa, uint64_t txg);

extern void brt_create(spa_t *spa);
Expand Down
2 changes: 1 addition & 1 deletion include/sys/dbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ void dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx);
dbuf_dirty_record_t *dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
dbuf_dirty_record_t *dbuf_dirty_lightweight(dnode_t *dn, uint64_t blkid,
dmu_tx_t *tx);
boolean_t dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
boolean_t dbuf_undirty(dmu_buf_impl_t *db, uint64_t txg);
int dmu_buf_get_bp_from_dbuf(dmu_buf_impl_t *db, blkptr_t **bp);
int dmu_buf_untransform_direct(dmu_buf_impl_t *db, spa_t *spa);
arc_buf_t *dbuf_loan_arcbuf(dmu_buf_impl_t *db);
Expand Down
1 change: 1 addition & 0 deletions include/sys/dmu_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ typedef struct {
dbuf_dirty_record_t *dsa_dr;
void (*dsa_done)(struct zgd *, int);
struct zgd *dsa_zgd;
uint64_t dsa_txg;
dmu_tx_t *dsa_tx;
} dmu_sync_arg_t;

Expand Down
4 changes: 1 addition & 3 deletions module/zfs/brt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1421,16 +1421,14 @@ brt_pending_add(spa_t *spa, const blkptr_t *bp, dmu_tx_t *tx)
}

void
brt_pending_remove(spa_t *spa, const blkptr_t *bp, dmu_tx_t *tx)
brt_pending_remove(spa_t *spa, const blkptr_t *bp, uint64_t txg)
{
brt_t *brt;
avl_tree_t *pending_tree;
kmutex_t *pending_lock;
brt_pending_entry_t *bpe, bpe_search;
uint64_t txg;

brt = spa->spa_brt;
txg = dmu_tx_get_txg(tx);
ASSERT3U(txg, !=, 0);
pending_tree = &brt->brt_pending_tree[txg & TXG_MASK];
pending_lock = &brt->brt_pending_lock[txg & TXG_MASK];
Expand Down
17 changes: 8 additions & 9 deletions module/zfs/dbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2006,7 +2006,7 @@ dbuf_free_range(dnode_t *dn, uint64_t start_blkid, uint64_t end_blkid,

/* found a level 0 buffer in the range */
mutex_enter(&db->db_mtx);
if (dbuf_undirty(db, tx)) {
if (dbuf_undirty(db, tx->tx_txg)) {
/* mutex has been dropped and dbuf destroyed */
continue;
}
Expand Down Expand Up @@ -2536,9 +2536,8 @@ dbuf_undirty_bonus(dbuf_dirty_record_t *dr)
* transaction. Return whether this evicted the dbuf.
*/
boolean_t
dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
dbuf_undirty(dmu_buf_impl_t *db, uint64_t txg)
{
uint64_t txg = tx->tx_txg;
boolean_t brtwrite;
boolean_t diowrite;

Expand Down Expand Up @@ -2574,7 +2573,7 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
* transaction group.
*/
brt_pending_remove(dmu_objset_spa(db->db_objset),
&dr->dt.dl.dr_overridden_by, tx);
&dr->dt.dl.dr_overridden_by, txg);
}

dnode_t *dn = dr->dr_dnode;
Expand Down Expand Up @@ -2687,7 +2686,7 @@ dmu_buf_will_dirty_impl(dmu_buf_t *db_fake, int flags, dmu_tx_t *tx)
(void) dbuf_read(db, NULL, flags);
if (undirty) {
mutex_enter(&db->db_mtx);
VERIFY(!dbuf_undirty(db, tx));
VERIFY(!dbuf_undirty(db, tx->tx_txg));
mutex_exit(&db->db_mtx);
}
(void) dbuf_dirty(db, tx);
Expand Down Expand Up @@ -2829,7 +2828,7 @@ dmu_buf_will_clone_or_dio(dmu_buf_t *db_fake, dmu_tx_t *tx)
* hold on the db, so it should never be evicted after calling
* dbuf_undirty().
*/
VERIFY3B(dbuf_undirty(db, tx), ==, B_FALSE);
VERIFY3B(dbuf_undirty(db, tx->tx_txg), ==, B_FALSE);
ASSERT0P(dbuf_find_dirty_eq(db, tx->tx_txg));

if (db->db_buf != NULL) {
Expand Down Expand Up @@ -2912,7 +2911,7 @@ dmu_buf_will_fill(dmu_buf_t *db_fake, dmu_tx_t *tx, boolean_t canfail)
* as if the clone was never done.
*/
if (dr && dr->dt.dl.dr_brtwrite) {
VERIFY(!dbuf_undirty(db, tx));
VERIFY(!dbuf_undirty(db, tx->tx_txg));
db->db_state = DB_UNCACHED;
}
}
Expand Down Expand Up @@ -2993,7 +2992,7 @@ dmu_buf_fill_done(dmu_buf_t *dbuf, dmu_tx_t *tx, boolean_t failed)
"fill done handling freed in flight");
failed = B_FALSE;
} else if (failed) {
VERIFY(!dbuf_undirty(db, tx));
VERIFY(!dbuf_undirty(db, tx->tx_txg));
arc_buf_destroy(db->db_buf, db);
db->db_buf = NULL;
dbuf_clear_data(db);
Expand Down Expand Up @@ -3144,7 +3143,7 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
* pending clone and mark the block as uncached. This will be
* as if the clone was never done.
*/
VERIFY(!dbuf_undirty(db, tx));
VERIFY(!dbuf_undirty(db, tx->tx_txg));
db->db_state = DB_UNCACHED;
}
ASSERT(db->db_buf == NULL);
Expand Down
2 changes: 2 additions & 0 deletions module/zfs/dmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,7 @@ dmu_sync_late_arrival(zio_t *pio, objset_t *os, dmu_sync_cb_t *done, zgd_t *zgd,
dsa->dsa_dr = NULL;
dsa->dsa_done = done;
dsa->dsa_zgd = zgd;
dsa->dsa_txg = tx->tx_txg;
dsa->dsa_tx = tx;

/*
Expand Down Expand Up @@ -2198,6 +2199,7 @@ dmu_sync(zio_t *pio, uint64_t txg, dmu_sync_cb_t *done, zgd_t *zgd)
dsa->dsa_dr = dr;
dsa->dsa_done = done;
dsa->dsa_zgd = zgd;
dsa->dsa_txg = 0;
dsa->dsa_tx = NULL;

zio_nowait(arc_write(pio, os->os_spa, txg, zgd->zgd_bp,
Expand Down
5 changes: 3 additions & 2 deletions module/zfs/dmu_direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ dmu_write_direct_done(zio_t *zio)
* calling dbuf_undirty().
*/
mutex_enter(&db->db_mtx);
VERIFY3B(dbuf_undirty(db, dsa->dsa_tx), ==, B_FALSE);
VERIFY3B(dbuf_undirty(db, dsa->dsa_txg), ==, B_FALSE);
mutex_exit(&db->db_mtx);
}

Expand Down Expand Up @@ -189,7 +189,8 @@ dmu_write_direct(zio_t *pio, dmu_buf_impl_t *db, abd_t *data, dmu_tx_t *tx)

dmu_sync_arg_t *dsa = kmem_zalloc(sizeof (dmu_sync_arg_t), KM_SLEEP);
dsa->dsa_dr = dr_head;
dsa->dsa_tx = tx;
dsa->dsa_txg = tx->tx_txg;
dsa->dsa_tx = NULL;

zio_t *zio = zio_write(pio, os->os_spa, txg, bp, data,
db->db.db_size, db->db.db_size, &zp,
Expand Down

0 comments on commit bacde33

Please sign in to comment.