From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C7F823E0092 for ; Fri, 15 May 2026 16:25:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778862300; cv=none; b=YWQofckAuxKmfxEIoycX24lz9nlIJG9/huNpwGnhI2qeZkeuUjTIdSsL9kCTkodtT+FL7iH9srLornB93t9k7uvWSe0qKkds6JbBHIOCdE3tVqYd4bJr44Cdeatlpq+MWQjPp4CDBnPoSIGfQm0eqRqklsRJCHG28GjSWEtpVeo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778862300; c=relaxed/simple; bh=dvyaAGwaAEmKdhHRQ6Trfstm6Ieb9ZAn2zLUlooC8QE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rlyVLcEfdf9qdhRjBD8cF+Ac5+qLa254+5O9bRH/bNnrhBqTP2sVoIOvD2LWpOGR2BvuA+OLTsM4KsERa0nU7wG2PBK3zOLCDRfGu92+ISd3OwO1k+Ze/SQNbVkG2hT10azzDfi8bLjE1DR8TharcMa46yO9UJNT4yLf1NKNi4I= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ovGCot7F; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ovGCot7F" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A7B1C2BCB3; Fri, 15 May 2026 16:24:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778862300; bh=dvyaAGwaAEmKdhHRQ6Trfstm6Ieb9ZAn2zLUlooC8QE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ovGCot7Fct19IIkkgts4PSq3Hkjx4cZBUTmShXiE2+2xLMJTahWSp3ehfRUgXBkIo A51/OcvpuibLhpf2opV/nbf9sBldvUTY2TOoZ/0Wc/PXW+FPa/r3TrKBNmYshH2E56 YlCMq1kAjRUwTVlCzQtRwMwwv5GmErW3PXrFpUPsBQLCBVcMWPX5n9tpKqA+Kkngix 6driDpZcyRd/6uLimC5IunBP7dMk2WLNcACyRlUuYhhjTqERzFC1bCQhlqJkXF/3oV SlevGnQWcx21aAdwCiNKasLfDBwyfJTWwsno3MrOQvWQ7xnr/JiZdvj55mlGb+LHRk cs2np44xkpaSg== From: "Harry Yoo (Oracle)" Date: Sat, 16 May 2026 01:24:32 +0900 Subject: [PATCH RFC 8/8] mm/slab: allow changing max_{full,empty}_sheaves at runtime Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260516-sheaves-tuning-v1-8-221aa3e1d829@kernel.org> References: <20260516-sheaves-tuning-v1-0-221aa3e1d829@kernel.org> In-Reply-To: <20260516-sheaves-tuning-v1-0-221aa3e1d829@kernel.org> To: Vlastimil Babka , Andrew Morton , Hao Li , Christoph Lameter , David Rientjes , Roman Gushchin Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Suren Baghdasaryan , "Liam R. Howlett" X-Mailer: b4 0.16-dev Replace MAX_FULL_SHEAVES and MAX_EMPTY_SHEAVES with per-cache tunables, and expose them via sysfs attributes as max_{full,empty}_sheaves. Keep the default value 10 to preserve the existing behavior. Let us measure the impact of this parameter and discuss whether it is actually needed before landing this in mainline. Signed-off-by: Harry Yoo (Oracle) --- mm/slab.h | 2 ++ mm/slub.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/mm/slab.h b/mm/slab.h index 907a8207809c..22df364a2ef7 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -205,6 +205,8 @@ struct kmem_cache { struct reciprocal_value reciprocal_size; unsigned int offset; /* Free pointer offset */ unsigned short sheaf_capacity; + unsigned short max_full_sheaves; + unsigned short max_empty_sheaves; struct kmem_cache_order_objects oo; /* Allocation and freeing of slabs */ diff --git a/mm/slub.c b/mm/slub.c index 856639d3d3f0..e9b33567d98c 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -396,9 +396,6 @@ void stat_add(const struct kmem_cache *s, enum stat_item si, int v) #endif } -#define MAX_FULL_SHEAVES 10 -#define MAX_EMPTY_SHEAVES 10 - struct node_barn { spinlock_t lock; struct list_head sheaves_full; @@ -3287,7 +3284,7 @@ barn_replace_full_sheaf(struct kmem_cache *s, struct node_barn *barn, lockdep_assert_held(this_cpu_ptr(&s->cpu_sheaves->lock)); /* we don't repeat this check under barn->lock as it's not critical */ - if (data_race(barn->nr_full) >= MAX_FULL_SHEAVES) + if (data_race(barn->nr_full) >= s->max_full_sheaves) return ERR_PTR(-E2BIG); if (!data_race(barn->nr_empty)) return ERR_PTR(-ENOMEM); @@ -5251,7 +5248,7 @@ void kmem_cache_return_sheaf(struct kmem_cache *s, gfp_t gfp, * If the barn has too many full sheaves or we fail to refill the sheaf, * simply flush and free it. */ - if (!barn || data_race(barn->nr_full) >= MAX_FULL_SHEAVES) { + if (!barn || data_race(barn->nr_full) >= s->max_full_sheaves) { local_unlock(&s->cpu_sheaves->lock); goto free_sheaf; } @@ -6072,7 +6069,7 @@ static void rcu_free_sheaf(struct rcu_head *head) * limit but that should be rare and harmless. */ - if (data_race(barn->nr_full) < MAX_FULL_SHEAVES) { + if (data_race(barn->nr_full) < s->max_full_sheaves) { stat(s, BARN_PUT); barn_put_full_sheaf(s, barn, sheaf); local_unlock(&s->cpu_sheaves->lock); @@ -6083,7 +6080,7 @@ static void rcu_free_sheaf(struct rcu_head *head) sheaf_flush_unused(s, sheaf); empty: - if (barn && data_race(barn->nr_empty) < MAX_EMPTY_SHEAVES) { + if (barn && data_race(barn->nr_empty) < s->max_empty_sheaves) { barn_put_empty_sheaf(s, barn, sheaf); local_unlock(&s->cpu_sheaves->lock); return; @@ -8843,6 +8840,8 @@ int do_kmem_cache_create(struct kmem_cache *s, const char *name, #endif s->align = args->align; s->ctor = args->ctor; + s->max_full_sheaves = 10; + s->max_empty_sheaves = 10; #ifdef CONFIG_HARDENED_USERCOPY s->useroffset = args->useroffset; s->usersize = args->usersize; @@ -9359,6 +9358,46 @@ static ssize_t sheaf_capacity_store(struct kmem_cache *s, } SLAB_ATTR(sheaf_capacity); +static ssize_t max_full_sheaves_show(struct kmem_cache *s, char *buf) +{ + return sysfs_emit(buf, "%hu\n", s->max_full_sheaves); +} + +static ssize_t max_full_sheaves_store(struct kmem_cache *s, const char *buf, + size_t length) +{ + unsigned short max_full_sheaves; + int err; + + err = kstrtou16(buf, 10, &max_full_sheaves); + if (err) + return err; + + s->max_full_sheaves = max_full_sheaves; + return length; +} +SLAB_ATTR(max_full_sheaves); + +static ssize_t max_empty_sheaves_show(struct kmem_cache *s, char *buf) +{ + return sysfs_emit(buf, "%hu\n", s->max_empty_sheaves); +} + +static ssize_t max_empty_sheaves_store(struct kmem_cache *s, const char *buf, + size_t length) +{ + unsigned short max_empty_sheaves; + int err; + + err = kstrtou16(buf, 10, &max_empty_sheaves); + if (err) + return err; + + s->max_empty_sheaves = max_empty_sheaves; + return length; +} +SLAB_ATTR(max_empty_sheaves); + static ssize_t min_partial_show(struct kmem_cache *s, char *buf) { return sysfs_emit(buf, "%lu\n", s->min_partial); @@ -9721,6 +9760,8 @@ static const struct attribute *const slab_attrs[] = { &objs_per_slab_attr.attr, &order_attr.attr, &sheaf_capacity_attr.attr, + &max_full_sheaves_attr.attr, + &max_empty_sheaves_attr.attr, &min_partial_attr.attr, &cpu_partial_attr.attr, &objects_partial_attr.attr, -- 2.43.0