aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/rmap.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/mm/rmap.c b/mm/rmap.c
index b3deda8b5019..57306fa0114d 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -433,7 +433,7 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
433{ 433{
434 struct mm_struct *mm = vma->vm_mm; 434 struct mm_struct *mm = vma->vm_mm;
435 unsigned long address; 435 unsigned long address;
436 pte_t *pte, entry; 436 pte_t *pte;
437 spinlock_t *ptl; 437 spinlock_t *ptl;
438 int ret = 0; 438 int ret = 0;
439 439
@@ -445,17 +445,18 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
445 if (!pte) 445 if (!pte)
446 goto out; 446 goto out;
447 447
448 if (!pte_dirty(*pte) && !pte_write(*pte)) 448 if (pte_dirty(*pte) || pte_write(*pte)) {
449 goto unlock; 449 pte_t entry;
450 450
451 entry = ptep_get_and_clear(mm, address, pte); 451 flush_cache_page(vma, address, pte_pfn(*pte));
452 entry = pte_mkclean(entry); 452 entry = ptep_clear_flush(vma, address, pte);
453 entry = pte_wrprotect(entry); 453 entry = pte_wrprotect(entry);
454 ptep_establish(vma, address, pte, entry); 454 entry = pte_mkclean(entry);
455 lazy_mmu_prot_update(entry); 455 set_pte_at(vma, address, pte, entry);
456 ret = 1; 456 lazy_mmu_prot_update(entry);
457 ret = 1;
458 }
457 459
458unlock:
459 pte_unmap_unlock(pte, ptl); 460 pte_unmap_unlock(pte, ptl);
460out: 461out:
461 return ret; 462 return ret;
@@ -490,6 +491,8 @@ int page_mkclean(struct page *page)
490 if (mapping) 491 if (mapping)
491 ret = page_mkclean_file(mapping, page); 492 ret = page_mkclean_file(mapping, page);
492 } 493 }
494 if (page_test_and_clear_dirty(page))
495 ret = 1;
493 496
494 return ret; 497 return ret;
495} 498}