From 923d730329290c7dc8ae5b4d27c6ed01d24d9f4c Mon Sep 17 00:00:00 2001 From: Matthew Macy Date: Sat, 12 Dec 2020 16:00:00 -0800 Subject: [PATCH] dmu_zfetch: fix memory leak The last change caused the read completion callback to not be called if the IO was still in progress. This change restores allocation of the arc buf callback, but in the callback path checks the new acb_nobuf field to know to skip buffer allocation. Reviewed-by: Brian Behlendorf Signed-off-by: Matt Macy Closes #11324 --- include/sys/arc_impl.h | 1 + module/zfs/arc.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/sys/arc_impl.h b/include/sys/arc_impl.h index 6adcd4b54b7f..94123fc10e67 100644 --- a/include/sys/arc_impl.h +++ b/include/sys/arc_impl.h @@ -99,6 +99,7 @@ struct arc_callback { boolean_t acb_encrypted; boolean_t acb_compressed; boolean_t acb_noauth; + boolean_t acb_nobuf; zbookmark_phys_t acb_zb; zio_t *acb_zio_dummy; zio_t *acb_zio_head; diff --git a/module/zfs/arc.c b/module/zfs/arc.c index 1bc27391c941..8519eda30df7 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -5759,7 +5759,7 @@ arc_read_done(zio_t *zio) */ int callback_cnt = 0; for (acb = callback_list; acb != NULL; acb = acb->acb_next) { - if (!acb->acb_done) + if (!acb->acb_done || acb->acb_nobuf) continue; callback_cnt++; @@ -5999,7 +5999,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, } ASSERT(*arc_flags & ARC_FLAG_NOWAIT); - if (done && !no_buf) { + if (done) { arc_callback_t *acb = NULL; acb = kmem_zalloc(sizeof (arc_callback_t), @@ -6009,6 +6009,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, acb->acb_compressed = compressed_read; acb->acb_encrypted = encrypted_read; acb->acb_noauth = noauth_read; + acb->acb_nobuf = no_buf; acb->acb_zb = *zb; if (pio != NULL) acb->acb_zio_dummy = zio_null(pio, @@ -6018,8 +6019,6 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, acb->acb_zio_head = head_zio; acb->acb_next = hdr->b_l1hdr.b_acb; hdr->b_l1hdr.b_acb = acb; - mutex_exit(hash_lock); - goto out; } mutex_exit(hash_lock); goto out;