On Wed Nov 12, 2025 at 2:13 AM JST, Joel Fernandes wrote:
> Add an iteration layer on top of the basic list infrastructure,
> enabling iteration over the actual container items.
>
> Enables users to iterate over actual items without manually performing
> container_of operations. Provide macros to make caller's life easier.
>
> Signed-off-by: Joel Fernandes <[email protected]>
> ---
>  rust/kernel/clist.rs | 210 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 207 insertions(+), 3 deletions(-)
>
> diff --git a/rust/kernel/clist.rs b/rust/kernel/clist.rs
> index 5ea505d463ad..01b78ba157a1 100644
> --- a/rust/kernel/clist.rs
> +++ b/rust/kernel/clist.rs
> @@ -2,17 +2,104 @@
>  
>  //! A C doubly circular intrusive linked list interface for rust code.
>  //!
> -//! TODO: Doctest example will be added in later commit in series due to 
> dependencies.
> +//! # Examples
> +//!
> +//! ```
> +//! use kernel::{bindings, clist::Clist, clist_iterate, impl_from_list_head, 
> 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(crate) struct SampleItemC {
> +//! #     pub value: i32,
> +//! #     pub link: bindings::list_head,
> +//! # }
> +//! #
> +//! # let mut head = MaybeUninit::<bindings::list_head>::uninit();
> +//! #
> +//! # // SAFETY: head and all the items are test objects allocated in this 
> scope.
> +//! # unsafe { bindings::INIT_LIST_HEAD(head.as_mut_ptr()) };
> +//! # // SAFETY: head is a test object allocated in this scope.
> +//! # let mut head = unsafe { head.assume_init() };
> +//! # 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: pointers are to allocated test objects with a list_head 
> field.
> +//! #     unsafe {
> +//! #         (*ptr).value = i as i32 * 10;
> +//! #         bindings::INIT_LIST_HEAD(&mut (*ptr).link);
> +//! #         bindings::list_add_tail(&mut (*ptr).link, &mut head);
> +//! #     }
> +//! # }
> +//!
> +//! // Rust wrapper for the C struct.
> +//! // The list item struct in this example is defined in C code as:
> +//! //   struct SampleItemC {
> +//! //       int value;
> +//! //       struct list_head link;
> +//! //   };
> +//! //
> +//! #[repr(transparent)]
> +//! pub(crate) struct Item(Opaque<SampleItemC>);
> +//!
> +//! // Generate the link type.
> +//! impl_from_list_head!(pub(crate), Item, SampleItemC, link);
> +//!
> +//! impl Item {
> +//!     pub(crate) fn value(&self) -> i32 {
> +//!         // SAFETY: Item has same layout as SampleItemC.
> +//!         unsafe { (*self.0.get()).value }
> +//!     }
> +//! }
> +//!
> +//! // Create Clist (from a sentinel head).
> +//! // SAFETY: head is allocated by test code and Clist has the same layout.
> +//! let list = unsafe { Clist::from_raw(&mut head) };
> +//!
> +//! // Now iterate using clist_iterate! macro.
> +//! let mut found_0 = false;
> +//! let mut found_10 = false;
> +//! let mut found_20 = false;
> +//!
> +//! for item in clist_iterate!(list, Item, link) {
> +//!     let val = item.value();
> +//!     if val == 0 { found_0 = true; }
> +//!     if val == 10 { found_10 = true; }
> +//!     if val == 20 { found_20 = true; }
> +//! }
> +//!
> +//! assert!(found_0 && found_10 && found_20);
> +//! ```
>  
>  use crate::{
>      bindings,
>      types::Opaque, //
>  };
> +use core::marker::PhantomData;

IIUC the typical order of imports is `core`, then `kernel`, then 
`crate` (here crate == kernel though), with a space between them.

> +
> +/// Trait for associating a link type with its container item type.
> +///
> +/// Implemented by "field link types" that are `list_head` links embedded in 
> intrusive
> +/// C linked lists. Each link type is unique to a specific item type and its 
> `list_head` field,
> +/// making it possible for an item to be added to multiple lists.
> +pub trait ClistLink {
> +    /// The item type that contains the `list_head` field linking to other 
> items in the list.
> +    type Item: FromListHead<Self>
> +    where
> +        Self: Sized;
> +}
>  
>  /// A C linked list with a sentinel head
>  ///
> -/// A sentinel head is one which is not embedded in an item. It represents 
> the entire
> -/// linked list and can be used for add, remove, empty operations etc.
> +/// Represents the entire linked list and can be used for add, remove, empty 
> operations etc.
> +/// A sentinel head is one which is not embedded in an item.

This comment changes, but its substance remains the same - let's get its
final form in the previous patch?

>  ///
>  /// # Invariants
>  ///
> @@ -69,6 +156,15 @@ pub fn iter_heads(&self) -> ClistHeadIter<'_> {
>              head: &self.0,
>          }
>      }
> +
> +    /// Create a high-level iterator over typed items.
> +    #[inline]
> +    pub fn iter<L: ClistLink>(&self) -> ClistIter<'_, L> {
> +        ClistIter {
> +            head_iter: self.iter_heads(),
> +            _phantom: PhantomData,
> +        }
> +    }

