aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorDeHackEd <[email protected]>2017-06-12 14:41:03 -0400
committerBrian Behlendorf <[email protected]>2017-06-12 11:41:03 -0700
commit419c80e6dc2cd83372a77dfaf6f04e446d1f0267 (patch)
tree1d0f447d2ef1b85353b39d4d789780609de0a807 /module
parent851aa99c899e5d7ddc937e223359b8892eeeca5d (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.c25
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);
}