All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] mm: remove activate_page() from unuse_pte()
@ 2020-08-18 18:47 Yu Zhao
  2020-08-18 18:47 ` [PATCH v2 2/3] mm: remove superfluous __ClearPageActive() Yu Zhao
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Yu Zhao @ 2020-08-18 18:47 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Alexander Duyck, Huang Ying, David Hildenbrand, Michal Hocko,
	Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, linux-mm, linux-kernel,
	Joonsoo Kim, Yu Zhao

We don't initially add anon pages to active lruvec after
commit b518154e59aa ("mm/vmscan: protect the workingset on anonymous LRU").
Remove activate_page() from unuse_pte(), which seems to be missed by
the commit. And make the function static while we are at it.

Before the commit, we called lru_cache_add_active_or_unevictable() to
add new ksm pages to active lruvec. Therefore, activate_page() wasn't
necessary for them in the first place.

Signed-off-by: Yu Zhao <yuzhao@google.com>
---
 include/linux/swap.h | 1 -
 mm/swap.c            | 4 ++--
 mm/swapfile.c        | 5 -----
 3 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/include/linux/swap.h b/include/linux/swap.h
index 661046994db4..df6207346078 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -340,7 +340,6 @@ extern void lru_note_cost_page(struct page *);
 extern void lru_cache_add(struct page *);
 extern void lru_add_page_tail(struct page *page, struct page *page_tail,
 			 struct lruvec *lruvec, struct list_head *head);
-extern void activate_page(struct page *);
 extern void mark_page_accessed(struct page *);
 extern void lru_add_drain(void);
 extern void lru_add_drain_cpu(int cpu);
diff --git a/mm/swap.c b/mm/swap.c
index d16d65d9b4e0..25c4043491b3 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -348,7 +348,7 @@ static bool need_activate_page_drain(int cpu)
 	return pagevec_count(&per_cpu(lru_pvecs.activate_page, cpu)) != 0;
 }
 
-void activate_page(struct page *page)
+static void activate_page(struct page *page)
 {
 	page = compound_head(page);
 	if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
@@ -368,7 +368,7 @@ static inline void activate_page_drain(int cpu)
 {
 }
 
-void activate_page(struct page *page)
+static void activate_page(struct page *page)
 {
 	pg_data_t *pgdat = page_pgdat(page);
 
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 12f59e641b5e..c287c560f96d 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1925,11 +1925,6 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
 		lru_cache_add_inactive_or_unevictable(page, vma);
 	}
 	swap_free(entry);
-	/*
-	 * Move the page to the active list so it is not
-	 * immediately swapped out again after swapon.
-	 */
-	activate_page(page);
 out:
 	pte_unmap_unlock(pte, ptl);
 	if (page != swapcache) {
-- 
2.28.0.220.ged08abb693-goog


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/3] mm: remove superfluous __ClearPageActive()
  2020-08-18 18:47 [PATCH v2 1/3] mm: remove activate_page() from unuse_pte() Yu Zhao
@ 2020-08-18 18:47 ` Yu Zhao
  2020-08-19 23:04   ` Yang Shi
  2020-08-18 18:47 ` [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters() Yu Zhao
  2020-08-19 22:16 ` [PATCH v2 1/3] mm: remove activate_page() from unuse_pte() Yang Shi
  2 siblings, 1 reply; 10+ messages in thread
From: Yu Zhao @ 2020-08-18 18:47 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Alexander Duyck, Huang Ying, David Hildenbrand, Michal Hocko,
	Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, linux-mm, linux-kernel,
	Joonsoo Kim, Yu Zhao

To activate a page, mark_page_accessed() always holds a reference
on it. It either gets a new reference when adding a page to
lru_pvecs.activate_page or reuses an existing one it previously
got when it added a page to lru_pvecs.lru_add. So it doesn't call
SetPageActive() on a page that doesn't have any reference left.
Therefore, the race is impossible these days (I didn't brother to
dig into its history).

For other paths, namely reclaim and migration, a reference count is
always held while calling SetPageActive() on a page.

SetPageSlabPfmemalloc() also uses SetPageActive(), but it's irrelevant
to LRU pages.

Signed-off-by: Yu Zhao <yuzhao@google.com>
---
 mm/memremap.c | 2 --
 mm/swap.c     | 2 --
 2 files changed, 4 deletions(-)

diff --git a/mm/memremap.c b/mm/memremap.c
index 03e38b7a38f1..3a06eb91cb59 100644
--- a/mm/memremap.c
+++ b/mm/memremap.c
@@ -451,8 +451,6 @@ void free_devmap_managed_page(struct page *page)
 		return;
 	}
 
-	/* Clear Active bit in case of parallel mark_page_accessed */
-	__ClearPageActive(page);
 	__ClearPageWaiters(page);
 
 	mem_cgroup_uncharge(page);
diff --git a/mm/swap.c b/mm/swap.c
index 25c4043491b3..999a84dbe12c 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -900,8 +900,6 @@ void release_pages(struct page **pages, int nr)
 			del_page_from_lru_list(page, lruvec, page_off_lru(page));
 		}
 
-		/* Clear Active bit in case of parallel mark_page_accessed */
-		__ClearPageActive(page);
 		__ClearPageWaiters(page);
 
 		list_add(&page->lru, &pages_to_free);
-- 
2.28.0.220.ged08abb693-goog


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters()
  2020-08-18 18:47 [PATCH v2 1/3] mm: remove activate_page() from unuse_pte() Yu Zhao
  2020-08-18 18:47 ` [PATCH v2 2/3] mm: remove superfluous __ClearPageActive() Yu Zhao
@ 2020-08-18 18:47 ` Yu Zhao
  2020-08-19 23:06   ` Yang Shi
  2020-08-20  6:18   ` Michal Hocko
  2020-08-19 22:16 ` [PATCH v2 1/3] mm: remove activate_page() from unuse_pte() Yang Shi
  2 siblings, 2 replies; 10+ messages in thread
From: Yu Zhao @ 2020-08-18 18:47 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Alexander Duyck, Huang Ying, David Hildenbrand, Michal Hocko,
	Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, linux-mm, linux-kernel,
	Joonsoo Kim, Yu Zhao

Presumably __ClearPageWaiters() was added to follow the previously
removed __ClearPageActive() pattern.

Only flags that are in PAGE_FLAGS_CHECK_AT_FREE needs to be properly
cleared because otherwise we think there may be some kind of leak.
PG_waiters is not one of those flags and leaving the clearing to
PAGE_FLAGS_CHECK_AT_PREP is more appropriate.

Signed-off-by: Yu Zhao <yuzhao@google.com>
---
 include/linux/page-flags.h | 2 +-
 mm/filemap.c               | 2 ++
 mm/memremap.c              | 2 --
 mm/swap.c                  | 3 ---
 4 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6be1aa559b1e..dba80a2bdfba 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -318,7 +318,7 @@ static inline int TestClearPage##uname(struct page *page) { return 0; }
 	TESTSETFLAG_FALSE(uname) TESTCLEARFLAG_FALSE(uname)
 
 __PAGEFLAG(Locked, locked, PF_NO_TAIL)
-PAGEFLAG(Waiters, waiters, PF_ONLY_HEAD) __CLEARPAGEFLAG(Waiters, waiters, PF_ONLY_HEAD)
+PAGEFLAG(Waiters, waiters, PF_ONLY_HEAD)
 PAGEFLAG(Error, error, PF_NO_TAIL) TESTCLEARFLAG(Error, error, PF_NO_TAIL)
 PAGEFLAG(Referenced, referenced, PF_HEAD)
 	TESTCLEARFLAG(Referenced, referenced, PF_HEAD)
diff --git a/mm/filemap.c b/mm/filemap.c
index 1aaea26556cc..75240c7ef73f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1079,6 +1079,8 @@ static void wake_up_page_bit(struct page *page, int bit_nr)
 		 * other pages on it.
 		 *
 		 * That's okay, it's a rare case. The next waker will clear it.
+		 * Otherwise the bit will be cleared by PAGE_FLAGS_CHECK_AT_PREP
+		 * when the page is being freed.
 		 */
 	}
 	spin_unlock_irqrestore(&q->lock, flags);
