]> granicus.if.org Git - zfs/commitdiff
OpenZFS 9677 - panic from zio_write_gang_block()
authorBrad Lewis <brad.lewis@delphix.com>
Thu, 15 Mar 2018 19:47:26 +0000 (13:47 -0600)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 3 Oct 2018 16:50:06 +0000 (09:50 -0700)
Panic from zio_write_gang_block() when creating dump device
on fragmented rpool.

Authored by: Brad Lewis <brad.lewis@delphix.com>
Reviewed by: Matt Ahrens <matt@delphix.com>
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Prashanth Sreenivasa <pks@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Ported-by: Behlendorf <behlendorf1@llnl.gov>
OpenZFS-issue: https://illumos.org/issues/9677
OpenZFS-commit: https://github.com/openzfs/openzfs/commit/7341a7d
Closes #7975

module/zfs/zio.c

index d3208a1e706e071577ddcd7584a3ea69e3b4652f..e8c2ca89aff9cd3e855e4870e06c603bb00dc523 100644 (file)
@@ -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