diff --git a/mm/coldpgs.c b/mm/coldpgs.c index 8793f385e0274302a1a88787d7dcd8b2aad9dc44..9d98739c6ceffde508988bdbffadffbe6ef759e8 100644 --- a/mm/coldpgs.c +++ b/mm/coldpgs.c @@ -925,7 +925,33 @@ static unsigned long reclaim_coldpgs_from_list(struct mem_cgroup *memcg, #ifdef CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH my_try_to_unmap_flush(); #endif - my_free_unref_page_list(&free_pages); + + if (filter->batch) { + /* Free pages in batch */ + LIST_HEAD(batch_free_pages); + + batch = 0; + + while (!list_empty(&free_pages)) { + page = lru_to_page(&free_pages); + list_move(&page->lru, &batch_free_pages); + + if (++batch >= filter->batch) { + my_free_unref_page_list(&batch_free_pages); + + cond_resched(); + batch = 0; + INIT_LIST_HEAD(&batch_free_pages); + } + } + + /* Don't forget the remaining pages */ + if (!list_empty(&batch_free_pages)) + my_free_unref_page_list(&batch_free_pages); + } else { + /* Free pages in one shot */ + my_free_unref_page_list(&free_pages); + } /* Put all pages back to the list */ list_splice(&keep_pages, list); @@ -1453,6 +1479,9 @@ static int reclaim_coldpgs_read_stats(struct seq_file *m, void *v) */ for (i = 0; i < RECLAIM_COLDPGS_STAT_MAX; i++) total->counts[i] += stats->counts[i]; + + /* Avoid taking up CPU too long time. */ + cond_resched(); } for (i = 0; i < RECLAIM_COLDPGS_STAT_MAX; i++) {