diff --git a/mm/memremap.c b/mm/memremap.c
index 3a06eb91cb59..a9d02ffaf9e3 100644
--- a/mm/memremap.c
+++ b/mm/memremap.c
@@ -451,8 +451,6 @@ void free_devmap_managed_page(struct page *page)
 		return;
 	}
 
-	__ClearPageWaiters(page);
-
 	mem_cgroup_uncharge(page);
 
 	/*
diff --git a/mm/swap.c b/mm/swap.c
index 999a84dbe12c..40bf20a75278 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -90,7 +90,6 @@ static void __page_cache_release(struct page *page)
 		del_page_from_lru_list(page, lruvec, page_off_lru(page));
 		spin_unlock_irqrestore(&pgdat->lru_lock, flags);
 	}
-	__ClearPageWaiters(page);
 }
 
 static void __put_single_page(struct page *page)
@@ -900,8 +899,6 @@ void release_pages(struct page **pages, int nr)
 			del_page_from_lru_list(page, lruvec, page_off_lru(page));
 		}
 
-		__ClearPageWaiters(page);
-
 		list_add(&page->lru, &pages_to_free);
 	}
 	if (locked_pgdat)
-- 
2.28.0.220.ged08abb693-goog


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/3] mm: remove activate_page() from unuse_pte()
  2020-08-18 18:47 [PATCH v2 1/3] mm: remove activate_page() from unuse_pte() Yu Zhao
  2020-08-18 18:47 ` [PATCH v2 2/3] mm: remove superfluous __ClearPageActive() Yu Zhao
  2020-08-18 18:47 ` [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters() Yu Zhao
@ 2020-08-19 22:16 ` Yang Shi
  2 siblings, 0 replies; 10+ messages in thread
From: Yang Shi @ 2020-08-19 22:16 UTC (permalink / raw)
  To: Yu Zhao
  Cc: Andrew Morton, Alexander Duyck, Huang Ying, David Hildenbrand,
	Michal Hocko, Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, Linux MM,
	Linux Kernel Mailing List, Joonsoo Kim

On Tue, Aug 18, 2020 at 11:47 AM Yu Zhao <yuzhao@google.com> wrote:
>
> We don't initially add anon pages to active lruvec after
> commit b518154e59aa ("mm/vmscan: protect the workingset on anonymous LRU").
> Remove activate_page() from unuse_pte(), which seems to be missed by
> the commit. And make the function static while we are at it.
>
> Before the commit, we called lru_cache_add_active_or_unevictable() to
> add new ksm pages to active lruvec. Therefore, activate_page() wasn't
> necessary for them in the first place.

Reviewed-by: Yang Shi <shy828301@gmail.com>

>
> Signed-off-by: Yu Zhao <yuzhao@google.com>
> ---
>  include/linux/swap.h | 1 -
>  mm/swap.c            | 4 ++--
>  mm/swapfile.c        | 5 -----
>  3 files changed, 2 insertions(+), 8 deletions(-)
>
> diff --git a/include/linux/swap.h b/include/linux/swap.h
> index 661046994db4..df6207346078 100644
> --- a/include/linux/swap.h
> +++ b/include/linux/swap.h
> @@ -340,7 +340,6 @@ extern void lru_note_cost_page(struct page *);
>  extern void lru_cache_add(struct page *);
>  extern void lru_add_page_tail(struct page *page, struct page *page_tail,
>                          struct lruvec *lruvec, struct list_head *head);
> -extern void activate_page(struct page *);
>  extern void mark_page_accessed(struct page *);
>  extern void lru_add_drain(void);
>  extern void lru_add_drain_cpu(int cpu);
> diff --git a/mm/swap.c b/mm/swap.c
> index d16d65d9b4e0..25c4043491b3 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -348,7 +348,7 @@ static bool need_activate_page_drain(int cpu)
>         return pagevec_count(&per_cpu(lru_pvecs.activate_page, cpu)) != 0;
>  }
>
> -void activate_page(struct page *page)
> +static void activate_page(struct page *page)
>  {
>         page = compound_head(page);
>         if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
> @@ -368,7 +368,7 @@ static inline void activate_page_drain(int cpu)
>  {
>  }
>
> -void activate_page(struct page *page)
> +static void activate_page(struct page *page)
>  {
>         pg_data_t *pgdat = page_pgdat(page);
>
> diff --git a/mm/swapfile.c b/mm/swapfile.c
> index 12f59e641b5e..c287c560f96d 100644
> --- a/mm/swapfile.c
> +++ b/mm/swapfile.c
> @@ -1925,11 +1925,6 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
>                 lru_cache_add_inactive_or_unevictable(page, vma);
>         }
>         swap_free(entry);
> -       /*
> -        * Move the page to the active list so it is not
> -        * immediately swapped out again after swapon.
> -        */
> -       activate_page(page);
>  out:
>         pte_unmap_unlock(pte, ptl);
>         if (page != swapcache) {
> --
> 2.28.0.220.ged08abb693-goog
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 2/3] mm: remove superfluous __ClearPageActive()
  2020-08-18 18:47 ` [PATCH v2 2/3] mm: remove superfluous __ClearPageActive() Yu Zhao
@ 2020-08-19 23:04   ` Yang Shi
  0 siblings, 0 replies; 10+ messages in thread
