From: Brad Lewis Date: Thu, 15 Mar 2018 19:47:26 +0000 (-0600) Subject: OpenZFS 9677 - panic from zio_write_gang_block() X-Git-Tag: zfs-0.8.0-rc2~78 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c955398b527fd0996cc03b55ba26a4647bd826cd;p=zfs 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 Reviewed by: Matt Ahrens Reviewed by: George Wilson Reviewed by: Prashanth Sreenivasa Approved by: Robert Mustacchi Ported-by: Behlendorf OpenZFS-issue: https://illumos.org/issues/9677 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/7341a7d Closes #7975 --- 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