Skip to content

Commit

Permalink
mm: make lru_add_drain_all() selective
Browse files Browse the repository at this point in the history
make lru_add_drain_all() only selectively interrupt the cpus that have
per-cpu free pages that can be drained.

This is important in nohz mode where calling mlockall(), for example,
otherwise will interrupt every core unnecessarily.

This is important on workloads where nohz cores are handling 10 Gb traffic
in userspace.  Those CPUs do not enter the kernel and place pages into LRU
pagevecs and they really, really don't want to be interrupted, or they
drop packets on the floor.

Signed-off-by: Chris Metcalf <[email protected]>
Reviewed-by: Tejun Heo <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
cmetcalf-tilera authored and torvalds committed Sep 12, 2013
1 parent 9cb2dc1 commit 5fbc461
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
2 changes: 1 addition & 1 deletion include/linux/swap.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ extern void activate_page(struct page *);
extern void mark_page_accessed(struct page *);
extern void lru_add_drain(void);
extern void lru_add_drain_cpu(int cpu);
extern int lru_add_drain_all(void);
extern void lru_add_drain_all(void);
extern void rotate_reclaimable_page(struct page *page);
extern void deactivate_page(struct page *page);
extern void swap_setup(void);
Expand Down
44 changes: 39 additions & 5 deletions mm/swap.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,11 @@ static void activate_page_drain(int cpu)
pagevec_lru_move_fn(pvec, __activate_page, NULL);
}

static bool need_activate_page_drain(int cpu)
{
return pagevec_count(&per_cpu(activate_page_pvecs, cpu)) != 0;
}

void activate_page(struct page *page)
{
if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
Expand All @@ -449,6 +454,11 @@ static inline void activate_page_drain(int cpu)
{
}

static bool need_activate_page_drain(int cpu)
{
return false;
}

void activate_page(struct page *page)
{
struct zone *zone = page_zone(page);
Expand Down Expand Up @@ -701,12 +711,36 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
lru_add_drain();
}

/*
* Returns 0 for success
*/
int lru_add_drain_all(void)
static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);

void lru_add_drain_all(void)
{
return schedule_on_each_cpu(lru_add_drain_per_cpu);
static DEFINE_MUTEX(lock);
static struct cpumask has_work;
int cpu;

mutex_lock(&lock);
get_online_cpus();
cpumask_clear(&has_work);

for_each_online_cpu(cpu) {
struct work_struct *work = &per_cpu(lru_add_drain_work, cpu);

if (pagevec_count(&per_cpu(lru_add_pvec, cpu)) ||
pagevec_count(&per_cpu(lru_rotate_pvecs, cpu)) ||
pagevec_count(&per_cpu(lru_deactivate_pvecs, cpu)) ||
need_activate_page_drain(cpu)) {
INIT_WORK(work, lru_add_drain_per_cpu);
schedule_work_on(cpu, work);
cpumask_set_cpu(cpu, &has_work);
}
}

for_each_cpu(cpu, &has_work)
flush_work(&per_cpu(lru_add_drain_work, cpu));

put_online_cpus();
mutex_unlock(&lock);
}

/*
Expand Down

0 comments on commit 5fbc461

Please sign in to comment.