Skip to content

Commit

Permalink
Fix regression in dmu_buf_will_fill()
Browse files Browse the repository at this point in the history
Direct I/O implementation added condition to call dbuf_undirty()
only in case of block cloning.  But the condition is not right if
the block is no longer dirty in this TXG, but still in DB_NOFILL
state.  It resulted in block not reverting to DB_UNCACHED and
following NULL de-reference on attempt to access absent db_data.

While there, add assertions for db_data to make debugging easier.

Reviewed-by: Brian Atkinson <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Alexander Motin <[email protected]>
Sponsored by:	iXsystems, Inc.
Closes openzfs#16829
  • Loading branch information
amotin authored and ixhamza committed Dec 3, 2024
1 parent 1f1c5c4 commit 0b69a86
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 2 deletions.
7 changes: 6 additions & 1 deletion module/os/freebsd/zfs/dmu_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ dmu_write_pages(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
db->db_offset + bufoff);
thiscpy = MIN(PAGESIZE, tocpy - copied);
va = zfs_map_page(*ma, &sf);
ASSERT(db->db_data != NULL);
memcpy((char *)db->db_data + bufoff, va, thiscpy);
zfs_unmap_page(sf);
ma += 1;
Expand Down Expand Up @@ -172,6 +173,7 @@ dmu_read_pages(objset_t *os, uint64_t object, vm_page_t *ma, int count,
ASSERT3U(db->db_size, >, PAGE_SIZE);
bufoff = IDX_TO_OFF(m->pindex) % db->db_size;
va = zfs_map_page(m, &sf);
ASSERT(db->db_data != NULL);
memcpy(va, (char *)db->db_data + bufoff, PAGESIZE);
zfs_unmap_page(sf);
vm_page_valid(m);
Expand Down Expand Up @@ -211,8 +213,10 @@ dmu_read_pages(objset_t *os, uint64_t object, vm_page_t *ma, int count,
*/
tocpy = MIN(db->db_size - bufoff, PAGESIZE - pgoff);
ASSERT3S(tocpy, >=, 0);
if (m != bogus_page)
if (m != bogus_page) {
ASSERT(db->db_data != NULL);
memcpy(va + pgoff, (char *)db->db_data + bufoff, tocpy);
}

pgoff += tocpy;
ASSERT3S(pgoff, >=, 0);
Expand Down Expand Up @@ -290,6 +294,7 @@ dmu_read_pages(objset_t *os, uint64_t object, vm_page_t *ma, int count,
bufoff = IDX_TO_OFF(m->pindex) % db->db_size;
tocpy = MIN(db->db_size - bufoff, PAGESIZE);
va = zfs_map_page(m, &sf);
ASSERT(db->db_data != NULL);
memcpy(va, (char *)db->db_data + bufoff, tocpy);
if (tocpy < PAGESIZE) {
ASSERT3S(i, ==, *rahead - 1);
Expand Down
2 changes: 1 addition & 1 deletion module/zfs/dbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2916,7 +2916,7 @@ dmu_buf_will_fill(dmu_buf_t *db_fake, dmu_tx_t *tx, boolean_t canfail)
* pending clone and mark the block as uncached. This will be
* as if the clone was never done.
*/
if (dr && dr->dt.dl.dr_brtwrite) {
if (db->db_state == DB_NOFILL) {
VERIFY(!dbuf_undirty(db, tx));
db->db_state = DB_UNCACHED;
}
Expand Down
4 changes: 4 additions & 0 deletions module/zfs/dmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,7 @@ dmu_read_impl(dnode_t *dn, uint64_t offset, uint64_t size,
bufoff = offset - db->db_offset;
tocpy = MIN(db->db_size - bufoff, size);

ASSERT(db->db_data != NULL);
(void) memcpy(buf, (char *)db->db_data + bufoff, tocpy);

offset += tocpy;
Expand Down Expand Up @@ -1278,6 +1279,7 @@ dmu_write_impl(dmu_buf_t **dbp, int numbufs, uint64_t offset, uint64_t size,
else
dmu_buf_will_dirty(db, tx);

ASSERT(db->db_data != NULL);
(void) memcpy((char *)db->db_data + bufoff, buf, tocpy);

if (tocpy == db->db_size)
Expand Down Expand Up @@ -1426,6 +1428,7 @@ dmu_read_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size)
bufoff = zfs_uio_offset(uio) - db->db_offset;
tocpy = MIN(db->db_size - bufoff, size);

ASSERT(db->db_data != NULL);
err = zfs_uio_fault_move((char *)db->db_data + bufoff, tocpy,
UIO_READ, uio);

Expand Down Expand Up @@ -1550,6 +1553,7 @@ dmu_write_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx)
else
dmu_buf_will_dirty(db, tx);

ASSERT(db->db_data != NULL);
err = zfs_uio_fault_move((char *)db->db_data + bufoff,
tocpy, UIO_WRITE, uio);

Expand Down

0 comments on commit 0b69a86

Please sign in to comment.