diff options
Diffstat (limited to 'include/linux/memcontrol.h')
| -rw-r--r-- | include/linux/memcontrol.h | 58 | 
1 files changed, 58 insertions, 0 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 44c41462be33..ad8f1a397ae4 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -184,6 +184,23 @@ struct memcg_padding {  #endif  /* + * Remember four most recent foreign writebacks with dirty pages in this + * cgroup.  Inode sharing is expected to be uncommon and, even if we miss + * one in a given round, we're likely to catch it later if it keeps + * foreign-dirtying, so a fairly low count should be enough. + * + * See mem_cgroup_track_foreign_dirty_slowpath() for details. + */ +#define MEMCG_CGWB_FRN_CNT	4 + +struct memcg_cgwb_frn { +	u64 bdi_id;			/* bdi->id of the foreign inode */ +	int memcg_id;			/* memcg->css.id of foreign inode */ +	u64 at;				/* jiffies_64 at the time of dirtying */ +	struct wb_completion done;	/* tracks in-flight foreign writebacks */ +}; + +/*   * The memory controller data structure. The memory controller controls both   * page cache and RSS per cgroup. We would eventually like to provide   * statistics based on the statistics developed by Rik Van Riel for clock-pro, @@ -307,6 +324,7 @@ struct mem_cgroup {  #ifdef CONFIG_CGROUP_WRITEBACK  	struct list_head cgwb_list;  	struct wb_domain cgwb_domain; +	struct memcg_cgwb_frn cgwb_frn[MEMCG_CGWB_FRN_CNT];  #endif  	/* List of events which userspace want to receive */ @@ -668,6 +686,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,  void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,  			int val); +void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val);  static inline void mod_lruvec_state(struct lruvec *lruvec,  				    enum node_stat_item idx, int val) @@ -1072,6 +1091,14 @@ static inline void mod_lruvec_page_state(struct page *page,  	mod_node_page_state(page_pgdat(page), idx, val);  } +static inline void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, +					   int val) +{ +	struct page *page = virt_to_head_page(p); + +	__mod_node_page_state(page_pgdat(page), idx, val); +} +  static inline  unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,  					    gfp_t gfp_mask, @@ -1159,6 +1186,16 @@ static inline void __dec_lruvec_page_state(struct page *page,  	__mod_lruvec_page_state(page, idx, -1);  } +static inline void __inc_lruvec_slab_state(void *p, enum node_stat_item idx) +{ +	__mod_lruvec_slab_state(p, idx, 1); +} + +static inline void __dec_lruvec_slab_state(void *p, enum node_stat_item idx) +{ +	__mod_lruvec_slab_state(p, idx, -1); +} +  /* idx can be of type enum memcg_stat_item or node_stat_item */  static inline void inc_memcg_state(struct mem_cgroup *memcg,  				   int idx) @@ -1218,6 +1255,18 @@ void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,  			 unsigned long *pheadroom, unsigned long *pdirty,  			 unsigned long *pwriteback); +void mem_cgroup_track_foreign_dirty_slowpath(struct page *page, +					     struct bdi_writeback *wb); + +static inline void mem_cgroup_track_foreign_dirty(struct page *page, +						  struct bdi_writeback *wb) +{ +	if (unlikely(&page->mem_cgroup->css != wb->memcg_css)) +		mem_cgroup_track_foreign_dirty_slowpath(page, wb); +} + +void mem_cgroup_flush_foreign(struct bdi_writeback *wb); +  #else	/* CONFIG_CGROUP_WRITEBACK */  static inline struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb) @@ -1233,6 +1282,15 @@ static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,  {  } +static inline void mem_cgroup_track_foreign_dirty(struct page *page, +						  struct bdi_writeback *wb) +{ +} + +static inline void mem_cgroup_flush_foreign(struct bdi_writeback *wb) +{ +} +  #endif	/* CONFIG_CGROUP_WRITEBACK */  struct sock;  |