aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorBrad Lewis <[email protected]>2018-03-15 13:47:26 -0600
committerBrian Behlendorf <[email protected]>2018-10-03 09:50:06 -0700
commitc955398b527fd0996cc03b55ba26a4647bd826cd (patch)
tree4d6998164b8d1a0d505f003677ff67c208ba0dbc /module
parent84ddd4b0629be52ca7c519043cc2d155ac3ef7af (diff)
OpenZFS 9677 - panic from zio_write_gang_block()
Panic from zio_write_gang_block() when creating dump device on fragmented rpool. Authored by: Brad Lewis <[email protected]> Reviewed by: Matt Ahrens <[email protected]> Reviewed by: George Wilson <[email protected]> Reviewed by: Prashanth Sreenivasa <[email protected]> Approved by: Robert Mustacchi <[email protected]> Ported-by: Behlendorf <[email protected]> OpenZFS-issue: https://illumos.org/issues/9677 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/7341a7d Closes #7975
Diffstat (limited to 'module')
-rw-r--r--module/zfs/zio.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index d3208a1e7..e8c2ca89a 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -2603,7 +2603,13 @@ zio_write_gang_member_ready(zio_t *zio)
static void
zio_write_gang_done(zio_t *zio)
{
- abd_put(zio->io_abd);
+ /*
+ * The io_abd field will be NULL for a zio with no data. The io_flags
+ * will initially have the ZIO_FLAG_NODATA bit flag set, but we can't
+ * check for it here as it is cleared in zio_ready.
+ */
+ if (zio->io_abd != NULL)
+ abd_put(zio->io_abd);
}
static zio_t *
@@ -2624,6 +2630,7 @@ zio_write_gang_block(zio_t *pio)
int gbh_copies;
zio_prop_t zp;
int error;
+ boolean_t has_data = !(pio->io_flags & ZIO_FLAG_NODATA);
/*
* encrypted blocks need DVA[2] free so encrypted gang headers can't
@@ -2636,7 +2643,7 @@ zio_write_gang_block(zio_t *pio)
int flags = METASLAB_HINTBP_FAVOR | METASLAB_GANG_HEADER;
if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) {
ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
- ASSERT(!(pio->io_flags & ZIO_FLAG_NODATA));
+ ASSERT(has_data);
flags |= METASLAB_ASYNC_ALLOC;
VERIFY(zfs_refcount_held(&mc->mc_alloc_slots[pio->io_allocator],
@@ -2660,7 +2667,7 @@ zio_write_gang_block(zio_t *pio)
if (error) {
if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) {
ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
- ASSERT(!(pio->io_flags & ZIO_FLAG_NODATA));
+ ASSERT(has_data);
/*
* If we failed to allocate the gang block header then
@@ -2719,14 +2726,15 @@ zio_write_gang_block(zio_t *pio)
bzero(zp.zp_mac, ZIO_DATA_MAC_LEN);
zio_t *cio = zio_write(zio, spa, txg, &gbh->zg_blkptr[g],
- abd_get_offset(pio->io_abd, pio->io_size - resid), lsize,
- lsize, &zp, zio_write_gang_member_ready, NULL, NULL,
+ has_data ? abd_get_offset(pio->io_abd, pio->io_size -
+ resid) : NULL, lsize, lsize, &zp,
+ zio_write_gang_member_ready, NULL, NULL,
zio_write_gang_done, &gn->gn_child[g], pio->io_priority,
ZIO_GANG_CHILD_FLAGS(pio), &pio->io_bookmark);
if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) {
ASSERT(pio->io_priority == ZIO_PRIORITY_ASYNC_WRITE);
- ASSERT(!(pio->io_flags & ZIO_FLAG_NODATA));
+ ASSERT(has_data);
/*
* Gang children won't throttle but we should