1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-11-24 07:40:52 +00:00

fix an architectural problem introduced in r320156, ZFS ABD import

The implementation of ZFS refcount_t uses the emulated illumos mutex
(the sx lock) and the waiting memory allocation when ZFS_DEBUG is
enabled.  This makes refcount_t unsuitable for use in GEOM g_up
thread where sleeping is prohibited.

When importing the ABD change I modified vdev_geom using illumos
vdev_disk as an example.  As a result, I added a call to abd_return_buf
in vdev_geom_io_intr.  The latter is called on g_up thread while the
former uses refcount_t.

This change fixes the problem by deferring the abd_return_buf call to
the previously unused vdev_geom_io_done that is called on a ZFS zio
taskqueue thread where sleeping is allowed.

A side bonus of this change is that now a vdev zio has a pointer
to its corresponding bio while the zio is active.

Reported by:	Shawn Webb <shawn.webb@hardenedbsd.org>
Tested by:	Shawn Webb <shawn.webb@hardenedbsd.org>
MFC after:	1 week
X-MFC with:	r320156
This commit is contained in:
Andriy Gapon 2017-06-28 13:59:20 +00:00
parent bb751fbbc7
commit 1db5f1724b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=320452
2 changed files with 14 additions and 7 deletions

View File

@ -453,6 +453,10 @@ struct zio {
avl_node_t io_alloc_node;
zio_alloc_list_t io_alloc_list;
#ifdef __FreeBSD__
struct bio *io_bio;
#endif
/* Internal pipeline state */
enum zio_flag io_flags;
enum zio_stage io_stage;

View File

@ -989,13 +989,6 @@ vdev_geom_io_intr(struct bio *bp)
break;
}
if (zio->io_type == ZIO_TYPE_READ) {
abd_return_buf_copy(zio->io_abd, bp->bio_data, zio->io_size);
} else if (zio->io_type == ZIO_TYPE_WRITE) {
abd_return_buf(zio->io_abd, bp->bio_data, zio->io_size);
}
g_destroy_bio(bp);
zio_delay_interrupt(zio);
}
@ -1087,6 +1080,7 @@ vdev_geom_io_start(zio_t *zio)
break;
}
bp->bio_done = vdev_geom_io_intr;
zio->io_bio = bp;
g_io_request(bp, cp);
}
@ -1094,6 +1088,15 @@ vdev_geom_io_start(zio_t *zio)
static void
vdev_geom_io_done(zio_t *zio)
{
struct bio *bp = zio->io_bio;
if (zio->io_type == ZIO_TYPE_READ) {
abd_return_buf_copy(zio->io_abd, bp->bio_data, zio->io_size);
} else if (zio->io_type == ZIO_TYPE_WRITE) {
abd_return_buf(zio->io_abd, bp->bio_data, zio->io_size);
}
g_destroy_bio(bp);
}
static void