rust: sync: arc: Implement DropRcu for Arc

We can actually reuse the `drop_rcu()` function of `Box` to implement
`DropRcu` for `Arc` since `Arc` is backed by `KBox`.

Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 289f77a..a9f2c98 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -18,9 +18,12 @@
 
 use crate::{
     alloc::{AllocError, Flags, KBox},
+    container_of,
     ffi::c_void,
+    field::HasField,
     fmt,
     init::InPlaceInit,
+    sync::rcu::{DropRcu, RcuHead},
     sync::Refcount,
     try_init,
     types::ForeignOwnable,
@@ -475,6 +478,68 @@ fn drop(&mut self) {
     }
 }
 
+// SAFETY: `ArcInner<T>` contains a `T` and `T` contains a `RcuHead`.
+unsafe impl<T> HasField<ArcInner<T>, RcuHead> for ArcInner<T>
+where
+    T: HasField<T, RcuHead>,
+{
+    unsafe fn field_container_of(ptr: *mut RcuHead) -> *mut Self {
+        // SAFETY: Per function safety requirement, `ptr` points to the `rcu_head` in `T` in an
+        // `ArcInner<T>`.
+        let obj = unsafe { T::field_container_of(ptr) };
+
+        // SAFETY: `obj` points to the `data` field of a `ArcInner<T>`.
+        unsafe { container_of!(obj, ArcInner<T>, data) }
+    }
+
+    unsafe fn raw_get_field(ptr: *mut Self) -> *mut RcuHead {
+        // SAFETY: Per function safety requirement, `ptr` is valid pointer of `ArcInner<T>`.
+        let obj = unsafe { &raw mut (*ptr).data };
+
+        // SAFETY: `obj` is a valid `T`.
+        unsafe { T::raw_get_field(obj) }
+    }
+}
+
+/// [`Arc<T>`] supports RCU async drop if `T` has [`RcuHead`] in it.
+///
+/// # Examples
+/// ```
+/// use kernel::sync::{Arc, rcu::{DropRcu, RcuHead, WithRcuHead}};
+///
+/// let arc = Arc::new(WithRcuHead::<i32>::new(42), GFP_KERNEL)?;
+///
+/// arc.drop_rcu(); // <- use kfree_rcu().
+///
+/// # Ok::<(), Error>(())
+/// ```
+impl<T: HasField<T, RcuHead> + Send + Sync + 'static> DropRcu for Arc<T> {
+    unsafe fn drop_rcu_ptr(ptr: *mut c_void) {
+        // CAST: `ptr` should points the `ArcInner<T>` per implementation of `ForeignOwnable`.
+        let ptr = ptr.cast::<ArcInner<T>>();
+
+        // INVARIANT: If the refcount reaches zero, there are no other instances of `Arc`, and
+        // this instance is being dropped, so the broken invariant is not observable.
+        // SAFETY: By the type invariant, there is necessarily a reference to the object.
+        let is_zero = unsafe { &*ptr }.refcount.dec_and_test();
+        if is_zero {
+            // SAFETY: The pointer was initialised from the result of `KBox::leak`.
+            unsafe { KBox::from_raw(ptr) }.drop_rcu();
+        }
+    }
+
+    type RcuBorrowed<'a> = &'a T;
+
+    unsafe fn rcu_borrow<'a>(ptr: *mut c_void) -> &'a T {
+        // CAST: `ptr` should points to a `ArcInner<T>` per the `ForeignOwnable` impl.
+        let ptr = ptr.cast::<ArcInner<T>>();
+
+        // SAFETY: `ptr` is a valid pointer and the function guarantees that returned reference is
+        // valid for a grace period.
+        unsafe { &(*ptr).data }
+    }
+}
+
 impl<T: ?Sized> From<UniqueArc<T>> for Arc<T> {
     fn from(item: UniqueArc<T>) -> Self {
         item.inner
diff --git a/rust/kernel/sync/rcu.rs b/rust/kernel/sync/rcu.rs
index 809eaa3..6d4f9de 100644
--- a/rust/kernel/sync/rcu.rs
+++ b/rust/kernel/sync/rcu.rs
@@ -308,3 +308,39 @@ unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> Self::BorrowedMut<'a> {
         unsafe { T::borrow_mut(ptr) }
     }
 }
+
+/// `RcuDrop<T>` impl `Clone` if `T: Clone`.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::sync::{Arc, rcu::{DropRcu, RcuDrop, RcuHead, read_lock, WithRcuHead}};
+/// use core::ops::Deref;
+///
+/// let rcu_drop = RcuDrop::new(Arc::new(WithRcuHead::<i32>::new(42), GFP_KERNEL)?);
+/// let cloned = rcu_drop.clone();
+///
+/// let g = read_lock();
+/// let w = cloned.with_rcu(&g).deref();
+///
+/// drop(cloned);
+/// drop(rcu_drop); // <- kfree_rcu()
+///
+/// assert_eq!(*w, 42);
+///
+/// # Ok::<(), Error>(())
+/// ```
+impl<T: DropRcu + Clone> Clone for RcuDrop<T> {
+    fn clone(&self) -> Self {
+        let ptr = self.0;
+
+        // SAFETY: Normally it's unsafe but here we keep it in a `ManuallyDrop` as if the
+        // `from_foreign()` has not been called.
+        let temp = ManuallyDrop::new(unsafe { <T as ForeignOwnable>::from_foreign(ptr) });
+
+        let new = temp.deref().clone();
+
+        // INVARIANTS: Trivial.
+        Self(new.into_foreign(), PhantomData)
+    }
+}