From: Johan Hovold <johan@kernel.org>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J . Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
Tzung-Bi Shih <tzungbi@kernel.org>,
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>,
Linus Walleij <linusw@kernel.org>,
Jonathan Corbet <corbet@lwn.net>, Shuah Khan <shuah@kernel.org>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Wolfram Sang <wsa+renesas@sang-engineering.com>,
Simona Vetter <simona.vetter@ffwll.ch>,
Dan Williams <dan.j.williams@intel.com>,
Jason Gunthorpe <jgg@nvidia.com>,
linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org, Johan Hovold <johan@kernel.org>
Subject: [PATCH v2 2/3] Revert "revocable: Add Kunit test cases"
Date: Wed, 4 Feb 2026 15:28:48 +0100 [thread overview]
Message-ID: <20260204142849.22055-3-johan@kernel.org> (raw)
In-Reply-To: <20260204142849.22055-1-johan@kernel.org>
This reverts commit cd7693419bb5abd91ad2f407dab69c480e417a61.
The new revocable functionality is fundamentally broken and at a minimum
needs to be redesigned.
Drop the revocable Kunit tests to allow the implementation to be reverted.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
MAINTAINERS | 1 -
drivers/base/Kconfig | 8 -
drivers/base/Makefile | 3 -
drivers/base/revocable_test.c | 284 ----------------------------------
4 files changed, 296 deletions(-)
delete mode 100644 drivers/base/revocable_test.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 7759e9103070..93c07c645c68 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22390,7 +22390,6 @@ M: Tzung-Bi Shih <tzungbi@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/base/revocable.c
-F: drivers/base/revocable_test.c
F: include/linux/revocable.h
RFKILL
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 9f318b98144d..1786d87b29e2 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -250,11 +250,3 @@ config FW_DEVLINK_SYNC_STATE_TIMEOUT
work on.
endmenu
-
-# Kunit test cases
-config REVOCABLE_KUNIT_TEST
- tristate "Kunit tests for revocable" if !KUNIT_ALL_TESTS
- depends on KUNIT && BROKEN
- default KUNIT_ALL_TESTS
- help
- Kunit tests for the revocable API.
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 4c6607616a73..8074a10183dc 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -35,6 +35,3 @@ ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
# define_trace.h needs to know how to find our header
CFLAGS_trace.o := -I$(src)
obj-$(CONFIG_TRACING) += trace.o
-
-# Kunit test cases
-obj-$(CONFIG_REVOCABLE_KUNIT_TEST) += revocable_test.o
diff --git a/drivers/base/revocable_test.c b/drivers/base/revocable_test.c
deleted file mode 100644
index 27f5d7d96f4b..000000000000
--- a/drivers/base/revocable_test.c
+++ /dev/null
@@ -1,284 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright 2026 Google LLC
- *
- * Kunit tests for the revocable API.
- *
- * The test cases cover the following scenarios:
- *
- * - Basic: Verifies that a consumer can successfully access the resource
- * provided via the provider.
- *
- * - Revocation: Verifies that after the provider revokes the resource,
- * the consumer correctly receives a NULL pointer on a subsequent access.
- *
- * - Try Access Macro: Same as "Revocation" but uses the
- * REVOCABLE_TRY_ACCESS_WITH() and REVOCABLE_TRY_ACCESS_SCOPED().
- *
- * - Provider Use-after-free: Verifies revocable_init() correctly handles
- * race conditions where the provider is being released.
- *
- * - Concurrent Access: Verifies multiple threads can access the resource.
- */
-
-#include <kunit/test.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/refcount.h>
-#include <linux/revocable.h>
-
-static void revocable_test_basic(struct kunit *test)
-{
- struct revocable_provider __rcu *rp;
- struct revocable rev;
- void *real_res = (void *)0x12345678, *res;
- int ret;
-
- rp = revocable_provider_alloc(real_res);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rp);
-
- ret = revocable_init(rp, &rev);
- KUNIT_ASSERT_EQ(test, ret, 0);
-
- res = revocable_try_access(&rev);
- KUNIT_EXPECT_PTR_EQ(test, res, real_res);
- revocable_withdraw_access(&rev);
-
- revocable_deinit(&rev);
- revocable_provider_revoke(&rp);
- KUNIT_EXPECT_PTR_EQ(test, unrcu_pointer(rp), NULL);
-}
-
-static void revocable_test_revocation(struct kunit *test)
-{
- struct revocable_provider __rcu *rp;
- struct revocable rev;
- void *real_res = (void *)0x12345678, *res;
- int ret;
-
- rp = revocable_provider_alloc(real_res);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rp);
-
- ret = revocable_init(rp, &rev);
- KUNIT_ASSERT_EQ(test, ret, 0);
-
- res = revocable_try_access(&rev);
- KUNIT_EXPECT_PTR_EQ(test, res, real_res);
- revocable_withdraw_access(&rev);
-
- revocable_provider_revoke(&rp);
- KUNIT_EXPECT_PTR_EQ(test, unrcu_pointer(rp), NULL);
-
- res = revocable_try_access(&rev);
- KUNIT_EXPECT_PTR_EQ(test, res, NULL);
- revocable_withdraw_access(&rev);
-
- revocable_deinit(&rev);
-}
-
-static void revocable_test_try_access_macro(struct kunit *test)
-{
- struct revocable_provider __rcu *rp;
- void *real_res = (void *)0x12345678, *res;
-
- rp = revocable_provider_alloc(real_res);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rp);
-
- {
- REVOCABLE_TRY_ACCESS_WITH(rp, res);
- KUNIT_EXPECT_PTR_EQ(test, res, real_res);
- }
-
- revocable_provider_revoke(&rp);
- KUNIT_EXPECT_PTR_EQ(test, unrcu_pointer(rp), NULL);
-
- {
- REVOCABLE_TRY_ACCESS_WITH(rp, res);
- KUNIT_EXPECT_PTR_EQ(test, res, NULL);
- }
-}
-
-static void revocable_test_try_access_macro2(struct kunit *test)
-{
- struct revocable_provider __rcu *rp;
- void *real_res = (void *)0x12345678, *res;
- bool accessed;
-
- rp = revocable_provider_alloc(real_res);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rp);
-
- accessed = false;
- REVOCABLE_TRY_ACCESS_SCOPED(rp, res) {
- KUNIT_EXPECT_PTR_EQ(test, res, real_res);
- accessed = true;
- }
- KUNIT_EXPECT_TRUE(test, accessed);
-
- revocable_provider_revoke(&rp);
- KUNIT_EXPECT_PTR_EQ(test, unrcu_pointer(rp), NULL);
-
- accessed = false;
- REVOCABLE_TRY_ACCESS_SCOPED(rp, res) {
- KUNIT_EXPECT_PTR_EQ(test, res, NULL);
- accessed = true;
- }
- KUNIT_EXPECT_TRUE(test, accessed);
-}
-
-static void revocable_test_provider_use_after_free(struct kunit *test)
-{
- struct revocable_provider __rcu *rp;
- struct revocable_provider *old_rp;
- struct revocable rev;
- void *real_res = (void *)0x12345678;
- int ret;
-
- rp = revocable_provider_alloc(real_res);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rp);
-
- ret = revocable_init(NULL, &rev);
- KUNIT_EXPECT_NE(test, ret, 0);
-
- /* Simulate the provider has been freed. */
- old_rp = rcu_replace_pointer(rp, NULL, 1);
- ret = revocable_init(rp, &rev);
- KUNIT_EXPECT_NE(test, ret, 0);
- rcu_replace_pointer(rp, old_rp, 1);
-
- struct {
- struct srcu_struct srcu;
- void __rcu *res;
- struct kref kref;
- struct rcu_head rcu;
- } *rp_internal = (void *)rp;
-
- /* Simulate the provider is releasing. */
- refcount_set(&rp_internal->kref.refcount, 0);
- ret = revocable_init(rp, &rev);
- KUNIT_EXPECT_NE(test, ret, 0);
- refcount_set(&rp_internal->kref.refcount, 1);
-
- revocable_provider_revoke(&rp);
- KUNIT_EXPECT_PTR_EQ(test, unrcu_pointer(rp), NULL);
- ret = revocable_init(rp, &rev);
- KUNIT_EXPECT_NE(test, ret, 0);
-}
-
-struct test_concurrent_access_context {
- struct kunit *test;
- struct revocable_provider __rcu *rp;
- struct revocable rev;
- struct completion started, enter, exit;
- struct task_struct *thread;
- void *expected_res;
-};
-
-static int test_concurrent_access_provider(void *data)
-{
- struct test_concurrent_access_context *ctx = data;
-
- complete(&ctx->started);
-
- wait_for_completion(&ctx->enter);
- revocable_provider_revoke(&ctx->rp);
- KUNIT_EXPECT_PTR_EQ(ctx->test, unrcu_pointer(ctx->rp), NULL);
-
- return 0;
-}
-
-static int test_concurrent_access_consumer(void *data)
-{
- struct test_concurrent_access_context *ctx = data;
- void *res;
-
- complete(&ctx->started);
-
- wait_for_completion(&ctx->enter);
- res = revocable_try_access(&ctx->rev);
- KUNIT_EXPECT_PTR_EQ(ctx->test, res, ctx->expected_res);
-
- wait_for_completion(&ctx->exit);
- revocable_withdraw_access(&ctx->rev);
-
- return 0;
-}
-
-static void revocable_test_concurrent_access(struct kunit *test)
-{
- struct revocable_provider __rcu *rp;
- void *real_res = (void *)0x12345678;
- struct test_concurrent_access_context *ctx;
- int ret, i;
-
- rp = revocable_provider_alloc(real_res);
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rp);
-
- ctx = kunit_kmalloc_array(test, 3, sizeof(*ctx), GFP_KERNEL);
- KUNIT_ASSERT_NOT_NULL(test, ctx);
-
- for (i = 0; i < 3; ++i) {
- ctx[i].test = test;
- init_completion(&ctx[i].started);
- init_completion(&ctx[i].enter);
- init_completion(&ctx[i].exit);
-
- if (i == 0) {
- ctx[i].rp = rp;
- ctx[i].thread = kthread_run(
- test_concurrent_access_provider, ctx + i,
- "revocable_provider_%d", i);
- } else {
- ret = revocable_init(rp, &ctx[i].rev);
- KUNIT_ASSERT_EQ(test, ret, 0);
-
- ctx[i].thread = kthread_run(
- test_concurrent_access_consumer, ctx + i,
- "revocable_consumer_%d", i);
- }
- KUNIT_ASSERT_FALSE(test, IS_ERR(ctx[i].thread));
-
- wait_for_completion(&ctx[i].started);
- }
- ctx[1].expected_res = real_res;
- ctx[2].expected_res = NULL;
-
- /* consumer1 enters read-side critical section */
- complete(&ctx[1].enter);
- msleep(100);
- /* provider0 revokes the resource */
- complete(&ctx[0].enter);
- msleep(100);
- /* consumer2 enters read-side critical section */
- complete(&ctx[2].enter);
- msleep(100);
-
- /* consumer{1,2} exit read-side critical section */
- complete(&ctx[1].exit);
- complete(&ctx[2].exit);
-
- for (i = 0; i < 3; ++i)
- kthread_stop(ctx[i].thread);
- for (i = 1; i < 3; ++i)
- revocable_deinit(&ctx[i].rev);
-}
-
-static struct kunit_case revocable_test_cases[] = {
- KUNIT_CASE(revocable_test_basic),
- KUNIT_CASE(revocable_test_revocation),
- KUNIT_CASE(revocable_test_try_access_macro),
- KUNIT_CASE(revocable_test_try_access_macro2),
- KUNIT_CASE(revocable_test_provider_use_after_free),
- KUNIT_CASE(revocable_test_concurrent_access),
- {}
-};
-
-static struct kunit_suite revocable_test_suite = {
- .name = "revocable_test",
- .test_cases = revocable_test_cases,
-};
-
-kunit_test_suite(revocable_test_suite);
-
-MODULE_DESCRIPTION("KUnit tests for the revocable API");
-MODULE_LICENSE("GPL");
--
2.52.0
next prev parent reply other threads:[~2026-02-04 14:33 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-04 14:28 [PATCH v2 0/3] Revert "revocable: Revocable resource management" Johan Hovold
2026-02-04 14:28 ` [PATCH v2 1/3] Revert "selftests: revocable: Add kselftest cases" Johan Hovold
2026-02-04 14:28 ` Johan Hovold [this message]
2026-02-04 14:28 ` [PATCH v2 3/3] Revert "revocable: Revocable resource management" Johan Hovold
2026-02-05 8:51 ` Tzung-Bi Shih
2026-02-05 11:56 ` Danilo Krummrich
2026-02-06 9:14 ` Tzung-Bi Shih
2026-02-05 14:03 ` Johan Hovold
2026-02-06 9:14 ` Tzung-Bi Shih
2026-02-06 15:07 ` Johan Hovold
2026-02-06 15:13 ` [PATCH v2 0/3] " Greg Kroah-Hartman
2026-02-07 14:00 ` Tzung-Bi Shih
2026-02-13 8:32 ` Bartosz Golaszewski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260204142849.22055-3-johan@kernel.org \
--to=johan@kernel.org \
--cc=bartosz.golaszewski@oss.qualcomm.com \
--cc=corbet@lwn.net \
--cc=dakr@kernel.org \
--cc=dan.j.williams@intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=jgg@nvidia.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linusw@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=shuah@kernel.org \
--cc=simona.vetter@ffwll.ch \
--cc=tzungbi@kernel.org \
--cc=wsa+renesas@sang-engineering.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.