[PATCH 03/10] rust: xarray: add `contains_index` method

Andreas Hindborg posted 10 patches 2 months ago
There is a newer version of this series
[PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Andreas Hindborg 2 months ago
Add a convenience method `contains_index` to check whether an element
exists at a given index in the XArray. This method provides a more
ergonomic API compared to calling `get` and checking for `Some`.

Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
 rust/kernel/xarray.rs | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/rust/kernel/xarray.rs b/rust/kernel/xarray.rs
index d9762c6bef19c..ede48b5e1dba3 100644
--- a/rust/kernel/xarray.rs
+++ b/rust/kernel/xarray.rs
@@ -218,6 +218,27 @@ fn load<F, U>(&self, index: usize, f: F) -> Option<U>
         Some(f(ptr))
     }
 
+    /// Checks if the XArray contains an element at the specified index.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use kernel::{alloc::{flags::GFP_KERNEL, kbox::KBox}, xarray::{AllocKind, XArray}};
+    /// let xa = KBox::pin_init(XArray::new(AllocKind::Alloc), GFP_KERNEL)?;
+    ///
+    /// let mut guard = xa.lock();
+    /// assert_eq!(guard.contains_index(42), false);
+    ///
+    /// guard.store(42, KBox::new(0u32, GFP_KERNEL)?, GFP_KERNEL)?;
+    ///
+    /// assert_eq!(guard.contains_index(42), true);
+    ///
+    /// # Ok::<(), kernel::error::Error>(())
+    /// ```
+    pub fn contains_index(&self, index: usize) -> bool {
+        self.get(index).is_some()
+    }
+
     /// Provides a reference to the element at the given index.
     pub fn get(&self, index: usize) -> Option<T::Borrowed<'_>> {
         self.load(index, |ptr| {

-- 
2.51.2
Re: [PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Tamir Duberstein 1 month, 1 week ago
On Wed, Dec 3, 2025 at 5:27 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> Add a convenience method `contains_index` to check whether an element
> exists at a given index in the XArray. This method provides a more
> ergonomic API compared to calling `get` and checking for `Some`.

It isn't clear when you'd want this API, and neither this nor the
example are particularly motivating.

>
> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
> ---
>  rust/kernel/xarray.rs | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
>
> diff --git a/rust/kernel/xarray.rs b/rust/kernel/xarray.rs
> index d9762c6bef19c..ede48b5e1dba3 100644
> --- a/rust/kernel/xarray.rs
> +++ b/rust/kernel/xarray.rs
> @@ -218,6 +218,27 @@ fn load<F, U>(&self, index: usize, f: F) -> Option<U>
>          Some(f(ptr))
>      }
>
> +    /// Checks if the XArray contains an element at the specified index.
> +    ///
> +    /// # Examples
> +    ///
> +    /// ```
> +    /// # use kernel::{alloc::{flags::GFP_KERNEL, kbox::KBox}, xarray::{AllocKind, XArray}};
> +    /// let xa = KBox::pin_init(XArray::new(AllocKind::Alloc), GFP_KERNEL)?;
> +    ///
> +    /// let mut guard = xa.lock();
> +    /// assert_eq!(guard.contains_index(42), false);
> +    ///
> +    /// guard.store(42, KBox::new(0u32, GFP_KERNEL)?, GFP_KERNEL)?;
> +    ///
> +    /// assert_eq!(guard.contains_index(42), true);
> +    ///
> +    /// # Ok::<(), kernel::error::Error>(())
> +    /// ```
> +    pub fn contains_index(&self, index: usize) -> bool {
> +        self.get(index).is_some()
> +    }
> +
>      /// Provides a reference to the element at the given index.
>      pub fn get(&self, index: usize) -> Option<T::Borrowed<'_>> {
>          self.load(index, |ptr| {
>
> --
> 2.51.2
>
>
Re: [PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Andreas Hindborg 1 month ago
Tamir Duberstein <tamird@gmail.com> writes:

> On Wed, Dec 3, 2025 at 5:27 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>
>> Add a convenience method `contains_index` to check whether an element
>> exists at a given index in the XArray. This method provides a more
>> ergonomic API compared to calling `get` and checking for `Some`.
>
> It isn't clear when you'd want this API, and neither this nor the
> example are particularly motivating.

I added this when I had a line reading `if xa.get(index).is_none()
{...}`. I think it reads better as `if !xa.contains_index(index) {...}`.

Do you have an idea of how to improve the motivational factor of the
example? Writing motivating examples is not my top skill.


Best regards,
Andreas Hindborg
Re: [PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Tamir Duberstein 1 month ago
On Wed, Jan 7, 2026 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> Tamir Duberstein <tamird@gmail.com> writes:
>
> > On Wed, Dec 3, 2025 at 5:27 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
> >>
> >> Add a convenience method `contains_index` to check whether an element
> >> exists at a given index in the XArray. This method provides a more
> >> ergonomic API compared to calling `get` and checking for `Some`.
> >
> > It isn't clear when you'd want this API, and neither this nor the
> > example are particularly motivating.
>
> I added this when I had a line reading `if xa.get(index).is_none()
> {...}`. I think it reads better as `if !xa.contains_index(index) {...}`.

What was the code surrounding it?

> Do you have an idea of how to improve the motivational factor of the
> example? Writing motivating examples is not my top skill.

IMO writing a better example is not the issue; rather it would be good
to understand why you need it. In my experience `Option::is_none` is a
smell, but hard to say without seeing the surrounding code.

> Best regards,
> Andreas Hindborg
>
>
Re: [PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Andreas Hindborg 1 month ago
Tamir Duberstein <tamird@gmail.com> writes:

> On Wed, Jan 7, 2026 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>
>> Tamir Duberstein <tamird@gmail.com> writes:
>>
>> > On Wed, Dec 3, 2025 at 5:27 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>> >>
>> >> Add a convenience method `contains_index` to check whether an element
>> >> exists at a given index in the XArray. This method provides a more
>> >> ergonomic API compared to calling `get` and checking for `Some`.
>> >
>> > It isn't clear when you'd want this API, and neither this nor the
>> > example are particularly motivating.
>>
>> I added this when I had a line reading `if xa.get(index).is_none()
>> {...}`. I think it reads better as `if !xa.contains_index(index) {...}`.
>
> What was the code surrounding it?
>
>> Do you have an idea of how to improve the motivational factor of the
>> example? Writing motivating examples is not my top skill.
>
> IMO writing a better example is not the issue; rather it would be good
> to understand why you need it. In my experience `Option::is_none` is a
> smell, but hard to say without seeing the surrounding code.

    fn get_cache_page(&mut self, sector: u64) -> Result<&mut NullBlockPage> {
        let index = Self::to_index(sector);

        if self.cache_guard.contains_index(index) {
            Ok(self.cache_guard.get_mut(index).expect("Index is present"))
        } else {
            let page = if self.disk_storage.cache_size_used.load(ordering::Relaxed)
                < self.disk_storage.cache_size
            {
                self.hw_data_guard
                    .page
                    .take()
                    .expect("Expected to have a page available")
            } else {
                self.extract_cache_page()?
            };
            Ok(self
                .cache_guard
                .insert_entry(index, page, Some(&mut self.hw_data_guard.preload))
                .expect("Should be able to insert")
                .into_mut())
        }
    }

For lifetime reasons, I cannot borrow `self` in the taken arm.


Best regards,
Andreas Hindborg
Re: [PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Tamir Duberstein 1 month ago
On Thu, Jan 8, 2026 at 4:38 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> Tamir Duberstein <tamird@gmail.com> writes:
>
> > On Wed, Jan 7, 2026 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
> >>
> >> Tamir Duberstein <tamird@gmail.com> writes:
> >>
> >> > On Wed, Dec 3, 2025 at 5:27 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
> >> >>
> >> >> Add a convenience method `contains_index` to check whether an element
> >> >> exists at a given index in the XArray. This method provides a more
> >> >> ergonomic API compared to calling `get` and checking for `Some`.
> >> >
> >> > It isn't clear when you'd want this API, and neither this nor the
> >> > example are particularly motivating.
> >>
> >> I added this when I had a line reading `if xa.get(index).is_none()
> >> {...}`. I think it reads better as `if !xa.contains_index(index) {...}`.
> >
> > What was the code surrounding it?
> >
> >> Do you have an idea of how to improve the motivational factor of the
> >> example? Writing motivating examples is not my top skill.
> >
> > IMO writing a better example is not the issue; rather it would be good
> > to understand why you need it. In my experience `Option::is_none` is a
> > smell, but hard to say without seeing the surrounding code.
>
>     fn get_cache_page(&mut self, sector: u64) -> Result<&mut NullBlockPage> {
>         let index = Self::to_index(sector);
>
>         if self.cache_guard.contains_index(index) {
>             Ok(self.cache_guard.get_mut(index).expect("Index is present"))
>         } else {
>             let page = if self.disk_storage.cache_size_used.load(ordering::Relaxed)
>                 < self.disk_storage.cache_size
>             {
>                 self.hw_data_guard
>                     .page
>                     .take()
>                     .expect("Expected to have a page available")
>             } else {
>                 self.extract_cache_page()?
>             };
>             Ok(self
>                 .cache_guard
>                 .insert_entry(index, page, Some(&mut self.hw_data_guard.preload))
>                 .expect("Should be able to insert")
>                 .into_mut())
>         }
>     }
>
> For lifetime reasons, I cannot borrow `self` in the taken arm.

That's surprising. Couldn't you destructure Self so that all the
references derive from the single mutable reference &mut self?

>
>
> Best regards,
> Andreas Hindborg
>
>
Re: [PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Andreas Hindborg 4 weeks, 1 day ago
"Tamir Duberstein" <tamird@gmail.com> writes:

> On Thu, Jan 8, 2026 at 4:38 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>
>> Tamir Duberstein <tamird@gmail.com> writes:
>>
>> > On Wed, Jan 7, 2026 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>> >>
>> >> Tamir Duberstein <tamird@gmail.com> writes:
>> >>
>> >> > On Wed, Dec 3, 2025 at 5:27 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>> >> >>
>> >> >> Add a convenience method `contains_index` to check whether an element
>> >> >> exists at a given index in the XArray. This method provides a more
>> >> >> ergonomic API compared to calling `get` and checking for `Some`.
>> >> >
>> >> > It isn't clear when you'd want this API, and neither this nor the
>> >> > example are particularly motivating.
>> >>
>> >> I added this when I had a line reading `if xa.get(index).is_none()
>> >> {...}`. I think it reads better as `if !xa.contains_index(index) {...}`.
>> >
>> > What was the code surrounding it?
>> >
>> >> Do you have an idea of how to improve the motivational factor of the
>> >> example? Writing motivating examples is not my top skill.
>> >
>> > IMO writing a better example is not the issue; rather it would be good
>> > to understand why you need it. In my experience `Option::is_none` is a
>> > smell, but hard to say without seeing the surrounding code.
>>
>>     fn get_cache_page(&mut self, sector: u64) -> Result<&mut NullBlockPage> {
>>         let index = Self::to_index(sector);
>>
>>         if self.cache_guard.contains_index(index) {
>>             Ok(self.cache_guard.get_mut(index).expect("Index is present"))
>>         } else {
>>             let page = if self.disk_storage.cache_size_used.load(ordering::Relaxed)
>>                 < self.disk_storage.cache_size
>>             {
>>                 self.hw_data_guard
>>                     .page
>>                     .take()
>>                     .expect("Expected to have a page available")
>>             } else {
>>                 self.extract_cache_page()?
>>             };
>>             Ok(self
>>                 .cache_guard
>>                 .insert_entry(index, page, Some(&mut self.hw_data_guard.preload))
>>                 .expect("Should be able to insert")
>>                 .into_mut())
>>         }
>>     }
>>
>> For lifetime reasons, I cannot borrow `self` in the taken arm.
>
> That's surprising. Couldn't you destructure Self so that all the
> references derive from the single mutable reference &mut self?

I don't think so, because I still need `&mut self` around to do the call
to `extract_cache_page`.


Best regards,
Andreas Hindborg
Re: [PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Tamir Duberstein 4 weeks, 1 day ago
On Fri, Jan 9, 2026 at 5:38 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> "Tamir Duberstein" <tamird@gmail.com> writes:
>
> > On Thu, Jan 8, 2026 at 4:38 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
> >>
> >> Tamir Duberstein <tamird@gmail.com> writes:
> >>
> >> > On Wed, Jan 7, 2026 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
> >> >>
> >> >> Tamir Duberstein <tamird@gmail.com> writes:
> >> >>
> >> >> > On Wed, Dec 3, 2025 at 5:27 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
> >> >> >>
> >> >> >> Add a convenience method `contains_index` to check whether an element
> >> >> >> exists at a given index in the XArray. This method provides a more
> >> >> >> ergonomic API compared to calling `get` and checking for `Some`.
> >> >> >
> >> >> > It isn't clear when you'd want this API, and neither this nor the
> >> >> > example are particularly motivating.
> >> >>
> >> >> I added this when I had a line reading `if xa.get(index).is_none()
> >> >> {...}`. I think it reads better as `if !xa.contains_index(index) {...}`.
> >> >
> >> > What was the code surrounding it?
> >> >
> >> >> Do you have an idea of how to improve the motivational factor of the
> >> >> example? Writing motivating examples is not my top skill.
> >> >
> >> > IMO writing a better example is not the issue; rather it would be good
> >> > to understand why you need it. In my experience `Option::is_none` is a
> >> > smell, but hard to say without seeing the surrounding code.
> >>
> >>     fn get_cache_page(&mut self, sector: u64) -> Result<&mut NullBlockPage> {
> >>         let index = Self::to_index(sector);
> >>
> >>         if self.cache_guard.contains_index(index) {
> >>             Ok(self.cache_guard.get_mut(index).expect("Index is present"))
> >>         } else {
> >>             let page = if self.disk_storage.cache_size_used.load(ordering::Relaxed)
> >>                 < self.disk_storage.cache_size
> >>             {
> >>                 self.hw_data_guard
> >>                     .page
> >>                     .take()
> >>                     .expect("Expected to have a page available")
> >>             } else {
> >>                 self.extract_cache_page()?
> >>             };
> >>             Ok(self
> >>                 .cache_guard
> >>                 .insert_entry(index, page, Some(&mut self.hw_data_guard.preload))
> >>                 .expect("Should be able to insert")
> >>                 .into_mut())
> >>         }
> >>     }
> >>
> >> For lifetime reasons, I cannot borrow `self` in the taken arm.
> >
> > That's surprising. Couldn't you destructure Self so that all the
> > references derive from the single mutable reference &mut self?
>
> I don't think so, because I still need `&mut self` around to do the call
> to `extract_cache_page`.

Hmm, I must have missed it before, but can't this all be fixed with an
early return?

         if let Some(page) = self.cache_guard.get_mut(index) {
             return Ok(page);
         }

>
>
> Best regards,
> Andreas Hindborg
>
>
>
Re: [PATCH 03/10] rust: xarray: add `contains_index` method
Posted by Gary Guo 4 weeks, 1 day ago
On Fri Jan 9, 2026 at 3:59 PM GMT, Tamir Duberstein wrote:
> On Fri, Jan 9, 2026 at 5:38 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>
>> "Tamir Duberstein" <tamird@gmail.com> writes:
>>
>> > On Thu, Jan 8, 2026 at 4:38 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>> >>
>> >> Tamir Duberstein <tamird@gmail.com> writes:
>> >>
>> >> > On Wed, Jan 7, 2026 at 1:34 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>> >> >>
>> >> >> Tamir Duberstein <tamird@gmail.com> writes:
>> >> >>
>> >> >> > On Wed, Dec 3, 2025 at 5:27 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>> >> >> >>
>> >> >> >> Add a convenience method `contains_index` to check whether an element
>> >> >> >> exists at a given index in the XArray. This method provides a more
>> >> >> >> ergonomic API compared to calling `get` and checking for `Some`.
>> >> >> >
>> >> >> > It isn't clear when you'd want this API, and neither this nor the
>> >> >> > example are particularly motivating.
>> >> >>
>> >> >> I added this when I had a line reading `if xa.get(index).is_none()
>> >> >> {...}`. I think it reads better as `if !xa.contains_index(index) {...}`.
>> >> >
>> >> > What was the code surrounding it?
>> >> >
>> >> >> Do you have an idea of how to improve the motivational factor of the
>> >> >> example? Writing motivating examples is not my top skill.
>> >> >
>> >> > IMO writing a better example is not the issue; rather it would be good
>> >> > to understand why you need it. In my experience `Option::is_none` is a
>> >> > smell, but hard to say without seeing the surrounding code.
>> >>
>> >>     fn get_cache_page(&mut self, sector: u64) -> Result<&mut NullBlockPage> {
>> >>         let index = Self::to_index(sector);
>> >>
>> >>         if self.cache_guard.contains_index(index) {
>> >>             Ok(self.cache_guard.get_mut(index).expect("Index is present"))
>> >>         } else {
>> >>             let page = if self.disk_storage.cache_size_used.load(ordering::Relaxed)
>> >>                 < self.disk_storage.cache_size
>> >>             {
>> >>                 self.hw_data_guard
>> >>                     .page
>> >>                     .take()
>> >>                     .expect("Expected to have a page available")
>> >>             } else {
>> >>                 self.extract_cache_page()?
>> >>             };
>> >>             Ok(self
>> >>                 .cache_guard
>> >>                 .insert_entry(index, page, Some(&mut self.hw_data_guard.preload))
>> >>                 .expect("Should be able to insert")
>> >>                 .into_mut())
>> >>         }
>> >>     }
>> >>
>> >> For lifetime reasons, I cannot borrow `self` in the taken arm.
>> >
>> > That's surprising. Couldn't you destructure Self so that all the
>> > references derive from the single mutable reference &mut self?
>>
>> I don't think so, because I still need `&mut self` around to do the call
>> to `extract_cache_page`.
>
> Hmm, I must have missed it before, but can't this all be fixed with an
> early return?
>
>          if let Some(page) = self.cache_guard.get_mut(index) {
>              return Ok(page);
>          }

The returned lifetime needs to be same as the lifetime of `&mut self` (let's
call it `'self`). This would mean that `get_mut` would also need to borrow it
for `'self` (mutably), so it cannot be borrowed again, mutably or otherwise,
later in the function. This is a classical category of borrowck false positives
that only Polonoius can address, not the current generation of borrow checker.

Best,
Gary