OSDN Git Service

mm/huge_memory: streamline COW logic in do_huge_pmd_wp_page()
[uclinux-h8/linux.git] / mm / huge_memory.c
index 057b13b..a5f651c 100644 (file)
@@ -1303,7 +1303,6 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf)
        page = pmd_page(orig_pmd);
        VM_BUG_ON_PAGE(!PageHead(page), page);
 
-       /* Lock page for reuse_swap_page() */
        if (!trylock_page(page)) {
                get_page(page);
                spin_unlock(vmf->ptl);
@@ -1319,10 +1318,15 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf)
        }
 
        /*
-        * We can only reuse the page if nobody else maps the huge page or it's
-        * part.
+        * See do_wp_page(): we can only map the page writable if there are
+        * no additional references. Note that we always drain the LRU
+        * pagevecs immediately after adding a THP.
         */
-       if (reuse_swap_page(page)) {
+       if (page_count(page) > 1 + PageSwapCache(page) * thp_nr_pages(page))
+               goto unlock_fallback;
+       if (PageSwapCache(page))
+               try_to_free_swap(page);
+       if (page_count(page) == 1) {
                pmd_t entry;
                entry = pmd_mkyoung(orig_pmd);
                entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
@@ -1333,6 +1337,7 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf)
                return VM_FAULT_WRITE;
        }
 
+unlock_fallback:
        unlock_page(page);
        spin_unlock(vmf->ptl);
 fallback: