]> granicus.if.org Git - zfs/commitdiff
Fix zio leak in dbuf_read()
authorTom Caputi <tcaputi@datto.com>
Tue, 15 Jan 2019 20:23:40 +0000 (15:23 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 15 Jan 2019 20:23:40 +0000 (12:23 -0800)
Currently, dbuf_read() may decide to create a zio_root which is
used as a parent for any child zios created in dbuf_read_impl().
However, if there is an error in dbuf_read_impl(), this zio is
never executed and ends up leaked. This patch simply ensures
that we always execute the root zio, even i it has no real work
to do.

Reviewed-by: Matt Ahrens <mahrens@delphix.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #8267

module/zfs/dbuf.c

index a22fbdc118ab214b6cb855f6b7bdcd407cb59aed..826934b3669bc0695580183cc22e8378faff229a 100644 (file)
@@ -1565,8 +1565,17 @@ dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags)
                DB_DNODE_EXIT(db);
                DBUF_STAT_BUMP(hash_misses);
 
-               if (!err && need_wait)
-                       err = zio_wait(zio);
+               /*
+                * If we created a zio_root we must execute it to avoid
+                * leaking it, even if it isn't attached to any work due
+                * to an error in dbuf_read_impl().
+                */
+               if (need_wait) {
+                       if (err == 0)
+                               err = zio_wait(zio);
+                       else
+                               VERIFY0(zio_wait(zio));
+               }
        } else {
                /*
                 * Another reader came in while the dbuf was in flight