diff options
-rw-r--r-- | mm/memory.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/mm/memory.c b/mm/memory.c index dd7d7fc5ed60..65962534b4ed 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1467,11 +1467,21 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1467 | goto gotten; | 1467 | goto gotten; |
1468 | 1468 | ||
1469 | /* | 1469 | /* |
1470 | * Only catch write-faults on shared writable pages, read-only | 1470 | * Take out anonymous pages first, anonymous shared vmas are |
1471 | * shared pages can get COWed by get_user_pages(.write=1, .force=1). | 1471 | * not dirty accountable. |
1472 | */ | 1472 | */ |
1473 | if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) == | 1473 | if (PageAnon(old_page)) { |
1474 | if (!TestSetPageLocked(old_page)) { | ||
1475 | reuse = can_share_swap_page(old_page); | ||
1476 | unlock_page(old_page); | ||
1477 | } | ||
1478 | } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) == | ||
1474 | (VM_WRITE|VM_SHARED))) { | 1479 | (VM_WRITE|VM_SHARED))) { |
1480 | /* | ||
1481 | * Only catch write-faults on shared writable pages, | ||
1482 | * read-only shared pages can get COWed by | ||
1483 | * get_user_pages(.write=1, .force=1). | ||
1484 | */ | ||
1475 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) { | 1485 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) { |
1476 | /* | 1486 | /* |
1477 | * Notify the address space that the page is about to | 1487 | * Notify the address space that the page is about to |
@@ -1503,9 +1513,6 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1503 | dirty_page = old_page; | 1513 | dirty_page = old_page; |
1504 | get_page(dirty_page); | 1514 | get_page(dirty_page); |
1505 | reuse = 1; | 1515 | reuse = 1; |
1506 | } else if (PageAnon(old_page) && !TestSetPageLocked(old_page)) { | ||
1507 | reuse = can_share_swap_page(old_page); | ||
1508 | unlock_page(old_page); | ||
1509 | } | 1516 | } |
1510 | 1517 | ||
1511 | if (reuse) { | 1518 | if (reuse) { |