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) }
Alice