Skip to content

fix prefetching of indirect blocks while destroying #14603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 24, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 9 additions & 15 deletions module/zfs/dmu_traverse.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,23 +154,18 @@ typedef enum resume_skip {
* Otherwise returns RESUME_SKIP_NONE.
*/
static resume_skip_t
resume_skip_check(traverse_data_t *td, const dnode_phys_t *dnp,
resume_skip_check(const traverse_data_t *td, const dnode_phys_t *dnp,
const zbookmark_phys_t *zb)
{
if (td->td_resume != NULL && !ZB_IS_ZERO(td->td_resume)) {
if (td->td_resume != NULL) {
/*
* If we already visited this bp & everything below,
* don't bother doing it again.
*/
if (zbookmark_subtree_completed(dnp, zb, td->td_resume))
return (RESUME_SKIP_ALL);

/*
* If we found the block we're trying to resume from, zero
* the bookmark out to indicate that we have resumed.
*/
if (memcmp(zb, td->td_resume, sizeof (*zb)) == 0) {
memset(td->td_resume, 0, sizeof (*zb));
if (td->td_flags & TRAVERSE_POST)
return (RESUME_SKIP_CHILDREN);
}
Expand All @@ -182,7 +177,7 @@ resume_skip_check(traverse_data_t *td, const dnode_phys_t *dnp,
* Returns B_TRUE, if prefetch read is issued, otherwise B_FALSE.
*/
static boolean_t
traverse_prefetch_metadata(traverse_data_t *td,
traverse_prefetch_metadata(traverse_data_t *td, const dnode_phys_t *dnp,
const blkptr_t *bp, const zbookmark_phys_t *zb)
{
arc_flags_t flags = ARC_FLAG_NOWAIT | ARC_FLAG_PREFETCH |
Expand All @@ -192,11 +187,10 @@ traverse_prefetch_metadata(traverse_data_t *td,
if (!(td->td_flags & TRAVERSE_PREFETCH_METADATA))
return (B_FALSE);
/*
* If we are in the process of resuming, don't prefetch, because
* some children will not be needed (and in fact may have already
* been freed).
* If this bp is before the resume point, it may have already been
* freed.
*/
if (td->td_resume != NULL && !ZB_IS_ZERO(td->td_resume))
if (resume_skip_check(td, dnp, zb) != RESUME_SKIP_NONE)
return (B_FALSE);
if (BP_IS_HOLE(bp) || bp->blk_birth <= td->td_min_txg)
return (B_FALSE);
Expand Down Expand Up @@ -344,7 +338,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
SET_BOOKMARK(czb, zb->zb_objset,
zb->zb_object, zb->zb_level - 1,
zb->zb_blkid * epb + pidx);
if (traverse_prefetch_metadata(td,
if (traverse_prefetch_metadata(td, dnp,
&((blkptr_t *)buf->b_data)[pidx],
czb) == B_TRUE) {
prefetched++;
Expand Down Expand Up @@ -506,12 +500,12 @@ prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *dnp,

for (j = 0; j < dnp->dn_nblkptr; j++) {
SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j);
traverse_prefetch_metadata(td, &dnp->dn_blkptr[j], &czb);
traverse_prefetch_metadata(td, dnp, &dnp->dn_blkptr[j], &czb);
}

if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID);
traverse_prefetch_metadata(td, DN_SPILL_BLKPTR(dnp), &czb);
traverse_prefetch_metadata(td, dnp, DN_SPILL_BLKPTR(dnp), &czb);
}
}

Expand Down