Skip to content

Commit d9367bd

Browse files
RichardWeiYangtorvalds
authored andcommitted
mm, page_alloc: enable pcpu_drain with zone capability
drain_all_pages is documented to drain per-cpu pages for a given zone (if non-NULL). The current implementation doesn't match the description though. It will drain all pcp pages for all zones that happen to have cached pages on the same cpu as the given zone. This will lead to premature pcp cache draining for zones that are not of any interest to the caller - e.g. compaction, hwpoison or memory offline. This forces the page allocator to take locks and potential lock contention as a result. There is no real reason for this sub-optimal implementation. Replace per-cpu work item with a dedicated structure which contains a pointer to the zone and pass it over to the worker. This will get the zone information all the way down to the worker function and do the right job. [akpm@linux-foundation.org: avoid 80-col tricks] [mhocko@suse.com: refactor the whole changelog] Link: http://lkml.kernel.org/r/20181212142550.61686-1-richard.weiyang@gmail.com Signed-off-by: Wei Yang <richard.weiyang@gmail.com> Acked-by: Michal Hocko <mhocko@suse.com> Reviewed-by: Oscar Salvador <osalvador@suse.de> Reviewed-by: David Hildenbrand <david@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent d53ce04 commit d9367bd

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

mm/page_alloc.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,12 @@ int _node_numa_mem_[MAX_NUMNODES];
9797
#endif
9898

9999
/* work_structs for global per-cpu drains */
100+
struct pcpu_drain {
101+
struct zone *zone;
102+
struct work_struct work;
103+
};
100104
DEFINE_MUTEX(pcpu_drain_mutex);
101-
DEFINE_PER_CPU(struct work_struct, pcpu_drain);
105+
DEFINE_PER_CPU(struct pcpu_drain, pcpu_drain);
102106

103107
#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
104108
volatile unsigned long latent_entropy __latent_entropy;
@@ -2658,6 +2662,10 @@ void drain_local_pages(struct zone *zone)
26582662

26592663
static void drain_local_pages_wq(struct work_struct *work)
26602664
{
2665+
struct pcpu_drain *drain;
2666+
2667+
drain = container_of(work, struct pcpu_drain, work);
2668+
26612669
/*
26622670
* drain_all_pages doesn't use proper cpu hotplug protection so
26632671
* we can race with cpu offline when the WQ can move this from
@@ -2666,7 +2674,7 @@ static void drain_local_pages_wq(struct work_struct *work)
26662674
* a different one.
26672675
*/
26682676
preempt_disable();
2669-
drain_local_pages(NULL);
2677+
drain_local_pages(drain->zone);
26702678
preempt_enable();
26712679
}
26722680

@@ -2737,12 +2745,14 @@ void drain_all_pages(struct zone *zone)
27372745
}
27382746

27392747
for_each_cpu(cpu, &cpus_with_pcps) {
2740-
struct work_struct *work = per_cpu_ptr(&pcpu_drain, cpu);
2741-
INIT_WORK(work, drain_local_pages_wq);
2742-
queue_work_on(cpu, mm_percpu_wq, work);
2748+
struct pcpu_drain *drain = per_cpu_ptr(&pcpu_drain, cpu);
2749+
2750+
drain->zone = zone;
2751+
INIT_WORK(&drain->work, drain_local_pages_wq);
2752+
queue_work_on(cpu, mm_percpu_wq, &drain->work);
27432753
}
27442754
for_each_cpu(cpu, &cpus_with_pcps)
2745-
flush_work(per_cpu_ptr(&pcpu_drain, cpu));
2755+
flush_work(&per_cpu_ptr(&pcpu_drain, cpu)->work);
27462756

27472757
mutex_unlock(&pcpu_drain_mutex);
27482758
}

0 commit comments

Comments
 (0)