RE: [PATCH] docs: kdoc: parse context_lock_struct() as struct declaration
From: Loktionov, Aleksandr
Date: Mon Sep 28 2026 - 11:24:34 EST
> -----Original Message-----
> From: Omokefe Emmanuel Onanaroghene <emmaonana18@xxxxxxxxx>
> Sent: Saturday, September 26, 2026 1:41 AM
> To: peterz@xxxxxxxxxxxxx; elver@xxxxxxxxxx; bvanassche@xxxxxxx; linux-
> doc@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
> Cc: corbet@xxxxxxx; skhan@xxxxxxxxxxxxxxxxxxx; rdunlap@xxxxxxxxxxxxx;
> mchehab@xxxxxxxxxx; Loktionov, Aleksandr
> <aleksandr.loktionov@xxxxxxxxx>; kees@xxxxxxxxxx;
> emmaonana18@xxxxxxxxx; tudor.ambarus@xxxxxxxxxx
> Subject: [PATCH] docs: kdoc: parse context_lock_struct() as struct
> declaration
>
> kernel-doc fails to parse struct declarations wrapped in
> context_lock_struct(), e.g. struct debugfs_cancellation:
>
> include/linux/debugfs.h:245 ... error: Cannot parse struct or union!
>
> Add a struct transform that expands context_lock_struct() to a plain
> struct declaration, and apply the struct transforms to the whole
> declaration before split_struct_proto(), matching what dump_var() and
> dump_function() already do for their prototypes. The member-only
> transform in dump_struct() is then redundant.
>
> Add a regression test for the debugfs_cancellation declaration.
>
> Fixes: 6e530e2e3119 ("debugfs: Make debugfs_cancellation a context
> lock struct")
> Signed-off-by: Omokefe Emmanuel Onanaroghene <emmaonana18@xxxxxxxxx>
> ---
> tools/lib/python/kdoc/kdoc_parser.py | 11 +++++++----
> tools/lib/python/kdoc/xforms_lists.py | 1 +
> tools/unittests/test_kdoc_parser.py | 26 ++++++++++++++++++++++++++
> 3 files changed, 34 insertions(+), 4 deletions(-)
>
> diff --git a/tools/lib/python/kdoc/kdoc_parser.py
> b/tools/lib/python/kdoc/kdoc_parser.py
> index d9ad1ddc87dd..80d4245acd17 100644
> --- a/tools/lib/python/kdoc/kdoc_parser.py
> +++ b/tools/lib/python/kdoc/kdoc_parser.py
> @@ -831,6 +831,13 @@ class KernelDoc:
> #
> source = source
> proto = trim_private_members(proto)
> +
> + #
> + # Expand macro-based declarations, like
> context_lock_struct(),
> + # into a plain struct/union declaration before splitting it,
> + # as dump_var() and dump_function() already do.
> + #
> + proto = self.xforms.apply("struct", proto)
> struct_parts = self.split_struct_proto(proto)
> if not struct_parts:
> self.emit_msg(ln, f"{proto} error: Cannot parse struct or
> union!") @@ -841,10 +848,6 @@ class KernelDoc:
> self.emit_msg(ln, f"expecting prototype for {decl_type}
> {self.entry.identifier}. "
> f"Prototype was for {decl_type}
> {declaration_name} instead")
> return
> - #
> - # Go through the list of members applying all of our
> transformations.
> - #
> - members = self.xforms.apply("struct", members)
>
> #
> # Deal with embedded struct and union members, and drop enums
> entirely.
> diff --git a/tools/lib/python/kdoc/xforms_lists.py
> b/tools/lib/python/kdoc/xforms_lists.py
> index e3dda2fe8a53..9f2c750a811b 100644
> --- a/tools/lib/python/kdoc/xforms_lists.py
> +++ b/tools/lib/python/kdoc/xforms_lists.py
> @@ -62,6 +62,7 @@ class CTransforms:
> (CMatch("struct_group_attr"), r"struct { \3+ };"),
> (CMatch("struct_group_tagged"), r"struct { \3+ };"),
> (CMatch("__struct_group"), r"struct { \4+ };"),
> + (CMatch("context_lock_struct"), r"struct \1"),
> ]
>
> #: Transforms for function prototypes.
> diff --git a/tools/unittests/test_kdoc_parser.py
> b/tools/unittests/test_kdoc_parser.py
> index c4a76ed13dbc..4baa78ca02b3 100755
> --- a/tools/unittests/test_kdoc_parser.py
> +++ b/tools/unittests/test_kdoc_parser.py
> @@ -418,6 +418,32 @@ class TestSelfValidate(GenerateKdocItem):
> """
> self.run_test(self.SOURCE, [self.DEFAULT.copy()],
> self.EXPORTS)
>
> +class TestContextLockStruct(GenerateKdocItem):
> + def test_context_lock_struct_declaration(self):
> + source = """
> + /**
> + * struct debugfs_cancellation - cancellation data
> + * @list: internal, for keeping track
> + * @cancel: callback to call
> + * @cancel_data: extra data for the callback to call
> + */
> + context_lock_struct(debugfs_cancellation) {
> + struct list_head list;
> + void (*cancel)(struct dentry *, void *);
> + void *cancel_data;
> + };
> + """
> +
> + kernel_doc = KernelDoc(self.config, "test.c", self.xforms)
> + patcher = patch('builtins.open', new_callable=mock_open,
> + read_data=dedent(source))
> + with patcher:
> + _, entries = kernel_doc.parse_kdoc()
> +
> + self.assertEqual(len(entries), 1)
> + self.assertEqual(entries[0].name, "debugfs_cancellation")
> + self.assertEqual(entries[0].warnings, [])
> +
> #
> # Class and logic to create dynamic tests from YAML #
> --
> 2.43.0
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@xxxxxxxxx>