Skip to content

Commit ff23e28

Browse files
committed
panic in zfs arc_release during zfs send of encrypted dataset
Authored by: Paul Zuchowski <[email protected]> Reviewed by: Jerry Jelinek <[email protected]> Reviewed by: Gordon Ross <[email protected]> Reviewed by: Toomas Soome <[email protected]> Approved by: Robert Mustacchi <[email protected]> Illumos-issue: https://www.illumos.org/issues/14003 Illumos-commit: illumos/illumos-gate@b541cf35 Porting Notes: The b_cv was removed in #15340 preventing us from adopting this change without modification. Instead, we adopt the approach taken in #15340 to wait for any in progress IO. Additionally, update trace_arc.h on Linux to include the new dtrace probe. While not required I opted to keep it. Signed-off-by: Brian Behlendorf <[email protected]> Issue #13479
1 parent ccf5a8a commit ff23e28

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

include/os/linux/zfs/sys/trace_arc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__hit);
105105
DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__iohit);
106106
DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__evict);
107107
DEFINE_ARC_BUF_HDR_EVENT(zfs_arc__delete);
108+
DEFINE_ARC_BUF_HDR_EVENT(zfs_arc_release__io);
108109
DEFINE_ARC_BUF_HDR_EVENT(zfs_new_state__mru);
109110
DEFINE_ARC_BUF_HDR_EVENT(zfs_new_state__mfu);
110111
DEFINE_ARC_BUF_HDR_EVENT(zfs_new_state__uncached);
@@ -388,6 +389,7 @@ DEFINE_DTRACE_PROBE1(arc__hit);
388389
DEFINE_DTRACE_PROBE1(arc__iohit);
389390
DEFINE_DTRACE_PROBE1(arc__evict);
390391
DEFINE_DTRACE_PROBE1(arc__delete);
392+
DEFINE_DTRACE_PROBE1(arc_release__io);
391393
DEFINE_DTRACE_PROBE1(new_state__mru);
392394
DEFINE_DTRACE_PROBE1(new_state__mfu);
393395
DEFINE_DTRACE_PROBE1(new_state__uncached);

module/zfs/arc.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6623,6 +6623,39 @@ arc_release(arc_buf_t *buf, const void *tag)
66236623
kmutex_t *hash_lock = HDR_LOCK(hdr);
66246624
mutex_enter(hash_lock);
66256625

6626+
/*
6627+
* Wait for any other IO for this hdr, as additional
6628+
* buf(s) could be about to appear, in which case
6629+
* we would not want to transition hdr to arc_anon.
6630+
*/
6631+
while (HDR_IO_IN_PROGRESS(hdr)) {
6632+
arc_callback_t *acb;
6633+
6634+
DTRACE_PROBE1(arc_release__io, arc_buf_hdr_t *, hdr);
6635+
6636+
acb = kmem_zalloc(sizeof (arc_callback_t), KM_SLEEP);
6637+
acb->acb_wait = B_TRUE;
6638+
mutex_init(&acb->acb_wait_lock, NULL, MUTEX_DEFAULT, NULL);
6639+
cv_init(&acb->acb_wait_cv, NULL, CV_DEFAULT, NULL);
6640+
6641+
acb->acb_zio_head = hdr->b_l1hdr.b_acb->acb_zio_head;
6642+
acb->acb_next = hdr->b_l1hdr.b_acb;
6643+
hdr->b_l1hdr.b_acb->acb_prev = acb;
6644+
hdr->b_l1hdr.b_acb = acb;
6645+
6646+
mutex_exit(hash_lock);
6647+
mutex_enter(&acb->acb_wait_lock);
6648+
while (acb->acb_wait)
6649+
cv_wait(&acb->acb_wait_cv, &acb->acb_wait_lock);
6650+
6651+
mutex_exit(&acb->acb_wait_lock);
6652+
mutex_destroy(&acb->acb_wait_lock);
6653+
cv_destroy(&acb->acb_wait_cv);
6654+
kmem_free(acb, sizeof (arc_callback_t));
6655+
6656+
mutex_enter(hash_lock);
6657+
}
6658+
66266659
/*
66276660
* This assignment is only valid as long as the hash_lock is
66286661
* held, we must be careful not to reference state or the

0 commit comments

Comments
 (0)