This looks very dangerous, as it gives any caller the freedom to specify
the type they want to upcast the `Clist` to, without using unsafe code.
One could easily invoke this with the wrong type and get no build error
or warning whatsoever.

A safer version would have the `Clist` generic over the kind of
conversion that needs to be performed, using e.g. a closure:

  pub struct Clist<'a, T, C: Fn(*mut bindings::list_head) -> *mut T> {
      head: &'a ClistHead,
      conv: C,
  }

`from_raw` would also take the closure as argument, which forces the
creator of the list to both specify what that list is for, and use an
`unsafe` statement for unsafe code. Here is a dummy example:

    let head: bindings::list_head = ...;

    // SAFETY: list_head always corresponds to the `list` member of
    // `type_embedding_list_head`.
    let conv = |head: *mut bindings::list_head| unsafe {
        crate::container_of!(head, type_embedding_list_head, list)
    };

    // SAFETY: ...
    unsafe { Clist::from_raw(head, conv) }

Then `conv` would be passed down to the `ClistIter` so it can return
references to the correct type.

By doing so you can remove the `ClinkList` and `FromListHead` traits,
the `impl_from_list_head` and `clist_iterate` macros, as well as the
hidden ad-hoc types these create. And importantly, all unsafe code must
be explicitly specified in an `unsafe` block, nothing is hidden by
macros.

This approach works better imho because each `list_head` is unique in
how it has to be iterated: there is no benefit in implementing things
using types and traits that will only ever be used in a single place
anyway. And if there was, we could always create a newtype for that.

Also as I suspected in v1 `Clist` appears to do very little apart from
providing an iterator, so I'm more convinced that the front type for
this should be `ClistHead`.

>  }
>  
>  /// Wraps a non-sentinel C `list_head` node for use in intrusive linked 
> lists.
> @@ -188,3 +284,111 @@ fn next(&mut self) -> Option<Self::Item> {
>          Some(self.current)
>      }
>  }
> +
> +/// High-level iterator over typed list items.
> +pub struct ClistIter<'a, L: ClistLink> {
> +    head_iter: ClistHeadIter<'a>,
> +
> +    /// The iterator yields immutable references to `L::Item`.
> +    _phantom: PhantomData<&'a L::Item>,
> +}
> +
> +// SAFETY: ClistIter yields `&L::Item`, which is Send when `L::Item: Send`.
> +unsafe impl<L: ClistLink> Send for ClistIter<'_, L> where L::Item: Send {}
> +
> +// SAFETY: ClistIter yields &L::Item, which is Sync when `L::Item: Sync`.
> +unsafe impl<L: ClistLink> Sync for ClistIter<'_, L> where L::Item: Sync {}

These implementations should also be automatic.

> +
> +impl<'a, L: ClistLink> Iterator for ClistIter<'a, L>
> +where
> +    L::Item: 'a,
> +{
> +    type Item = &'a L::Item;

This is going to work well when we want to parse lists read-only. But
I've also seen in some comments that you were considering supporting
addition and deletion of items?

In that case we will probably want to return some sort of guard type
that derefs to `Item` (similar to a mutex guard), while also providing
list management operations. We will probably also want distinct types
for read-only and read-modify behavior. I think this can be done later,
but better to keep this in mind when designing things.

> +
> +    fn next(&mut self) -> Option<Self::Item> {
> +        // Get next ClistHead.
> +        let head = self.head_iter.next()?;
> +
> +        // Convert to item using trait.
> +        // SAFETY: FromListHead impl guarantees valid conversion.
> +        Some(unsafe { L::Item::from_list_head(head) })

More idiomatic proposal:

    self.head_iter.next().map(|head| {
        // SAFETY: The FromListHead impl guarantees valid conversion.
        unsafe { L::Item::from_list_head(head) }
    })

Note that since kernel lists are bi-directional, you can also implement
`DoubleEndedIterator`!

Reply via email to