]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Reduce stack usage of dsl_dir_tempreserve_impl
authorDeHackEd <DeHackEd@users.noreply.github.com>
Mon, 12 Jun 2017 18:41:03 +0000 (14:41 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 12 Jun 2017 18:41:03 +0000 (11:41 -0700)
Buildbots and zfs-tests regularly see 7 kilobytes of stack
usage with this function. Convert self-calls to iterations

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: DHE <git@dehacked.net>
Closes #6219

module/zfs/dsl_dir.c

index 98aeff5dc8edf248ec6f719a16db71f07be21167..a3ef5896a3f22704f574b2e4aaacc14f098f8f98 100644 (file)
@@ -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);
        }