aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorMatthew Macy <[email protected]>2020-10-13 21:03:36 -0700
committerGitHub <[email protected]>2020-10-13 21:03:36 -0700
commit57dc5d42b185d2983717580b7fb58bfe423cd834 (patch)
treea0cd46563a64aed94762df41848892671609c750 /module
parent6ba2e72b7899771f588dc4557624c186be2c2176 (diff)
dmu_zfetch: don't leak unreferenced stream when zfetch is freed
Currently streams are only freed when: - They have no referencing zfetch and and their I/O references go to zero. - They are more than 2s old and a new I/O request comes in on the same zfetch. This means that we will leak unreferenced streams when their zfetch structure is freed. This change checks the reference count on a stream at zfetch free time. If it is zero we free it immediately. If it has remaining references we allow the prefetch callback to free it at I/O completion time. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Adam Moss <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Matt Macy <[email protected]> Closes #11052
Diffstat (limited to 'module')
-rw-r--r--module/zfs/dmu_zfetch.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/module/zfs/dmu_zfetch.c b/module/zfs/dmu_zfetch.c
index fa43fe4fc..5d061fe38 100644
--- a/module/zfs/dmu_zfetch.c
+++ b/module/zfs/dmu_zfetch.c
@@ -161,8 +161,12 @@ dmu_zfetch_fini(zfetch_t *zf)
zstream_t *zs;
mutex_enter(&zf->zf_lock);
- while ((zs = list_head(&zf->zf_stream)) != NULL)
- dmu_zfetch_stream_orphan(zf, zs);
+ while ((zs = list_head(&zf->zf_stream)) != NULL) {
+ if (zfs_refcount_count(&zs->zs_blocks) != 0)
+ dmu_zfetch_stream_orphan(zf, zs);
+ else
+ dmu_zfetch_stream_remove(zf, zs);
+ }
mutex_exit(&zf->zf_lock);
list_destroy(&zf->zf_stream);
mutex_destroy(&zf->zf_lock);