Re: [PATCH v13 1/1] rust: interop: Add list module for C linked list interface
From: Joel Fernandes <joelagnelf@nvidia.com>
Date: 2026-03-18 18:31:50
Also in:
amd-gfx, dri-devel, intel-gfx, intel-xe, linux-doc, lkml, rust-for-linux
On 3/18/2026 8:40 AM, Alice Ryhl wrote:
On Tue, Mar 17, 2026 at 04:17:10PM -0400, Joel Fernandes wrote:quoted
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 <redacted> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Acked-by: Alexandre Courbot <acourbot@nvidia.com> Acked-by: Gary Guo <gary@garyguo.net> Acked-by: Miguel Ojeda <ojeda@kernel.org> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com> --- 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.rsdiff --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 <joelagnelf@nvidia.com> +M: Alexandre Courbot <acourbot@nvidia.com> +L: rust-for-linux@vger.kernel.org +S: Maintained +T: git https://github.com/Rust-for-Linux/linux.git interop-next +F: rust/kernel/interop/ + RUST [NUM] M: Alexandre Courbot <acourbot@nvidia.com> R: Yury Norov <yury.norov@gmail.com>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-yQJk77dPid89LExw@mail.gmail.com/ (local) Should be easy to do on apply if Danilo doesn't mind. :) I verified on my setup that it fixes it. thanks, -- Joel Fernandes