Re: [PATCH v15 1/9] rust: types: Add Ownable/Owned types

From: Andreas Hindborg

Date: Tue Feb 24 2026 - 05:43:57 EST


<aliceryhl@xxxxxxxxxx> writes:

> On Mon, Feb 23, 2026 at 03:59:22PM +0100, Andreas Hindborg wrote:
>> Alice Ryhl <aliceryhl@xxxxxxxxxx> writes:
>>
>> > On Fri, Feb 20, 2026 at 10:51:10AM +0100, Andreas Hindborg wrote:
>> >> From: Asahi Lina <lina+kernel@xxxxxxxxxxxxx>
>> >>
>> >> By analogy to `AlwaysRefCounted` and `ARef`, an `Ownable` type is a
>> >> (typically C FFI) type that *may* be owned by Rust, but need not be. Unlike
>> >> `AlwaysRefCounted`, this mechanism expects the reference to be unique
>> >> within Rust, and does not allow cloning.
>> >>
>> >> Conceptually, this is similar to a `KBox<T>`, except that it delegates
>> >> resource management to the `T` instead of using a generic allocator.
>> >>
>> >> [ om:
>> >> - Split code into separate file and `pub use` it from types.rs.
>> >> - Make from_raw() and into_raw() public.
>> >> - Remove OwnableMut, and make DerefMut dependent on Unpin instead.
>> >> - Usage example/doctest for Ownable/Owned.
>> >> - Fixes to documentation and commit message.
>> >> ]
>> >>
>> >> Link: https://lore.kernel.org/all/20250202-rust-page-v1-1-e3170d7fe55e@xxxxxxxxxxxxx/
>> >> Signed-off-by: Asahi Lina <lina+kernel@xxxxxxxxxxxxx>
>> >> Co-developed-by: Oliver Mangold <oliver.mangold@xxxxx>
>> >> Signed-off-by: Oliver Mangold <oliver.mangold@xxxxx>
>> >> Reviewed-by: Boqun Feng <boqun.feng@xxxxxxxxx>
>> >> Reviewed-by: Daniel Almeida <daniel.almeida@xxxxxxxxxxxxx>
>> >> [ Andreas: Updated documentation, examples, and formatting ]
>> >> Reviewed-by: Gary Guo <gary@xxxxxxxxxxx>
>> >> Co-developed-by: Andreas Hindborg <a.hindborg@xxxxxxxxxx>
>> >> Signed-off-by: Andreas Hindborg <a.hindborg@xxxxxxxxxx>
>> >
>> >> +/// let result = NonNull::new(KBox::into_raw(result))
>> >> +/// .expect("Raw pointer to newly allocation KBox is null, this should never happen.");
>> >
>> > KBox should probably have an into_raw_nonnull().
>>
>> I can add that.
>>
>> >
>> >> +/// let foo = Foo::new().expect("Failed to allocate a Foo. This shouldn't happen");
>> >> +/// assert!(*FOO_ALLOC_COUNT.lock() == 1);
>> >
>> > Use ? here.
>>
>> Ok.
>>
>> >
>> >> +/// }
>> >> +/// // `foo` is out of scope now, so we expect no live allocations.
>> >> +/// assert!(*FOO_ALLOC_COUNT.lock() == 0);
>> >> +/// ```
>> >> +pub unsafe trait Ownable {
>> >> + /// Releases the object.
>> >> + ///
>> >> + /// # Safety
>> >> + ///
>> >> + /// Callers must ensure that:
>> >> + /// - `this` points to a valid `Self`.
>> >> + /// - `*this` is no longer used after this call.
>> >> + unsafe fn release(this: NonNull<Self>);
>> >
>> > Honestly, not using it after this call may be too strong. I can imagine
>> > wanting a value where I have both an ARef<_> and Owned<_> reference to
>> > something similar to the existing Arc<_>/ListArc<_> pattern, and in that
>> > case the value may in fact be accessed after this call if you still have
>> > an ARef<_>.
>>
>> I do not understand your use case.
>>
>> You are not supposed to have both an `ARef` and an `Owned` at the same
>> time. The `Owned` is to `ARef` what `UniqueArc` is to `Arc`. It is
>> supposed to be unique and no `ARef` can be live while the `Owned` is
>> live.
>>
>> A `ListArc` is "at most one per list link" and it takes a refcount on
>> the object by owning an `Arc`. As far as I recall, it does not provide
>> mutable access to anything but the list link. To me, that is a very
>> different situation.
>
> I mean, even Page is kind of an example like that.
>
> Pages are refcounted, but when you have a higher-order page, the
> __free_pages() call does something special beyond what put_page(). For
> example, if you have an order-2 page, which consists of 4 pages, then
> the refcount only keeps the first page alive, and __free_pages() frees
> the 3 extra pages right away even if refcount is still non-zero. The
> first page then stays alive until the last put_page() is called.

I see. We currently only support order 0 pages. I think we can handle
this situation later, if we need to handle higher order pages.

In that case, we could hand out `Owned<Page>` for the head page and then
provide some way of getting a `&Page` for the tail pages. Obtaining
`Owned<Page>` for a tail page does not make sense.

More likely we will build an abstraction for `struct folio`. We can
still hand some kind of page reference for tail pages from an `Owned<Folio>`.

Best regards,
Andreas Hindborg