[PATCH v7 16/31] rust: ptr: add const_align_up()

John Hubbard posted 31 patches 2 weeks, 5 days ago
There is a newer version of this series
[PATCH v7 16/31] rust: ptr: add const_align_up()
Posted by John Hubbard 2 weeks, 5 days ago
Add const_align_up() to kernel::ptr as the const-compatible equivalent
of Alignable::align_up().

Suggested-by: Danilo Krummrich <dakr@kernel.org>
Suggested-by: Gary Guo <gary@garyguo.net>
Suggested-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
 rust/kernel/ptr.rs | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
index bdc2d79ff669..7e99f129543b 100644
--- a/rust/kernel/ptr.rs
+++ b/rust/kernel/ptr.rs
@@ -253,3 +253,27 @@ fn size(p: *const Self) -> usize {
         p.len() * size_of::<T>()
     }
 }
+
+/// Aligns `value` up to `align`.
+///
+/// This is the const-compatible equivalent of [`Alignable::align_up`].
+///
+/// Returns [`None`] on overflow.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::ptr::{const_align_up, Alignment};
+/// use kernel::sizes::SZ_4K;
+///
+/// assert_eq!(const_align_up(0x4f, Alignment::new::<16>()), Some(0x50));
+/// assert_eq!(const_align_up(0x40, Alignment::new::<16>()), Some(0x40));
+/// assert_eq!(const_align_up(1, Alignment::new::<SZ_4K>()), Some(SZ_4K));
+/// ```
+#[inline(always)]
+pub const fn const_align_up(value: usize, align: Alignment) -> Option<usize> {
+    match value.checked_add(align.as_usize() - 1) {
+        Some(v) => Some(v & align.mask()),
+        None => None,
+    }
+}
-- 
2.53.0
Re: [PATCH v7 16/31] rust: ptr: add const_align_up()
Posted by Alice Ryhl 2 weeks, 3 days ago
On Tue, Mar 17, 2026 at 11:54 PM John Hubbard <jhubbard@nvidia.com> wrote:
>
> Add const_align_up() to kernel::ptr as the const-compatible equivalent
> of Alignable::align_up().
>
> Suggested-by: Danilo Krummrich <dakr@kernel.org>
> Suggested-by: Gary Guo <gary@garyguo.net>
> Suggested-by: Miguel Ojeda <ojeda@kernel.org>
> Signed-off-by: John Hubbard <jhubbard@nvidia.com>

I think it would be nice to implement the trait versions of this in
terms of this method, so we only have one implementation.

Alice
Re: [PATCH v7 16/31] rust: ptr: add const_align_up()
Posted by Gary Guo 2 weeks, 3 days ago
On Fri Mar 20, 2026 at 9:48 AM GMT, Alice Ryhl wrote:
> On Tue, Mar 17, 2026 at 11:54 PM John Hubbard <jhubbard@nvidia.com> wrote:
>>
>> Add const_align_up() to kernel::ptr as the const-compatible equivalent
>> of Alignable::align_up().
>>
>> Suggested-by: Danilo Krummrich <dakr@kernel.org>
>> Suggested-by: Gary Guo <gary@garyguo.net>
>> Suggested-by: Miguel Ojeda <ojeda@kernel.org>
>> Signed-off-by: John Hubbard <jhubbard@nvidia.com>
>
> I think it would be nice to implement the trait versions of this in
> terms of this method, so we only have one implementation.
>
> Alice

The `align_up` is implemented for multiple integer types with macros, so I think
what we have right now is fine.

Best,
Gary
Re: [PATCH v7 16/31] rust: ptr: add const_align_up()
Posted by David Rheinsberg 2 weeks, 3 days ago
Hi

