From: Zijun Hu Date: Mon, 14 Jul 2025 15:34:15 +0000 (+0800) Subject: char: misc: Add a case to test registering miscdevice again without reinitialization X-Git-Tag: v6.18-rc1~74^2~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2334668aaf410382412b8c81f7014283f3e80354;p=thirdparty%2Fkernel%2Flinux.git char: misc: Add a case to test registering miscdevice again without reinitialization For miscdevice who wants dynamic minor, add a cast to test if it can be successfully registered again without reinitialization: 1) Provide Both miscdevice @dev_A and @dev_B want to request dynamic minor by initializing their minor to MISC_DYNAMIC_MINOR. 2) Register then de-register @dev_A. 3) Register @dev_B. 4) Register @dev_A again without reinitialization. 5) Check if @dev_A can be successfully registered. Signed-off-by: Zijun Hu Link: https://lore.kernel.org/r/20250714-rfc_miscdev-v6-4-2ed949665bde@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/char/misc_minor_kunit.c b/drivers/char/misc_minor_kunit.c index 3184f383bea8c..6fc8b05169c57 100644 --- a/drivers/char/misc_minor_kunit.c +++ b/drivers/char/misc_minor_kunit.c @@ -602,6 +602,49 @@ static void miscdev_test_invalid_input(struct kunit *test) misc_deregister(&misc_test); } +/* + * Verify if @miscdyn_a can still be registered successfully without + * reinitialization even if its minor ever owned was requested by + * another miscdevice such as @miscdyn_b. + */ +static void miscdev_test_dynamic_reentry(struct kunit *test) +{ + struct miscdevice miscdyn_a = { + .name = "miscdyn_a", + .minor = MISC_DYNAMIC_MINOR, + .fops = &miscdev_test_fops, + }; + struct miscdevice miscdyn_b = { + .name = "miscdyn_b", + .minor = MISC_DYNAMIC_MINOR, + .fops = &miscdev_test_fops, + }; + int ret, minor_a; + + ret = misc_register(&miscdyn_a); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn_a.minor)); + minor_a = miscdyn_a.minor; + if (ret != 0) + return; + misc_deregister(&miscdyn_a); + + ret = misc_register(&miscdyn_b); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, miscdyn_b.minor, minor_a); + if (ret != 0) + return; + + ret = misc_register(&miscdyn_a); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_TRUE(test, is_valid_dynamic_minor(miscdyn_a.minor)); + KUNIT_EXPECT_NE(test, miscdyn_a.minor, miscdyn_b.minor); + if (ret == 0) + misc_deregister(&miscdyn_a); + + misc_deregister(&miscdyn_b); +} + static struct kunit_case test_cases[] = { KUNIT_CASE(kunit_static_minor), KUNIT_CASE(kunit_misc_dynamic_minor), @@ -611,6 +654,7 @@ static struct kunit_case test_cases[] = { KUNIT_CASE(miscdev_test_duplicate_name), KUNIT_CASE(miscdev_test_duplicate_name_leak), KUNIT_CASE_PARAM(miscdev_test_duplicate_error, miscdev_gen_params), + KUNIT_CASE(miscdev_test_dynamic_reentry), {} };