|
@@ -1199,7 +1199,17 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
|
|
|
|
page = pmd_page(orig_pmd);
|
|
page = pmd_page(orig_pmd);
|
|
VM_BUG_ON_PAGE(!PageCompound(page) || !PageHead(page), page);
|
|
VM_BUG_ON_PAGE(!PageCompound(page) || !PageHead(page), page);
|
|
- if (page_mapcount(page) == 1) {
|
|
|
|
|
|
+ /*
|
|
|
|
+ * We can only reuse the page if nobody else maps the huge page or it's
|
|
|
|
+ * part. We can do it by checking page_mapcount() on each sub-page, but
|
|
|
|
+ * it's expensive.
|
|
|
|
+ * The cheaper way is to check page_count() to be equal 1: every
|
|
|
|
+ * mapcount takes page reference reference, so this way we can
|
|
|
|
+ * guarantee, that the PMD is the only mapping.
|
|
|
|
+ * This can give false negative if somebody pinned the page, but that's
|
|
|
|
+ * fine.
|
|
|
|
+ */
|
|
|
|
+ if (page_mapcount(page) == 1 && page_count(page) == 1) {
|
|
pmd_t entry;
|
|
pmd_t entry;
|
|
entry = pmd_mkyoung(orig_pmd);
|
|
entry = pmd_mkyoung(orig_pmd);
|
|
entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
|
|
entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
|