diff options
Diffstat (limited to 'include/linux/memcontrol.h')
| -rw-r--r-- | include/linux/memcontrol.h | 175 | 
1 files changed, 78 insertions, 97 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index dbb6118370c1..1dcb763bb610 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */  /* memcontrol.h - Memory Controller   *   * Copyright IBM Corporation, 2007 @@ -5,16 +6,6 @@   *   * Copyright 2007 OpenVZ SWsoft Inc   * Author: Pavel Emelianov <[email protected]> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details.   */  #ifndef _LINUX_MEMCONTROL_H @@ -94,8 +85,8 @@ enum mem_cgroup_events_target {  	MEM_CGROUP_NTARGETS,  }; -struct mem_cgroup_stat_cpu { -	long count[MEMCG_NR_STAT]; +struct memcg_vmstats_percpu { +	long stat[MEMCG_NR_STAT];  	unsigned long events[NR_VM_EVENT_ITEMS];  	unsigned long nr_page_events;  	unsigned long targets[MEM_CGROUP_NTARGETS]; @@ -126,6 +117,10 @@ struct memcg_shrinker_map {  struct mem_cgroup_per_node {  	struct lruvec		lruvec; +	/* Legacy local VM stats */ +	struct lruvec_stat __percpu *lruvec_stat_local; + +	/* Subtree VM stats (batched updates) */  	struct lruvec_stat __percpu *lruvec_stat_cpu;  	atomic_long_t		lruvec_stat[NR_VM_NODE_STAT_ITEMS]; @@ -273,14 +268,19 @@ struct mem_cgroup {  	atomic_t		moving_account;  	struct task_struct	*move_lock_task; -	/* memory.stat */ -	struct mem_cgroup_stat_cpu __percpu *stat_cpu; +	/* Legacy local VM stats and events */ +	struct memcg_vmstats_percpu __percpu *vmstats_local; + +	/* Subtree VM stats and events (batched updates) */ +	struct memcg_vmstats_percpu __percpu *vmstats_percpu;  	MEMCG_PADDING(_pad2_); -	atomic_long_t		stat[MEMCG_NR_STAT]; -	atomic_long_t		events[NR_VM_EVENT_ITEMS]; -	atomic_long_t memory_events[MEMCG_NR_MEMORY_EVENTS]; +	atomic_long_t		vmstats[MEMCG_NR_STAT]; +	atomic_long_t		vmevents[NR_VM_EVENT_ITEMS]; + +	/* memory.events */ +	atomic_long_t		memory_events[MEMCG_NR_MEMORY_EVENTS];  	unsigned long		socket_pressure; @@ -501,22 +501,6 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);  void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,  		int zid, int nr_pages); -unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg, -					   int nid, unsigned int lru_mask); - -static inline -unsigned long mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru) -{ -	struct mem_cgroup_per_node *mz; -	unsigned long nr_pages = 0; -	int zid; - -	mz = container_of(lruvec, struct mem_cgroup_per_node, lruvec); -	for (zid = 0; zid < MAX_NR_ZONES; zid++) -		nr_pages += mz->lru_zone_size[zid][lru]; -	return nr_pages; -} -  static inline  unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,  		enum lru_list lru, int zone_idx) @@ -570,10 +554,9 @@ void unlock_page_memcg(struct page *page);   * idx can be of type enum memcg_stat_item or node_stat_item.   * Keep in sync with memcg_exact_page_state().   */ -static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, -					     int idx) +static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)  { -	long x = atomic_long_read(&memcg->stat[idx]); +	long x = atomic_long_read(&memcg->vmstats[idx]);  #ifdef CONFIG_SMP  	if (x < 0)  		x = 0; @@ -581,23 +564,27 @@ static inline unsigned long memcg_page_state(struct mem_cgroup *memcg,  	return x;  } -/* idx can be of type enum memcg_stat_item or node_stat_item */ -static inline void __mod_memcg_state(struct mem_cgroup *memcg, -				     int idx, int val) +/* + * idx can be of type enum memcg_stat_item or node_stat_item. + * Keep in sync with memcg_exact_page_state(). + */ +static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg, +						   int idx)  { -	long x; +	long x = 0; +	int cpu; -	if (mem_cgroup_disabled()) -		return; - -	x = val + __this_cpu_read(memcg->stat_cpu->count[idx]); -	if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) { -		atomic_long_add(x, &memcg->stat[idx]); +	for_each_possible_cpu(cpu) +		x += per_cpu(memcg->vmstats_local->stat[idx], cpu); +#ifdef CONFIG_SMP +	if (x < 0)  		x = 0; -	} -	__this_cpu_write(memcg->stat_cpu->count[idx], x); +#endif +	return x;  } +void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val); +  /* idx can be of type enum memcg_stat_item or node_stat_item */  static inline void mod_memcg_state(struct mem_cgroup *memcg,  				   int idx, int val) @@ -658,32 +645,29 @@ static inline unsigned long lruvec_page_state(struct lruvec *lruvec,  	return x;  } -static inline void __mod_lruvec_state(struct lruvec *lruvec, -				      enum node_stat_item idx, int val) +static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, +						    enum node_stat_item idx)  {  	struct mem_cgroup_per_node *pn; -	long x; - -	/* Update node */ -	__mod_node_page_state(lruvec_pgdat(lruvec), idx, val); +	long x = 0; +	int cpu;  	if (mem_cgroup_disabled()) -		return; +		return node_page_state(lruvec_pgdat(lruvec), idx);  	pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec); - -	/* Update memcg */ -	__mod_memcg_state(pn->memcg, idx, val); - -	/* Update lruvec */ -	x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]); -	if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) { -		atomic_long_add(x, &pn->lruvec_stat[idx]); +	for_each_possible_cpu(cpu) +		x += per_cpu(pn->lruvec_stat_local->count[idx], cpu); +#ifdef CONFIG_SMP +	if (x < 0)  		x = 0; -	} -	__this_cpu_write(pn->lruvec_stat_cpu->count[idx], x); +#endif +	return x;  } +void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, +			int val); +  static inline void mod_lruvec_state(struct lruvec *lruvec,  				    enum node_stat_item idx, int val)  { @@ -724,22 +708,8 @@ unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,  						gfp_t gfp_mask,  						unsigned long *total_scanned); -static inline void __count_memcg_events(struct mem_cgroup *memcg, -					enum vm_event_item idx, -					unsigned long count) -{ -	unsigned long x; - -	if (mem_cgroup_disabled()) -		return; - -	x = count + __this_cpu_read(memcg->stat_cpu->events[idx]); -	if (unlikely(x > MEMCG_CHARGE_BATCH)) { -		atomic_long_add(x, &memcg->events[idx]); -		x = 0; -	} -	__this_cpu_write(memcg->stat_cpu->events[idx], x); -} +void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx, +			  unsigned long count);  static inline void count_memcg_events(struct mem_cgroup *memcg,  				      enum vm_event_item idx, @@ -777,8 +747,14 @@ static inline void count_memcg_event_mm(struct mm_struct *mm,  static inline void memcg_memory_event(struct mem_cgroup *memcg,  				      enum memcg_memory_event event)  { -	atomic_long_inc(&memcg->memory_events[event]); -	cgroup_file_notify(&memcg->events_file); +	do { +		atomic_long_inc(&memcg->memory_events[event]); +		cgroup_file_notify(&memcg->events_file); + +		if (cgrp_dfl_root.flags & CGRP_ROOT_MEMORY_LOCAL_EVENTS) +			break; +	} while ((memcg = parent_mem_cgroup(memcg)) && +		 !mem_cgroup_is_root(memcg));  }  static inline void memcg_memory_event_mm(struct mm_struct *mm, @@ -960,11 +936,6 @@ static inline bool mem_cgroup_online(struct mem_cgroup *memcg)  	return true;  } -static inline unsigned long -mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru) -{ -	return 0; -}  static inline  unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,  		enum lru_list lru, int zone_idx) @@ -972,13 +943,6 @@ unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,  	return 0;  } -static inline unsigned long -mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg, -			     int nid, unsigned int lru_mask) -{ -	return 0; -} -  static inline unsigned long mem_cgroup_get_max(struct mem_cgroup *memcg)  {  	return 0; @@ -1039,8 +1003,13 @@ static inline void mem_cgroup_print_oom_group(struct mem_cgroup *memcg)  {  } -static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, -					     int idx) +static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx) +{ +	return 0; +} + +static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg, +						   int idx)  {  	return 0;  } @@ -1075,6 +1044,12 @@ static inline unsigned long lruvec_page_state(struct lruvec *lruvec,  	return node_page_state(lruvec_pgdat(lruvec), idx);  } +static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, +						    enum node_stat_item idx) +{ +	return node_page_state(lruvec_pgdat(lruvec), idx); +} +  static inline void __mod_lruvec_state(struct lruvec *lruvec,  				      enum node_stat_item idx, int val)  { @@ -1117,6 +1092,12 @@ static inline void count_memcg_events(struct mem_cgroup *memcg,  {  } +static inline void __count_memcg_events(struct mem_cgroup *memcg, +					enum vm_event_item idx, +					unsigned long count) +{ +} +  static inline void count_memcg_page_event(struct page *page,  					  int idx)  {  |