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
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
>
>
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
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
>
>
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
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
>
>
"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
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
>
>
>
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
© 2016 - 2026 Red Hat, Inc.