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 <behlendorf1@llnl.gov>
Reviewed-by: Adam Moss <c@yotes.com>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Signed-off-by: Matt Macy <mmacy@FreeBSD.org>
Closes #11052
This commit is contained in:
Matthew Macy 2020-10-13 21:03:36 -07:00 committed by GitHub
parent 6ba2e72b78
commit 57dc5d42b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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);