From: Yang Shi @ 2020-08-19 23:04 UTC (permalink / raw)
  To: Yu Zhao
  Cc: Andrew Morton, Alexander Duyck, Huang Ying, David Hildenbrand,
	Michal Hocko, Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, Linux MM,
	Linux Kernel Mailing List, Joonsoo Kim

On Tue, Aug 18, 2020 at 11:47 AM Yu Zhao <yuzhao@google.com> wrote:
>
> To activate a page, mark_page_accessed() always holds a reference
> on it. It either gets a new reference when adding a page to
> lru_pvecs.activate_page or reuses an existing one it previously
> got when it added a page to lru_pvecs.lru_add. So it doesn't call
> SetPageActive() on a page that doesn't have any reference left.
> Therefore, the race is impossible these days (I didn't brother to
> dig into its history).
>
> For other paths, namely reclaim and migration, a reference count is
> always held while calling SetPageActive() on a page.
>
> SetPageSlabPfmemalloc() also uses SetPageActive(), but it's irrelevant
> to LRU pages.

Seems fine to me. Reviewed-by: Yang Shi <shy828301@gmail.com>

>
> Signed-off-by: Yu Zhao <yuzhao@google.com>
> ---
>  mm/memremap.c | 2 --
>  mm/swap.c     | 2 --
>  2 files changed, 4 deletions(-)
>
> diff --git a/mm/memremap.c b/mm/memremap.c
> index 03e38b7a38f1..3a06eb91cb59 100644
> --- a/mm/memremap.c
> +++ b/mm/memremap.c
> @@ -451,8 +451,6 @@ void free_devmap_managed_page(struct page *page)
>                 return;
>         }
>
> -       /* Clear Active bit in case of parallel mark_page_accessed */
> -       __ClearPageActive(page);
>         __ClearPageWaiters(page);
>
>         mem_cgroup_uncharge(page);
> diff --git a/mm/swap.c b/mm/swap.c
> index 25c4043491b3..999a84dbe12c 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -900,8 +900,6 @@ void release_pages(struct page **pages, int nr)
>                         del_page_from_lru_list(page, lruvec, page_off_lru(page));
>                 }
>
> -               /* Clear Active bit in case of parallel mark_page_accessed */
> -               __ClearPageActive(page);
>                 __ClearPageWaiters(page);
>
>                 list_add(&page->lru, &pages_to_free);
> --
> 2.28.0.220.ged08abb693-goog
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters()
  2020-08-18 18:47 ` [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters() Yu Zhao
@ 2020-08-19 23:06   ` Yang Shi
  2020-08-19 23:39     ` Yu Zhao
  2020-08-20  6:18   ` Michal Hocko
  1 sibling, 1 reply; 10+ messages in thread
