Skip to content

Commit 6b36dd4

Browse files
committed
vdev_disk: move abd return and free off the interrupt handler
Freeing an ABD can take sleeping locks to update various stats. We aren't allowed to sleep on an interrupt handler. So, move the free off to the io_done callback. We should never have been freeing things in the interrupt handler, but we got away with it because we were usually freeing a linear ABD, which at most is returning two objects to a cache and never sleeping. Scatter ABDs can be used now, and those have more complex locking. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Tony Hutter <[email protected]> Signed-off-by: Rob Norris <[email protected]> Closes openzfs#16687 (cherry picked from commit e7425ae)
1 parent 46efc30 commit 6b36dd4

File tree

1 file changed

+27
-13
lines changed

1 file changed

+27
-13
lines changed

module/os/linux/zfs/vdev_disk.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -828,21 +828,13 @@ BIO_END_IO_PROTO(vbio_completion, bio, error)
828828
bio_put(bio);
829829

830830
/*
831-
* If we copied the ABD before issuing it, clean up and return the copy
832-
* to the ADB, with changes if appropriate.
831+
* We're likely in an interrupt context so we can't do ABD/memory work
832+
* here; instead we stash vbio on the zio and take care of it in the
833+
* done callback.
833834
*/
834-
if (vbio->vbio_abd != NULL) {
835-
if (zio->io_type == ZIO_TYPE_READ)
836-
abd_copy(zio->io_abd, vbio->vbio_abd, zio->io_size);
835+
ASSERT3P(zio->io_bio, ==, NULL);
836+
zio->io_bio = vbio;
837837

838-
abd_free(vbio->vbio_abd);
839-
vbio->vbio_abd = NULL;
840-
}
841-
842-
/* Final cleanup */
843-
kmem_free(vbio, sizeof (vbio_t));
844-
845-
/* All done, submit for processing */
846838
zio_delay_interrupt(zio);
847839
}
848840

@@ -1496,6 +1488,28 @@ vdev_disk_io_start(zio_t *zio)
14961488
static void
14971489
vdev_disk_io_done(zio_t *zio)
14981490
{
1491+
/* If this was a read or write, we need to clean up the vbio */
1492+
if (zio->io_bio != NULL) {
1493+
vbio_t *vbio = zio->io_bio;
1494+
zio->io_bio = NULL;
1495+
1496+
/*
1497+
* If we copied the ABD before issuing it, clean up and return
1498+
* the copy to the ADB, with changes if appropriate.
1499+
*/
1500+
if (vbio->vbio_abd != NULL) {
1501+
if (zio->io_type == ZIO_TYPE_READ)
1502+
abd_copy(zio->io_abd, vbio->vbio_abd,
1503+
zio->io_size);
1504+
1505+
abd_free(vbio->vbio_abd);
1506+
vbio->vbio_abd = NULL;
1507+
}
1508+
1509+
/* Final cleanup */
1510+
kmem_free(vbio, sizeof (vbio_t));
1511+
}
1512+
14991513
/*
15001514
* If the device returned EIO, we revalidate the media. If it is
15011515
* determined the media has changed this triggers the asynchronous

0 commit comments

Comments
 (0)