diff mbox series

[next] mm/vmscan: __isolate_lru_page_prepare clean up

Message ID 1605859413-53864-1-git-send-email-alex.shi@linux.alibaba.com (mailing list archive)
State New, archived
Headers show
Series [next] mm/vmscan: __isolate_lru_page_prepare clean up | expand

Commit Message

Alex Shi Nov. 20, 2020, 8:03 a.m. UTC
The function just return 2 results, so use a 'switch' to deal with its
result is unnecessary, and simplify it to a bool func as Vlastimil
suggested.

Also removed 'goto' in using by reusing list_move().

Signed-off-by: Alex Shi <alex.shi@linux.alibaba.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Michal Hocko <mhocko@suse.com>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
---
 mm/compaction.c |  2 +-
 mm/vmscan.c     | 53 ++++++++++++++++++++++++-------------------------
 2 files changed, 27 insertions(+), 28 deletions(-)

Comments

Andrew Morton Nov. 20, 2020, 11:13 p.m. UTC | #1
On Fri, 20 Nov 2020 16:03:33 +0800 Alex Shi <alex.shi@linux.alibaba.com> wrote:

> The function just return 2 results, so use a 'switch' to deal with its
> result is unnecessary, and simplify it to a bool func as Vlastimil
> suggested.
> 
> Also removed 'goto' in using by reusing list_move().
> 
> ...
>
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -1540,7 +1540,7 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
>   */
>  int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
>  {
> -	int ret = -EBUSY;
> +	int ret = false;
>  
>  	/* Only take pages on the LRU. */
>  	if (!PageLRU(page))
> @@ -1590,7 +1590,7 @@ int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
>  	if ((mode & ISOLATE_UNMAPPED) && page_mapped(page))
>  		return ret;
>  
> -	return 0;
> +	return true;
>  }

The resulting __isolate_lru_page_prepare() is rather unpleasing.

- Why return an int and not a bool?

- `int ret = false' is a big hint that `ret' should have bool type!

- Why not just remove `ret' and do `return false' in all those `return
  ret' places?

- The __isolate_lru_page_prepare() kerneldoc still says "returns 0 on
  success, -ve errno on failure".
Alex Shi Nov. 22, 2020, noon UTC | #2
在 2020/11/21 上午7:13, Andrew Morton 写道:
> On Fri, 20 Nov 2020 16:03:33 +0800 Alex Shi <alex.shi@linux.alibaba.com> wrote:
> 
>> The function just return 2 results, so use a 'switch' to deal with its
>> result is unnecessary, and simplify it to a bool func as Vlastimil
>> suggested.
>>
>> Also removed 'goto' in using by reusing list_move().
>>
>> ...
>>
>> --- a/mm/vmscan.c
>> +++ b/mm/vmscan.c
>> @@ -1540,7 +1540,7 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
>>   */
>>  int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
>>  {
>> -	int ret = -EBUSY;
>> +	int ret = false;
>>  
>>  	/* Only take pages on the LRU. */
>>  	if (!PageLRU(page))
>> @@ -1590,7 +1590,7 @@ int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
>>  	if ((mode & ISOLATE_UNMAPPED) && page_mapped(page))
>>  		return ret;
>>  
>> -	return 0;
>> +	return true;
>>  }
> 
> The resulting __isolate_lru_page_prepare() is rather unpleasing.
> 
> - Why return an int and not a bool?
> 
> - `int ret = false' is a big hint that `ret' should have bool type!
> 
> - Why not just remove `ret' and do `return false' in all those `return
>   ret' places?
> 
> - The __isolate_lru_page_prepare() kerneldoc still says "returns 0 on
>   success, -ve errno on failure".  
> 

Hi Andrew,

Thanks a lot for caching and sorry for the bad patch.
It initially a 'int' version, and change it to bool in a hurry weekend.
I am sorry.

From 36c4fbda2d55633d3c1a3e79f045cd9877453ab7 Mon Sep 17 00:00:00 2001
From: Alex Shi <alex.shi@linux.alibaba.com>
Date: Fri, 20 Nov 2020 14:49:16 +0800
Subject: [PATCH v2 next] mm/vmscan: __isolate_lru_page_prepare clean up

The function just return 2 results, so use a 'switch' to deal with its
result is unnecessary, and simplify it to a bool func as Vlastimil
suggested.

Also remove 'goto' by reusing list_move().

Signed-off-by: Alex Shi <alex.shi@linux.alibaba.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Michal Hocko <mhocko@suse.com>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
---
 mm/compaction.c |  2 +-
 mm/vmscan.c     | 69 +++++++++++++++++++++++--------------------------
 2 files changed, 34 insertions(+), 37 deletions(-)

diff --git a/mm/compaction.c b/mm/compaction.c
index b68931854253..8d71ffebe6cb 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -988,7 +988,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
 		if (unlikely(!get_page_unless_zero(page)))
 			goto isolate_fail;
 
-		if (__isolate_lru_page_prepare(page, isolate_mode) != 0)
+		if (!__isolate_lru_page_prepare(page, isolate_mode))
 			goto isolate_fail_put;
 
 		/* Try isolate the page */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index c6f94e55c3fe..ab2fdee0828e 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1536,19 +1536,17 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
  * page:	page to consider
  * mode:	one of the LRU isolation modes defined above
  *
- * returns 0 on success, -ve errno on failure.
+ * returns ture on success, false on failure.
  */
-int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
+bool __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
 {
-	int ret = -EBUSY;
-
 	/* Only take pages on the LRU. */
 	if (!PageLRU(page))
-		return ret;
+		return false;
 
 	/* Compaction should not handle unevictable pages but CMA can do so */
 	if (PageUnevictable(page) && !(mode & ISOLATE_UNEVICTABLE))
-		return ret;
+		return false;
 
 	/*
 	 * To minimise LRU disruption, the caller can indicate that it only
@@ -1561,7 +1559,7 @@ int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
 	if (mode & ISOLATE_ASYNC_MIGRATE) {
 		/* All the caller can do on PageWriteback is block */
 		if (PageWriteback(page))
-			return ret;
+			return false;
 
 		if (PageDirty(page)) {
 			struct address_space *mapping;
@@ -1577,20 +1575,20 @@ int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
 			 * from the page cache.
 			 */
 			if (!trylock_page(page))
-				return ret;
+				return false;
 
 			mapping = page_mapping(page);
 			migrate_dirty = !mapping || mapping->a_ops->migratepage;
 			unlock_page(page);
 			if (!migrate_dirty)
-				return ret;
+				return false;
 		}
 	}
 
 	if ((mode & ISOLATE_UNMAPPED) && page_mapped(page))
-		return ret;
+		return false;
 
-	return 0;
+	return true;
 }
 
 /*
@@ -1674,35 +1672,34 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
 		 * only when the page is being freed somewhere else.
 		 */
 		scan += nr_pages;
-		switch (__isolate_lru_page_prepare(page, mode)) {
-		case 0:
+		if (!__isolate_lru_page_prepare(page, mode)) {
+			/* else it is being freed elsewhere */
+			list_move(&page->lru, src);
+			continue;
+		}
+		/*
+		 * Be careful not to clear PageLRU until after we're
+		 * sure the page is not being freed elsewhere -- the
+		 * page release code relies on it.
+		 */
+		if (unlikely(!get_page_unless_zero(page))) {
+			list_move(&page->lru, src);
+			continue;
+		}
+
+		if (!TestClearPageLRU(page)) {
 			/*
-			 * Be careful not to clear PageLRU until after we're
-			 * sure the page is not being freed elsewhere -- the
-			 * page release code relies on it.
+			 * This page may in other isolation path,
+			 * but we still hold lru_lock.
 			 */
-			if (unlikely(!get_page_unless_zero(page)))
-				goto busy;
-
-			if (!TestClearPageLRU(page)) {
-				/*
-				 * This page may in other isolation path,
-				 * but we still hold lru_lock.
-				 */
-				put_page(page);
-				goto busy;
-			}
-
-			nr_taken += nr_pages;
-			nr_zone_taken[page_zonenum(page)] += nr_pages;
-			list_move(&page->lru, dst);
-			break;
-
-		default:
-busy:
-			/* else it is being freed elsewhere */
+			put_page(page);
 			list_move(&page->lru, src);
+			continue;
 		}
+
+		nr_taken += nr_pages;
+		nr_zone_taken[page_zonenum(page)] += nr_pages;
+		list_move(&page->lru, dst);
 	}
 
 	/*
Matthew Wilcox Nov. 22, 2020, 12:35 p.m. UTC | #3
On Sun, Nov 22, 2020 at 08:00:19PM +0800, Alex Shi wrote:
>  mm/compaction.c |  2 +-
>  mm/vmscan.c     | 69 +++++++++++++++++++++++--------------------------
>  2 files changed, 34 insertions(+), 37 deletions(-)

How is it possible you're changing the signature of a function without
touching a header file?  Surely __isolate_lru_page_prepare() must be declared
in mm/internal.h ?

> +++ b/mm/vmscan.c
> @@ -1536,19 +1536,17 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
>   * page:	page to consider
>   * mode:	one of the LRU isolation modes defined above
>   *
> - * returns 0 on success, -ve errno on failure.
> + * returns ture on success, false on failure.

"true".

> @@ -1674,35 +1672,34 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
>  		 * only when the page is being freed somewhere else.
>  		 */
>  		scan += nr_pages;
> -		switch (__isolate_lru_page_prepare(page, mode)) {
> -		case 0:
> +		if (!__isolate_lru_page_prepare(page, mode)) {
> +			/* else it is being freed elsewhere */

I don't think the word "else" helps here.  Just
			/* It is being freed elsewhere */

> +		if (!TestClearPageLRU(page)) {
>  			/*
> +			 * This page may in other isolation path,
> +			 * but we still hold lru_lock.
>  			 */

I don't think this comment helps me understand what's going on here.
Maybe:

			/* Another thread is already isolating this page */

> +			put_page(page);
>  			list_move(&page->lru, src);
> +			continue;
>  		}
Alex Shi Nov. 22, 2020, 2 p.m. UTC | #4
在 2020/11/22 下午8:35, Matthew Wilcox 写道:
> On Sun, Nov 22, 2020 at 08:00:19PM +0800, Alex Shi wrote:
>>  mm/compaction.c |  2 +-
>>  mm/vmscan.c     | 69 +++++++++++++++++++++++--------------------------
>>  2 files changed, 34 insertions(+), 37 deletions(-)
> 
> How is it possible you're changing the signature of a function without
> touching a header file?  Surely __isolate_lru_page_prepare() must be declared
> in mm/internal.h ?
> 
>> +++ b/mm/vmscan.c
>> @@ -1536,19 +1536,17 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
>>   * page:	page to consider
>>   * mode:	one of the LRU isolation modes defined above
>>   *
>> - * returns 0 on success, -ve errno on failure.
>> + * returns ture on success, false on failure.
> 
> "true".
> 
>> @@ -1674,35 +1672,34 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
>>  		 * only when the page is being freed somewhere else.
>>  		 */
>>  		scan += nr_pages;
>> -		switch (__isolate_lru_page_prepare(page, mode)) {
>> -		case 0:
>> +		if (!__isolate_lru_page_prepare(page, mode)) {
>> +			/* else it is being freed elsewhere */
> 
> I don't think the word "else" helps here.  Just
> 			/* It is being freed elsewhere */
> 
>> +		if (!TestClearPageLRU(page)) {
>>  			/*
>> +			 * This page may in other isolation path,
>> +			 * but we still hold lru_lock.
>>  			 */
> 
> I don't think this comment helps me understand what's going on here.
> Maybe:
> 
> 			/* Another thread is already isolating this page */
> 
>> +			put_page(page);
>>  			list_move(&page->lru, src);
>> +			continue;
>>  		}

Hi Matthew,

Thanks a lot for all comments, I picked all up and here is the v3:

From 167131dd106a96fd08af725df850e0da6ec899af Mon Sep 17 00:00:00 2001
From: Alex Shi <alex.shi@linux.alibaba.com>
Date: Fri, 20 Nov 2020 14:49:16 +0800
Subject: [PATCH v3 next] mm/vmscan: __isolate_lru_page_prepare clean up

The function just return 2 results, so use a 'switch' to deal with its
result is unnecessary, and simplify it to a bool func as Vlastimil
suggested.

Also remove 'goto' by reusing list_move(), and take Matthew Wilcox's
suggestion to update comments in function.

Signed-off-by: Alex Shi <alex.shi@linux.alibaba.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Hugh Dickins <hughd@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Michal Hocko <mhocko@suse.com>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
---
 include/linux/swap.h |  2 +-
 mm/compaction.c      |  2 +-
 mm/vmscan.c          | 68 ++++++++++++++++++++------------------------
 3 files changed, 33 insertions(+), 39 deletions(-)

diff --git a/include/linux/swap.h b/include/linux/swap.h
index 596bc2f4d9b0..5bba15ac5a2e 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -356,7 +356,7 @@ extern void lru_cache_add_inactive_or_unevictable(struct page *page,
 extern unsigned long zone_reclaimable_pages(struct zone *zone);
 extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 					gfp_t gfp_mask, nodemask_t *mask);
-extern int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode);
+extern bool __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode);
 extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
 						  unsigned long nr_pages,
 						  gfp_t gfp_mask,
diff --git a/mm/compaction.c b/mm/compaction.c
index b68931854253..8d71ffebe6cb 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -988,7 +988,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
 		if (unlikely(!get_page_unless_zero(page)))
 			goto isolate_fail;
 
-		if (__isolate_lru_page_prepare(page, isolate_mode) != 0)
+		if (!__isolate_lru_page_prepare(page, isolate_mode))
 			goto isolate_fail_put;
 
 		/* Try isolate the page */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index c6f94e55c3fe..4d2703c43310 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1536,19 +1536,17 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
  * page:	page to consider
  * mode:	one of the LRU isolation modes defined above
  *
- * returns 0 on success, -ve errno on failure.
+ * returns true on success, false on failure.
  */
-int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
+bool __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
 {
-	int ret = -EBUSY;
-
 	/* Only take pages on the LRU. */
 	if (!PageLRU(page))
-		return ret;
+		return false;
 
 	/* Compaction should not handle unevictable pages but CMA can do so */
 	if (PageUnevictable(page) && !(mode & ISOLATE_UNEVICTABLE))
-		return ret;
+		return false;
 
 	/*
 	 * To minimise LRU disruption, the caller can indicate that it only
@@ -1561,7 +1559,7 @@ int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
 	if (mode & ISOLATE_ASYNC_MIGRATE) {
 		/* All the caller can do on PageWriteback is block */
 		if (PageWriteback(page))
-			return ret;
+			return false;
 
 		if (PageDirty(page)) {
 			struct address_space *mapping;
@@ -1577,20 +1575,20 @@ int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
 			 * from the page cache.
 			 */
 			if (!trylock_page(page))
-				return ret;
+				return false;
 
 			mapping = page_mapping(page);
 			migrate_dirty = !mapping || mapping->a_ops->migratepage;
 			unlock_page(page);
 			if (!migrate_dirty)
-				return ret;
+				return false;
 		}
 	}
 
 	if ((mode & ISOLATE_UNMAPPED) && page_mapped(page))
-		return ret;
+		return false;
 
-	return 0;
+	return true;
 }
 
 /*
@@ -1674,35 +1672,31 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
 		 * only when the page is being freed somewhere else.
 		 */
 		scan += nr_pages;
-		switch (__isolate_lru_page_prepare(page, mode)) {
-		case 0:
-			/*
-			 * Be careful not to clear PageLRU until after we're
-			 * sure the page is not being freed elsewhere -- the
-			 * page release code relies on it.
-			 */
-			if (unlikely(!get_page_unless_zero(page)))
-				goto busy;
-
-			if (!TestClearPageLRU(page)) {
-				/*
-				 * This page may in other isolation path,
-				 * but we still hold lru_lock.
-				 */
-				put_page(page);
-				goto busy;
-			}
-
-			nr_taken += nr_pages;
-			nr_zone_taken[page_zonenum(page)] += nr_pages;
-			list_move(&page->lru, dst);
-			break;
+		if (!__isolate_lru_page_prepare(page, mode)) {
+			/* It is being freed elsewhere */
+			list_move(&page->lru, src);
+			continue;
+		}
+		/*
+		 * Be careful not to clear PageLRU until after we're
+		 * sure the page is not being freed elsewhere -- the
+		 * page release code relies on it.
+		 */
+		if (unlikely(!get_page_unless_zero(page))) {
+			list_move(&page->lru, src);
+			continue;
+		}
 
-		default:
-busy:
-			/* else it is being freed elsewhere */
+		if (!TestClearPageLRU(page)) {
+			/* Another thread is already isolating this page */
+			put_page(page);
 			list_move(&page->lru, src);
+			continue;
 		}
+
+		nr_taken += nr_pages;
+		nr_zone_taken[page_zonenum(page)] += nr_pages;
+		list_move(&page->lru, dst);
 	}
 
 	/*
Vlastimil Babka Nov. 24, 2020, 11:21 a.m. UTC | #5
On 11/22/20 3:00 PM, Alex Shi wrote:
> Thanks a lot for all comments, I picked all up and here is the v3:
> 
>  From 167131dd106a96fd08af725df850e0da6ec899af Mon Sep 17 00:00:00 2001
> From: Alex Shi <alex.shi@linux.alibaba.com>
> Date: Fri, 20 Nov 2020 14:49:16 +0800
> Subject: [PATCH v3 next] mm/vmscan: __isolate_lru_page_prepare clean up
> 
> The function just return 2 results, so use a 'switch' to deal with its
> result is unnecessary, and simplify it to a bool func as Vlastimil
> suggested.
> 
> Also remove 'goto' by reusing list_move(), and take Matthew Wilcox's
> suggestion to update comments in function.

I wouldn't mind if the goto stayed, but it's not repeating that much 
without it (list_move() + continue, 3 times) so...

Acked-by: Vlastimil Babka <vbabka@suse.cz>

> Signed-off-by: Alex Shi <alex.shi@linux.alibaba.com>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Matthew Wilcox <willy@infradead.org>
> Cc: Hugh Dickins <hughd@google.com>
> Cc: Yu Zhao <yuzhao@google.com>
> Cc: Vlastimil Babka <vbabka@suse.cz>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: linux-mm@kvack.org
> Cc: linux-kernel@vger.kernel.org
> ---
>   include/linux/swap.h |  2 +-
>   mm/compaction.c      |  2 +-
>   mm/vmscan.c          | 68 ++++++++++++++++++++------------------------
>   3 files changed, 33 insertions(+), 39 deletions(-)
> 
> diff --git a/include/linux/swap.h b/include/linux/swap.h
> index 596bc2f4d9b0..5bba15ac5a2e 100644
> --- a/include/linux/swap.h
> +++ b/include/linux/swap.h
> @@ -356,7 +356,7 @@ extern void lru_cache_add_inactive_or_unevictable(struct page *page,
>   extern unsigned long zone_reclaimable_pages(struct zone *zone);
>   extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
>   					gfp_t gfp_mask, nodemask_t *mask);
> -extern int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode);
> +extern bool __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode);
>   extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
>   						  unsigned long nr_pages,
>   						  gfp_t gfp_mask,
> diff --git a/mm/compaction.c b/mm/compaction.c
> index b68931854253..8d71ffebe6cb 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -988,7 +988,7 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
>   		if (unlikely(!get_page_unless_zero(page)))
>   			goto isolate_fail;
>   
> -		if (__isolate_lru_page_prepare(page, isolate_mode) != 0)
> +		if (!__isolate_lru_page_prepare(page, isolate_mode))
>   			goto isolate_fail_put;
>   
>   		/* Try isolate the page */
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index c6f94e55c3fe..4d2703c43310 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -1536,19 +1536,17 @@ unsigned int reclaim_clean_pages_from_list(struct zone *zone,
>    * page:	page to consider
>    * mode:	one of the LRU isolation modes defined above
>    *
> - * returns 0 on success, -ve errno on failure.
> + * returns true on success, false on failure.
>    */
> -int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
> +bool __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
>   {
> -	int ret = -EBUSY;
> -
>   	/* Only take pages on the LRU. */
>   	if (!PageLRU(page))
> -		return ret;
> +		return false;
>   
>   	/* Compaction should not handle unevictable pages but CMA can do so */
>   	if (PageUnevictable(page) && !(mode & ISOLATE_UNEVICTABLE))
> -		return ret;
> +		return false;
>   
>   	/*
>   	 * To minimise LRU disruption, the caller can indicate that it only
> @@ -1561,7 +1559,7 @@ int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
>   	if (mode & ISOLATE_ASYNC_MIGRATE) {
>   		/* All the caller can do on PageWriteback is block */
>   		if (PageWriteback(page))
> -			return ret;
> +			return false;
>   
>   		if (PageDirty(page)) {
>   			struct address_space *mapping;
> @@ -1577,20 +1575,20 @@ int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
>   			 * from the page cache.
>   			 */
>   			if (!trylock_page(page))
> -				return ret;
> +				return false;
>   
>   			mapping = page_mapping(page);
>   			migrate_dirty = !mapping || mapping->a_ops->migratepage;
>   			unlock_page(page);
>   			if (!migrate_dirty)
> -				return ret;
> +				return false;
>   		}
>   	}
>   
>   	if ((mode & ISOLATE_UNMAPPED) && page_mapped(page))
> -		return ret;
> +		return false;
>   
> -	return 0;
> +	return true;
>   }
>   
>   /*
> @@ -1674,35 +1672,31 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
>   		 * only when the page is being freed somewhere else.
>   		 */
>   		scan += nr_pages;
> -		switch (__isolate_lru_page_prepare(page, mode)) {
> -		case 0:
> -			/*
> -			 * Be careful not to clear PageLRU until after we're
> -			 * sure the page is not being freed elsewhere -- the
> -			 * page release code relies on it.
> -			 */
> -			if (unlikely(!get_page_unless_zero(page)))
> -				goto busy;
> -
> -			if (!TestClearPageLRU(page)) {
> -				/*
> -				 * This page may in other isolation path,
> -				 * but we still hold lru_lock.
> -				 */
> -				put_page(page);
> -				goto busy;
> -			}
> -
> -			nr_taken += nr_pages;
> -			nr_zone_taken[page_zonenum(page)] += nr_pages;
> -			list_move(&page->lru, dst);
> -			break;
> +		if (!__isolate_lru_page_prepare(page, mode)) {
> +			/* It is being freed elsewhere */
> +			list_move(&page->lru, src);
> +			continue;
> +		}
> +		/*
> +		 * Be careful not to clear PageLRU until after we're
> +		 * sure the page is not being freed elsewhere -- the
> +		 * page release code relies on it.
> +		 */
> +		if (unlikely(!get_page_unless_zero(page))) {
> +			list_move(&page->lru, src);
> +			continue;
> +		}
>   
> -		default:
> -busy:
> -			/* else it is being freed elsewhere */
> +		if (!TestClearPageLRU(page)) {
> +			/* Another thread is already isolating this page */
> +			put_page(page);
>   			list_move(&page->lru, src);
> +			continue;
>   		}
> +
> +		nr_taken += nr_pages;
> +		nr_zone_taken[page_zonenum(page)] += nr_pages;
> +		list_move(&page->lru, dst);
>   	}
>   
>   	/*
>
Andrew Morton Nov. 25, 2020, 11:43 p.m. UTC | #6
On Tue, 24 Nov 2020 12:21:28 +0100 Vlastimil Babka <vbabka@suse.cz> wrote:

> On 11/22/20 3:00 PM, Alex Shi wrote:
> > Thanks a lot for all comments, I picked all up and here is the v3:
> > 
> >  From 167131dd106a96fd08af725df850e0da6ec899af Mon Sep 17 00:00:00 2001
> > From: Alex Shi <alex.shi@linux.alibaba.com>
> > Date: Fri, 20 Nov 2020 14:49:16 +0800
> > Subject: [PATCH v3 next] mm/vmscan: __isolate_lru_page_prepare clean up
> > 
> > The function just return 2 results, so use a 'switch' to deal with its
> > result is unnecessary, and simplify it to a bool func as Vlastimil
> > suggested.
> > 
> > Also remove 'goto' by reusing list_move(), and take Matthew Wilcox's
> > suggestion to update comments in function.
> 
> I wouldn't mind if the goto stayed, but it's not repeating that much 
> without it (list_move() + continue, 3 times) so...

I tried that, and .text became significantly larger, for reasons which
I didn't investigate ;)
Alex Shi Nov. 26, 2020, 2:25 a.m. UTC | #7
在 2020/11/26 上午7:43, Andrew Morton 写道:
> On Tue, 24 Nov 2020 12:21:28 +0100 Vlastimil Babka <vbabka@suse.cz> wrote:
> 
>> On 11/22/20 3:00 PM, Alex Shi wrote:
>>> Thanks a lot for all comments, I picked all up and here is the v3:
>>>
>>>  From 167131dd106a96fd08af725df850e0da6ec899af Mon Sep 17 00:00:00 2001
>>> From: Alex Shi <alex.shi@linux.alibaba.com>
>>> Date: Fri, 20 Nov 2020 14:49:16 +0800
>>> Subject: [PATCH v3 next] mm/vmscan: __isolate_lru_page_prepare clean up
>>>
>>> The function just return 2 results, so use a 'switch' to deal with its
>>> result is unnecessary, and simplify it to a bool func as Vlastimil
>>> suggested.
>>>
>>> Also remove 'goto' by reusing list_move(), and take Matthew Wilcox's
>>> suggestion to update comments in function.
>>
>> I wouldn't mind if the goto stayed, but it's not repeating that much 
>> without it (list_move() + continue, 3 times) so...
> 
> I tried that, and .text became significantly larger, for reasons which
> I didn't investigate ;)
> 


Uh, BTW, with the gcc 8.3.1 and centos 7, goto or continue version has same size
on my side with or w/o DEBUG_LIST. But actually, this clean up patch could
add 10 bytes also with or w/o DEDBUG_LIST.

Maybe related with different compiler?

Thanks
Alex
Vlastimil Babka Nov. 26, 2020, 3:23 p.m. UTC | #8
On 11/26/20 3:25 AM, Alex Shi wrote:
> 
> 
> 在 2020/11/26 上午7:43, Andrew Morton 写道:
>> On Tue, 24 Nov 2020 12:21:28 +0100 Vlastimil Babka <vbabka@suse.cz> wrote:
>> 
>>> On 11/22/20 3:00 PM, Alex Shi wrote:
>>>> Thanks a lot for all comments, I picked all up and here is the v3:
>>>>
>>>>  From 167131dd106a96fd08af725df850e0da6ec899af Mon Sep 17 00:00:00 2001
>>>> From: Alex Shi <alex.shi@linux.alibaba.com>
>>>> Date: Fri, 20 Nov 2020 14:49:16 +0800
>>>> Subject: [PATCH v3 next] mm/vmscan: __isolate_lru_page_prepare clean up
>>>>
>>>> The function just return 2 results, so use a 'switch' to deal with its
>>>> result is unnecessary, and simplify it to a bool func as Vlastimil
>>>> suggested.
>>>>
>>>> Also remove 'goto' by reusing list_move(), and take Matthew Wilcox's
>>>> suggestion to update comments in function.
>>>
>>> I wouldn't mind if the goto stayed, but it's not repeating that much 
>>> without it (list_move() + continue, 3 times) so...
>> 
>> I tried that, and .text became significantly larger, for reasons which
>> I didn't investigate ;)

I found out that comparing whole .text doesn't often work as changes might be lost in alignment, or
once in a while cross the alignment boundary and become exagerated. bloat-o-meter works nice though.

> Uh, BTW, with the gcc 8.3.1 and centos 7, goto or continue version has same size
> on my side with or w/o DEBUG_LIST. But actually, this clean up patch could
> add 10 bytes also with or w/o DEDBUG_LIST.
> 
> Maybe related with different compiler?

gcc (SUSE Linux) 10.2.1 20201117 [revision 98ba03ffe0b9f37b4916ce6238fad754e00d720b]

./scripts/bloat-o-meter vmscan.o.before mm/vmscan.o
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-1 (-1)
Function                                     old     new   delta
isolate_lru_pages                           1125    1124      -1
Total: Before=57283, After=57282, chg -0.00%

Not surprising, as I'd expect the compiler to figure out by itself that list_move + continue
repeats and can be unified.  The reason for goto to stay would be rather readability (subjective).

> Thanks
> Alex
>
Alex Shi Nov. 27, 2020, 1:56 a.m. UTC | #9
在 2020/11/26 下午11:23, Vlastimil Babka 写道:
>>>
>>> I tried that, and .text became significantly larger, for reasons which
>>> I didn't investigate ;)
> 
> I found out that comparing whole .text doesn't often work as changes might be lost in alignment, or
> once in a while cross the alignment boundary and become exagerated. bloat-o-meter works nice though.
> 
>> Uh, BTW, with the gcc 8.3.1 and centos 7, goto or continue version has same size
>> on my side with or w/o DEBUG_LIST. But actually, this clean up patch could
>> add 10 bytes also with or w/o DEDBUG_LIST.
>>
>> Maybe related with different compiler?
> 
> gcc (SUSE Linux) 10.2.1 20201117 [revision 98ba03ffe0b9f37b4916ce6238fad754e00d720b]
> 
> ./scripts/bloat-o-meter vmscan.o.before mm/vmscan.o
> add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-1 (-1)
> Function                                     old     new   delta
> isolate_lru_pages                           1125    1124      -1
> Total: Before=57283, After=57282, chg -0.00%
> 
> Not surprising, as I'd expect the compiler to figure out by itself that list_move + continue
> repeats and can be unified.  The reason for goto to stay would be rather readability (subjective).

Hi Vlastimil,

Thanks for tool sharing! The gcc do give different.

My data is read from 'size' tool and isolate_lru_pages text size from 'objdump -d'. Maybe a
same way like bloat-o-meter. :)

Thanks
Alex
diff mbox series

Patch

diff --git a/mm/compaction.c b/mm/compaction.c
index b68931854253..8d71ffebe6cb 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -988,7 +988,7 @@  isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
 		if (unlikely(!get_page_unless_zero(page)))
 			goto isolate_fail;
 
-		if (__isolate_lru_page_prepare(page, isolate_mode) != 0)
+		if (!__isolate_lru_page_prepare(page, isolate_mode))
 			goto isolate_fail_put;
 
 		/* Try isolate the page */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index c6f94e55c3fe..7f32c1979804 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1540,7 +1540,7 @@  unsigned int reclaim_clean_pages_from_list(struct zone *zone,
  */
 int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
 {
-	int ret = -EBUSY;
+	int ret = false;
 
 	/* Only take pages on the LRU. */
 	if (!PageLRU(page))
@@ -1590,7 +1590,7 @@  int __isolate_lru_page_prepare(struct page *page, isolate_mode_t mode)
 	if ((mode & ISOLATE_UNMAPPED) && page_mapped(page))
 		return ret;
 
-	return 0;
+	return true;
 }
 
 /*
@@ -1674,35 +1674,34 @@  static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
 		 * only when the page is being freed somewhere else.
 		 */
 		scan += nr_pages;
-		switch (__isolate_lru_page_prepare(page, mode)) {
-		case 0:
+		if (!__isolate_lru_page_prepare(page, mode)) {
+			/* else it is being freed elsewhere */
+			list_move(&page->lru, src);
+			continue;
+		}
+		/*
+		 * Be careful not to clear PageLRU until after we're
+		 * sure the page is not being freed elsewhere -- the
+		 * page release code relies on it.
+		 */
+		if (unlikely(!get_page_unless_zero(page))) {
+			list_move(&page->lru, src);
+			continue;
+		}
+
+		if (!TestClearPageLRU(page)) {
 			/*
-			 * Be careful not to clear PageLRU until after we're
-			 * sure the page is not being freed elsewhere -- the
-			 * page release code relies on it.
+			 * This page may in other isolation path,
+			 * but we still hold lru_lock.
 			 */
-			if (unlikely(!get_page_unless_zero(page)))
-				goto busy;
-
-			if (!TestClearPageLRU(page)) {
-				/*
-				 * This page may in other isolation path,
-				 * but we still hold lru_lock.
-				 */
-				put_page(page);
-				goto busy;
-			}
-
-			nr_taken += nr_pages;
-			nr_zone_taken[page_zonenum(page)] += nr_pages;
-			list_move(&page->lru, dst);
-			break;
-
-		default:
-busy:
-			/* else it is being freed elsewhere */
+			put_page(page);
 			list_move(&page->lru, src);
+			continue;
 		}
+
+		nr_taken += nr_pages;
+		nr_zone_taken[page_zonenum(page)] += nr_pages;
+		list_move(&page->lru, dst);
 	}
 
 	/*