On 3/18/2026 8:40 AM, Alice Ryhl wrote:
> On Tue, Mar 17, 2026 at 04:17:10PM -0400, Joel Fernandes wrote:
>> Add a new module `kernel::interop::list` for working with C's doubly
>> circular linked lists. Provide low-level iteration over list nodes.
>>
>> Typed iteration over actual items is provided with a `clist_create`
>> macro to assist in creation of the `CList` type.
>>
>> Cc: Nikola Djukic <[email protected]>
>> Reviewed-by: Daniel Almeida <[email protected]>
>> Reviewed-by: Alexandre Courbot <[email protected]>
>> Acked-by: Alexandre Courbot <[email protected]>
>> Acked-by: Gary Guo <[email protected]>
>> Acked-by: Miguel Ojeda <[email protected]>
>> Signed-off-by: Joel Fernandes <[email protected]>
>> ---
>> MAINTAINERS | 8 +
>> rust/helpers/helpers.c | 1 +
>> rust/helpers/list.c | 17 ++
>> rust/kernel/interop.rs | 9 +
>> rust/kernel/interop/list.rs | 342 ++++++++++++++++++++++++++++++++++++
>> rust/kernel/lib.rs | 2 +
>> 6 files changed, 379 insertions(+)
>> create mode 100644 rust/helpers/list.c
>> create mode 100644 rust/kernel/interop.rs
>> create mode 100644 rust/kernel/interop/list.rs
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 4bd6b538a51f..e847099efcc2 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -23251,6 +23251,14 @@ T: git https://github.com/Rust-for-Linux/linux.git
>> alloc-next
>> F: rust/kernel/alloc.rs
>> F: rust/kernel/alloc/
>>
>> +RUST [INTEROP]
>> +M: Joel Fernandes <[email protected]>
>> +M: Alexandre Courbot <[email protected]>
>> +L: [email protected]
>> +S: Maintained
>> +T: git https://github.com/Rust-for-Linux/linux.git interop-next
>> +F: rust/kernel/interop/
>> +
>> RUST [NUM]
>> M: Alexandre Courbot <[email protected]>
>> R: Yury Norov <[email protected]>
>> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
>> index a3c42e51f00a..724fcb8240ac 100644
>> --- a/rust/helpers/helpers.c
>> +++ b/rust/helpers/helpers.c
>> @@ -35,6 +35,7 @@
>> #include "io.c"
>> #include "jump_label.c"
>> #include "kunit.c"
>> +#include "list.c"
>> #include "maple_tree.c"
>> #include "mm.c"
>> #include "mutex.c"
>> diff --git a/rust/helpers/list.c b/rust/helpers/list.c
>> new file mode 100644
>> index 000000000000..18095a5593c5
>> --- /dev/null
>> +++ b/rust/helpers/list.c
>> @@ -0,0 +1,17 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +/*
>> + * Helpers for C circular doubly linked list implementation.
>> + */
>> +
>> +#include <linux/list.h>
>> +
>> +__rust_helper void rust_helper_INIT_LIST_HEAD(struct list_head *list)
>> +{
>> + INIT_LIST_HEAD(list);
>> +}
>> +
>> +__rust_helper void rust_helper_list_add_tail(struct list_head *new, struct
>> list_head *head)
>> +{
>> + list_add_tail(new, head);
>> +}
>> diff --git a/rust/kernel/interop.rs b/rust/kernel/interop.rs
>> new file mode 100644
>> index 000000000000..b88140cf76dc
>> --- /dev/null
>> +++ b/rust/kernel/interop.rs
>> @@ -0,0 +1,9 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +//! Infrastructure for interfacing Rust code with C kernel subsystems.
>> +//!
>> +//! This module is intended for low-level, unsafe Rust infrastructure code
>> +//! that interoperates between Rust and C. It is NOT for use directly in
>> +//! Rust drivers.
>> +
>> +pub mod list;
>> diff --git a/rust/kernel/interop/list.rs b/rust/kernel/interop/list.rs
>> new file mode 100644
>> index 000000000000..328f6b0de2ce
>> --- /dev/null
>> +++ b/rust/kernel/interop/list.rs
>> @@ -0,0 +1,342 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +//! Rust interface for C doubly circular intrusive linked lists.
>> +//!
>> +//! This module provides Rust abstractions for iterating over C
>> `list_head`-based
>> +//! linked lists. It should only be used for cases where C and Rust code
>> share
>> +//! direct access to the same linked list through a C interop interface.
>> +//!
>> +//! Note: This *must not* be used by Rust components that just need a
>> linked list
>> +//! primitive. Use [`kernel::list::List`] instead.
>> +//!
>> +//! # Examples
>> +//!
>> +//! ```
>> +//! use kernel::{
>> +//! bindings,
>> +//! clist_create,
>> +//! types::Opaque,
>> +//! };
>> +//! # // Create test list with values (0, 10, 20) - normally done by C code
>> but it is
>> +//! # // emulated here for doctests using the C bindings.
>> +//! # use core::mem::MaybeUninit;
>> +//! #
>> +//! # /// C struct with embedded `list_head` (typically will be allocated
>> by C code).
>> +//! # #[repr(C)]
>> +//! # pub struct SampleItemC {
>> +//! # pub value: i32,
>> +//! # pub link: bindings::list_head,
>> +//! # }
>> +//! #
>> +//! # let mut head = MaybeUninit::<bindings::list_head>::uninit();
>> +//! #
>> +//! # let head = head.as_mut_ptr();
>> +//! # // SAFETY: `head` and all the items are test objects allocated in
>> this scope.
>> +//! # unsafe { bindings::INIT_LIST_HEAD(head) };
>> +//! #
>> +//! # let mut items = [
>> +//! # MaybeUninit::<SampleItemC>::uninit(),
>> +//! # MaybeUninit::<SampleItemC>::uninit(),
>> +//! # MaybeUninit::<SampleItemC>::uninit(),
>> +//! # ];
>> +//! #
>> +//! # for (i, item) in items.iter_mut().enumerate() {
>> +//! # let ptr = item.as_mut_ptr();
>> +//! # // SAFETY: `ptr` points to a valid `MaybeUninit<SampleItemC>`.
>> +//! # unsafe { (*ptr).value = i as i32 * 10 };
>> +//! # // SAFETY: `&raw mut` creates a pointer valid for
>> `INIT_LIST_HEAD`.
>> +//! # unsafe { bindings::INIT_LIST_HEAD(&raw mut (*ptr).link) };
>> +//! # // SAFETY: `link` was just initialized and `head` is a valid list
>> head.
>> +//! # unsafe { bindings::list_add_tail(&mut (*ptr).link, head) };
>> +//! # }
>> +//!
>> +//! //
>> +//! /// Rust wrapper for the C struct.
>> +//! ///
>> +//! /// The list item struct in this example is defined in C code as:
>> +//! ///
>> +//! /// ```c
>> +//! /// struct SampleItemC {
>> +//! /// int value;
>> +//! /// struct list_head link;
>> +//! /// };
>> +//! /// ```
>> +//! #[repr(transparent)]
>> +//! pub struct Item(Opaque<SampleItemC>);
>> +//!
>> +//! impl Item {
>> +//! pub fn value(&self) -> i32 {
>> +//! // SAFETY: `Item` has same layout as `SampleItemC`.
>> +//! unsafe { (*self.0.get()).value }
>> +//! }
>> +//! }
>> +//!
>> +//!
>> +//! // Create typed [`CList`] from sentinel head.
>> +//! // SAFETY: `head` is valid and initialized, items are `SampleItemC` with
>> +//! // embedded `link` field, and `Item` is `#[repr(transparent)]` over
>> `SampleItemC`.
>> +//! let list = clist_create!(unsafe { head, Item, SampleItemC, link });
>
> Bad news.
>
> My build triggers this warning:
>
> error: statement has unnecessary safety comment
> --> rust/doctests_kernel_generated.rs:7103:1
> |
> 7103 | let list = clist_create!(unsafe { head, Item, SampleItemC, link });
> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> |
> help: consider removing the safety comment
> --> rust/doctests_kernel_generated.rs:7101:4
> |
> 7101 | // SAFETY: `head` is valid and initialized, items are `SampleItemC`
> with
> |
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> = help: for further information visit
> https://rust-lang.github.io/rust-clippy/rust-1.94.0/index.html#unnecessary_safety_comment
> = note: `-D clippy::unnecessary-safety-comment` implied by `-D warnings`
> = help: to override `-D warnings` add
> `#[allow(clippy::unnecessary_safety_comment)]`
>
> This probably needs to be:
>
> unsafe { clist_create!(head, Item, SampleItemC, link) }
Oops, I sometimes run clippy wrong. I did: "CLIPPY=1 make" instead of "make
CLIPPY=1", the reason is habit. I have been doing "LLVM=1 make" for llvm
builds since many years.
Anyway, the fix is simple, just need to do // SAFETY*: as Miguel suggests
here, instead of // SAFETY:
https://lore.kernel.org/all/caniq72kendyupnwmzmhejytjioeijuk_c-yqjk77dpid89l...@mail.gmail.com/
Should be easy to do on apply if Danilo doesn't mind. :) I verified on my
setup that it fixes it.
thanks,
--
Joel Fernandes