diff options
Diffstat (limited to 'mm/rmap.c')
-rw-r--r-- | mm/rmap.c | 40 |
1 files changed, 22 insertions, 18 deletions
@@ -774,7 +774,7 @@ void page_remove_rmap(struct page *page) | |||
774 | * repeatedly from either try_to_unmap_anon or try_to_unmap_file. | 774 | * repeatedly from either try_to_unmap_anon or try_to_unmap_file. |
775 | */ | 775 | */ |
776 | static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | 776 | static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, |
777 | int migration) | 777 | enum ttu_flags flags) |
778 | { | 778 | { |
779 | struct mm_struct *mm = vma->vm_mm; | 779 | struct mm_struct *mm = vma->vm_mm; |
780 | unsigned long address; | 780 | unsigned long address; |
@@ -796,11 +796,13 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
796 | * If it's recently referenced (perhaps page_referenced | 796 | * If it's recently referenced (perhaps page_referenced |
797 | * skipped over this mm) then we should reactivate it. | 797 | * skipped over this mm) then we should reactivate it. |
798 | */ | 798 | */ |
799 | if (!migration) { | 799 | if (!(flags & TTU_IGNORE_MLOCK)) { |
800 | if (vma->vm_flags & VM_LOCKED) { | 800 | if (vma->vm_flags & VM_LOCKED) { |
801 | ret = SWAP_MLOCK; | 801 | ret = SWAP_MLOCK; |
802 | goto out_unmap; | 802 | goto out_unmap; |
803 | } | 803 | } |
804 | } | ||
805 | if (!(flags & TTU_IGNORE_ACCESS)) { | ||
804 | if (ptep_clear_flush_young_notify(vma, address, pte)) { | 806 | if (ptep_clear_flush_young_notify(vma, address, pte)) { |
805 | ret = SWAP_FAIL; | 807 | ret = SWAP_FAIL; |
806 | goto out_unmap; | 808 | goto out_unmap; |
@@ -840,12 +842,12 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
840 | * pte. do_swap_page() will wait until the migration | 842 | * pte. do_swap_page() will wait until the migration |
841 | * pte is removed and then restart fault handling. | 843 | * pte is removed and then restart fault handling. |
842 | */ | 844 | */ |
843 | BUG_ON(!migration); | 845 | BUG_ON(TTU_ACTION(flags) != TTU_MIGRATION); |
844 | entry = make_migration_entry(page, pte_write(pteval)); | 846 | entry = make_migration_entry(page, pte_write(pteval)); |
845 | } | 847 | } |
846 | set_pte_at(mm, address, pte, swp_entry_to_pte(entry)); | 848 | set_pte_at(mm, address, pte, swp_entry_to_pte(entry)); |
847 | BUG_ON(pte_file(*pte)); | 849 | BUG_ON(pte_file(*pte)); |
848 | } else if (PAGE_MIGRATION && migration) { | 850 | } else if (PAGE_MIGRATION && (TTU_ACTION(flags) == TTU_MIGRATION)) { |
849 | /* Establish migration entry for a file page */ | 851 | /* Establish migration entry for a file page */ |
850 | swp_entry_t entry; | 852 | swp_entry_t entry; |
851 | entry = make_migration_entry(page, pte_write(pteval)); | 853 | entry = make_migration_entry(page, pte_write(pteval)); |
@@ -1014,12 +1016,13 @@ static int try_to_mlock_page(struct page *page, struct vm_area_struct *vma) | |||
1014 | * vm_flags for that VMA. That should be OK, because that vma shouldn't be | 1016 | * vm_flags for that VMA. That should be OK, because that vma shouldn't be |
1015 | * 'LOCKED. | 1017 | * 'LOCKED. |
1016 | */ | 1018 | */ |
1017 | static int try_to_unmap_anon(struct page *page, int unlock, int migration) | 1019 | static int try_to_unmap_anon(struct page *page, enum ttu_flags flags) |
1018 | { | 1020 | { |
1019 | struct anon_vma *anon_vma; | 1021 | struct anon_vma *anon_vma; |
1020 | struct vm_area_struct *vma; | 1022 | struct vm_area_struct *vma; |
1021 | unsigned int mlocked = 0; | 1023 | unsigned int mlocked = 0; |
1022 | int ret = SWAP_AGAIN; | 1024 | int ret = SWAP_AGAIN; |
1025 | int unlock = TTU_ACTION(flags) == TTU_MUNLOCK; | ||
1023 | 1026 | ||
1024 | if (MLOCK_PAGES && unlikely(unlock)) | 1027 | if (MLOCK_PAGES && unlikely(unlock)) |
1025 | ret = SWAP_SUCCESS; /* default for try_to_munlock() */ | 1028 | ret = SWAP_SUCCESS; /* default for try_to_munlock() */ |
@@ -1035,7 +1038,7 @@ static int try_to_unmap_anon(struct page *page, int unlock, int migration) | |||
1035 | continue; /* must visit all unlocked vmas */ | 1038 | continue; /* must visit all unlocked vmas */ |
1036 | ret = SWAP_MLOCK; /* saw at least one mlocked vma */ | 1039 | ret = SWAP_MLOCK; /* saw at least one mlocked vma */ |
1037 | } else { | 1040 | } else { |
1038 | ret = try_to_unmap_one(page, vma, migration); | 1041 | ret = try_to_unmap_one(page, vma, flags); |
1039 | if (ret == SWAP_FAIL || !page_mapped(page)) | 1042 | if (ret == SWAP_FAIL || !page_mapped(page)) |
1040 | break; | 1043 | break; |
1041 | } | 1044 | } |
@@ -1059,8 +1062,7 @@ static int try_to_unmap_anon(struct page *page, int unlock, int migration) | |||
1059 | /** | 1062 | /** |
1060 | * try_to_unmap_file - unmap/unlock file page using the object-based rmap method | 1063 | * try_to_unmap_file - unmap/unlock file page using the object-based rmap method |
1061 | * @page: the page to unmap/unlock | 1064 | * @page: the page to unmap/unlock |
1062 | * @unlock: request for unlock rather than unmap [unlikely] | 1065 | * @flags: action and flags |
1063 | * @migration: unmapping for migration - ignored if @unlock | ||
1064 | * | 1066 | * |
1065 | * Find all the mappings of a page using the mapping pointer and the vma chains | 1067 | * Find all the mappings of a page using the mapping pointer and the vma chains |
1066 | * contained in the address_space struct it points to. | 1068 | * contained in the address_space struct it points to. |
@@ -1072,7 +1074,7 @@ static int try_to_unmap_anon(struct page *page, int unlock, int migration) | |||
1072 | * vm_flags for that VMA. That should be OK, because that vma shouldn't be | 1074 | * vm_flags for that VMA. That should be OK, because that vma shouldn't be |
1073 | * 'LOCKED. | 1075 | * 'LOCKED. |
1074 | */ | 1076 | */ |
1075 | static int try_to_unmap_file(struct page *page, int unlock, int migration) | 1077 | static int try_to_unmap_file(struct page *page, enum ttu_flags flags) |
1076 | { | 1078 | { |
1077 | struct address_space *mapping = page->mapping; | 1079 | struct address_space *mapping = page->mapping; |
1078 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | 1080 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); |
@@ -1084,6 +1086,7 @@ static int try_to_unmap_file(struct page *page, int unlock, int migration) | |||
1084 | unsigned long max_nl_size = 0; | 1086 | unsigned long max_nl_size = 0; |
1085 | unsigned int mapcount; | 1087 | unsigned int mapcount; |
1086 | unsigned int mlocked = 0; | 1088 | unsigned int mlocked = 0; |
1089 | int unlock = TTU_ACTION(flags) == TTU_MUNLOCK; | ||
1087 | 1090 | ||
1088 | if (MLOCK_PAGES && unlikely(unlock)) | 1091 | if (MLOCK_PAGES && unlikely(unlock)) |
1089 | ret = SWAP_SUCCESS; /* default for try_to_munlock() */ | 1092 | ret = SWAP_SUCCESS; /* default for try_to_munlock() */ |
@@ -1096,7 +1099,7 @@ static int try_to_unmap_file(struct page *page, int unlock, int migration) | |||
1096 | continue; /* must visit all vmas */ | 1099 | continue; /* must visit all vmas */ |
1097 | ret = SWAP_MLOCK; | 1100 | ret = SWAP_MLOCK; |
1098 | } else { | 1101 | } else { |
1099 | ret = try_to_unmap_one(page, vma, migration); | 1102 | ret = try_to_unmap_one(page, vma, flags); |
1100 | if (ret == SWAP_FAIL || !page_mapped(page)) | 1103 | if (ret == SWAP_FAIL || !page_mapped(page)) |
1101 | goto out; | 1104 | goto out; |
1102 | } | 1105 | } |
@@ -1121,7 +1124,8 @@ static int try_to_unmap_file(struct page *page, int unlock, int migration) | |||
1121 | ret = SWAP_MLOCK; /* leave mlocked == 0 */ | 1124 | ret = SWAP_MLOCK; /* leave mlocked == 0 */ |
1122 | goto out; /* no need to look further */ | 1125 | goto out; /* no need to look further */ |
1123 | } | 1126 | } |
1124 | if (!MLOCK_PAGES && !migration && (vma->vm_flags & VM_LOCKED)) | 1127 | if (!MLOCK_PAGES && !(flags & TTU_IGNORE_MLOCK) && |
1128 | (vma->vm_flags & VM_LOCKED)) | ||
1125 | continue; | 1129 | continue; |
1126 | cursor = (unsigned long) vma->vm_private_data; | 1130 | cursor = (unsigned long) vma->vm_private_data; |
1127 | if (cursor > max_nl_cursor) | 1131 | if (cursor > max_nl_cursor) |
@@ -1155,7 +1159,7 @@ static int try_to_unmap_file(struct page *page, int unlock, int migration) | |||
1155 | do { | 1159 | do { |
1156 | list_for_each_entry(vma, &mapping->i_mmap_nonlinear, | 1160 | list_for_each_entry(vma, &mapping->i_mmap_nonlinear, |
1157 | shared.vm_set.list) { | 1161 | shared.vm_set.list) { |
1158 | if (!MLOCK_PAGES && !migration && | 1162 | if (!MLOCK_PAGES && !(flags & TTU_IGNORE_MLOCK) && |
1159 | (vma->vm_flags & VM_LOCKED)) | 1163 | (vma->vm_flags & VM_LOCKED)) |
1160 | continue; | 1164 | continue; |
1161 | cursor = (unsigned long) vma->vm_private_data; | 1165 | cursor = (unsigned long) vma->vm_private_data; |
@@ -1195,7 +1199,7 @@ out: | |||
1195 | /** | 1199 | /** |
1196 | * try_to_unmap - try to remove all page table mappings to a page | 1200 | * try_to_unmap - try to remove all page table mappings to a page |
1197 | * @page: the page to get unmapped | 1201 | * @page: the page to get unmapped |
1198 | * @migration: migration flag | 1202 | * @flags: action and flags |
1199 | * | 1203 | * |
1200 | * Tries to remove all the page table entries which are mapping this | 1204 | * Tries to remove all the page table entries which are mapping this |
1201 | * page, used in the pageout path. Caller must hold the page lock. | 1205 | * page, used in the pageout path. Caller must hold the page lock. |
@@ -1206,16 +1210,16 @@ out: | |||
1206 | * SWAP_FAIL - the page is unswappable | 1210 | * SWAP_FAIL - the page is unswappable |
1207 | * SWAP_MLOCK - page is mlocked. | 1211 | * SWAP_MLOCK - page is mlocked. |
1208 | */ | 1212 | */ |
1209 | int try_to_unmap(struct page *page, int migration) | 1213 | int try_to_unmap(struct page *page, enum ttu_flags flags) |
1210 | { | 1214 | { |
1211 | int ret; | 1215 | int ret; |
1212 | 1216 | ||
1213 | BUG_ON(!PageLocked(page)); | 1217 | BUG_ON(!PageLocked(page)); |
1214 | 1218 | ||
1215 | if (PageAnon(page)) | 1219 | if (PageAnon(page)) |
1216 | ret = try_to_unmap_anon(page, 0, migration); | 1220 | ret = try_to_unmap_anon(page, flags); |
1217 | else | 1221 | else |
1218 | ret = try_to_unmap_file(page, 0, migration); | 1222 | ret = try_to_unmap_file(page, flags); |
1219 | if (ret != SWAP_MLOCK && !page_mapped(page)) | 1223 | if (ret != SWAP_MLOCK && !page_mapped(page)) |
1220 | ret = SWAP_SUCCESS; | 1224 | ret = SWAP_SUCCESS; |
1221 | return ret; | 1225 | return ret; |
@@ -1240,8 +1244,8 @@ int try_to_munlock(struct page *page) | |||
1240 | VM_BUG_ON(!PageLocked(page) || PageLRU(page)); | 1244 | VM_BUG_ON(!PageLocked(page) || PageLRU(page)); |
1241 | 1245 | ||
1242 | if (PageAnon(page)) | 1246 | if (PageAnon(page)) |
1243 | return try_to_unmap_anon(page, 1, 0); | 1247 | return try_to_unmap_anon(page, TTU_MUNLOCK); |
1244 | else | 1248 | else |
1245 | return try_to_unmap_file(page, 1, 0); | 1249 | return try_to_unmap_file(page, TTU_MUNLOCK); |
1246 | } | 1250 | } |
1247 | 1251 | ||