@@ -1419,24 +1419,28 @@ dmu_read_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size)
1419
1419
if (err )
1420
1420
return (err );
1421
1421
1422
- for (i = 0 ; i < numbufs ; i ++ ) {
1422
+ for (i = 0 ; i < numbufs && size > 0 ; ) {
1423
1423
uint64_t tocpy ;
1424
1424
int64_t bufoff ;
1425
1425
dmu_buf_t * db = dbp [i ];
1426
1426
1427
- ASSERT (size > 0 );
1428
-
1429
1427
bufoff = zfs_uio_offset (uio ) - db -> db_offset ;
1430
1428
tocpy = MIN (db -> db_size - bufoff , size );
1431
1429
1432
1430
ASSERT (db -> db_data != NULL );
1433
- err = zfs_uio_fault_move ((char * )db -> db_data + bufoff , tocpy ,
1434
- UIO_READ , uio );
1435
1431
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 )
1437
1440
break ;
1438
1441
1439
- size -= tocpy ;
1442
+ if (bufoff + moved >= db -> db_size )
1443
+ i ++ ;
1440
1444
}
1441
1445
dmu_buf_rele_array (dbp , numbufs , FTAG );
1442
1446
@@ -1536,13 +1540,11 @@ dmu_write_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx)
1536
1540
if (err )
1537
1541
return (err );
1538
1542
1539
- for (int i = 0 ; i < numbufs ; i ++ ) {
1543
+ for (int i = 0 ; i < numbufs && write_size > 0 ; ) {
1540
1544
uint64_t tocpy ;
1541
1545
int64_t bufoff ;
1542
1546
dmu_buf_t * db = dbp [i ];
1543
1547
1544
- ASSERT (write_size > 0 );
1545
-
1546
1548
offset_t off = zfs_uio_offset (uio );
1547
1549
bufoff = off - db -> db_offset ;
1548
1550
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)
1555
1557
dmu_buf_will_dirty (db , tx );
1556
1558
1557
1559
ASSERT (db -> db_data != NULL );
1560
+ uint64_t resid_before = uio -> uio_resid ;
1558
1561
err = zfs_uio_fault_move ((char * )db -> db_data + bufoff ,
1559
1562
tocpy , UIO_WRITE , uio );
1563
+ uint64_t moved = resid_before - uio -> uio_resid ;
1560
1564
1561
1565
if (tocpy == db -> db_size && dmu_buf_fill_done (db , tx , err )) {
1562
1566
/* The fill was reverted. Undo any uio progress. */
1563
1567
zfs_uio_advance (uio , off - zfs_uio_offset (uio ));
1564
1568
}
1565
1569
1566
- if (err )
1570
+ if (err || moved == 0 )
1567
1571
break ;
1568
1572
1569
- write_size -= tocpy ;
1570
- size -= tocpy ;
1573
+ write_size -= moved ;
1574
+ size -= moved ;
1575
+
1576
+ if (bufoff + moved >= db -> db_size )
1577
+ i ++ ;
1571
1578
}
1572
1579
1573
1580
IMPLY (err == 0 , write_size == 0 );
0 commit comments