|
@@ -1288,11 +1288,6 @@ void page_remove_rmap(struct page *page, bool compound)
|
|
*/
|
|
*/
|
|
}
|
|
}
|
|
|
|
|
|
-struct rmap_private {
|
|
|
|
- enum ttu_flags flags;
|
|
|
|
- int lazyfreed;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* @arg: enum ttu_flags will be passed to this argument
|
|
* @arg: enum ttu_flags will be passed to this argument
|
|
*/
|
|
*/
|
|
@@ -1308,8 +1303,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
|
|
pte_t pteval;
|
|
pte_t pteval;
|
|
struct page *subpage;
|
|
struct page *subpage;
|
|
int ret = SWAP_AGAIN;
|
|
int ret = SWAP_AGAIN;
|
|
- struct rmap_private *rp = arg;
|
|
|
|
- enum ttu_flags flags = rp->flags;
|
|
|
|
|
|
+ enum ttu_flags flags = (enum ttu_flags)arg;
|
|
|
|
|
|
/* munlock has nothing to gain from examining un-locked vmas */
|
|
/* munlock has nothing to gain from examining un-locked vmas */
|
|
if ((flags & TTU_MUNLOCK) && !(vma->vm_flags & VM_LOCKED))
|
|
if ((flags & TTU_MUNLOCK) && !(vma->vm_flags & VM_LOCKED))
|
|
@@ -1427,11 +1421,21 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
|
|
VM_BUG_ON_PAGE(!PageSwapCache(page) && PageSwapBacked(page),
|
|
VM_BUG_ON_PAGE(!PageSwapCache(page) && PageSwapBacked(page),
|
|
page);
|
|
page);
|
|
|
|
|
|
- if (!PageDirty(page)) {
|
|
|
|
- /* It's a freeable page by MADV_FREE */
|
|
|
|
- dec_mm_counter(mm, MM_ANONPAGES);
|
|
|
|
- rp->lazyfreed++;
|
|
|
|
- goto discard;
|
|
|
|
|
|
+ /* MADV_FREE page check */
|
|
|
|
+ if (!PageSwapBacked(page)) {
|
|
|
|
+ if (!PageDirty(page)) {
|
|
|
|
+ dec_mm_counter(mm, MM_ANONPAGES);
|
|
|
|
+ goto discard;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If the page was redirtied, it cannot be
|
|
|
|
+ * discarded. Remap the page to page table.
|
|
|
|
+ */
|
|
|
|
+ set_pte_at(mm, address, pvmw.pte, pteval);
|
|
|
|
+ ret = SWAP_DIRTY;
|
|
|
|
+ page_vma_mapped_walk_done(&pvmw);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
if (swap_duplicate(entry) < 0) {
|
|
if (swap_duplicate(entry) < 0) {
|
|
@@ -1499,18 +1503,15 @@ static int page_mapcount_is_zero(struct page *page)
|
|
* SWAP_AGAIN - we missed a mapping, try again later
|
|
* SWAP_AGAIN - we missed a mapping, try again later
|
|
* SWAP_FAIL - the page is unswappable
|
|
* SWAP_FAIL - the page is unswappable
|
|
* SWAP_MLOCK - page is mlocked.
|
|
* SWAP_MLOCK - page is mlocked.
|
|
|
|
+ * SWAP_DIRTY - page is dirty MADV_FREE page
|
|
*/
|
|
*/
|
|
int try_to_unmap(struct page *page, enum ttu_flags flags)
|
|
int try_to_unmap(struct page *page, enum ttu_flags flags)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
- struct rmap_private rp = {
|
|
|
|
- .flags = flags,
|
|
|
|
- .lazyfreed = 0,
|
|
|
|
- };
|
|
|
|
|
|
|
|
struct rmap_walk_control rwc = {
|
|
struct rmap_walk_control rwc = {
|
|
.rmap_one = try_to_unmap_one,
|
|
.rmap_one = try_to_unmap_one,
|
|
- .arg = &rp,
|
|
|
|
|
|
+ .arg = (void *)flags,
|
|
.done = page_mapcount_is_zero,
|
|
.done = page_mapcount_is_zero,
|
|
.anon_lock = page_lock_anon_vma_read,
|
|
.anon_lock = page_lock_anon_vma_read,
|
|
};
|
|
};
|
|
@@ -1531,11 +1532,8 @@ int try_to_unmap(struct page *page, enum ttu_flags flags)
|
|
else
|
|
else
|
|
ret = rmap_walk(page, &rwc);
|
|
ret = rmap_walk(page, &rwc);
|
|
|
|
|
|
- if (ret != SWAP_MLOCK && !page_mapcount(page)) {
|
|
|
|
|
|
+ if (ret != SWAP_MLOCK && !page_mapcount(page))
|
|
ret = SWAP_SUCCESS;
|
|
ret = SWAP_SUCCESS;
|
|
- if (rp.lazyfreed && !PageDirty(page))
|
|
|
|
- ret = SWAP_LZFREE;
|
|
|
|
- }
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1562,14 +1560,10 @@ static int page_not_mapped(struct page *page)
|
|
int try_to_munlock(struct page *page)
|
|
int try_to_munlock(struct page *page)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
- struct rmap_private rp = {
|
|
|
|
- .flags = TTU_MUNLOCK,
|
|
|
|
- .lazyfreed = 0,
|
|
|
|
- };
|
|
|
|
|
|
|
|
struct rmap_walk_control rwc = {
|
|
struct rmap_walk_control rwc = {
|
|
.rmap_one = try_to_unmap_one,
|
|
.rmap_one = try_to_unmap_one,
|
|
- .arg = &rp,
|
|
|
|
|
|
+ .arg = (void *)TTU_MUNLOCK,
|
|
.done = page_not_mapped,
|
|
.done = page_not_mapped,
|
|
.anon_lock = page_lock_anon_vma_read,
|
|
.anon_lock = page_lock_anon_vma_read,
|
|
|
|
|