hammer2 - Fix stack blowout in lookup iteration
authorMatthew Dillon <dillon@apollo.backplane.com>
Sat, 8 Mar 2014 05:49:30 +0000 (21:49 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sat, 8 Mar 2014 05:49:30 +0000 (21:49 -0800)
* hammer2_chain_lookup()->hammer2_chain_next()->hammer2_chain_lookup()
  stacking could blow out the kernel stack.

* Inline the iteration within hammer2_chain_lookup() when the lookup runs
  out of blockrefs without finding anything at the current level, instead
  of having it call hammer2_chain_next().

sys/vfs/hammer2/hammer2_chain.c

index 42ab8a8..0f232da 100644 (file)
@@ -2063,9 +2063,25 @@ again:
                spin_unlock(&above->cst.spin);
                if (key_beg == key_end) /* short cut single-key case */
                        return (NULL);
-               return (hammer2_chain_next(parentp, NULL, key_nextp,
-                                          key_beg, key_end,
-                                          cache_indexp, flags));
+
+               /*
+                * Stop if we reached the end of the iteration.
+                */
+               if (parent->bref.type != HAMMER2_BREF_TYPE_INDIRECT &&
+                   parent->bref.type != HAMMER2_BREF_TYPE_FREEMAP_NODE) {
+                       return (NULL);
+               }
+
+               /*
+                * Calculate next key, stop if we reached the end of the
+                * iteration, otherwise go up one level and loop.
+                */
+               key_beg = parent->bref.key +
+                         ((hammer2_key_t)1 << parent->bref.keybits);
+               if (key_beg == 0 || key_beg > key_end)
+                       return (NULL);
+               parent = hammer2_chain_getparent(parentp, how_maybe);
+               goto again;
        }
 
        /*