git: hammer2 - Fix excess chain structure allocations during bulkfree (3)
commit f7a9ce16252aa547c85ff84ec40272848e5587bd Author: Matthew Dillon Date: Fri Mar 11 17:18:38 2022 -0800 hammer2 - Fix excess chain structure allocations during bulkfree (3) * Fix excess chain structure allocations during bulkfree, AGAIN. This time for real. The algorithmic change I made was not sufficient, because I was not backing-out the recursion all the way after hitting a deferral. Instead, the code was re-recursing down another branch while still really deep into the tree. The problem was mostly triggered on the inode radix tree for filesystems containing many inodes (like a hundred million inodes), and would lead to a kmalloc panic due to memory exhaustion. * Fixed for real this time. When we hit the recursion limit, the code fully backs out of the traversal (recording its placemarkers on the way back up), then starts again at the deepest placemarker rather than the shallowest placemarker. Summary of changes: sys/vfs/hammer2/hammer2_bulkfree.c | 39 -- 1 file changed, 37 insertions(+), 2 deletions(-) http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/f7a9ce16252aa547c85ff84ec40272848e5587bd -- DragonFly BSD source repository
git: hammer2 - Fix excess chain structure allocations during bulkfree (2)
commit 784d105b6000afc68e4b26e8acf5b4d6a79ea1f7 Author: Matthew Dillon Date: Fri Jan 14 12:55:36 2022 -0800 hammer2 - Fix excess chain structure allocations during bulkfree (2) Try to fix this again. The last attempt failed. Basically the problem is that when the depth-first traversal gets too deep, it has to defer the node at that point by adding it to a list. * Change the order to insert deferrals on the head instead of the tail in order to exhaust the most recently deferred sub-tree as quickly as possible (LIFO order). We previously exhausted deferred sub-trees in FIFO order but this often resulted in multiple levels of the radix tree building up on the list, which could blow-up memory use. * Once the list limit is reached (well, really 1/4 of the list limit), we previously continued to accumulate deferral as long as the relative depth was less then 3. Unfortunately, the maximum radix tree table size of roughly 512 elements could cause the number of deferrals even after the limit was reached to be up to 134 million chains (512 * 512 * 512). This is fixed by removing any depth test when the list limit is exhausted. * This combination of fixes should prevent the number of deferrals from blowing out hammer2's kmalloc pool. Theoretically the worst-case possible deferrals should now be 512 chains x max depth of radix tree. A very reasonable number. Summary of changes: sys/vfs/hammer2/hammer2.h | 1 + sys/vfs/hammer2/hammer2_bulkfree.c | 51 -- sys/vfs/hammer2/hammer2_vfsops.c | 3 +++ 3 files changed, 42 insertions(+), 13 deletions(-) http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/784d105b6000afc68e4b26e8acf5b4d6a79ea1f7 -- DragonFly BSD source repository
git: hammer2 - Fix excess chain structure allocations during bulkfree
commit 1dddac0a529e5053f361fc4614980b4cba145a61 Author: Matthew Dillon Date: Fri Jan 7 16:41:35 2022 -0800 hammer2 - Fix excess chain structure allocations during bulkfree * On H2 filesystems with a very large number of inodes, such as those used for backups or which contain many snapshots (e.g. tens of millions of inodes), the bulkfree process may attempt to track more hammer2_chain structures than the kmalloc subsystem allows. * This issue might also have contributed to reported lockups during bulkfree (if the bulkfree wound up eating too much non-pagable kernel memory), though the more typical outcome is a kernel panic when the kmalloc limit is exceeded for the pool. * During bulkfree, H2 must control recursion depth during the scan. It does this by deferring deep nodes in the topology by recording a pointer to a referenced hammer2_chain structure on a list. Once the recursion backs out, H2 then processes these saved chains. Topologies greater than 32 nodes deep can wind up being deferred more than once to cover the entire depth. It is possible for an excessive number of chains to accumulate on the deferral list during the scan, each structure burning up kernel memory. * Emplace a limit on the number of chains which can be deferred, vfs.hammer2.limit_saved_chains, with a reasonable default. When the limit is reached, the bulkfree simply records a chain higher-up in the recursion instead of going deeper, thus limiting the number of chains that will be deferred. This has the effect is capping memory use during the bulkfree scan. The cost is slightly less scan efficiency, but it should mostly be in the noise. Summary of changes: sys/vfs/hammer2/hammer2.h | 1 + sys/vfs/hammer2/hammer2_bulkfree.c | 28 +++- sys/vfs/hammer2/hammer2_vfsops.c | 5 + 3 files changed, 33 insertions(+), 1 deletion(-) http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/1dddac0a529e5053f361fc4614980b4cba145a61 -- DragonFly BSD source repository