{
struct page *old_page, *new_page = NULL;
pte_t entry;
- int ret = 0;
+ int page_copied = 0;
unsigned long mmun_start = 0; /* For mmu_notifiers */
unsigned long mmun_end = 0; /* For mmu_notifiers */
struct mem_cgroup *memcg;
&ptl);
if (!pte_same(*page_table, orig_pte)) {
unlock_page(old_page);
- goto unlock;
+ pte_unmap_unlock(page_table, ptl);
+ page_cache_release(old_page);
+ return 0;
}
page_cache_release(old_page);
}
&ptl);
if (!pte_same(*page_table, orig_pte)) {
unlock_page(old_page);
- goto unlock;
+ pte_unmap_unlock(page_table, ptl);
+ page_cache_release(old_page);
+ return 0;
}
page_mkwrite = 1;
}
/* Free the old page.. */
new_page = old_page;
- ret |= VM_FAULT_WRITE;
+ page_copied = 1;
} else
mem_cgroup_cancel_charge(new_page, memcg);
if (new_page)
page_cache_release(new_page);
-unlock:
+
pte_unmap_unlock(page_table, ptl);
- if (mmun_end > mmun_start)
- mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
+ mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
if (old_page) {
/*
* Don't let another task, with possibly unlocked vma,
* keep the mlocked page.
*/
- if ((ret & VM_FAULT_WRITE) && (vma->vm_flags & VM_LOCKED)) {
+ if (page_copied && (vma->vm_flags & VM_LOCKED)) {
lock_page(old_page); /* LRU manipulation */
munlock_vma_page(old_page);
unlock_page(old_page);
}
page_cache_release(old_page);
}
- return ret;
+ return page_copied ? VM_FAULT_WRITE : 0;
oom_free_new:
page_cache_release(new_page);
oom: