[RFC PATCH 1/3] mm: Drop locked from isolate_migratepages_block

From: Alexander Duyck
Date: Thu Aug 13 2020 - 00:02:40 EST


From: Alexander Duyck <alexander.h.duyck@xxxxxxxxxxxxxxx>

We can drop the need for the locked variable by making use of the
lruvec_holds_page_lru_lock function. By doing this we can avoid some rcu
locking ugliness for the case where the lruvec is still holding the LRU
lock associated with the page. Instead we can just use the lruvec and if it
is NULL we assume the lock was released.

Signed-off-by: Alexander Duyck <alexander.h.duyck@xxxxxxxxxxxxxxx>
---
mm/compaction.c | 45 ++++++++++++++++++++-------------------------
1 file changed, 20 insertions(+), 25 deletions(-)

diff --git a/mm/compaction.c b/mm/compaction.c
index b99c96c4862d..5021a18ef722 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -803,9 +803,8 @@ static bool too_many_isolated(pg_data_t *pgdat)
{
pg_data_t *pgdat = cc->zone->zone_pgdat;
unsigned long nr_scanned = 0, nr_isolated = 0;
- struct lruvec *lruvec;
+ struct lruvec *lruvec = NULL;
unsigned long flags = 0;
- struct lruvec *locked = NULL;
struct page *page = NULL, *valid_page = NULL;
unsigned long start_pfn = low_pfn;
bool skip_on_failure = false;
@@ -866,9 +865,9 @@ static bool too_many_isolated(pg_data_t *pgdat)
* a fatal signal is pending.
*/
if (!(low_pfn % SWAP_CLUSTER_MAX)) {
- if (locked) {
- unlock_page_lruvec_irqrestore(locked, flags);
- locked = NULL;
+ if (lruvec) {
+ unlock_page_lruvec_irqrestore(lruvec, flags);
+ lruvec = NULL;
}

if (fatal_signal_pending(current)) {
@@ -949,9 +948,9 @@ static bool too_many_isolated(pg_data_t *pgdat)
*/
if (unlikely(__PageMovable(page)) &&
!PageIsolated(page)) {
- if (locked) {
- unlock_page_lruvec_irqrestore(locked, flags);
- locked = NULL;
+ if (lruvec) {
+ unlock_page_lruvec_irqrestore(lruvec, flags);
+ lruvec = NULL;
}

if (!isolate_movable_page(page, isolate_mode))
@@ -992,16 +991,13 @@ static bool too_many_isolated(pg_data_t *pgdat)
if (!TestClearPageLRU(page))
goto isolate_fail_put;

- rcu_read_lock();
- lruvec = mem_cgroup_page_lruvec(page, pgdat);
-
/* If we already hold the lock, we can skip some rechecking */
- if (lruvec != locked) {
- if (locked)
- unlock_page_lruvec_irqrestore(locked, flags);
+ if (!lruvec || !lruvec_holds_page_lru_lock(page, lruvec)) {
+ if (lruvec)
+ unlock_page_lruvec_irqrestore(lruvec, flags);

+ lruvec = mem_cgroup_page_lruvec(page, pgdat);
compact_lock_irqsave(&lruvec->lru_lock, &flags, cc);
- locked = lruvec;
rcu_read_unlock();

lruvec_memcg_debug(lruvec, page);
@@ -1023,8 +1019,7 @@ static bool too_many_isolated(pg_data_t *pgdat)
SetPageLRU(page);
goto isolate_fail_put;
}
- } else
- rcu_read_unlock();
+ }

/* The whole page is taken off the LRU; skip the tail pages. */
if (PageCompound(page))
@@ -1057,9 +1052,9 @@ static bool too_many_isolated(pg_data_t *pgdat)

isolate_fail_put:
/* Avoid potential deadlock in freeing page under lru_lock */
- if (locked) {
- unlock_page_lruvec_irqrestore(locked, flags);
- locked = NULL;
+ if (lruvec) {
+ unlock_page_lruvec_irqrestore(lruvec, flags);
+ lruvec = NULL;
}
put_page(page);

@@ -1073,9 +1068,9 @@ static bool too_many_isolated(pg_data_t *pgdat)
* page anyway.
*/
if (nr_isolated) {
- if (locked) {
- unlock_page_lruvec_irqrestore(locked, flags);
- locked = NULL;
+ if (lruvec) {
+ unlock_page_lruvec_irqrestore(lruvec, flags);
+ lruvec = NULL;
}
putback_movable_pages(&cc->migratepages);
cc->nr_migratepages = 0;
@@ -1102,8 +1097,8 @@ static bool too_many_isolated(pg_data_t *pgdat)
page = NULL;

isolate_abort:
- if (locked)
- unlock_page_lruvec_irqrestore(locked, flags);
+ if (lruvec)
+ unlock_page_lruvec_irqrestore(lruvec, flags);
if (page) {
SetPageLRU(page);
put_page(page);