Reduce dsl_scan_visitbp stack usage by moving blkptr_t to heap
Github issue 22 reported a stack overrun when the zfs module was loaded, possibly related to the presence of existing zpools created under zfs-fuse. The stack trace showed 9 levels of recursion between dsl_scan_visitbp() and dsl_scan_recurse(). To reduce stack overhead in that code path, this commit moves the 128 byte blkptr_t data strucutre in dsl_scan_visitbp() to the heap. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
911d2e0df4
commit
410d8c4e15
|
@ -789,18 +789,21 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_t *zb,
|
||||||
{
|
{
|
||||||
dsl_pool_t *dp = scn->scn_dp;
|
dsl_pool_t *dp = scn->scn_dp;
|
||||||
arc_buf_t *buf = NULL;
|
arc_buf_t *buf = NULL;
|
||||||
blkptr_t bp_toread = *bp;
|
blkptr_t *bp_toread;
|
||||||
|
|
||||||
|
bp_toread = kmem_alloc(sizeof (blkptr_t), KM_SLEEP);
|
||||||
|
*bp_toread = *bp;
|
||||||
|
|
||||||
/* ASSERT(pbuf == NULL || arc_released(pbuf)); */
|
/* ASSERT(pbuf == NULL || arc_released(pbuf)); */
|
||||||
|
|
||||||
if (dsl_scan_check_pause(scn, zb))
|
if (dsl_scan_check_pause(scn, zb))
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
if (dsl_scan_check_resume(scn, dnp, zb))
|
if (dsl_scan_check_resume(scn, dnp, zb))
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
if (bp->blk_birth == 0)
|
if (bp->blk_birth == 0)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
scn->scn_visited_this_txg++;
|
scn->scn_visited_this_txg++;
|
||||||
|
|
||||||
|
@ -811,7 +814,7 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_t *zb,
|
||||||
pbuf, bp);
|
pbuf, bp);
|
||||||
|
|
||||||
if (bp->blk_birth <= scn->scn_phys.scn_cur_min_txg)
|
if (bp->blk_birth <= scn->scn_phys.scn_cur_min_txg)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
if (BP_GET_TYPE(bp) != DMU_OT_USERGROUP_USED) {
|
if (BP_GET_TYPE(bp) != DMU_OT_USERGROUP_USED) {
|
||||||
/*
|
/*
|
||||||
|
@ -826,12 +829,12 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_t *zb,
|
||||||
* it (original untranslated -> translations from
|
* it (original untranslated -> translations from
|
||||||
* deleted snap -> now).
|
* deleted snap -> now).
|
||||||
*/
|
*/
|
||||||
bp_toread = *bp;
|
*bp_toread = *bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dsl_scan_recurse(scn, ds, ostype, dnp, &bp_toread, zb, tx,
|
if (dsl_scan_recurse(scn, ds, ostype, dnp, bp_toread, zb, tx,
|
||||||
&buf) != 0)
|
&buf) != 0)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If dsl_scan_ddt() has aready visited this block, it will have
|
* If dsl_scan_ddt() has aready visited this block, it will have
|
||||||
|
@ -841,7 +844,7 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_t *zb,
|
||||||
if (ddt_class_contains(dp->dp_spa,
|
if (ddt_class_contains(dp->dp_spa,
|
||||||
scn->scn_phys.scn_ddt_class_max, bp)) {
|
scn->scn_phys.scn_ddt_class_max, bp)) {
|
||||||
ASSERT(buf == NULL);
|
ASSERT(buf == NULL);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -856,6 +859,8 @@ dsl_scan_visitbp(blkptr_t *bp, const zbookmark_t *zb,
|
||||||
}
|
}
|
||||||
if (buf)
|
if (buf)
|
||||||
(void) arc_buf_remove_ref(buf, &buf);
|
(void) arc_buf_remove_ref(buf, &buf);
|
||||||
|
out:
|
||||||
|
kmem_free(bp_toread, sizeof(blkptr_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue