diff options
Diffstat (limited to 'mm/percpu-internal.h')
| -rw-r--r-- | mm/percpu-internal.h | 55 | 
1 files changed, 54 insertions, 1 deletions
diff --git a/mm/percpu-internal.h b/mm/percpu-internal.h index 0468ba500bd4..18b768ac7dca 100644 --- a/mm/percpu-internal.h +++ b/mm/percpu-internal.h @@ -6,6 +6,25 @@  #include <linux/percpu.h>  /* + * There are two chunk types: root and memcg-aware. + * Chunks of each type have separate slots list. + * + * Memcg-aware chunks have an attached vector of obj_cgroup pointers, which is + * used to store memcg membership data of a percpu object.  Obj_cgroups are + * ref-counted pointers to a memory cgroup with an ability to switch dynamically + * to the parent memory cgroup.  This allows to reclaim a deleted memory cgroup + * without reclaiming of all outstanding objects, which hold a reference at it. + */ +enum pcpu_chunk_type { +	PCPU_CHUNK_ROOT, +#ifdef CONFIG_MEMCG_KMEM +	PCPU_CHUNK_MEMCG, +#endif +	PCPU_NR_CHUNK_TYPES, +	PCPU_FAIL_ALLOC = PCPU_NR_CHUNK_TYPES +}; + +/*   * pcpu_block_md is the metadata block struct.   * Each chunk's bitmap is split into a number of full blocks.   * All units are in terms of bits. @@ -54,6 +73,9 @@ struct pcpu_chunk {  	int			end_offset;	/* additional area required to  						   have the region end page  						   aligned */ +#ifdef CONFIG_MEMCG_KMEM +	struct obj_cgroup	**obj_cgroups;	/* vector of object cgroups */ +#endif  	int			nr_pages;	/* # of pages served by this chunk */  	int			nr_populated;	/* # of populated pages */ @@ -63,7 +85,7 @@ struct pcpu_chunk {  extern spinlock_t pcpu_lock; -extern struct list_head *pcpu_slot; +extern struct list_head *pcpu_chunk_lists;  extern int pcpu_nr_slots;  extern int pcpu_nr_empty_pop_pages; @@ -106,6 +128,37 @@ static inline int pcpu_chunk_map_bits(struct pcpu_chunk *chunk)  	return pcpu_nr_pages_to_map_bits(chunk->nr_pages);  } +#ifdef CONFIG_MEMCG_KMEM +static inline enum pcpu_chunk_type pcpu_chunk_type(struct pcpu_chunk *chunk) +{ +	if (chunk->obj_cgroups) +		return PCPU_CHUNK_MEMCG; +	return PCPU_CHUNK_ROOT; +} + +static inline bool pcpu_is_memcg_chunk(enum pcpu_chunk_type chunk_type) +{ +	return chunk_type == PCPU_CHUNK_MEMCG; +} + +#else +static inline enum pcpu_chunk_type pcpu_chunk_type(struct pcpu_chunk *chunk) +{ +	return PCPU_CHUNK_ROOT; +} + +static inline bool pcpu_is_memcg_chunk(enum pcpu_chunk_type chunk_type) +{ +	return false; +} +#endif + +static inline struct list_head *pcpu_chunk_list(enum pcpu_chunk_type chunk_type) +{ +	return &pcpu_chunk_lists[pcpu_nr_slots * +				 pcpu_is_memcg_chunk(chunk_type)]; +} +  #ifdef CONFIG_PERCPU_STATS  #include <linux/spinlock.h>  |