On Tue, Mar 17, 2026, at 11:53 PM, John Hubbard wrote:
> Add const_align_up() to kernel::ptr as the const-compatible equivalent
> of Alignable::align_up().
>
> Suggested-by: Danilo Krummrich <dakr@kernel.org>
> Suggested-by: Gary Guo <gary@garyguo.net>
> Suggested-by: Miguel Ojeda <ojeda@kernel.org>
> Signed-off-by: John Hubbard <jhubbard@nvidia.com>
> ---
>  rust/kernel/ptr.rs | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
> index bdc2d79ff669..7e99f129543b 100644
> --- a/rust/kernel/ptr.rs
> +++ b/rust/kernel/ptr.rs
> @@ -253,3 +253,27 @@ fn size(p: *const Self) -> usize {
>          p.len() * size_of::<T>()
>      }
>  }
> +
> +/// Aligns `value` up to `align`.
> +///
> +/// This is the const-compatible equivalent of [`Alignable::align_up`].
> +///
> +/// Returns [`None`] on overflow.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// use kernel::ptr::{const_align_up, Alignment};
> +/// use kernel::sizes::SZ_4K;
> +///
> +/// assert_eq!(const_align_up(0x4f, Alignment::new::<16>()), Some(0x50));
> +/// assert_eq!(const_align_up(0x40, Alignment::new::<16>()), Some(0x40));
> +/// assert_eq!(const_align_up(1, Alignment::new::<SZ_4K>()), Some(SZ_4K));
> +/// ```
> +#[inline(always)]
> +pub const fn const_align_up(value: usize, align: Alignment) -> Option<usize> {
> +    match value.checked_add(align.as_usize() - 1) {
> +        Some(v) => Some(v & align.mask()),
> +        None => None,
> +    }

This would return `None` if the value is already aligned, but the addition overflows `usize`, right? For instance, this would incorrectly return `None`: `const_align_up(usize::MAX - 1, 2.into())`

FYI, `core` provides `usize::checked_next_multiple_of()` ((const-)stable since 1.73). So an alternative would be:

pub const fn const_align_up(value: usize, align: Alignment) -> Option<usize> {
    value.checked_next_multiple_of(align.as_usize())
}

David
Re: [PATCH v7 16/31] rust: ptr: add const_align_up()
Posted by Alice Ryhl 2 weeks, 3 days ago
On Fri, Mar 20, 2026 at 9:38 AM David Rheinsberg <david@readahead.eu> wrote:
>
> Hi
>
> On Tue, Mar 17, 2026, at 11:53 PM, John Hubbard wrote:
> > Add const_align_up() to kernel::ptr as the const-compatible equivalent
> > of Alignable::align_up().
> >
> > Suggested-by: Danilo Krummrich <dakr@kernel.org>
> > Suggested-by: Gary Guo <gary@garyguo.net>
> > Suggested-by: Miguel Ojeda <ojeda@kernel.org>
> > Signed-off-by: John Hubbard <jhubbard@nvidia.com>
> > ---
> >  rust/kernel/ptr.rs | 24 ++++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >
> > diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
> > index bdc2d79ff669..7e99f129543b 100644
> > --- a/rust/kernel/ptr.rs
> > +++ b/rust/kernel/ptr.rs
> > @@ -253,3 +253,27 @@ fn size(p: *const Self) -> usize {
> >          p.len() * size_of::<T>()
> >      }
> >  }
> > +
> > +/// Aligns `value` up to `align`.
> > +///
> > +/// This is the const-compatible equivalent of [`Alignable::align_up`].
> > +///
> > +/// Returns [`None`] on overflow.
> > +///
> > +/// # Examples
> > +///
> > +/// ```
> > +/// use kernel::ptr::{const_align_up, Alignment};
> > +/// use kernel::sizes::SZ_4K;
> > +///
> > +/// assert_eq!(const_align_up(0x4f, Alignment::new::<16>()), Some(0x50));
> > +/// assert_eq!(const_align_up(0x40, Alignment::new::<16>()), Some(0x40));
> > +/// assert_eq!(const_align_up(1, Alignment::new::<SZ_4K>()), Some(SZ_4K));
> > +/// ```
> > +#[inline(always)]
> > +pub const fn const_align_up(value: usize, align: Alignment) -> Option<usize> {
> > +    match value.checked_add(align.as_usize() - 1) {
> > +        Some(v) => Some(v & align.mask()),
> > +        None => None,
> > +    }
>
> This would return `None` if the value is already aligned, but the addition overflows `usize`, right? For instance, this would incorrectly return `None`: `const_align_up(usize::MAX - 1, 2.into())`

No, in that case it computes `usize::MAX-1 + (2-1)` which is just
usize::MAX and does not overflow. After applying the mask, it returns
`usize::MAX-1` as the return value.

> FYI, `core` provides `usize::checked_next_multiple_of()` ((const-)stable since 1.73). So an alternative would be:
>
> pub const fn const_align_up(value: usize, align: Alignment) -> Option<usize> {
>     value.checked_next_multiple_of(align.as_usize())
> }

That would return value+align when value is already aligned, which is wrong.

Alice