Re: [PATCH v7 16/31] rust: ptr: add const_align_up()
From: Alice Ryhl
Date: Fri Mar 20 2026 - 05:08:20 EST
On Fri, Mar 20, 2026 at 9:58 AM David Rheinsberg <david@xxxxxxxxxxxx> wrote:
>
> Hi
>
> On Fri, Mar 20, 2026, at 9:44 AM, Alice Ryhl wrote:
> > On Fri, Mar 20, 2026 at 9:38 AM David Rheinsberg <david@xxxxxxxxxxxx> 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@xxxxxxxxxx>
> >> > Suggested-by: Gary Guo <gary@xxxxxxxxxxx>
> >> > Suggested-by: Miguel Ojeda <ojeda@xxxxxxxxxx>
> >> > Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx>
> >> > ---
> >> > 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.
>
> My bad! If alignment is below `usize::MAX / 2` then this always works. Once alignment gets bigger, the function fails, though. The following assertion does not hold:
>
> assert_eq!(const_align_up(usize::MAX - 1, (usize::MAX - 1).into()), Some(usize::MAX - 1));
>
> Doesn't matter too much, I guess, but with `checked_next_multiple_of()` this assertion holds.
The Alignment type can only hold values that are a power of two.
> >> 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.
>
> You sure? (emphasis mine:)
>
> "Calculates the smallest value greater than or **EQUAL TO** self that is a multiple of rhs."
>
> assert_eq!(16_u64.next_multiple_of(8), 16);
Okay, well, weird naming then.
Alice