Skip to content

Commit 9b61937

Browse files
committed
Fix partial uiomove size handling
1 parent 1af41fd commit 9b61937

File tree

1 file changed

+20
-13
lines changed

1 file changed

+20
-13
lines changed

module/zfs/dmu.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,24 +1419,28 @@ dmu_read_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size)
14191419
if (err)
14201420
return (err);
14211421

1422-
for (i = 0; i < numbufs; i++) {
1422+
for (i = 0; i < numbufs && size > 0; ) {
14231423
uint64_t tocpy;
14241424
int64_t bufoff;
14251425
dmu_buf_t *db = dbp[i];
14261426

1427-
ASSERT(size > 0);
1428-
14291427
bufoff = zfs_uio_offset(uio) - db->db_offset;
14301428
tocpy = MIN(db->db_size - bufoff, size);
14311429

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

1436-
if (err)
1432+
uint64_t resid_before = uio->uio_resid;
1433+
err = zfs_uio_fault_move((char *)db->db_data + bufoff,
1434+
tocpy, UIO_READ, uio);
1435+
uint64_t moved = resid_before - uio->uio_resid;
1436+
1437+
size -= moved;
1438+
1439+
if (err || moved == 0)
14371440
break;
14381441

1439-
size -= tocpy;
1442+
if (bufoff + moved >= db->db_size)
1443+
i++;
14401444
}
14411445
dmu_buf_rele_array(dbp, numbufs, FTAG);
14421446

@@ -1536,13 +1540,11 @@ dmu_write_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx)
15361540
if (err)
15371541
return (err);
15381542

1539-
for (int i = 0; i < numbufs; i++) {
1543+
for (int i = 0; i < numbufs && write_size > 0; ) {
15401544
uint64_t tocpy;
15411545
int64_t bufoff;
15421546
dmu_buf_t *db = dbp[i];
15431547

1544-
ASSERT(write_size > 0);
1545-
15461548
offset_t off = zfs_uio_offset(uio);
15471549
bufoff = off - db->db_offset;
15481550
tocpy = MIN(db->db_size - bufoff, write_size);
@@ -1555,19 +1557,24 @@ dmu_write_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx)
15551557
dmu_buf_will_dirty(db, tx);
15561558

15571559
ASSERT(db->db_data != NULL);
1560+
uint64_t resid_before = uio->uio_resid;
15581561
err = zfs_uio_fault_move((char *)db->db_data + bufoff,
15591562
tocpy, UIO_WRITE, uio);
1563+
uint64_t moved = resid_before - uio->uio_resid;
15601564

15611565
if (tocpy == db->db_size && dmu_buf_fill_done(db, tx, err)) {
15621566
/* The fill was reverted. Undo any uio progress. */
15631567
zfs_uio_advance(uio, off - zfs_uio_offset(uio));
15641568
}
15651569

1566-
if (err)
1570+
if (err || moved == 0)
15671571
break;
15681572

1569-
write_size -= tocpy;
1570-
size -= tocpy;
1573+
write_size -= moved;
1574+
size -= moved;
1575+
1576+
if (bufoff + moved >= db->db_size)
1577+
i++;
15711578
}
15721579

15731580
IMPLY(err == 0, write_size == 0);

0 commit comments

Comments
 (0)