diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/mm/memory.c b/mm/memory.c index 7e3683fd4f3c..11673c5d2c20 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -434,7 +434,9 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
434 | /* pte contains position in swap or file, so copy. */ | 434 | /* pte contains position in swap or file, so copy. */ |
435 | if (unlikely(!pte_present(pte))) { | 435 | if (unlikely(!pte_present(pte))) { |
436 | if (!pte_file(pte)) { | 436 | if (!pte_file(pte)) { |
437 | swap_duplicate(pte_to_swp_entry(pte)); | 437 | swp_entry_t entry = pte_to_swp_entry(pte); |
438 | |||
439 | swap_duplicate(entry); | ||
438 | /* make sure dst_mm is on swapoff's mmlist. */ | 440 | /* make sure dst_mm is on swapoff's mmlist. */ |
439 | if (unlikely(list_empty(&dst_mm->mmlist))) { | 441 | if (unlikely(list_empty(&dst_mm->mmlist))) { |
440 | spin_lock(&mmlist_lock); | 442 | spin_lock(&mmlist_lock); |
@@ -443,6 +445,16 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
443 | &src_mm->mmlist); | 445 | &src_mm->mmlist); |
444 | spin_unlock(&mmlist_lock); | 446 | spin_unlock(&mmlist_lock); |
445 | } | 447 | } |
448 | if (is_write_migration_entry(entry) && | ||
449 | is_cow_mapping(vm_flags)) { | ||
450 | /* | ||
451 | * COW mappings require pages in both parent | ||
452 | * and child to be set to read. | ||
453 | */ | ||
454 | make_migration_entry_read(&entry); | ||
455 | pte = swp_entry_to_pte(entry); | ||
456 | set_pte_at(src_mm, addr, src_pte, pte); | ||
457 | } | ||
446 | } | 458 | } |
447 | goto out_set_pte; | 459 | goto out_set_pte; |
448 | } | 460 | } |
@@ -1879,6 +1891,10 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1879 | goto out; | 1891 | goto out; |
1880 | 1892 | ||
1881 | entry = pte_to_swp_entry(orig_pte); | 1893 | entry = pte_to_swp_entry(orig_pte); |
1894 | if (is_migration_entry(entry)) { | ||
1895 | migration_entry_wait(mm, pmd, address); | ||
1896 | goto out; | ||
1897 | } | ||
1882 | page = lookup_swap_cache(entry); | 1898 | page = lookup_swap_cache(entry); |
1883 | if (!page) { | 1899 | if (!page) { |
1884 | swapin_readahead(entry, address, vma); | 1900 | swapin_readahead(entry, address, vma); |