|
@@ -774,7 +774,7 @@ void page_remove_rmap(struct page *page)
|
|
|
* repeatedly from either try_to_unmap_anon or try_to_unmap_file.
|
|
|
*/
|
|
|
static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
|
|
|
- int migration)
|
|
|
+ enum ttu_flags flags)
|
|
|
{
|
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
|
unsigned long address;
|
|
@@ -796,11 +796,13 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
|
|
|
* If it's recently referenced (perhaps page_referenced
|
|
|
* skipped over this mm) then we should reactivate it.
|
|
|
*/
|
|
|
- if (!migration) {
|
|
|
+ if (!(flags & TTU_IGNORE_MLOCK)) {
|
|
|
if (vma->vm_flags & VM_LOCKED) {
|
|
|
ret = SWAP_MLOCK;
|
|
|
goto out_unmap;
|
|
|
}
|
|
|
+ }
|
|
|
+ if (!(flags & TTU_IGNORE_ACCESS)) {
|
|
|
if (ptep_clear_flush_young_notify(vma, address, pte)) {
|
|
|
ret = SWAP_FAIL;
|
|
|
goto out_unmap;
|
|
@@ -840,12 +842,12 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
|
|
|
* pte. do_swap_page() will wait until the migration
|
|
|
* pte is removed and then restart fault handling.
|
|
|
*/
|
|
|
- BUG_ON(!migration);
|
|
|
+ BUG_ON(TTU_ACTION(flags) != TTU_MIGRATION);
|
|
|
entry = make_migration_entry(page, pte_write(pteval));
|
|
|
}
|
|
|
set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
|
|
|
BUG_ON(pte_file(*pte));
|
|
|
- } else if (PAGE_MIGRATION && migration) {
|
|
|
+ } else if (PAGE_MIGRATION && (TTU_ACTION(flags) == TTU_MIGRATION)) {
|
|
|
/* Establish migration entry for a file page */
|
|
|
swp_entry_t entry;
|
|
|
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)
|
|
|
* vm_flags for that VMA. That should be OK, because that vma shouldn't be
|
|
|
* 'LOCKED.
|
|
|
*/
|
|
|
-static int try_to_unmap_anon(struct page *page, int unlock, int migration)
|
|
|
+static int try_to_unmap_anon(struct page *page, enum ttu_flags flags)
|
|
|
{
|
|
|
struct anon_vma *anon_vma;
|
|
|
struct vm_area_struct *vma;
|
|
|
unsigned int mlocked = 0;
|
|
|
int ret = SWAP_AGAIN;
|
|
|
+ int unlock = TTU_ACTION(flags) == TTU_MUNLOCK;
|
|
|
|
|
|
if (MLOCK_PAGES && unlikely(unlock))
|
|
|
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)
|
|
|
continue; /* must visit all unlocked vmas */
|
|
|
ret = SWAP_MLOCK; /* saw at least one mlocked vma */
|
|
|
} else {
|
|
|
- ret = try_to_unmap_one(page, vma, migration);
|
|
|
+ ret = try_to_unmap_one(page, vma, flags);
|
|
|
if (ret == SWAP_FAIL || !page_mapped(page))
|
|
|
break;
|
|
|
}
|
|
@@ -1059,8 +1062,7 @@ static int try_to_unmap_anon(struct page *page, int unlock, int migration)
|
|
|
/**
|
|
|
* try_to_unmap_file - unmap/unlock file page using the object-based rmap method
|
|
|
* @page: the page to unmap/unlock
|
|
|
- * @unlock: request for unlock rather than unmap [unlikely]
|
|
|
- * @migration: unmapping for migration - ignored if @unlock
|
|
|
+ * @flags: action and flags
|
|
|
*
|
|
|
* Find all the mappings of a page using the mapping pointer and the vma chains
|
|
|
* 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)
|
|
|
* vm_flags for that VMA. That should be OK, because that vma shouldn't be
|
|
|
* 'LOCKED.
|
|
|
*/
|
|
|
-static int try_to_unmap_file(struct page *page, int unlock, int migration)
|
|
|
+static int try_to_unmap_file(struct page *page, enum ttu_flags flags)
|
|
|
{
|
|
|
struct address_space *mapping = page->mapping;
|
|
|
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)
|
|
|
unsigned long max_nl_size = 0;
|
|
|
unsigned int mapcount;
|
|
|
unsigned int mlocked = 0;
|
|
|
+ int unlock = TTU_ACTION(flags) == TTU_MUNLOCK;
|
|
|
|
|
|
if (MLOCK_PAGES && unlikely(unlock))
|
|
|
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)
|
|
|
continue; /* must visit all vmas */
|
|
|
ret = SWAP_MLOCK;
|
|
|
} else {
|
|
|
- ret = try_to_unmap_one(page, vma, migration);
|
|
|
+ ret = try_to_unmap_one(page, vma, flags);
|
|
|
if (ret == SWAP_FAIL || !page_mapped(page))
|
|
|
goto out;
|
|
|
}
|
|
@@ -1121,7 +1124,8 @@ static int try_to_unmap_file(struct page *page, int unlock, int migration)
|
|
|
ret = SWAP_MLOCK; /* leave mlocked == 0 */
|
|
|
goto out; /* no need to look further */
|
|
|
}
|
|
|
- if (!MLOCK_PAGES && !migration && (vma->vm_flags & VM_LOCKED))
|
|
|
+ if (!MLOCK_PAGES && !(flags & TTU_IGNORE_MLOCK) &&
|
|
|
+ (vma->vm_flags & VM_LOCKED))
|
|
|
continue;
|
|
|
cursor = (unsigned long) vma->vm_private_data;
|
|
|
if (cursor > max_nl_cursor)
|
|
@@ -1155,7 +1159,7 @@ static int try_to_unmap_file(struct page *page, int unlock, int migration)
|
|
|
do {
|
|
|
list_for_each_entry(vma, &mapping->i_mmap_nonlinear,
|
|
|
shared.vm_set.list) {
|
|
|
- if (!MLOCK_PAGES && !migration &&
|
|
|
+ if (!MLOCK_PAGES && !(flags & TTU_IGNORE_MLOCK) &&
|
|
|
(vma->vm_flags & VM_LOCKED))
|
|
|
continue;
|
|
|
cursor = (unsigned long) vma->vm_private_data;
|
|
@@ -1195,7 +1199,7 @@ out:
|
|
|
/**
|
|
|
* try_to_unmap - try to remove all page table mappings to a page
|
|
|
* @page: the page to get unmapped
|
|
|
- * @migration: migration flag
|
|
|
+ * @flags: action and flags
|
|
|
*
|
|
|
* Tries to remove all the page table entries which are mapping this
|
|
|
* page, used in the pageout path. Caller must hold the page lock.
|
|
@@ -1206,16 +1210,16 @@ out:
|
|
|
* SWAP_FAIL - the page is unswappable
|
|
|
* SWAP_MLOCK - page is mlocked.
|
|
|
*/
|
|
|
-int try_to_unmap(struct page *page, int migration)
|
|
|
+int try_to_unmap(struct page *page, enum ttu_flags flags)
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
BUG_ON(!PageLocked(page));
|
|
|
|
|
|
if (PageAnon(page))
|
|
|
- ret = try_to_unmap_anon(page, 0, migration);
|
|
|
+ ret = try_to_unmap_anon(page, flags);
|
|
|
else
|
|
|
- ret = try_to_unmap_file(page, 0, migration);
|
|
|
+ ret = try_to_unmap_file(page, flags);
|
|
|
if (ret != SWAP_MLOCK && !page_mapped(page))
|
|
|
ret = SWAP_SUCCESS;
|
|
|
return ret;
|
|
@@ -1240,8 +1244,8 @@ int try_to_munlock(struct page *page)
|
|
|
VM_BUG_ON(!PageLocked(page) || PageLRU(page));
|
|
|
|
|
|
if (PageAnon(page))
|
|
|
- return try_to_unmap_anon(page, 1, 0);
|
|
|
+ return try_to_unmap_anon(page, TTU_MUNLOCK);
|
|
|
else
|
|
|
- return try_to_unmap_file(page, 1, 0);
|
|
|
+ return try_to_unmap_file(page, TTU_MUNLOCK);
|
|
|
}
|
|
|
|