hugetlbfs: use i_mmap_rwsem for more pmd sharing synchronization
[linux-2.6-microblaze.git] / mm / rmap.c
index 0c7b2a9..2df75a1 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
  *
  * inode->i_mutex      (while writing or truncating, not reading or faulting)
  *   mm->mmap_sem
- *     page->flags PG_locked (lock_page)
+ *     page->flags PG_locked (lock_page)   * (see huegtlbfs below)
  *       hugetlbfs_i_mmap_rwsem_key (in huge_pmd_share)
  *         mapping->i_mmap_rwsem
+ *           hugetlb_fault_mutex (hugetlbfs specific page fault mutex)
  *           anon_vma->rwsem
  *             mm->page_table_lock or pte_lock
  *               pgdat->lru_lock (in mark_page_accessed, isolate_lru_page)
  * anon_vma->rwsem,mapping->i_mutex      (memory_failure, collect_procs_anon)
  *   ->tasklist_lock
  *     pte map lock
+ *
+ * * hugetlbfs PageHuge() pages take locks in this order:
+ *         mapping->i_mmap_rwsem
+ *           hugetlb_fault_mutex (hugetlbfs specific page fault mutex)
+ *             page->flags PG_locked (lock_page)
  */
 
 #include <linux/mm.h>
@@ -251,18 +257,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 +312,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 +483,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 +1081,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 +1093,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);
 }
 
 /**
@@ -1159,6 +1184,9 @@ void page_add_new_anon_rmap(struct page *page,
                VM_BUG_ON_PAGE(!PageTransHuge(page), page);
                /* increment count (starts at -1) */
                atomic_set(compound_mapcount_ptr(page), 0);
+               if (hpage_pincount_available(page))
+                       atomic_set(compound_pincount_ptr(page), 0);
+
                __inc_node_page_state(page, NR_ANON_THPS);
        } else {
                /* Anon THP always mapped first with PMD */
@@ -1273,12 +1301,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 +1322,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);
-       }
 }
 
 /**
@@ -1381,6 +1415,9 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                /*
                 * If sharing is possible, start and end will be adjusted
                 * accordingly.
+                *
+                * If called for a huge page, caller must hold i_mmap_rwsem
+                * in write mode as it is possible to call huge_pmd_unshare.
                 */
                adjust_range_if_pmd_sharing_possible(vma, &range.start,
                                                     &range.end);
@@ -1428,6 +1465,12 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                address = pvmw.address;
 
                if (PageHuge(page)) {
+                       /*
+                        * To call huge_pmd_unshare, i_mmap_rwsem must be
+                        * held in write mode.  Caller needs to explicitly
+                        * do this outside rmap routines.
+                        */
+                       VM_BUG_ON(!(flags & TTU_RMAP_LOCKED));
                        if (huge_pmd_unshare(mm, &address, pvmw.pte)) {
                                /*
                                 * huge_pmd_unshare unmapped an entire PMD
@@ -1671,23 +1714,9 @@ discard:
        return ret;
 }
 
-bool is_vma_temporary_stack(struct vm_area_struct *vma)
-{
-       int maybe_stack = vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP);
-
-       if (!maybe_stack)
-               return false;
-
-       if ((vma->vm_flags & VM_STACK_INCOMPLETE_SETUP) ==
-                                               VM_STACK_INCOMPLETE_SETUP)
-               return true;
-
-       return false;
-}
-
 static bool invalid_migration_vma(struct vm_area_struct *vma, void *arg)
 {
-       return is_vma_temporary_stack(vma);
+       return vma_is_temporary_stack(vma);
 }
 
 static int page_mapcount_is_zero(struct page *page)
@@ -1949,6 +1978,9 @@ void hugepage_add_new_anon_rmap(struct page *page,
 {
        BUG_ON(address < vma->vm_start || address >= vma->vm_end);
        atomic_set(compound_mapcount_ptr(page), 0);
+       if (hpage_pincount_available(page))
+               atomic_set(compound_pincount_ptr(page), 0);
+
        __page_set_anon_rmap(page, vma, address, 1);
 }
 #endif /* CONFIG_HUGETLB_PAGE */