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 9007F3CA4AB for ; Thu, 2 Apr 2026 14:37:03 +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=1775140623; cv=none; b=XBIPwPfoQerWbhwqCFxF1Kn3z1MZfuesVf3bwRN2NMCO49LZC8l3/BT9GS8RGzoJDz+8D0OEwc1/JJMJredv+L7dCn2VMP+9XZWbaV9g3QkPB0QSHJLAMdF2MCPxVQOgpygJPRpIjdHZT1ShBJkkOkg/O/XjWKrfzdKF2Ki5KwM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775140623; c=relaxed/simple; bh=QiaYc6bmCawV6VUIowBRoKVqPAmV1+wQMNXQSnjt2ok=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=h0qn6U+KeFoBftprUYLW5MVQfBH/boiqgddGVAzBiKIFkse/siGm2rbLrNpFVbtbeGz5Y/NrQjrjqoPxwdHbyv7tWXBfDRySw46IBo19+4q5XAOS6YgwNtX71KtFTV2ohDM2ktHi70oxFwakjuAy4pxdgUkPgu0wuIgySpCkwOc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RvIXmouu; 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="RvIXmouu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4E3F1C116C6; Thu, 2 Apr 2026 14:37:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1775140623; bh=QiaYc6bmCawV6VUIowBRoKVqPAmV1+wQMNXQSnjt2ok=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=RvIXmouuVV9SqPjGgkGaI1+M8nGHGje1mOdW96Ke2al7DYx06XmM7fv+qUvJIcwts 5DKaFpDJyLkIn+VfwKl/qNFW/V0v3nFb/6Qs8i0S6bF2X3h91n+s+XiARDqfZsob1m +3OYn+rS2zZjr5eQmrzpRQ1ABk1pEWz2MVZVhFN3mGghdlEVF6+QRwxou0k2AqPOkL 7WNGKHd2Q+pTnGkgIr12TpoIjM/qZdfUdzACaz+T/Ng8+Ve9iHbCYUuQwUTCZD++CD oJRT20eYUr3HLV4yxi52RQw7nNMLsVdo2dFAzHEvMxI5tGQFqriYwGAkqqAwbiOcyk ixOyF7fojCEwA== Message-ID: <26e81ffe-08ad-4c3f-a360-d45c3cb32ee2@kernel.org> Date: Thu, 2 Apr 2026 16:36:59 +0200 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 V1 2/2] lib/tests/slub_kunit: add a test case for {kmalloc,kfree}_nolock To: "Harry Yoo (Oracle)" , Andrew Morton Cc: Hao Li , Christoph Lameter , David Rientjes , Roman Gushchin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, Alexei Starovoitov References: <20260330120517.104743-1-harry@kernel.org> <20260330120517.104743-3-harry@kernel.org> From: "Vlastimil Babka (SUSE)" Content-Language: en-US In-Reply-To: <20260330120517.104743-3-harry@kernel.org> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 3/30/26 2:05 PM, Harry Yoo (Oracle) wrote: > Testing invocation of {kmalloc,kfree}_nolock() during kmalloc() or > kfree() is tricky, and it is even harder to ensure that slowpaths are > properly tested. Lack of such testing has led to late discovery of > the bug fixed by commit a1e244a9f177 ("mm/slab: use prandom if > !allow_spin"). > > Add a slub_kunit test that allocates and frees objects in a tight loop > while a perf event triggers NMIs on the same task, invoking > {kmalloc,kfree}_nolock() from the NMI handler. > > Signed-off-by: Harry Yoo (Oracle) perf_event_create_kernel_counter() seems to only exist with CONFIG_PERF_EVENTS, there's not even some "return -EINVAL" skeleton otherwise, AFAICS. Didn't check the various other definitions, but guess we'll need to put some/all of this behind #ifdef's then? > --- > lib/tests/slub_kunit.c | 88 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 88 insertions(+) > > diff --git a/lib/tests/slub_kunit.c b/lib/tests/slub_kunit.c > index 848b682a2d70..2ed5f90a748a 100644 > --- a/lib/tests/slub_kunit.c > +++ b/lib/tests/slub_kunit.c > @@ -7,6 +7,7 @@ > #include > #include > #include > +#include > #include "../mm/slab.h" > > static struct kunit_resource resource; > @@ -291,6 +292,92 @@ static void test_krealloc_redzone_zeroing(struct kunit *test) > kmem_cache_destroy(s); > } > > +#define REPEAT_TIMES 1000 > +#define LOOP_SIZE 1000 > +static void *objects[LOOP_SIZE]; > + > +struct nmi_context { > + struct kunit *test; > + int callback_count; > + int alloc_ok; > + int alloc_fail; > + struct perf_event *event; > +}; > + > +static struct perf_event_attr nmi_hw_attr = { > + .type = PERF_TYPE_HARDWARE, > + .config = PERF_COUNT_HW_CPU_CYCLES, > + .size = sizeof(struct perf_event_attr), > + .pinned = 1, > + .disabled = 1, > + .freq = 1, > + .sample_freq = 100000, > +}; > + > +static void kmalloc_kfree_nolock_in_nmi(struct perf_event *event, > + struct perf_sample_data *data, > + struct pt_regs *regs) > +{ > + void *objp; > + gfp_t gfp; > + struct nmi_context *ctx = event->overflow_handler_context; > + > + /* __GFP_ACCOUNT to test kmalloc_nolock() in alloc_slab_obj_exts() */ > + gfp = (ctx->callback_count % 2) ? 0 : __GFP_ACCOUNT; > + objp = kmalloc_nolock(64, gfp, NUMA_NO_NODE); > + > + if (objp) > + ctx->alloc_ok++; > + else > + ctx->alloc_fail++; > + > + kfree_nolock(objp); > + ctx->callback_count++; > +} > + > +static void test_kmalloc_kfree_nolock(struct kunit *test) > +{ > + int i, j; > + struct nmi_context ctx = { .test = test }; > + struct perf_event *event; > + bool alloc_fail = false; > + > + event = perf_event_create_kernel_counter(&nmi_hw_attr, -1, current, > + kmalloc_kfree_nolock_in_nmi, > + &ctx); > + if (IS_ERR(event)) > + kunit_skip(test, "Failed to create perf event"); > + ctx.event = event; > + perf_event_enable(ctx.event); > + for (i = 0; i < REPEAT_TIMES; i++) { > + for (j = 0; j < LOOP_SIZE; j++) { > + gfp_t gfp = (i % 2) ? 0 : __GFP_ACCOUNT; > + > + objects[j] = kmalloc(64, gfp); > + if (!objects[j]) { > + j--; > + while (j >= 0) > + kfree(objects[j--]); > + alloc_fail = true; > + goto cleanup; > + } > + } > + for (j = 0; j < LOOP_SIZE; j++) > + kfree(objects[j]); > + } > + > +cleanup: > + perf_event_disable(ctx.event); > + perf_event_release_kernel(ctx.event); > + > + kunit_info(test, "callback_count: %d, alloc_ok: %d, alloc_fail: %d\n", > + ctx.callback_count, ctx.alloc_ok, ctx.alloc_fail); > + > + if (alloc_fail) > + kunit_skip(test, "Allocation failed"); > + KUNIT_EXPECT_EQ(test, 0, slab_errors); > +} > + > static int test_init(struct kunit *test) > { > slab_errors = 0; > @@ -315,6 +402,7 @@ static struct kunit_case test_cases[] = { > KUNIT_CASE(test_kfree_rcu_wq_destroy), > KUNIT_CASE(test_leak_destroy), > KUNIT_CASE(test_krealloc_redzone_zeroing), > + KUNIT_CASE_SLOW(test_kmalloc_kfree_nolock), > {} > }; >