Skip to contentSkip to conversation

mm: prevent endless growth of anon_vma hierarchy

PATCH In review Konstantin Khlebnikov 2 participants 2 messages Dec 17, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v4 1/1 mm: prevent endless growth of anon_vma hierarchy

Constantly forking task causes unlimited grow of anon_vma chain. Each next child allocates new level of anon_vmas and links vma to all previous levels because pages might be inherited from any level.

This patch adds heuristic which decides to reuse existing anon_vma instead of forking new one. It adds counter anon_vma->degree which counts linked vmas and directly descending anon_vmas and reuses anon_vma if counter is lower than two. As a result each anon_vma has either vma or at least two descending anon_vmas. In such trees half of nodes are leafs with alive vmas, thus count of anon_vmas is no more than two times bigger than count of vmas. This heuristic reuses anon_vmas as few as possible because each reuse adds false aliasing among vmas and rmap walker ought to scan more ptes when it searches where page is might be mapped.

Fixes 5beb49305251 ("mm: change anon_vma linking to fix multi-process server scalability issue")
Cc Stable <[email protected]> (2.6.34+)

---

v2: update degree in anon_vma_prepare for merged anon_vma
v3: update comment and commit message
v4: reorder anon_vma fields, update commit message, patch for current mmotm

---
 include/linux/rmap.h |   10 ++++++++++
 mm/rmap.c            |   41 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 50 insertions(+), 1 deletion(-)
include/linux/rmap.h +10 -0
index 94d5bca..40bf29e 100644
@@ -37,6 +37,16 @@ struct anon_vma {
 	atomic_t refcount;
 
 	/*
+	 * Count of child anon_vmas and VMAs which points to this anon_vma.
+	 *
+	 * This counter is used for making decision about reusing anon_vma
+	 * instead of forking new one. See comments in function anon_vma_clone.
+	 */
+	unsigned degree;
+
+	struct anon_vma *parent;	/* Parent of this anon_vma */
+
+	/*
 	 * NOTE: the LSB of the rb_root.rb_node is set by
 	 * mm_take_all_locks() _after_ taking the above lock. So the
 	 * rb_root must only be read/written after taking the above lock
mm/rmap.c +40 -1

107 lines not on this page · raw message

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Reviewed-by on v4 1/1
#1 lore raw

mm/rmap.c static inline void unlock_anon_vma_root(struct anon_vma *root) · line 249

Quoted 11 lines · Konstantin Khlebnikov
mm/rmap.c +7 -0
@@ -236,6 +240,13 @@ static inline void unlock_anon_vma_root(struct anon_vma *root)
 /*
  * Attach the anon_vmas from src to dst.
  * Returns 0 on success, -ENOMEM on failure.
+ *
+ * If dst->anon_vma is NULL this function tries to find and reuse existing
+ * anon_vma which has no vmas and only one child anon_vma. This prevents
+ * degradation of anon_vma hierarchy to endless linear chain in case of
+ * constantly forking task. In other hand anon_vma with more than one child
+ * isn't reused even if was no alive vma, thus rmap walker has a good chance
+ * to avoid scanning whole hieraryhy when it searches where page is mapped.
                              ^^^^^^^^^
                              hierarchy

Other than that:

Thanks for fixing this long standing issue, Konstantin.