From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mta0.migadu.com (out-220.mta0.migadu.com [91.218.175.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 693E5470421 for ; Tue, 13 Oct 2026 02:52:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.220 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791859958; cv=none; b=uDaFaoYH2zI4INdXWuc2QaCtJDf86ruao6CbWGX/bhEFUuheTQ7Mb2mN7nnVWO4IKRti/5HIBniDgFXKyAb+zX76fkcQbu8c7L6UBpqz2d4OkDetmGETKIXmO6SMI7caqA3qxhsQD/6PKKGHOtTL7FMOsww833cETItv6Am9yUg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791859958; c=relaxed/simple; bh=uL6ePUcLBZZOUIyB5RLHnAYGU9PprjKQPlmJBefHVMY=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=kCHvjCm/ctI5mS/hLZ3+1tblSJx5G8ve3aw8cTPjtSF6NjScVu6fb+uB/Ib+pdzxUA48v9GkCvhiedzorDhMVMXJI51gsqelCATSReobvdWSWNVeIDLfiGfqcLXLsx5vU0poDY4p59dXUVRNwfIvWEwZDJ4OKEQZVXRti5Ce3Aw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=NAMtpaTP; arc=none smtp.client-ip=91.218.175.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="NAMtpaTP" X-Envelope-To: linux-kernel@vger.kernel.org DKIM-Signature: a=rsa-sha256; bh=uL6ePUcLBZZOUIyB5RLHnAYGU9PprjKQPlmJBefHVMY=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1791859953; v=1; x=1792464753; b=NAMtpaTPaCQ5A3BTTO3fwnlTUTeVof9HIoOGcULZS+jzEK5ALCPSDHs+G2rJtftClVL2B4Uw 8G2dxy/mHsi0XK3sZIcQYIjPxYzpVb9PGXdsqCR1OIgj+Rb24JiQONZiPoa5aomONHCzQcDD9QG OrXo0ye+S5CeYVkCzx/61iIs= X-Envelope-To: linux-kernel@vger.kernel.org Received: by smtp.migadu.com with ESMTPS id 6830bd04216ac914; Tue, 13 Oct 2026 02:52:33 +0000 X-Mizu-Trace-ID: 6830bd04216ac914 X-Migadu-Flow: FLOW_OUT Message-ID: Date: Tue, 13 Oct 2026 10:52:28 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 1/2] mm/shrinker: size shrinker_info_unit to a power of two To: Konstantin Khorenko , Andrew Morton , Dave Chinner , Roman Gushchin , Muchun Song , Johannes Weiner , Michal Hocko , Shakeel Butt Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, cgroups@vger.kernel.org References: <20261012-b4-prep-vstor-144715-size-shrinker_info_unit-to-a-power-of-two-v1-0-5a7608393b7a@virtuozzo.com> <20261012-b4-prep-vstor-144715-size-shrinker_info_unit-to-a-power-of-two-v1-1-5a7608393b7a@virtuozzo.com> From: Qi Zheng In-Reply-To: <20261012-b4-prep-vstor-144715-size-shrinker_info_unit-to-a-power-of-two-v1-1-5a7608393b7a@virtuozzo.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 10/13/26 3:02 AM, Konstantin Khorenko wrote: > Every memory cgroup allocates, per NUMA node, one shrinker_info_unit > for every SHRINKER_UNIT_BITS shrinker ids up to shrinker_nr_max. The > unit holds BITS_PER_LONG atomic_long_t of deferred work, a power of > two, plus the one-word bitmap of shrinkers with objects charged to the > cgroup. That word takes the unit just past the power of two, to 520 > bytes on 64-bit, so every unit comes from kmalloc-1k and almost half of > it is padding. > > The units are allocated when the cgroup goes online and freed when it is > freed, so a dying cgroup keeps them until the last reference to it is > gone. Their number is the number of memory cgroups, times the NUMA > nodes, times shrinker_nr_max / SHRINKER_UNIT_BITS. shrinker_nr_max is > the peak number of memcg-aware shrinkers registered at once, and every > superblock registers one, so a host that mounts many filesystems and > runs many cgroups carries the padding as unreclaimable slab, and keeps > paying it for new cgroups after the mounts are gone. > > Let a unit cover one id less than a word holds. The bitmap still fits > one word, and nr_deferred[] plus that word add up to BITS_PER_LONG > longs, so the unit fills a power-of-two kmalloc slot exactly and, on > 64-bit, the memory taken by units halves, for about one unit more in > BITS_PER_LONG. > round_up() in expand_shrinker_info() needs a power-of-two step and > becomes roundup(); the other uses of SHRINKER_UNIT_BITS are divisions, > modulos and multiplications that do not care. Assert the unit size at > build time, since the layout depends on it. > > Assisted-by: LLM > Signed-off-by: Konstantin Khorenko > --- > include/linux/shrinker.h | 9 ++++++++- > mm/shrinker.c | 2 +- > 2 files changed, 9 insertions(+), 2 deletions(-) > > diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h > index 1a00be90d93a9..c250ab68d346c 100644 > --- a/include/linux/shrinker.h > +++ b/include/linux/shrinker.h > @@ -7,7 +7,11 @@ > #include > #include > > -#define SHRINKER_UNIT_BITS BITS_PER_LONG > +/* > + * One id less than a word holds, so that nr_deferred[] and the map word add > + * up to BITS_PER_LONG longs: a power of two, which fills a kmalloc slot. > + */ > +#define SHRINKER_UNIT_BITS (BITS_PER_LONG - 1) > > /* > * Bitmap and deferred work of shrinker::id corresponding to memcg-aware > @@ -18,6 +22,9 @@ struct shrinker_info_unit { > DECLARE_BITMAP(map, SHRINKER_UNIT_BITS); > }; > > +static_assert(!(sizeof(struct shrinker_info_unit) & > + (sizeof(struct shrinker_info_unit) - 1))); > + > struct shrinker_info { > struct rcu_head rcu; > int map_nr_max; > diff --git a/mm/shrinker.c b/mm/shrinker.c > index 7ec2a9704f6f2..a9418072a509e 100644 > --- a/mm/shrinker.c > +++ b/mm/shrinker.c > @@ -159,7 +159,7 @@ static int expand_one_shrinker_info(struct mem_cgroup *memcg, int new_size, > static int expand_shrinker_info(int new_id) > { > int ret = 0; > - int new_nr_max = round_up(new_id + 1, SHRINKER_UNIT_BITS); > + int new_nr_max = roundup(new_id + 1, SHRINKER_UNIT_BITS); > int new_size, old_size = 0; > struct mem_cgroup *memcg; > > Acked-by: Qi Zheng Thanks, Qi