From: Yang Shi @ 2020-08-19 23:06 UTC (permalink / raw)
  To: Yu Zhao
  Cc: Andrew Morton, Alexander Duyck, Huang Ying, David Hildenbrand,
	Michal Hocko, Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, Linux MM,
	Linux Kernel Mailing List, Joonsoo Kim

On Tue, Aug 18, 2020 at 11:47 AM Yu Zhao <yuzhao@google.com> wrote:
>
> Presumably __ClearPageWaiters() was added to follow the previously
> removed __ClearPageActive() pattern.
>
> Only flags that are in PAGE_FLAGS_CHECK_AT_FREE needs to be properly
> cleared because otherwise we think there may be some kind of leak.
> PG_waiters is not one of those flags and leaving the clearing to
> PAGE_FLAGS_CHECK_AT_PREP is more appropriate.

Actually TBH I'm not very keen to this change, it seems the clearing
is just moved around and the allocation side pays for that instead of
free side.

>
> Signed-off-by: Yu Zhao <yuzhao@google.com>
> ---
>  include/linux/page-flags.h | 2 +-
>  mm/filemap.c               | 2 ++
>  mm/memremap.c              | 2 --
>  mm/swap.c                  | 3 ---
>  4 files changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 6be1aa559b1e..dba80a2bdfba 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -318,7 +318,7 @@ static inline int TestClearPage##uname(struct page *page) { return 0; }
>         TESTSETFLAG_FALSE(uname) TESTCLEARFLAG_FALSE(uname)
>
>  __PAGEFLAG(Locked, locked, PF_NO_TAIL)
> -PAGEFLAG(Waiters, waiters, PF_ONLY_HEAD) __CLEARPAGEFLAG(Waiters, waiters, PF_ONLY_HEAD)
> +PAGEFLAG(Waiters, waiters, PF_ONLY_HEAD)
>  PAGEFLAG(Error, error, PF_NO_TAIL) TESTCLEARFLAG(Error, error, PF_NO_TAIL)
>  PAGEFLAG(Referenced, referenced, PF_HEAD)
>         TESTCLEARFLAG(Referenced, referenced, PF_HEAD)
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 1aaea26556cc..75240c7ef73f 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -1079,6 +1079,8 @@ static void wake_up_page_bit(struct page *page, int bit_nr)
>                  * other pages on it.
>                  *
>                  * That's okay, it's a rare case. The next waker will clear it.
> +                * Otherwise the bit will be cleared by PAGE_FLAGS_CHECK_AT_PREP
> +                * when the page is being freed.
>                  */
>         }
>         spin_unlock_irqrestore(&q->lock, flags);
> diff --git a/mm/memremap.c b/mm/memremap.c
> index 3a06eb91cb59..a9d02ffaf9e3 100644
> --- a/mm/memremap.c
> +++ b/mm/memremap.c
> @@ -451,8 +451,6 @@ void free_devmap_managed_page(struct page *page)
>                 return;
>         }
>
> -       __ClearPageWaiters(page);
> -
>         mem_cgroup_uncharge(page);
>
>         /*
> diff --git a/mm/swap.c b/mm/swap.c
> index 999a84dbe12c..40bf20a75278 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -90,7 +90,6 @@ static void __page_cache_release(struct page *page)
>                 del_page_from_lru_list(page, lruvec, page_off_lru(page));
>                 spin_unlock_irqrestore(&pgdat->lru_lock, flags);
>         }
> -       __ClearPageWaiters(page);
>  }
>
>  static void __put_single_page(struct page *page)
> @@ -900,8 +899,6 @@ void release_pages(struct page **pages, int nr)
>                         del_page_from_lru_list(page, lruvec, page_off_lru(page));
>                 }
>
> -               __ClearPageWaiters(page);
> -
>                 list_add(&page->lru, &pages_to_free);
>         }
>         if (locked_pgdat)
> --
> 2.28.0.220.ged08abb693-goog
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters()
  2020-08-19 23:06   ` Yang Shi
@ 2020-08-19 23:39     ` Yu Zhao
  2020-08-20  0:16       ` Yang Shi
  0 siblings, 1 reply; 10+ messages in thread
From: Yu Zhao @ 2020-08-19 23:39 UTC (permalink / raw)
  To: Yang Shi
  Cc: Andrew Morton, Alexander Duyck, Huang Ying, David Hildenbrand,
	Michal Hocko, Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, Linux MM,
	Linux Kernel Mailing List, Joonsoo Kim

On Wed, Aug 19, 2020 at 04:06:32PM -0700, Yang Shi wrote:
> On Tue, Aug 18, 2020 at 11:47 AM Yu Zhao <yuzhao@google.com> wrote:
> >
> > Presumably __ClearPageWaiters() was added to follow the previously
> > removed __ClearPageActive() pattern.
> >
> > Only flags that are in PAGE_FLAGS_CHECK_AT_FREE needs to be properly
> > cleared because otherwise we think there may be some kind of leak.
> > PG_waiters is not one of those flags and leaving the clearing to
> > PAGE_FLAGS_CHECK_AT_PREP is more appropriate.
> 
> Actually TBH I'm not very keen to this change, it seems the clearing
> is just moved around and the allocation side pays for that instead of
> free side.

I'll assume you are referring to the overhead from clearing
PG_waiters. First of all, there is no overhead -- we should have a
serious talk with the hardware team who makes word-size bitwise AND
more than one instruction. And the clearing is done in
free_pages_prepare(), which has nothing to do with allocations.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters()
  2020-08-19 23:39     ` Yu Zhao
@ 2020-08-20  0:16       ` Yang Shi
  0 siblings, 0 replies; 10+ messages in thread
From: Yang Shi @ 2020-08-20  0:16 UTC (permalink / raw)
  To: Yu Zhao
  Cc: Andrew Morton, Alexander Duyck, Huang Ying, David Hildenbrand,
	Michal Hocko, Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, Linux MM,
	Linux Kernel Mailing List, Joonsoo Kim

On Wed, Aug 19, 2020 at 4:39 PM Yu Zhao <yuzhao@google.com> wrote:
>
> On Wed, Aug 19, 2020 at 04:06:32PM -0700, Yang Shi wrote:
> > On Tue, Aug 18, 2020 at 11:47 AM Yu Zhao <yuzhao@google.com> wrote:
> > >
> > > Presumably __ClearPageWaiters() was added to follow the previously
> > > removed __ClearPageActive() pattern.
> > >
> > > Only flags that are in PAGE_FLAGS_CHECK_AT_FREE needs to be properly
> > > cleared because otherwise we think there may be some kind of leak.
> > > PG_waiters is not one of those flags and leaving the clearing to
> > > PAGE_FLAGS_CHECK_AT_PREP is more appropriate.
> >
> > Actually TBH I'm not very keen to this change, it seems the clearing
> > is just moved around and the allocation side pays for that instead of
> > free side.
>
> I'll assume you are referring to the overhead from clearing
> PG_waiters. First of all, there is no overhead -- we should have a
> serious talk with the hardware team who makes word-size bitwise AND
> more than one instruction. And the clearing is done in
> free_pages_prepare(), which has nothing to do with allocations.

Oh, yes, you are right. Now I'm wondering why we have the waiter bit
cleared at the first place.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters()
  2020-08-18 18:47 ` [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters() Yu Zhao
  2020-08-19 23:06   ` Yang Shi
@ 2020-08-20  6:18   ` Michal Hocko
  2020-08-20  8:12     ` Yu Zhao
  1 sibling, 1 reply; 10+ messages in thread
From: Michal Hocko @ 2020-08-20  6:18 UTC (permalink / raw)
  To: Yu Zhao
  Cc: Andrew Morton, Alexander Duyck, Huang Ying, David Hildenbrand,
	Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, linux-mm, linux-kernel,
	Joonsoo Kim

On Tue 18-08-20 12:47:04, Yu Zhao wrote:
> Presumably __ClearPageWaiters() was added to follow the previously
> removed __ClearPageActive() pattern.

I do not think so. Please have a look at 62906027091f ("mm: add
PageWaiters indicating tasks are waiting for a page bit") and a
discussion when the patch has been proposed. Sorry I do not have a link
handy but I do remember that the handling was quite subtle.
 
> Only flags that are in PAGE_FLAGS_CHECK_AT_FREE needs to be properly
> cleared because otherwise we think there may be some kind of leak.
> PG_waiters is not one of those flags and leaving the clearing to
> PAGE_FLAGS_CHECK_AT_PREP is more appropriate.

What is the point of this patch in the first place? Page waiters is
quite subtle and I wouldn't touch it without having a very good reason.

> Signed-off-by: Yu Zhao <yuzhao@google.com>
> ---
>  include/linux/page-flags.h | 2 +-
>  mm/filemap.c               | 2 ++
>  mm/memremap.c              | 2 --
>  mm/swap.c                  | 3 ---
>  4 files changed, 3 insertions(+), 6 deletions(-)
> 
> diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
> index 6be1aa559b1e..dba80a2bdfba 100644
> --- a/include/linux/page-flags.h
> +++ b/include/linux/page-flags.h
> @@ -318,7 +318,7 @@ static inline int TestClearPage##uname(struct page *page) { return 0; }
>  	TESTSETFLAG_FALSE(uname) TESTCLEARFLAG_FALSE(uname)
>  
>  __PAGEFLAG(Locked, locked, PF_NO_TAIL)
> -PAGEFLAG(Waiters, waiters, PF_ONLY_HEAD) __CLEARPAGEFLAG(Waiters, waiters, PF_ONLY_HEAD)
> +PAGEFLAG(Waiters, waiters, PF_ONLY_HEAD)
>  PAGEFLAG(Error, error, PF_NO_TAIL) TESTCLEARFLAG(Error, error, PF_NO_TAIL)
>  PAGEFLAG(Referenced, referenced, PF_HEAD)
>  	TESTCLEARFLAG(Referenced, referenced, PF_HEAD)
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 1aaea26556cc..75240c7ef73f 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -1079,6 +1079,8 @@ static void wake_up_page_bit(struct page *page, int bit_nr)
>  		 * other pages on it.
>  		 *
>  		 * That's okay, it's a rare case. The next waker will clear it.
> +		 * Otherwise the bit will be cleared by PAGE_FLAGS_CHECK_AT_PREP
> +		 * when the page is being freed.
>  		 */
>  	}
>  	spin_unlock_irqrestore(&q->lock, flags);
> diff --git a/mm/memremap.c b/mm/memremap.c
> index 3a06eb91cb59..a9d02ffaf9e3 100644
> --- a/mm/memremap.c
> +++ b/mm/memremap.c
> @@ -451,8 +451,6 @@ void free_devmap_managed_page(struct page *page)
>  		return;
>  	}
>  
> -	__ClearPageWaiters(page);
> -
>  	mem_cgroup_uncharge(page);
>  
>  	/*
> diff --git a/mm/swap.c b/mm/swap.c
> index 999a84dbe12c..40bf20a75278 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -90,7 +90,6 @@ static void __page_cache_release(struct page *page)
>  		del_page_from_lru_list(page, lruvec, page_off_lru(page));
>  		spin_unlock_irqrestore(&pgdat->lru_lock, flags);
>  	}
> -	__ClearPageWaiters(page);
>  }
>  
>  static void __put_single_page(struct page *page)
> @@ -900,8 +899,6 @@ void release_pages(struct page **pages, int nr)
>  			del_page_from_lru_list(page, lruvec, page_off_lru(page));
>  		}
>  
> -		__ClearPageWaiters(page);
> -
>  		list_add(&page->lru, &pages_to_free);
>  	}
>  	if (locked_pgdat)
> -- 
> 2.28.0.220.ged08abb693-goog
> 

-- 
Michal Hocko
SUSE Labs

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters()
  2020-08-20  6:18   ` Michal Hocko
@ 2020-08-20  8:12     ` Yu Zhao
  0 siblings, 0 replies; 10+ messages in thread
From: Yu Zhao @ 2020-08-20  8:12 UTC (permalink / raw)
  To: Michal Hocko
  Cc: Andrew Morton, Alexander Duyck, Huang Ying, David Hildenbrand,
	Yang Shi, Qian Cai, Mel Gorman, Nicholas Piggin,
	Jérôme Glisse, Hugh Dickins, linux-mm, linux-kernel,
	Joonsoo Kim

On Thu, Aug 20, 2020 at 08:18:27AM +0200, Michal Hocko wrote:
> On Tue 18-08-20 12:47:04, Yu Zhao wrote:
> > Presumably __ClearPageWaiters() was added to follow the previously
> > removed __ClearPageActive() pattern.
> 
> I do not think so. Please have a look at 62906027091f ("mm: add
> PageWaiters indicating tasks are waiting for a page bit") and a
> discussion when the patch has been proposed. Sorry I do not have a link
> handy but I do remember that the handling was quite subtle.
>  
> > Only flags that are in PAGE_FLAGS_CHECK_AT_FREE needs to be properly
> > cleared because otherwise we think there may be some kind of leak.
> > PG_waiters is not one of those flags and leaving the clearing to
> > PAGE_FLAGS_CHECK_AT_PREP is more appropriate.
> 
> What is the point of this patch in the first place? Page waiters is
> quite subtle and I wouldn't touch it without having a very good reason.

I appreciate your caution. And I just studied the history [1] (I admit
this is something I should have done beforehand), and didn't find any
discussion on __ClearPageWaiters() specifically. So I would ask why it
was added originally. I was hoping Nicholas could help us.

[1] https://lore.kernel.org/lkml/20161225030030.23219-3-npiggin@gmail.com/

Given its triviality, I can't argue how useful this patch is. So I'll
go with how evident it is: we are removing __ClearPageWaiters() from
paths where pages have no references left -- they can't have any
waiters or be on any wait queues.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-08-20  8:13 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-18 18:47 [PATCH v2 1/3] mm: remove activate_page() from unuse_pte() Yu Zhao
2020-08-18 18:47 ` [PATCH v2 2/3] mm: remove superfluous __ClearPageActive() Yu Zhao
2020-08-19 23:04   ` Yang Shi
2020-08-18 18:47 ` [PATCH v2 3/3] mm: remove superfluous __ClearPageWaiters() Yu Zhao
2020-08-19 23:06   ` Yang Shi
2020-08-19 23:39     ` Yu Zhao
2020-08-20  0:16       ` Yang Shi
2020-08-20  6:18   ` Michal Hocko
2020-08-20  8:12     ` Yu Zhao
2020-08-19 22:16 ` [PATCH v2 1/3] mm: remove activate_page() from unuse_pte() Yang Shi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.