Commit 96fff2dc authored by Kartik Prajapati's avatar Kartik Prajapati Committed by Miguel Ojeda
Browse files

rust: types: add `ARef::into_raw`

Add a method for `ARef` that is analogous to `Arc::into_raw`. It is the
inverse operation of `ARef::from_raw`, and allows you to convert the
`ARef` back into a raw pointer while retaining ownership of the
refcount.

This new function will be used by [1] for converting the type in an
`ARef` using `ARef::from_raw(ARef::into_raw(me).cast())`. Alice has
also needed the same function for other use-cases in the past, but [1]
is the first to go upstream.

This was implemented independently by Kartik and Alice. The two versions
were merged by Alice, so all mistakes are Alice's.

Link: https://lore.kernel.org/r/20240801-vma-v3-1-db6c1c0afda9@google.com [1]
Link: https://github.com/Rust-for-Linux/linux/issues/1044


Signed-off-by: default avatarKartik Prajapati <kartikprajapati987@gmail.com>
Co-developed-by: default avatarAlice Ryhl <aliceryhl@google.com>
Signed-off-by: default avatarAlice Ryhl <aliceryhl@google.com>
Reviewed-by: default avatarBenno Lossin <benno.lossin@proton.me>
[ Reworded to correct the author reference and changed tag to Link
  since it is not a bug. - Miguel ]
Signed-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
parent c7305116
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
use core::{
    cell::UnsafeCell,
    marker::{PhantomData, PhantomPinned},
    mem::MaybeUninit,
    mem::{ManuallyDrop, MaybeUninit},
    ops::{Deref, DerefMut},
    pin::Pin,
    ptr::NonNull,
@@ -396,6 +396,35 @@ pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
            _p: PhantomData,
        }
    }

    /// Consumes the `ARef`, returning a raw pointer.
    ///
    /// This function does not change the refcount. After calling this function, the caller is
    /// responsible for the refcount previously managed by the `ARef`.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::ptr::NonNull;
    /// use kernel::types::{ARef, AlwaysRefCounted};
    ///
    /// struct Empty {}
    ///
    /// unsafe impl AlwaysRefCounted for Empty {
    ///     fn inc_ref(&self) {}
    ///     unsafe fn dec_ref(_obj: NonNull<Self>) {}
    /// }
    ///
    /// let mut data = Empty {};
    /// let ptr = NonNull::<Empty>::new(&mut data as *mut _).unwrap();
    /// let data_ref: ARef<Empty> = unsafe { ARef::from_raw(ptr) };
    /// let raw_ptr: NonNull<Empty> = ARef::into_raw(data_ref);
    ///
    /// assert_eq!(ptr, raw_ptr);
    /// ```
    pub fn into_raw(me: Self) -> NonNull<T> {
        ManuallyDrop::new(me).ptr
    }
}

impl<T: AlwaysRefCounted> Clone for ARef<T> {