diff options
author | Tom Caputi <[email protected]> | 2019-01-15 15:23:40 -0500 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-01-15 12:23:40 -0800 |
commit | 5e7f3ace5807f950f3529361e03970101e61aa44 (patch) | |
tree | ca4082ed13bc96da3b8bf1350dd1c0d74c05956d | |
parent | 7b02fae7a6670579437d1fb490362f70168b0666 (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.c | 13 |
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 |