summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Caputi <[email protected]>2019-01-15 15:23:40 -0500
committerBrian Behlendorf <[email protected]>2019-01-15 12:23:40 -0800
commit5e7f3ace5807f950f3529361e03970101e61aa44 (patch)
treeca4082ed13bc96da3b8bf1350dd1c0d74c05956d
parent7b02fae7a6670579437d1fb490362f70168b0666 (diff)
Fix zio leak in dbuf_read()
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 <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Tom Caputi <[email protected]> Closes #8267
-rw-r--r--module/zfs/dbuf.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c
index a22fbdc11..826934b36 100644
--- a/module/zfs/dbuf.c
+++ b/module/zfs/dbuf.c
@@ -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