tcp: Protect accesses to .ts_recent_stamp with {READ,WRITE}_ONCE()
[linux-2.6-microblaze.git] / mm / rmap.c
index 0c7b2a9..b3e3819 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -251,18 +251,37 @@ 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. On the other hand, an anon_vma with more than one
- * child isn't reused even if there was no alive vma, thus rmap walker has a
- * good chance of avoiding scanning the whole hierarchy when it searches where
- * page is mapped.
+ * anon_vma_clone() is called by __vma_split(), __split_vma(), copy_vma() and
+ * anon_vma_fork(). The first three want an exact copy of src, while the last
+ * one, anon_vma_fork(), may try to reuse an existing anon_vma to prevent
+ * endless growth of anon_vma. Since dst->anon_vma is set to NULL before call,
+ * we can identify this case by checking (!dst->anon_vma && src->anon_vma).
+ *
+ * If (!dst->anon_vma && src->anon_vma) is true, 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. On the other hand, an anon_vma with more
+ * than one child isn't reused even if there was no alive vma, thus rmap
+ * walker has a good chance of avoiding scanning the whole hierarchy when it
+ * searches where page is mapped.
  */
 int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
 {
        struct anon_vma_chain *avc, *pavc;
        struct anon_vma *root = NULL;
+       struct vm_area_struct *prev = dst->vm_prev, *pprev = src->vm_prev;
+
+       /*
+        * If parent share anon_vma with its vm_prev, keep this sharing in in
+        * child.
+        *
+        * 1. Parent has vm_prev, which implies we have vm_prev.
+        * 2. Parent and its vm_prev have the same anon_vma.
+        */
+       if (!dst->anon_vma && src->anon_vma &&
+           pprev && pprev->anon_vma == src->anon_vma)
+               dst->anon_vma = prev->anon_vma;
+
 
        list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) {
                struct anon_vma *anon_vma;
@@ -287,8 +306,8 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
                 * will always reuse it. Root anon_vma is never reused:
                 * it has self-parent reference and at least one child.
                 */
-               if (!dst->anon_vma && anon_vma != src->anon_vma &&
-                               anon_vma->degree < 2)
+               if (!dst->anon_vma && src->anon_vma &&
+                   anon_vma != src->anon_vma && anon_vma->degree < 2)
                        dst->anon_vma = anon_vma;
        }
        if (dst->anon_vma)
@@ -458,9 +477,10 @@ void __init anon_vma_init(void)
  * chain and verify that the page in question is indeed mapped in it
  * [ something equivalent to page_mapped_in_vma() ].
  *
- * Since anon_vma's slab is DESTROY_BY_RCU and we know from page_remove_rmap()
- * that the anon_vma pointer from page->mapping is valid if there is a
- * mapcount, we can dereference the anon_vma after observing those.
+ * Since anon_vma's slab is SLAB_TYPESAFE_BY_RCU and we know from
+ * page_remove_rmap() that the anon_vma pointer from page->mapping is valid
+ * if there is a mapcount, we can dereference the anon_vma after observing
+ * those.
  */
 struct anon_vma *page_get_anon_vma(struct page *page)
 {
@@ -1055,7 +1075,6 @@ static void __page_set_anon_rmap(struct page *page,
 static void __page_check_anon_rmap(struct page *page,
        struct vm_area_struct *vma, unsigned long address)
 {
-#ifdef CONFIG_DEBUG_VM
        /*
         * The page's anon-rmap details (mapping and index) are guaranteed to
         * be set up correctly at this point.
@@ -1068,9 +1087,9 @@ static void __page_check_anon_rmap(struct page *page,
         * are initially only visible via the pagetables, and the pte is locked
         * over the call to page_add_new_anon_rmap.
         */
-       BUG_ON(page_anon_vma(page)->root != vma->anon_vma->root);
-       BUG_ON(page_to_pgoff(page) != linear_page_index(vma, address));
-#endif
+       VM_BUG_ON_PAGE(page_anon_vma(page)->root != vma->anon_vma->root, page);
+       VM_BUG_ON_PAGE(page_to_pgoff(page) != linear_page_index(vma, address),
+                      page);
 }
 
 /**
@@ -1273,12 +1292,20 @@ static void page_remove_anon_compound_rmap(struct page *page)
        if (TestClearPageDoubleMap(page)) {
                /*
                 * Subpages can be mapped with PTEs too. Check how many of
-                * themi are still mapped.
+                * them are still mapped.
                 */
                for (i = 0, nr = 0; i < HPAGE_PMD_NR; i++) {
                        if (atomic_add_negative(-1, &page[i]._mapcount))
                                nr++;
                }
+
+               /*
+                * Queue the page for deferred split if at least one small
+                * page of the compound page is unmapped, but at least one
+                * small page is still mapped.
+                */
+               if (nr && nr < HPAGE_PMD_NR)
+                       deferred_split_huge_page(page);
        } else {
                nr = HPAGE_PMD_NR;
        }
@@ -1286,10 +1313,8 @@ static void page_remove_anon_compound_rmap(struct page *page)
        if (unlikely(PageMlocked(page)))
                clear_page_mlock(page);
 
-       if (nr) {
+       if (nr)
                __mod_node_page_state(page_pgdat(page), NR_ANON_MAPPED, -nr);
-               deferred_split_huge_page(page);
-       }
 }
 
 /**