@@ -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,14 @@ 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);
+ rcu_read_lock();
+ 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 +1020,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 +1053,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 +1069,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 +1098,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);