On Mon, Apr 23, 2018 at 02:06:31PM +0300, Kirill Tkhai wrote: > >> diff --git a/mm/vmscan.c b/mm/vmscan.c > >> index 4f02fe83537e..f63eb5596c35 100644 > >> --- a/mm/vmscan.c > >> +++ b/mm/vmscan.c > >> @@ -172,6 +172,22 @@ static DECLARE_RWSEM(shrinker_rwsem); > >> #if defined(CONFIG_MEMCG) && !defined(CONFIG_SLOB) > >> static DEFINE_IDR(shrinkers_id_idr); > >> > >> +static int expand_shrinker_id(int id) > >> +{ > >> + if (likely(id < shrinkers_max_nr)) > >> + return 0; > >> + > >> + id = shrinkers_max_nr * 2; > >> + if (id == 0) > >> + id = BITS_PER_BYTE; > >> + > >> + if (expand_shrinker_maps(shrinkers_max_nr, id)) > >> + return -ENOMEM; > >> + > >> + shrinkers_max_nr = id; > >> + return 0; > >> +} > >> + > > > > I think this function should live in memcontrol.c and shrinkers_max_nr > > should be private to memcontrol.c. > > It can't be private as shrink_slab_memcg() uses this value to get the last bit of bitmap. Yeah, you're right, sorry I haven't noticed that. What about moving id allocation to this function as well? IMHO it would make the code flow a little bit more straightforward. I mean, alloc_shrinker_id() { int id = idr_alloc(...) if (id >= memcg_nr_shrinker_ids) memcg_grow_shrinker_map(...) return id; } > > >> static int add_memcg_shrinker(struct shrinker *shrinker) > >> { > >> int id, ret; > >> @@ -180,6 +196,11 @@ static int add_memcg_shrinker(struct shrinker *shrinker) > >> ret = id = idr_alloc(&shrinkers_id_idr, shrinker, 0, 0, GFP_KERNEL); > >> if (ret < 0) > >> goto unlock; > >> + ret = expand_shrinker_id(id); > >> + if (ret < 0) { > >> + idr_remove(&shrinkers_id_idr, id); > >> + goto unlock; > >> + } > >> shrinker->id = id; > >> ret = 0; > >> unlock: > >>