diff options
author | DeHackEd <[email protected]> | 2017-06-12 14:41:03 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-06-12 11:41:03 -0700 |
commit | 419c80e6dc2cd83372a77dfaf6f04e446d1f0267 (patch) | |
tree | 1d0f447d2ef1b85353b39d4d789780609de0a807 /module | |
parent | 851aa99c899e5d7ddc937e223359b8892eeeca5d (diff) |
Reduce stack usage of dsl_dir_tempreserve_impl
Buildbots and zfs-tests regularly see 7 kilobytes of stack
usage with this function. Convert self-calls to iterations
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: DHE <[email protected]>
Closes #6219
Diffstat (limited to 'module')
-rw-r--r-- | module/zfs/dsl_dir.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c index 98aeff5dc..a3ef5896a 100644 --- a/module/zfs/dsl_dir.c +++ b/module/zfs/dsl_dir.c @@ -1119,11 +1119,16 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, boolean_t ignorequota, list_t *tr_list, dmu_tx_t *tx, boolean_t first) { - uint64_t txg = tx->tx_txg; + uint64_t txg; uint64_t quota; struct tempreserve *tr; - int retval = EDQUOT; - uint64_t ref_rsrv = 0; + int retval; + uint64_t ref_rsrv; + +top_of_function: + txg = tx->tx_txg; + retval = EDQUOT; + ref_rsrv = 0; ASSERT3U(txg, !=, 0); ASSERT3S(asize, >, 0); @@ -1220,10 +1225,18 @@ dsl_dir_tempreserve_impl(dsl_dir_t *dd, uint64_t asize, boolean_t netfree, /* see if it's OK with our parent */ if (dd->dd_parent != NULL && parent_rsrv != 0) { - boolean_t ismos = (dsl_dir_phys(dd)->dd_head_dataset_obj == 0); + /* + * Recurse on our parent without recursion. This has been + * observed to be potentially large stack usage even within + * the test suite. Largest seen stack was 7632 bytes on linux. + */ + + dd = dd->dd_parent; + asize = parent_rsrv; + ignorequota = (dsl_dir_phys(dd)->dd_head_dataset_obj == 0); + first = B_FALSE; + goto top_of_function; - return (dsl_dir_tempreserve_impl(dd->dd_parent, - parent_rsrv, netfree, ismos, tr_list, tx, B_FALSE)); } else { return (0); } |