Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1587954 > unrolled thread
| Started by | Shaohua Li <shli@fb.com> |
|---|---|
| First post | 2017-02-24 22:40 +0100 |
| Last post | 2017-02-27 17:50 +0100 |
| Articles | 17 — 5 participants |
Back to article view | Back to linux.kernel
[PATCH V5 0/6] mm: fix some MADV_FREE issues Shaohua Li <shli@fb.com> - 2017-02-24 22:40 +0100
[PATCH V5 6/6] proc: show MADV_FREE pages info in smaps Shaohua Li <shli@fb.com> - 2017-02-24 22:40 +0100
Re: [PATCH V5 6/6] proc: show MADV_FREE pages info in smaps Michal Hocko <mhocko@kernel.org> - 2017-02-27 16:10 +0100
Re: [PATCH V5 6/6] proc: show MADV_FREE pages info in smaps "Hillf Danton" <hillf.zj@alibaba-inc.com> - 2017-02-28 04:30 +0100
[PATCH V5 4/6] mm: reclaim MADV_FREE pages Shaohua Li <shli@fb.com> - 2017-02-24 22:40 +0100
Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages Minchan Kim <minchan@kernel.org> - 2017-02-27 07:50 +0100
Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages Michal Hocko <mhocko@kernel.org> - 2017-02-27 17:40 +0100
Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages Minchan Kim <minchan@kernel.org> - 2017-02-28 06:50 +0100
Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages Michal Hocko <mhocko@kernel.org> - 2017-02-27 16:30 +0100
Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages Johannes Weiner <hannes@cmpxchg.org> - 2017-02-27 18:30 +0100
Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages "Hillf Danton" <hillf.zj@alibaba-inc.com> - 2017-02-28 04:30 +0100
[PATCH V5 1/6] mm: delete unnecessary TTU_* flags Shaohua Li <shli@fb.com> - 2017-02-24 22:40 +0100
Re: [PATCH V5 1/6] mm: delete unnecessary TTU_* flags Michal Hocko <mhocko@kernel.org> - 2017-02-27 16:10 +0100
[PATCH V5 2/6] mm: don't assume anonymous pages have SwapBacked flag Shaohua Li <shli@fb.com> - 2017-02-24 22:40 +0100
Re: [PATCH V5 2/6] mm: don't assume anonymous pages have SwapBacked flag "Hillf Danton" <hillf.zj@alibaba-inc.com> - 2017-02-27 08:00 +0100
Re: [PATCH V5 2/6] mm: don't assume anonymous pages have SwapBacked flag Michal Hocko <mhocko@kernel.org> - 2017-02-27 16:00 +0100
Re: [PATCH V5 2/6] mm: don't assume anonymous pages have SwapBacked flag Michal Hocko <mhocko@kernel.org> - 2017-02-27 17:50 +0100
| From | Shaohua Li <shli@fb.com> |
|---|---|
| Date | 2017-02-24 22:40 +0100 |
| Subject | [PATCH V5 0/6] mm: fix some MADV_FREE issues |
| Message-ID | <tevKN-693-3@gated-at.bofh.it> |
Hi, We are trying to use MADV_FREE in jemalloc. Several issues are found. Without solving the issues, jemalloc can't use the MADV_FREE feature. - Doesn't support system without swap enabled. Because if swap is off, we can't or can't efficiently age anonymous pages. And since MADV_FREE pages are mixed with other anonymous pages, we can't reclaim MADV_FREE pages. In current implementation, MADV_FREE will fallback to MADV_DONTNEED without swap enabled. But in our environment, a lot of machines don't enable swap. This will prevent our setup using MADV_FREE. - Increases memory pressure. page reclaim bias file pages reclaim against anonymous pages. This doesn't make sense for MADV_FREE pages, because those pages could be freed easily and refilled with very slight penality. Even page reclaim doesn't bias file pages, there is still an issue, because MADV_FREE pages and other anonymous pages are mixed together. To reclaim a MADV_FREE page, we probably must scan a lot of other anonymous pages, which is inefficient. In our test, we usually see oom with MADV_FREE enabled and nothing without it. - Accounting. There are two accounting problems. We don't have a global accounting. If the system is abnormal, we don't know if it's a problem from MADV_FREE side. The other problem is RSS accounting. MADV_FREE pages are accounted as normal anon pages and reclaimed lazily, so application's RSS becomes bigger. This confuses our workloads. We have monitoring daemon running and if it finds applications' RSS becomes abnormal, the daemon will kill the applications even kernel can reclaim the memory easily. To address the first the two issues, we can either put MADV_FREE pages into a separate LRU list (Minchan's previous patches and V1 patches), or put them into LRU_INACTIVE_FILE list (suggested by Johannes). The patchset use the second idea. The reason is LRU_INACTIVE_FILE list is tiny nowadays and should be full of used once file pages. So we can still efficiently reclaim MADV_FREE pages there without interference with other anon and active file pages. Putting the pages into inactive file list also has an advantage which allows page reclaim to prioritize MADV_FREE pages and used once file pages. MADV_FREE pages are put into the lru list and clear SwapBacked flag, so PageAnon(page) && !PageSwapBacked(page) will indicate a MADV_FREE pages. These pages will directly freed without pageout if they are clean, otherwise normal swap will reclaim them. For the third issue, the previous post adds global accounting and a separate RSS count for MADV_FREE pages. The problem is we never get accurate accounting for MADV_FREE pages. The pages are mapped to userspace, can be dirtied without notice from kernel side. To get accurate accounting, we could write protect the page, but then there is extra page fault overhead, which people don't want to pay. Jemalloc guys have concerns about the inaccurate accounting, so this post drops the accounting patches temporarily. The info exported to /proc/pid/smaps for MADV_FREE pages are kept, which is the only place we can get accurate accounting right now. Thanks, Shaohua V4->V5: - Fix some minor issues pointed out by Johannes - Integrate Johannes's cleanup patch - Fix a bug to avoid swapin page is dicarded silently V3->V4: - rebase to latest -mm tree - Address several issues pointed out by Johannes and Minchan - Dropped vmstat and RSS accounting http://marc.info/?l=linux-mm&m=148778961127710&w=2 V2->V3: - rebase to latest -mm tree - Address severl issues pointed out by Minchan - Add more descriptions http://marc.info/?l=linux-mm&m=148710098701674&w=2 V1->V2: - Put MADV_FREE pages into LRU_INACTIVE_FILE list instead of adding a new lru list, suggested by Johannes - Add RSS support http://marc.info/?l=linux-mm&m=148616481928054&w=2 Minchan previous patches: http://marc.info/?l=linux-mm&m=144800657002763&w=2 ---------------------- Shaohua Li (6): mm: delete unnecessary TTU_* flags mm: don't assume anonymous pages have SwapBacked flag mm: move MADV_FREE pages into LRU_INACTIVE_FILE list mm: reclaim MADV_FREE pages mm: enable MADV_FREE for swapless system proc: show MADV_FREE pages info in smaps Documentation/filesystems/proc.txt | 4 +++ fs/proc/task_mmu.c | 8 +++++- include/linux/rmap.h | 24 ++++++++---------- include/linux/swap.h | 2 +- include/linux/vm_event_item.h | 2 +- mm/huge_memory.c | 6 ++--- mm/khugepaged.c | 8 +++--- mm/madvise.c | 11 ++------- mm/memory-failure.c | 2 +- mm/migrate.c | 3 ++- mm/rmap.c | 43 +++++++++++++++----------------- mm/swap.c | 50 +++++++++++++++++++++----------------- mm/vmscan.c | 45 +++++++++++++++++++--------------- mm/vmstat.c | 1 + 14 files changed, 107 insertions(+), 102 deletions(-) -- 2.9.3
[toc] | [next] | [standalone]
| From | Shaohua Li <shli@fb.com> |
|---|---|
| Date | 2017-02-24 22:40 +0100 |
| Subject | [PATCH V5 6/6] proc: show MADV_FREE pages info in smaps |
| Message-ID | <tevKN-693-17@gated-at.bofh.it> |
| In reply to | #1587954 |
show MADV_FREE pages info of each vma in smaps. The interface is for
diganose or monitoring purpose, userspace could use it to understand
what happens in the application. Since userspace could dirty MADV_FREE
pages without notice from kernel, this interface is the only place we
can get accurate accounting info about MADV_FREE pages.
Cc: Michal Hocko <mhocko@suse.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Shaohua Li <shli@fb.com>
---
Documentation/filesystems/proc.txt | 4 ++++
fs/proc/task_mmu.c | 8 +++++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index c94b467..45853e1 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -412,6 +412,7 @@ Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 892 kB
Anonymous: 0 kB
+LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
@@ -441,6 +442,9 @@ accessed.
"Anonymous" shows the amount of memory that does not belong to any file. Even
a mapping associated with a file may contain anonymous pages: when MAP_PRIVATE
and a page is modified, the file page is replaced by a private anonymous copy.
+"LazyFree" shows the amount of memory which is marked by madvise(MADV_FREE).
+The memory isn't freed immediately with madvise(). It's freed in memory
+pressure if the memory is clean.
"AnonHugePages" shows the ammount of memory backed by transparent hugepage.
"ShmemPmdMapped" shows the ammount of shared (shmem/tmpfs) memory backed by
huge pages.
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index ee3efb2..8a5ec00 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -440,6 +440,7 @@ struct mem_size_stats {
unsigned long private_dirty;
unsigned long referenced;
unsigned long anonymous;
+ unsigned long lazyfree;
unsigned long anonymous_thp;
unsigned long shmem_thp;
unsigned long swap;
@@ -456,8 +457,11 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
int i, nr = compound ? 1 << compound_order(page) : 1;
unsigned long size = nr * PAGE_SIZE;
- if (PageAnon(page))
+ if (PageAnon(page)) {
mss->anonymous += size;
+ if (!PageSwapBacked(page) && !dirty && !PageDirty(page))
+ mss->lazyfree += size;
+ }
mss->resident += size;
/* Accumulate the size in pages that have been accessed. */
@@ -770,6 +774,7 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
"Private_Dirty: %8lu kB\n"
"Referenced: %8lu kB\n"
"Anonymous: %8lu kB\n"
+ "LazyFree: %8lu kB\n"
"AnonHugePages: %8lu kB\n"
"ShmemPmdMapped: %8lu kB\n"
"Shared_Hugetlb: %8lu kB\n"
@@ -788,6 +793,7 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
mss.private_dirty >> 10,
mss.referenced >> 10,
mss.anonymous >> 10,
+ mss.lazyfree >> 10,
mss.anonymous_thp >> 10,
mss.shmem_thp >> 10,
mss.shared_hugetlb >> 10,
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-02-27 16:10 +0100 |
| Subject | Re: [PATCH V5 6/6] proc: show MADV_FREE pages info in smaps |
| Message-ID | <tfv63-7iD-43@gated-at.bofh.it> |
| In reply to | #1587955 |
On Fri 24-02-17 13:31:49, Shaohua Li wrote:
> show MADV_FREE pages info of each vma in smaps. The interface is for
> diganose or monitoring purpose, userspace could use it to understand
> what happens in the application. Since userspace could dirty MADV_FREE
> pages without notice from kernel, this interface is the only place we
> can get accurate accounting info about MADV_FREE pages.
>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Hugh Dickins <hughd@google.com>
> Cc: Rik van Riel <riel@redhat.com>
> Cc: Mel Gorman <mgorman@techsingularity.net>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Acked-by: Johannes Weiner <hannes@cmpxchg.org>
> Acked-by: Minchan Kim <minchan@kernel.org>
> Signed-off-by: Shaohua Li <shli@fb.com>
Acked-by: Michal Hocko <mhocko@suse.com>
> ---
> Documentation/filesystems/proc.txt | 4 ++++
> fs/proc/task_mmu.c | 8 +++++++-
> 2 files changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
> index c94b467..45853e1 100644
> --- a/Documentation/filesystems/proc.txt
> +++ b/Documentation/filesystems/proc.txt
> @@ -412,6 +412,7 @@ Private_Clean: 0 kB
> Private_Dirty: 0 kB
> Referenced: 892 kB
> Anonymous: 0 kB
> +LazyFree: 0 kB
> AnonHugePages: 0 kB
> ShmemPmdMapped: 0 kB
> Shared_Hugetlb: 0 kB
> @@ -441,6 +442,9 @@ accessed.
> "Anonymous" shows the amount of memory that does not belong to any file. Even
> a mapping associated with a file may contain anonymous pages: when MAP_PRIVATE
> and a page is modified, the file page is replaced by a private anonymous copy.
> +"LazyFree" shows the amount of memory which is marked by madvise(MADV_FREE).
> +The memory isn't freed immediately with madvise(). It's freed in memory
> +pressure if the memory is clean.
> "AnonHugePages" shows the ammount of memory backed by transparent hugepage.
> "ShmemPmdMapped" shows the ammount of shared (shmem/tmpfs) memory backed by
> huge pages.
> diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
> index ee3efb2..8a5ec00 100644
> --- a/fs/proc/task_mmu.c
> +++ b/fs/proc/task_mmu.c
> @@ -440,6 +440,7 @@ struct mem_size_stats {
> unsigned long private_dirty;
> unsigned long referenced;
> unsigned long anonymous;
> + unsigned long lazyfree;
> unsigned long anonymous_thp;
> unsigned long shmem_thp;
> unsigned long swap;
> @@ -456,8 +457,11 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
> int i, nr = compound ? 1 << compound_order(page) : 1;
> unsigned long size = nr * PAGE_SIZE;
>
> - if (PageAnon(page))
> + if (PageAnon(page)) {
> mss->anonymous += size;
> + if (!PageSwapBacked(page) && !dirty && !PageDirty(page))
> + mss->lazyfree += size;
> + }
>
> mss->resident += size;
> /* Accumulate the size in pages that have been accessed. */
> @@ -770,6 +774,7 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
> "Private_Dirty: %8lu kB\n"
> "Referenced: %8lu kB\n"
> "Anonymous: %8lu kB\n"
> + "LazyFree: %8lu kB\n"
> "AnonHugePages: %8lu kB\n"
> "ShmemPmdMapped: %8lu kB\n"
> "Shared_Hugetlb: %8lu kB\n"
> @@ -788,6 +793,7 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
> mss.private_dirty >> 10,
> mss.referenced >> 10,
> mss.anonymous >> 10,
> + mss.lazyfree >> 10,
> mss.anonymous_thp >> 10,
> mss.shmem_thp >> 10,
> mss.shared_hugetlb >> 10,
> --
> 2.9.3
>
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | "Hillf Danton" <hillf.zj@alibaba-inc.com> |
|---|---|
| Date | 2017-02-28 04:30 +0100 |
| Subject | Re: [PATCH V5 6/6] proc: show MADV_FREE pages info in smaps |
| Message-ID | <tfGEa-6YX-11@gated-at.bofh.it> |
| In reply to | #1587955 |
On February 25, 2017 5:32 AM Shaohua Li wrote: > > show MADV_FREE pages info of each vma in smaps. The interface is for > diganose or monitoring purpose, userspace could use it to understand > what happens in the application. Since userspace could dirty MADV_FREE > pages without notice from kernel, this interface is the only place we > can get accurate accounting info about MADV_FREE pages. > > Cc: Michal Hocko <mhocko@suse.com> > Cc: Hugh Dickins <hughd@google.com> > Cc: Rik van Riel <riel@redhat.com> > Cc: Mel Gorman <mgorman@techsingularity.net> > Cc: Andrew Morton <akpm@linux-foundation.org> > Acked-by: Johannes Weiner <hannes@cmpxchg.org> > Acked-by: Minchan Kim <minchan@kernel.org> > Signed-off-by: Shaohua Li <shli@fb.com> > --- Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
[toc] | [prev] | [next] | [standalone]
| From | Shaohua Li <shli@fb.com> |
|---|---|
| Date | 2017-02-24 22:40 +0100 |
| Subject | [PATCH V5 4/6] mm: reclaim MADV_FREE pages |
| Message-ID | <tevKN-693-15@gated-at.bofh.it> |
| In reply to | #1587954 |
When memory pressure is high, we free MADV_FREE pages. If the pages are
not dirty in pte, the pages could be freed immediately. Otherwise we
can't reclaim them. We put the pages back to anonumous LRU list (by
setting SwapBacked flag) and the pages will be reclaimed in normal
swapout way.
We use normal page reclaim policy. Since MADV_FREE pages are put into
inactive file list, such pages and inactive file pages are reclaimed
according to their age. This is expected, because we don't want to
reclaim too many MADV_FREE pages before used once pages.
Based on Minchan's original patch
Cc: Michal Hocko <mhocko@suse.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Shaohua Li <shli@fb.com>
---
include/linux/rmap.h | 2 +-
mm/huge_memory.c | 2 ++
mm/madvise.c | 1 +
mm/rmap.c | 40 +++++++++++++++++-----------------------
mm/vmscan.c | 34 ++++++++++++++++++++++------------
5 files changed, 43 insertions(+), 36 deletions(-)
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 7a39414..fee10d7 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -298,6 +298,6 @@ static inline int page_mkclean(struct page *page)
#define SWAP_AGAIN 1
#define SWAP_FAIL 2
#define SWAP_MLOCK 3
-#define SWAP_LZFREE 4
+#define SWAP_DIRTY 4
#endif /* _LINUX_RMAP_H */
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 3b7ee0c..4c7454b 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1571,6 +1571,8 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
set_pmd_at(mm, addr, pmd, orig_pmd);
tlb_remove_pmd_tlb_entry(tlb, pmd, addr);
}
+
+ mark_page_lazyfree(page);
ret = true;
out:
spin_unlock(ptl);
diff --git a/mm/madvise.c b/mm/madvise.c
index 61e10b1..225af7d 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -413,6 +413,7 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
set_pte_at(mm, addr, pte, ptent);
tlb_remove_tlb_entry(tlb, pte, addr);
}
+ mark_page_lazyfree(page);
}
out:
if (nr_swap) {
diff --git a/mm/rmap.c b/mm/rmap.c
index c621088..bb45712 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1281,11 +1281,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
*/
@@ -1301,8 +1296,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
pte_t pteval;
struct page *subpage;
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 */
if ((flags & TTU_MUNLOCK) && !(vma->vm_flags & VM_LOCKED))
@@ -1419,11 +1413,21 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
VM_BUG_ON_PAGE(!PageSwapCache(page) && PageSwapBacked(page),
page);
- if (!PageDirty(page)) {
+ /*
+ * swapin page could be clean, it has data stored in
+ * swap. We can't silently discard it without setting
+ * swap entry in the page table.
+ */
+ if (!PageDirty(page) && !PageSwapCache(page)) {
/* It's a freeable page by MADV_FREE */
dec_mm_counter(mm, MM_ANONPAGES);
- rp->lazyfreed++;
goto discard;
+ } else if (!PageSwapBacked(page)) {
+ /* dirty MADV_FREE page */
+ set_pte_at(mm, address, pvmw.pte, pteval);
+ ret = SWAP_DIRTY;
+ page_vma_mapped_walk_done(&pvmw);
+ break;
}
if (swap_duplicate(entry) < 0) {
@@ -1491,18 +1495,15 @@ static int page_mapcount_is_zero(struct page *page)
* SWAP_AGAIN - we missed a mapping, try again later
* SWAP_FAIL - the page is unswappable
* 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 ret;
- struct rmap_private rp = {
- .flags = flags,
- .lazyfreed = 0,
- };
struct rmap_walk_control rwc = {
.rmap_one = try_to_unmap_one,
- .arg = &rp,
+ .arg = (void *)flags,
.done = page_mapcount_is_zero,
.anon_lock = page_lock_anon_vma_read,
};
@@ -1523,11 +1524,8 @@ int try_to_unmap(struct page *page, enum ttu_flags flags)
else
ret = rmap_walk(page, &rwc);
- if (ret != SWAP_MLOCK && !page_mapcount(page)) {
+ if (ret != SWAP_MLOCK && !page_mapcount(page))
ret = SWAP_SUCCESS;
- if (rp.lazyfreed && !PageDirty(page))
- ret = SWAP_LZFREE;
- }
return ret;
}
@@ -1554,14 +1552,10 @@ static int page_not_mapped(struct page *page)
int try_to_munlock(struct page *page)
{
int ret;
- struct rmap_private rp = {
- .flags = TTU_MUNLOCK,
- .lazyfreed = 0,
- };
struct rmap_walk_control rwc = {
.rmap_one = try_to_unmap_one,
- .arg = &rp,
+ .arg = (void *)TTU_MUNLOCK,
.done = page_not_mapped,
.anon_lock = page_lock_anon_vma_read,
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 68ea50d..16ad821 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -911,7 +911,8 @@ static void page_check_dirty_writeback(struct page *page,
* Anonymous pages are not handled by flushers and must be written
* from reclaim context. Do not stall reclaim based on them
*/
- if (!page_is_file_cache(page)) {
+ if (!page_is_file_cache(page) ||
+ (PageAnon(page) && !PageSwapBacked(page))) {
*dirty = false;
*writeback = false;
return;
@@ -992,7 +993,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
goto keep_locked;
/* Double the slab pressure for mapped and swapcache pages */
- if (page_mapped(page) || PageSwapCache(page))
+ if ((page_mapped(page) || PageSwapCache(page)) &&
+ !(PageAnon(page) && !PageSwapBacked(page)))
sc->nr_scanned++;
may_enter_fs = (sc->gfp_mask & __GFP_FS) ||
@@ -1118,8 +1120,10 @@ static unsigned long shrink_page_list(struct list_head *page_list,
/*
* Anonymous process memory has backing store?
* Try to allocate it some swap space here.
+ * Lazyfree page could be freed directly
*/
- if (PageAnon(page) && !PageSwapCache(page)) {
+ if (PageAnon(page) && PageSwapBacked(page) &&
+ !PageSwapCache(page)) {
if (!(sc->gfp_mask & __GFP_IO))
goto keep_locked;
if (!add_to_swap(page, page_list))
@@ -1140,9 +1144,12 @@ static unsigned long shrink_page_list(struct list_head *page_list,
* The page is mapped into the page tables of one or more
* processes. Try to unmap it here.
*/
- if (page_mapped(page) && mapping) {
+ if (page_mapped(page)) {
switch (ret = try_to_unmap(page,
ttu_flags | TTU_BATCH_FLUSH)) {
+ case SWAP_DIRTY:
+ SetPageSwapBacked(page);
+ /* fall through */
case SWAP_FAIL:
nr_unmap_fail++;
goto activate_locked;
@@ -1150,8 +1157,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
goto keep_locked;
case SWAP_MLOCK:
goto cull_mlocked;
- case SWAP_LZFREE:
- goto lazyfree;
case SWAP_SUCCESS:
; /* try to free the page below */
}
@@ -1263,10 +1268,18 @@ static unsigned long shrink_page_list(struct list_head *page_list,
}
}
-lazyfree:
- if (!mapping || !__remove_mapping(mapping, page, true))
- goto keep_locked;
+ if (PageAnon(page) && !PageSwapBacked(page)) {
+ /* follow __remove_mapping for reference */
+ if (!page_ref_freeze(page, 1))
+ goto keep_locked;
+ if (PageDirty(page)) {
+ page_ref_unfreeze(page, 1);
+ goto keep_locked;
+ }
+ count_vm_event(PGLAZYFREED);
+ } else if (!mapping || !__remove_mapping(mapping, page, true))
+ goto keep_locked;
/*
* At this point, we have no other references and there is
* no way to pick any more up (removed from LRU, removed
@@ -1276,9 +1289,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
*/
__ClearPageLocked(page);
free_it:
- if (ret == SWAP_LZFREE)
- count_vm_event(PGLAZYFREED);
-
nr_reclaimed++;
/*
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Minchan Kim <minchan@kernel.org> |
|---|---|
| Date | 2017-02-27 07:50 +0100 |
| Subject | Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages |
| Message-ID | <tfni9-1BB-5@gated-at.bofh.it> |
| In reply to | #1587956 |
Hi Shaohua,
On Fri, Feb 24, 2017 at 01:31:47PM -0800, Shaohua Li wrote:
> When memory pressure is high, we free MADV_FREE pages. If the pages are
> not dirty in pte, the pages could be freed immediately. Otherwise we
> can't reclaim them. We put the pages back to anonumous LRU list (by
> setting SwapBacked flag) and the pages will be reclaimed in normal
> swapout way.
>
> We use normal page reclaim policy. Since MADV_FREE pages are put into
> inactive file list, such pages and inactive file pages are reclaimed
> according to their age. This is expected, because we don't want to
> reclaim too many MADV_FREE pages before used once pages.
>
> Based on Minchan's original patch
>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Minchan Kim <minchan@kernel.org>
> Cc: Hugh Dickins <hughd@google.com>
> Cc: Johannes Weiner <hannes@cmpxchg.org>
> Cc: Rik van Riel <riel@redhat.com>
> Cc: Mel Gorman <mgorman@techsingularity.net>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Shaohua Li <shli@fb.com>
> ---
> include/linux/rmap.h | 2 +-
> mm/huge_memory.c | 2 ++
> mm/madvise.c | 1 +
> mm/rmap.c | 40 +++++++++++++++++-----------------------
> mm/vmscan.c | 34 ++++++++++++++++++++++------------
> 5 files changed, 43 insertions(+), 36 deletions(-)
>
> diff --git a/include/linux/rmap.h b/include/linux/rmap.h
> index 7a39414..fee10d7 100644
> --- a/include/linux/rmap.h
> +++ b/include/linux/rmap.h
> @@ -298,6 +298,6 @@ static inline int page_mkclean(struct page *page)
> #define SWAP_AGAIN 1
> #define SWAP_FAIL 2
> #define SWAP_MLOCK 3
> -#define SWAP_LZFREE 4
> +#define SWAP_DIRTY 4
I still don't convinced why we should introduce SWAP_DIRTY in try_to_unmap.
https://marc.info/?l=linux-mm&m=148797879123238&w=2
We have been SetPageMlocked in there but why cannot we SetPageSwapBacked
in there? It's not a thing to change LRU type but it's just indication
we found the page's status changed in late.
>
> #endif /* _LINUX_RMAP_H */
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 3b7ee0c..4c7454b 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -1571,6 +1571,8 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
> set_pmd_at(mm, addr, pmd, orig_pmd);
> tlb_remove_pmd_tlb_entry(tlb, pmd, addr);
> }
> +
> + mark_page_lazyfree(page);
> ret = true;
> out:
> spin_unlock(ptl);
> diff --git a/mm/madvise.c b/mm/madvise.c
> index 61e10b1..225af7d 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -413,6 +413,7 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
> set_pte_at(mm, addr, pte, ptent);
> tlb_remove_tlb_entry(tlb, pte, addr);
> }
> + mark_page_lazyfree(page);
> }
> out:
> if (nr_swap) {
> diff --git a/mm/rmap.c b/mm/rmap.c
> index c621088..bb45712 100644
> --- a/mm/rmap.c
> +++ b/mm/rmap.c
> @@ -1281,11 +1281,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
> */
> @@ -1301,8 +1296,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
> pte_t pteval;
> struct page *subpage;
> 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 */
> if ((flags & TTU_MUNLOCK) && !(vma->vm_flags & VM_LOCKED))
> @@ -1419,11 +1413,21 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
> VM_BUG_ON_PAGE(!PageSwapCache(page) && PageSwapBacked(page),
> page);
>
> - if (!PageDirty(page)) {
> + /*
> + * swapin page could be clean, it has data stored in
> + * swap. We can't silently discard it without setting
> + * swap entry in the page table.
> + */
> + if (!PageDirty(page) && !PageSwapCache(page)) {
> /* It's a freeable page by MADV_FREE */
> dec_mm_counter(mm, MM_ANONPAGES);
> - rp->lazyfreed++;
> goto discard;
> + } else if (!PageSwapBacked(page)) {
> + /* dirty MADV_FREE page */
> + set_pte_at(mm, address, pvmw.pte, pteval);
> + ret = SWAP_DIRTY;
> + page_vma_mapped_walk_done(&pvmw);
> + break;
> }
>
> if (swap_duplicate(entry) < 0) {
> @@ -1491,18 +1495,15 @@ static int page_mapcount_is_zero(struct page *page)
> * SWAP_AGAIN - we missed a mapping, try again later
> * SWAP_FAIL - the page is unswappable
> * 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 ret;
> - struct rmap_private rp = {
> - .flags = flags,
> - .lazyfreed = 0,
> - };
>
> struct rmap_walk_control rwc = {
> .rmap_one = try_to_unmap_one,
> - .arg = &rp,
> + .arg = (void *)flags,
> .done = page_mapcount_is_zero,
> .anon_lock = page_lock_anon_vma_read,
> };
> @@ -1523,11 +1524,8 @@ int try_to_unmap(struct page *page, enum ttu_flags flags)
> else
> ret = rmap_walk(page, &rwc);
>
> - if (ret != SWAP_MLOCK && !page_mapcount(page)) {
> + if (ret != SWAP_MLOCK && !page_mapcount(page))
> ret = SWAP_SUCCESS;
> - if (rp.lazyfreed && !PageDirty(page))
> - ret = SWAP_LZFREE;
> - }
> return ret;
> }
>
> @@ -1554,14 +1552,10 @@ static int page_not_mapped(struct page *page)
> int try_to_munlock(struct page *page)
> {
> int ret;
> - struct rmap_private rp = {
> - .flags = TTU_MUNLOCK,
> - .lazyfreed = 0,
> - };
>
> struct rmap_walk_control rwc = {
> .rmap_one = try_to_unmap_one,
> - .arg = &rp,
> + .arg = (void *)TTU_MUNLOCK,
> .done = page_not_mapped,
> .anon_lock = page_lock_anon_vma_read,
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 68ea50d..16ad821 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -911,7 +911,8 @@ static void page_check_dirty_writeback(struct page *page,
> * Anonymous pages are not handled by flushers and must be written
> * from reclaim context. Do not stall reclaim based on them
> */
> - if (!page_is_file_cache(page)) {
> + if (!page_is_file_cache(page) ||
> + (PageAnon(page) && !PageSwapBacked(page))) {
> *dirty = false;
> *writeback = false;
> return;
> @@ -992,7 +993,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> goto keep_locked;
>
> /* Double the slab pressure for mapped and swapcache pages */
> - if (page_mapped(page) || PageSwapCache(page))
> + if ((page_mapped(page) || PageSwapCache(page)) &&
> + !(PageAnon(page) && !PageSwapBacked(page)))
> sc->nr_scanned++;
>
> may_enter_fs = (sc->gfp_mask & __GFP_FS) ||
> @@ -1118,8 +1120,10 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> /*
> * Anonymous process memory has backing store?
> * Try to allocate it some swap space here.
> + * Lazyfree page could be freed directly
> */
> - if (PageAnon(page) && !PageSwapCache(page)) {
> + if (PageAnon(page) && PageSwapBacked(page) &&
> + !PageSwapCache(page)) {
> if (!(sc->gfp_mask & __GFP_IO))
> goto keep_locked;
> if (!add_to_swap(page, page_list))
> @@ -1140,9 +1144,12 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> * The page is mapped into the page tables of one or more
> * processes. Try to unmap it here.
> */
> - if (page_mapped(page) && mapping) {
> + if (page_mapped(page)) {
> switch (ret = try_to_unmap(page,
> ttu_flags | TTU_BATCH_FLUSH)) {
> + case SWAP_DIRTY:
> + SetPageSwapBacked(page);
> + /* fall through */
> case SWAP_FAIL:
> nr_unmap_fail++;
> goto activate_locked;
> @@ -1150,8 +1157,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> goto keep_locked;
> case SWAP_MLOCK:
> goto cull_mlocked;
> - case SWAP_LZFREE:
> - goto lazyfree;
> case SWAP_SUCCESS:
> ; /* try to free the page below */
> }
> @@ -1263,10 +1268,18 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> }
> }
>
> -lazyfree:
> - if (!mapping || !__remove_mapping(mapping, page, true))
> - goto keep_locked;
> + if (PageAnon(page) && !PageSwapBacked(page)) {
> + /* follow __remove_mapping for reference */
> + if (!page_ref_freeze(page, 1))
> + goto keep_locked;
> + if (PageDirty(page)) {
> + page_ref_unfreeze(page, 1);
> + goto keep_locked;
> + }
>
> + count_vm_event(PGLAZYFREED);
> + } else if (!mapping || !__remove_mapping(mapping, page, true))
> + goto keep_locked;
> /*
> * At this point, we have no other references and there is
> * no way to pick any more up (removed from LRU, removed
> @@ -1276,9 +1289,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> */
> __ClearPageLocked(page);
> free_it:
> - if (ret == SWAP_LZFREE)
> - count_vm_event(PGLAZYFREED);
> -
> nr_reclaimed++;
>
> /*
> --
> 2.9.3
>
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org. For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-02-27 17:40 +0100 |
| Subject | Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages |
| Message-ID | <tfwv7-8at-7@gated-at.bofh.it> |
| In reply to | #1588523 |
On Mon 27-02-17 08:19:08, Shaohua Li wrote: > On Mon, Feb 27, 2017 at 03:33:15PM +0900, Minchan Kim wrote: [...] > > > --- a/include/linux/rmap.h > > > +++ b/include/linux/rmap.h > > > @@ -298,6 +298,6 @@ static inline int page_mkclean(struct page *page) > > > #define SWAP_AGAIN 1 > > > #define SWAP_FAIL 2 > > > #define SWAP_MLOCK 3 > > > -#define SWAP_LZFREE 4 > > > +#define SWAP_DIRTY 4 > > > > I still don't convinced why we should introduce SWAP_DIRTY in try_to_unmap. > > https://marc.info/?l=linux-mm&m=148797879123238&w=2 > > > > We have been SetPageMlocked in there but why cannot we SetPageSwapBacked > > in there? It's not a thing to change LRU type but it's just indication > > we found the page's status changed in late. > > This one I don't have strong preference. Personally I agree with Johannes, > handling failure in vmscan sounds better. But since the failure handling is > just one statement, this probably doesn't make too much difference. If Johannes > and you made an agreement, I'll follow. FWIW I like your current SWAP_DIRTY and the later handling at the vmscan level more. -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Minchan Kim <minchan@kernel.org> |
|---|---|
| Date | 2017-02-28 06:50 +0100 |
| Subject | Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages |
| Message-ID | <tfIPD-8sl-1@gated-at.bofh.it> |
| In reply to | #1588523 |
On Mon, Feb 27, 2017 at 08:19:08AM -0800, Shaohua Li wrote: > On Mon, Feb 27, 2017 at 03:33:15PM +0900, Minchan Kim wrote: > > Hi Shaohua, > > > > On Fri, Feb 24, 2017 at 01:31:47PM -0800, Shaohua Li wrote: > > > When memory pressure is high, we free MADV_FREE pages. If the pages are > > > not dirty in pte, the pages could be freed immediately. Otherwise we > > > can't reclaim them. We put the pages back to anonumous LRU list (by > > > setting SwapBacked flag) and the pages will be reclaimed in normal > > > swapout way. > > > > > > We use normal page reclaim policy. Since MADV_FREE pages are put into > > > inactive file list, such pages and inactive file pages are reclaimed > > > according to their age. This is expected, because we don't want to > > > reclaim too many MADV_FREE pages before used once pages. > > > > > > Based on Minchan's original patch > > > > > > Cc: Michal Hocko <mhocko@suse.com> > > > Cc: Minchan Kim <minchan@kernel.org> > > > Cc: Hugh Dickins <hughd@google.com> > > > Cc: Johannes Weiner <hannes@cmpxchg.org> > > > Cc: Rik van Riel <riel@redhat.com> > > > Cc: Mel Gorman <mgorman@techsingularity.net> > > > Cc: Andrew Morton <akpm@linux-foundation.org> > > > Signed-off-by: Shaohua Li <shli@fb.com> > > > --- > > > include/linux/rmap.h | 2 +- > > > mm/huge_memory.c | 2 ++ > > > mm/madvise.c | 1 + > > > mm/rmap.c | 40 +++++++++++++++++----------------------- > > > mm/vmscan.c | 34 ++++++++++++++++++++++------------ > > > 5 files changed, 43 insertions(+), 36 deletions(-) > > > > > > diff --git a/include/linux/rmap.h b/include/linux/rmap.h > > > index 7a39414..fee10d7 100644 > > > --- a/include/linux/rmap.h > > > +++ b/include/linux/rmap.h > > > @@ -298,6 +298,6 @@ static inline int page_mkclean(struct page *page) > > > #define SWAP_AGAIN 1 > > > #define SWAP_FAIL 2 > > > #define SWAP_MLOCK 3 > > > -#define SWAP_LZFREE 4 > > > +#define SWAP_DIRTY 4 > > > > I still don't convinced why we should introduce SWAP_DIRTY in try_to_unmap. > > https://marc.info/?l=linux-mm&m=148797879123238&w=2 > > > > We have been SetPageMlocked in there but why cannot we SetPageSwapBacked > > in there? It's not a thing to change LRU type but it's just indication > > we found the page's status changed in late. > > This one I don't have strong preference. Personally I agree with Johannes, > handling failure in vmscan sounds better. But since the failure handling is > just one statement, this probably doesn't make too much difference. If Johannes > and you made an agreement, I'll follow. I don't want to add unnecessary new return value(i.e., SWAP_DIRTY). If VM found lazyfree page dirty in try_to_unmap_one, it means "non-swappable page" so it's natural to set SetPageSwapBacked in there and return just SWAP_FAIL to activate it in vmscan.c. SWAP_FAIL means the page is non-swappable so it should be activated. I don't see any problem in there like software engineering pov. However, it seems everyone are happy with introdcuing SWAP_DIRTY so I don't insist on it which is not critical for this patchset. I looked over try_to_unmap and callers. Now, I think we could remove SWAP_MLOCK and maybe SWAP_AGAIN as well as SWAP_DIRTY that is to make try_to_unmap *bool*. So, it could be done by separate patchset. I will look into that in more. Acked-by: Minchan Kim <minchan@kernel.org> Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-02-27 16:30 +0100 |
| Subject | Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages |
| Message-ID | <tfvpp-7rK-37@gated-at.bofh.it> |
| In reply to | #1587956 |
On Fri 24-02-17 13:31:47, Shaohua Li wrote:
> When memory pressure is high, we free MADV_FREE pages. If the pages are
> not dirty in pte, the pages could be freed immediately. Otherwise we
> can't reclaim them. We put the pages back to anonumous LRU list (by
> setting SwapBacked flag) and the pages will be reclaimed in normal
> swapout way.
>
> We use normal page reclaim policy. Since MADV_FREE pages are put into
> inactive file list, such pages and inactive file pages are reclaimed
> according to their age. This is expected, because we don't want to
> reclaim too many MADV_FREE pages before used once pages.
>
> Based on Minchan's original patch
OK, this looks much more cleaner and easier to follow than the original
version I have seen.
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Minchan Kim <minchan@kernel.org>
> Cc: Hugh Dickins <hughd@google.com>
> Cc: Johannes Weiner <hannes@cmpxchg.org>
> Cc: Rik van Riel <riel@redhat.com>
> Cc: Mel Gorman <mgorman@techsingularity.net>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Shaohua Li <shli@fb.com>
Acked-by: Michal Hocko <mhocko@suse.com>
> ---
> include/linux/rmap.h | 2 +-
> mm/huge_memory.c | 2 ++
> mm/madvise.c | 1 +
> mm/rmap.c | 40 +++++++++++++++++-----------------------
> mm/vmscan.c | 34 ++++++++++++++++++++++------------
> 5 files changed, 43 insertions(+), 36 deletions(-)
>
> diff --git a/include/linux/rmap.h b/include/linux/rmap.h
> index 7a39414..fee10d7 100644
> --- a/include/linux/rmap.h
> +++ b/include/linux/rmap.h
> @@ -298,6 +298,6 @@ static inline int page_mkclean(struct page *page)
> #define SWAP_AGAIN 1
> #define SWAP_FAIL 2
> #define SWAP_MLOCK 3
> -#define SWAP_LZFREE 4
> +#define SWAP_DIRTY 4
>
> #endif /* _LINUX_RMAP_H */
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index 3b7ee0c..4c7454b 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -1571,6 +1571,8 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
> set_pmd_at(mm, addr, pmd, orig_pmd);
> tlb_remove_pmd_tlb_entry(tlb, pmd, addr);
> }
> +
> + mark_page_lazyfree(page);
> ret = true;
> out:
> spin_unlock(ptl);
> diff --git a/mm/madvise.c b/mm/madvise.c
> index 61e10b1..225af7d 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -413,6 +413,7 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
> set_pte_at(mm, addr, pte, ptent);
> tlb_remove_tlb_entry(tlb, pte, addr);
> }
> + mark_page_lazyfree(page);
> }
> out:
> if (nr_swap) {
> diff --git a/mm/rmap.c b/mm/rmap.c
> index c621088..bb45712 100644
> --- a/mm/rmap.c
> +++ b/mm/rmap.c
> @@ -1281,11 +1281,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
> */
> @@ -1301,8 +1296,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
> pte_t pteval;
> struct page *subpage;
> 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 */
> if ((flags & TTU_MUNLOCK) && !(vma->vm_flags & VM_LOCKED))
> @@ -1419,11 +1413,21 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
> VM_BUG_ON_PAGE(!PageSwapCache(page) && PageSwapBacked(page),
> page);
>
> - if (!PageDirty(page)) {
> + /*
> + * swapin page could be clean, it has data stored in
> + * swap. We can't silently discard it without setting
> + * swap entry in the page table.
> + */
> + if (!PageDirty(page) && !PageSwapCache(page)) {
> /* It's a freeable page by MADV_FREE */
> dec_mm_counter(mm, MM_ANONPAGES);
> - rp->lazyfreed++;
> goto discard;
> + } else if (!PageSwapBacked(page)) {
> + /* dirty MADV_FREE page */
> + set_pte_at(mm, address, pvmw.pte, pteval);
> + ret = SWAP_DIRTY;
> + page_vma_mapped_walk_done(&pvmw);
> + break;
> }
>
> if (swap_duplicate(entry) < 0) {
> @@ -1491,18 +1495,15 @@ static int page_mapcount_is_zero(struct page *page)
> * SWAP_AGAIN - we missed a mapping, try again later
> * SWAP_FAIL - the page is unswappable
> * 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 ret;
> - struct rmap_private rp = {
> - .flags = flags,
> - .lazyfreed = 0,
> - };
>
> struct rmap_walk_control rwc = {
> .rmap_one = try_to_unmap_one,
> - .arg = &rp,
> + .arg = (void *)flags,
> .done = page_mapcount_is_zero,
> .anon_lock = page_lock_anon_vma_read,
> };
> @@ -1523,11 +1524,8 @@ int try_to_unmap(struct page *page, enum ttu_flags flags)
> else
> ret = rmap_walk(page, &rwc);
>
> - if (ret != SWAP_MLOCK && !page_mapcount(page)) {
> + if (ret != SWAP_MLOCK && !page_mapcount(page))
> ret = SWAP_SUCCESS;
> - if (rp.lazyfreed && !PageDirty(page))
> - ret = SWAP_LZFREE;
> - }
> return ret;
> }
>
> @@ -1554,14 +1552,10 @@ static int page_not_mapped(struct page *page)
> int try_to_munlock(struct page *page)
> {
> int ret;
> - struct rmap_private rp = {
> - .flags = TTU_MUNLOCK,
> - .lazyfreed = 0,
> - };
>
> struct rmap_walk_control rwc = {
> .rmap_one = try_to_unmap_one,
> - .arg = &rp,
> + .arg = (void *)TTU_MUNLOCK,
> .done = page_not_mapped,
> .anon_lock = page_lock_anon_vma_read,
>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 68ea50d..16ad821 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -911,7 +911,8 @@ static void page_check_dirty_writeback(struct page *page,
> * Anonymous pages are not handled by flushers and must be written
> * from reclaim context. Do not stall reclaim based on them
> */
> - if (!page_is_file_cache(page)) {
> + if (!page_is_file_cache(page) ||
> + (PageAnon(page) && !PageSwapBacked(page))) {
> *dirty = false;
> *writeback = false;
> return;
> @@ -992,7 +993,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> goto keep_locked;
>
> /* Double the slab pressure for mapped and swapcache pages */
> - if (page_mapped(page) || PageSwapCache(page))
> + if ((page_mapped(page) || PageSwapCache(page)) &&
> + !(PageAnon(page) && !PageSwapBacked(page)))
> sc->nr_scanned++;
>
> may_enter_fs = (sc->gfp_mask & __GFP_FS) ||
> @@ -1118,8 +1120,10 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> /*
> * Anonymous process memory has backing store?
> * Try to allocate it some swap space here.
> + * Lazyfree page could be freed directly
> */
> - if (PageAnon(page) && !PageSwapCache(page)) {
> + if (PageAnon(page) && PageSwapBacked(page) &&
> + !PageSwapCache(page)) {
> if (!(sc->gfp_mask & __GFP_IO))
> goto keep_locked;
> if (!add_to_swap(page, page_list))
> @@ -1140,9 +1144,12 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> * The page is mapped into the page tables of one or more
> * processes. Try to unmap it here.
> */
> - if (page_mapped(page) && mapping) {
> + if (page_mapped(page)) {
> switch (ret = try_to_unmap(page,
> ttu_flags | TTU_BATCH_FLUSH)) {
> + case SWAP_DIRTY:
> + SetPageSwapBacked(page);
> + /* fall through */
> case SWAP_FAIL:
> nr_unmap_fail++;
> goto activate_locked;
> @@ -1150,8 +1157,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> goto keep_locked;
> case SWAP_MLOCK:
> goto cull_mlocked;
> - case SWAP_LZFREE:
> - goto lazyfree;
> case SWAP_SUCCESS:
> ; /* try to free the page below */
> }
> @@ -1263,10 +1268,18 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> }
> }
>
> -lazyfree:
> - if (!mapping || !__remove_mapping(mapping, page, true))
> - goto keep_locked;
> + if (PageAnon(page) && !PageSwapBacked(page)) {
> + /* follow __remove_mapping for reference */
> + if (!page_ref_freeze(page, 1))
> + goto keep_locked;
> + if (PageDirty(page)) {
> + page_ref_unfreeze(page, 1);
> + goto keep_locked;
> + }
>
> + count_vm_event(PGLAZYFREED);
> + } else if (!mapping || !__remove_mapping(mapping, page, true))
> + goto keep_locked;
> /*
> * At this point, we have no other references and there is
> * no way to pick any more up (removed from LRU, removed
> @@ -1276,9 +1289,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> */
> __ClearPageLocked(page);
> free_it:
> - if (ret == SWAP_LZFREE)
> - count_vm_event(PGLAZYFREED);
> -
> nr_reclaimed++;
>
> /*
> --
> 2.9.3
>
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Johannes Weiner <hannes@cmpxchg.org> |
|---|---|
| Date | 2017-02-27 18:30 +0100 |
| Subject | Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages |
| Message-ID | <tfxhv-jQ-5@gated-at.bofh.it> |
| In reply to | #1587956 |
On Fri, Feb 24, 2017 at 01:31:47PM -0800, Shaohua Li wrote: > When memory pressure is high, we free MADV_FREE pages. If the pages are > not dirty in pte, the pages could be freed immediately. Otherwise we > can't reclaim them. We put the pages back to anonumous LRU list (by > setting SwapBacked flag) and the pages will be reclaimed in normal > swapout way. > > We use normal page reclaim policy. Since MADV_FREE pages are put into > inactive file list, such pages and inactive file pages are reclaimed > according to their age. This is expected, because we don't want to > reclaim too many MADV_FREE pages before used once pages. > > Based on Minchan's original patch > > Cc: Michal Hocko <mhocko@suse.com> > Cc: Minchan Kim <minchan@kernel.org> > Cc: Hugh Dickins <hughd@google.com> > Cc: Johannes Weiner <hannes@cmpxchg.org> > Cc: Rik van Riel <riel@redhat.com> > Cc: Mel Gorman <mgorman@techsingularity.net> > Cc: Andrew Morton <akpm@linux-foundation.org> > Signed-off-by: Shaohua Li <shli@fb.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> FWIW, I agree with Minchan that this could be folded into the previous patch and would be a little neater. But I don't feel strongly in this case since I didn't have any trouble reviewing the patches like this - void mark_page_lazyfree(struct page *) is an easy API to remember.
[toc] | [prev] | [next] | [standalone]
| From | "Hillf Danton" <hillf.zj@alibaba-inc.com> |
|---|---|
| Date | 2017-02-28 04:30 +0100 |
| Subject | Re: [PATCH V5 4/6] mm: reclaim MADV_FREE pages |
| Message-ID | <tfGEa-6YX-13@gated-at.bofh.it> |
| In reply to | #1587956 |
On February 25, 2017 5:32 AM Shaohua Li wrote: > > When memory pressure is high, we free MADV_FREE pages. If the pages are > not dirty in pte, the pages could be freed immediately. Otherwise we > can't reclaim them. We put the pages back to anonumous LRU list (by > setting SwapBacked flag) and the pages will be reclaimed in normal > swapout way. > > We use normal page reclaim policy. Since MADV_FREE pages are put into > inactive file list, such pages and inactive file pages are reclaimed > according to their age. This is expected, because we don't want to > reclaim too many MADV_FREE pages before used once pages. > > Based on Minchan's original patch > > Cc: Michal Hocko <mhocko@suse.com> > Cc: Minchan Kim <minchan@kernel.org> > Cc: Hugh Dickins <hughd@google.com> > Cc: Johannes Weiner <hannes@cmpxchg.org> > Cc: Rik van Riel <riel@redhat.com> > Cc: Mel Gorman <mgorman@techsingularity.net> > Cc: Andrew Morton <akpm@linux-foundation.org> > Signed-off-by: Shaohua Li <shli@fb.com> > --- Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
[toc] | [prev] | [next] | [standalone]
| From | Shaohua Li <shli@fb.com> |
|---|---|
| Date | 2017-02-24 22:40 +0100 |
| Subject | [PATCH V5 1/6] mm: delete unnecessary TTU_* flags |
| Message-ID | <tevKN-693-19@gated-at.bofh.it> |
| In reply to | #1587954 |
Johannes pointed out TTU_LZFREE is unnecessary. It's true because we
always have the flag set if we want to do an unmap. For cases we don't
do an unmap, the TTU_LZFREE part of code should never run.
Also the TTU_UNMAP is unnecessary. If no other flags set (for
example, TTU_MIGRATION), an unmap is implied.
The patch includes Johannes's cleanup and dead TTU_ACTION macro removal
code
Cc: Michal Hocko <mhocko@suse.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Suggested-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Minchan Kim <minchan@kernel.org>
Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
Signed-off-by: Shaohua Li <shli@fb.com>
---
include/linux/rmap.h | 22 +++++++++-------------
mm/memory-failure.c | 2 +-
mm/rmap.c | 2 +-
mm/vmscan.c | 11 ++++-------
4 files changed, 15 insertions(+), 22 deletions(-)
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 8c89e90..7a39414 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -83,19 +83,17 @@ struct anon_vma_chain {
};
enum ttu_flags {
- TTU_UNMAP = 1, /* unmap mode */
- TTU_MIGRATION = 2, /* migration mode */
- TTU_MUNLOCK = 4, /* munlock mode */
- TTU_LZFREE = 8, /* lazy free mode */
- TTU_SPLIT_HUGE_PMD = 16, /* split huge PMD if any */
-
- TTU_IGNORE_MLOCK = (1 << 8), /* ignore mlock */
- TTU_IGNORE_ACCESS = (1 << 9), /* don't age */
- TTU_IGNORE_HWPOISON = (1 << 10),/* corrupted page is recoverable */
- TTU_BATCH_FLUSH = (1 << 11), /* Batch TLB flushes where possible
+ TTU_MIGRATION = 0x1, /* migration mode */
+ TTU_MUNLOCK = 0x2, /* munlock mode */
+
+ TTU_SPLIT_HUGE_PMD = 0x4, /* split huge PMD if any */
+ TTU_IGNORE_MLOCK = 0x8, /* ignore mlock */
+ TTU_IGNORE_ACCESS = 0x10, /* don't age */
+ TTU_IGNORE_HWPOISON = 0x20, /* corrupted page is recoverable */
+ TTU_BATCH_FLUSH = 0x40, /* Batch TLB flushes where possible
* and caller guarantees they will
* do a final flush if necessary */
- TTU_RMAP_LOCKED = (1 << 12) /* do not grab rmap lock:
+ TTU_RMAP_LOCKED = 0x80 /* do not grab rmap lock:
* caller holds it */
};
@@ -193,8 +191,6 @@ static inline void page_dup_rmap(struct page *page, bool compound)
int page_referenced(struct page *, int is_locked,
struct mem_cgroup *memcg, unsigned long *vm_flags);
-#define TTU_ACTION(x) ((x) & TTU_ACTION_MASK)
-
int try_to_unmap(struct page *, enum ttu_flags flags);
/* Avoid racy checks */
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 3d0f2fd..b78d080 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -906,7 +906,7 @@ EXPORT_SYMBOL_GPL(get_hwpoison_page);
static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
int trapno, int flags, struct page **hpagep)
{
- enum ttu_flags ttu = TTU_UNMAP | TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
+ enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
struct address_space *mapping;
LIST_HEAD(tokill);
int ret;
diff --git a/mm/rmap.c b/mm/rmap.c
index 8774791..96eb85c 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1418,7 +1418,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
*/
VM_BUG_ON_PAGE(!PageSwapCache(page), page);
- if (!PageDirty(page) && (flags & TTU_LZFREE)) {
+ if (!PageDirty(page)) {
/* It's a freeable page by MADV_FREE */
dec_mm_counter(mm, MM_ANONPAGES);
rp->lazyfreed++;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 26c3b40..68ea50d 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -971,7 +971,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
int may_enter_fs;
enum page_references references = PAGEREF_RECLAIM_CLEAN;
bool dirty, writeback;
- bool lazyfree = false;
int ret = SWAP_SUCCESS;
cond_resched();
@@ -1125,7 +1124,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
goto keep_locked;
if (!add_to_swap(page, page_list))
goto activate_locked;
- lazyfree = true;
may_enter_fs = 1;
/* Adding to swap updated mapping */
@@ -1143,9 +1141,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
* processes. Try to unmap it here.
*/
if (page_mapped(page) && mapping) {
- switch (ret = try_to_unmap(page, lazyfree ?
- (ttu_flags | TTU_BATCH_FLUSH | TTU_LZFREE) :
- (ttu_flags | TTU_BATCH_FLUSH))) {
+ switch (ret = try_to_unmap(page,
+ ttu_flags | TTU_BATCH_FLUSH)) {
case SWAP_FAIL:
nr_unmap_fail++;
goto activate_locked;
@@ -1353,7 +1350,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
}
ret = shrink_page_list(&clean_pages, zone->zone_pgdat, &sc,
- TTU_UNMAP|TTU_IGNORE_ACCESS, NULL, true);
+ TTU_IGNORE_ACCESS, NULL, true);
list_splice(&clean_pages, page_list);
mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE, -ret);
return ret;
@@ -1760,7 +1757,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
if (nr_taken == 0)
return 0;
- nr_reclaimed = shrink_page_list(&page_list, pgdat, sc, TTU_UNMAP,
+ nr_reclaimed = shrink_page_list(&page_list, pgdat, sc, 0,
&stat, false);
spin_lock_irq(&pgdat->lru_lock);
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-02-27 16:10 +0100 |
| Subject | Re: [PATCH V5 1/6] mm: delete unnecessary TTU_* flags |
| Message-ID | <tfv62-7iD-5@gated-at.bofh.it> |
| In reply to | #1587957 |
On Fri 24-02-17 13:31:44, Shaohua Li wrote:
> Johannes pointed out TTU_LZFREE is unnecessary. It's true because we
> always have the flag set if we want to do an unmap. For cases we don't
> do an unmap, the TTU_LZFREE part of code should never run.
>
> Also the TTU_UNMAP is unnecessary. If no other flags set (for
> example, TTU_MIGRATION), an unmap is implied.
>
> The patch includes Johannes's cleanup and dead TTU_ACTION macro removal
> code
>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Hugh Dickins <hughd@google.com>
> Cc: Rik van Riel <riel@redhat.com>
> Cc: Mel Gorman <mgorman@techsingularity.net>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Suggested-by: Johannes Weiner <hannes@cmpxchg.org>
> Acked-by: Johannes Weiner <hannes@cmpxchg.org>
> Acked-by: Minchan Kim <minchan@kernel.org>
> Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
> Signed-off-by: Shaohua Li <shli@fb.com>
Acked-by: Michal Hocko <mhocko@suse.com>
> ---
> include/linux/rmap.h | 22 +++++++++-------------
> mm/memory-failure.c | 2 +-
> mm/rmap.c | 2 +-
> mm/vmscan.c | 11 ++++-------
> 4 files changed, 15 insertions(+), 22 deletions(-)
>
> diff --git a/include/linux/rmap.h b/include/linux/rmap.h
> index 8c89e90..7a39414 100644
> --- a/include/linux/rmap.h
> +++ b/include/linux/rmap.h
> @@ -83,19 +83,17 @@ struct anon_vma_chain {
> };
>
> enum ttu_flags {
> - TTU_UNMAP = 1, /* unmap mode */
> - TTU_MIGRATION = 2, /* migration mode */
> - TTU_MUNLOCK = 4, /* munlock mode */
> - TTU_LZFREE = 8, /* lazy free mode */
> - TTU_SPLIT_HUGE_PMD = 16, /* split huge PMD if any */
> -
> - TTU_IGNORE_MLOCK = (1 << 8), /* ignore mlock */
> - TTU_IGNORE_ACCESS = (1 << 9), /* don't age */
> - TTU_IGNORE_HWPOISON = (1 << 10),/* corrupted page is recoverable */
> - TTU_BATCH_FLUSH = (1 << 11), /* Batch TLB flushes where possible
> + TTU_MIGRATION = 0x1, /* migration mode */
> + TTU_MUNLOCK = 0x2, /* munlock mode */
> +
> + TTU_SPLIT_HUGE_PMD = 0x4, /* split huge PMD if any */
> + TTU_IGNORE_MLOCK = 0x8, /* ignore mlock */
> + TTU_IGNORE_ACCESS = 0x10, /* don't age */
> + TTU_IGNORE_HWPOISON = 0x20, /* corrupted page is recoverable */
> + TTU_BATCH_FLUSH = 0x40, /* Batch TLB flushes where possible
> * and caller guarantees they will
> * do a final flush if necessary */
> - TTU_RMAP_LOCKED = (1 << 12) /* do not grab rmap lock:
> + TTU_RMAP_LOCKED = 0x80 /* do not grab rmap lock:
> * caller holds it */
> };
>
> @@ -193,8 +191,6 @@ static inline void page_dup_rmap(struct page *page, bool compound)
> int page_referenced(struct page *, int is_locked,
> struct mem_cgroup *memcg, unsigned long *vm_flags);
>
> -#define TTU_ACTION(x) ((x) & TTU_ACTION_MASK)
> -
> int try_to_unmap(struct page *, enum ttu_flags flags);
>
> /* Avoid racy checks */
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 3d0f2fd..b78d080 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -906,7 +906,7 @@ EXPORT_SYMBOL_GPL(get_hwpoison_page);
> static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
> int trapno, int flags, struct page **hpagep)
> {
> - enum ttu_flags ttu = TTU_UNMAP | TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
> + enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
> struct address_space *mapping;
> LIST_HEAD(tokill);
> int ret;
> diff --git a/mm/rmap.c b/mm/rmap.c
> index 8774791..96eb85c 100644
> --- a/mm/rmap.c
> +++ b/mm/rmap.c
> @@ -1418,7 +1418,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
> */
> VM_BUG_ON_PAGE(!PageSwapCache(page), page);
>
> - if (!PageDirty(page) && (flags & TTU_LZFREE)) {
> + if (!PageDirty(page)) {
> /* It's a freeable page by MADV_FREE */
> dec_mm_counter(mm, MM_ANONPAGES);
> rp->lazyfreed++;
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 26c3b40..68ea50d 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -971,7 +971,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> int may_enter_fs;
> enum page_references references = PAGEREF_RECLAIM_CLEAN;
> bool dirty, writeback;
> - bool lazyfree = false;
> int ret = SWAP_SUCCESS;
>
> cond_resched();
> @@ -1125,7 +1124,6 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> goto keep_locked;
> if (!add_to_swap(page, page_list))
> goto activate_locked;
> - lazyfree = true;
> may_enter_fs = 1;
>
> /* Adding to swap updated mapping */
> @@ -1143,9 +1141,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
> * processes. Try to unmap it here.
> */
> if (page_mapped(page) && mapping) {
> - switch (ret = try_to_unmap(page, lazyfree ?
> - (ttu_flags | TTU_BATCH_FLUSH | TTU_LZFREE) :
> - (ttu_flags | TTU_BATCH_FLUSH))) {
> + switch (ret = try_to_unmap(page,
> + ttu_flags | TTU_BATCH_FLUSH)) {
> case SWAP_FAIL:
> nr_unmap_fail++;
> goto activate_locked;
> @@ -1353,7 +1350,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
> }
>
> ret = shrink_page_list(&clean_pages, zone->zone_pgdat, &sc,
> - TTU_UNMAP|TTU_IGNORE_ACCESS, NULL, true);
> + TTU_IGNORE_ACCESS, NULL, true);
> list_splice(&clean_pages, page_list);
> mod_node_page_state(zone->zone_pgdat, NR_ISOLATED_FILE, -ret);
> return ret;
> @@ -1760,7 +1757,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec,
> if (nr_taken == 0)
> return 0;
>
> - nr_reclaimed = shrink_page_list(&page_list, pgdat, sc, TTU_UNMAP,
> + nr_reclaimed = shrink_page_list(&page_list, pgdat, sc, 0,
> &stat, false);
>
> spin_lock_irq(&pgdat->lru_lock);
> --
> 2.9.3
>
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Shaohua Li <shli@fb.com> |
|---|---|
| Date | 2017-02-24 22:40 +0100 |
| Subject | [PATCH V5 2/6] mm: don't assume anonymous pages have SwapBacked flag |
| Message-ID | <tevKO-693-25@gated-at.bofh.it> |
| In reply to | #1587954 |
There are a few places the code assumes anonymous pages should have
SwapBacked flag set. MADV_FREE pages are anonymous pages but we are
going to add them to LRU_INACTIVE_FILE list and clear SwapBacked flag
for them. The assumption doesn't hold any more, so fix them.
Cc: Michal Hocko <mhocko@suse.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Shaohua Li <shli@fb.com>
---
mm/huge_memory.c | 1 -
mm/khugepaged.c | 8 +++-----
mm/migrate.c | 3 ++-
mm/rmap.c | 3 ++-
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 7dda8d6..cf9fb46 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2361,7 +2361,6 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
VM_BUG_ON_PAGE(is_huge_zero_page(page), page);
VM_BUG_ON_PAGE(!PageLocked(page), page);
- VM_BUG_ON_PAGE(!PageSwapBacked(page), page);
VM_BUG_ON_PAGE(!PageCompound(page), page);
if (PageAnon(head)) {
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 34bce5c..a4b499f 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -481,8 +481,7 @@ void __khugepaged_exit(struct mm_struct *mm)
static void release_pte_page(struct page *page)
{
- /* 0 stands for page_is_file_cache(page) == false */
- dec_node_page_state(page, NR_ISOLATED_ANON + 0);
+ dec_node_page_state(page, NR_ISOLATED_ANON + page_is_file_cache(page));
unlock_page(page);
putback_lru_page(page);
}
@@ -530,7 +529,6 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
VM_BUG_ON_PAGE(PageCompound(page), page);
VM_BUG_ON_PAGE(!PageAnon(page), page);
- VM_BUG_ON_PAGE(!PageSwapBacked(page), page);
/*
* We can do it before isolate_lru_page because the
@@ -577,8 +575,8 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
result = SCAN_DEL_PAGE_LRU;
goto out;
}
- /* 0 stands for page_is_file_cache(page) == false */
- inc_node_page_state(page, NR_ISOLATED_ANON + 0);
+ inc_node_page_state(page,
+ NR_ISOLATED_ANON + page_is_file_cache(page));
VM_BUG_ON_PAGE(!PageLocked(page), page);
VM_BUG_ON_PAGE(PageLRU(page), page);
diff --git a/mm/migrate.c b/mm/migrate.c
index 2c63ac0..7c8df1f 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1943,7 +1943,8 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
/* Prepare a page as a migration target */
__SetPageLocked(new_page);
- __SetPageSwapBacked(new_page);
+ if (PageSwapBacked(page))
+ __SetPageSwapBacked(new_page);
/* anon mapping, we can simply copy page->mapping to the new page: */
new_page->mapping = page->mapping;
diff --git a/mm/rmap.c b/mm/rmap.c
index 96eb85c..c621088 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1416,7 +1416,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
* Store the swap location in the pte.
* See handle_pte_fault() ...
*/
- VM_BUG_ON_PAGE(!PageSwapCache(page), page);
+ VM_BUG_ON_PAGE(!PageSwapCache(page) && PageSwapBacked(page),
+ page);
if (!PageDirty(page)) {
/* It's a freeable page by MADV_FREE */
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | "Hillf Danton" <hillf.zj@alibaba-inc.com> |
|---|---|
| Date | 2017-02-27 08:00 +0100 |
| Subject | Re: [PATCH V5 2/6] mm: don't assume anonymous pages have SwapBacked flag |
| Message-ID | <tfnrV-1HV-7@gated-at.bofh.it> |
| In reply to | #1587958 |
On February 25, 2017 5:32 AM Shaohua Li wrote: > > There are a few places the code assumes anonymous pages should have > SwapBacked flag set. MADV_FREE pages are anonymous pages but we are > going to add them to LRU_INACTIVE_FILE list and clear SwapBacked flag > for them. The assumption doesn't hold any more, so fix them. > > Cc: Michal Hocko <mhocko@suse.com> > Cc: Minchan Kim <minchan@kernel.org> > Cc: Hugh Dickins <hughd@google.com> > Cc: Rik van Riel <riel@redhat.com> > Cc: Mel Gorman <mgorman@techsingularity.net> > Cc: Andrew Morton <akpm@linux-foundation.org> > Acked-by: Johannes Weiner <hannes@cmpxchg.org> > Signed-off-by: Shaohua Li <shli@fb.com> > --- Acked-by: Hillf Danton <hillf.zj@alibaba-inc.com>
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-02-27 16:00 +0100 |
| Subject | Re: [PATCH V5 2/6] mm: don't assume anonymous pages have SwapBacked flag |
| Message-ID | <tfuWl-6ZE-11@gated-at.bofh.it> |
| In reply to | #1587958 |
On Fri 24-02-17 13:31:45, Shaohua Li wrote:
> There are a few places the code assumes anonymous pages should have
> SwapBacked flag set. MADV_FREE pages are anonymous pages but we are
> going to add them to LRU_INACTIVE_FILE list and clear SwapBacked flag
> for them. The assumption doesn't hold any more, so fix them.
>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: Minchan Kim <minchan@kernel.org>
> Cc: Hugh Dickins <hughd@google.com>
> Cc: Rik van Riel <riel@redhat.com>
> Cc: Mel Gorman <mgorman@techsingularity.net>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Acked-by: Johannes Weiner <hannes@cmpxchg.org>
> Signed-off-by: Shaohua Li <shli@fb.com>
Looks good to me.
[...]
> index 96eb85c..c621088 100644
> --- a/mm/rmap.c
> +++ b/mm/rmap.c
> @@ -1416,7 +1416,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
> * Store the swap location in the pte.
> * See handle_pte_fault() ...
> */
> - VM_BUG_ON_PAGE(!PageSwapCache(page), page);
> + VM_BUG_ON_PAGE(!PageSwapCache(page) && PageSwapBacked(page),
> + page);
just this part makes me scratch my head. I really do not understand what
kind of problem it tries to prevent from, maybe I am missing something
obvoious...
>
> if (!PageDirty(page)) {
> /* It's a freeable page by MADV_FREE */
> --
> 2.9.3
>
--
Michal Hocko
SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-02-27 17:50 +0100 |
| Subject | Re: [PATCH V5 2/6] mm: don't assume anonymous pages have SwapBacked flag |
| Message-ID | <tfwEN-8dT-13@gated-at.bofh.it> |
| In reply to | #1588706 |
On Mon 27-02-17 08:10:24, Shaohua Li wrote: > On Mon, Feb 27, 2017 at 03:35:34PM +0100, Michal Hocko wrote: > > On Fri 24-02-17 13:31:45, Shaohua Li wrote: > > > There are a few places the code assumes anonymous pages should have > > > SwapBacked flag set. MADV_FREE pages are anonymous pages but we are > > > going to add them to LRU_INACTIVE_FILE list and clear SwapBacked flag > > > for them. The assumption doesn't hold any more, so fix them. > > > > > > Cc: Michal Hocko <mhocko@suse.com> > > > Cc: Minchan Kim <minchan@kernel.org> > > > Cc: Hugh Dickins <hughd@google.com> > > > Cc: Rik van Riel <riel@redhat.com> > > > Cc: Mel Gorman <mgorman@techsingularity.net> > > > Cc: Andrew Morton <akpm@linux-foundation.org> > > > Acked-by: Johannes Weiner <hannes@cmpxchg.org> > > > Signed-off-by: Shaohua Li <shli@fb.com> Anyway, feel free to add Acked-by: Michal Hocko <mhocko@suse.com> > > > > Looks good to me. > > [...] > > > index 96eb85c..c621088 100644 > > > --- a/mm/rmap.c > > > +++ b/mm/rmap.c > > > @@ -1416,7 +1416,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, > > > * Store the swap location in the pte. > > > * See handle_pte_fault() ... > > > */ > > > - VM_BUG_ON_PAGE(!PageSwapCache(page), page); > > > + VM_BUG_ON_PAGE(!PageSwapCache(page) && PageSwapBacked(page), > > > + page); > > > > just this part makes me scratch my head. I really do not understand what > > kind of problem it tries to prevent from, maybe I am missing something > > obvoious... > > Just check a page which isn't lazyfree but wrongly enters here without swap > entry. Or maybe you suggest we delete this statement? Ohh, I figured out when seeing later patch in the series, I then wanted to get back to this one but forgot... This on its own didn't really tell me much. Maybe a comment would be helpful or even drop the VM_BUG_ON altogether. -- Michal Hocko SUSE Labs
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web