In drm_dev_put() call in AlwaysRefCounted::dec_ref() we rely on struct
drm_device to be the first field in drm::Device, whereas everywhere
else we correctly obtain the address of the actual struct drm_device.
Analogous to the from_drm_device() helper, provide the
into_drm_device() helper in order to address this.
Fixes: 1e4b8896c0f3 ("rust: drm: add device abstraction")
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
rust/kernel/drm/device.rs | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs
index d0a9528121f1..d29c477e89a8 100644
--- a/rust/kernel/drm/device.rs
+++ b/rust/kernel/drm/device.rs
@@ -120,9 +120,13 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<A
// - `raw_data` is a valid pointer to uninitialized memory.
// - `raw_data` will not move until it is dropped.
unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| {
- // SAFETY: `__drm_dev_alloc()` was successful, hence `raw_drm` must be valid and the
+ // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was
+ // successful.
+ let drm_dev = unsafe { Self::into_drm_device(raw_drm) };
+
+ // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the
// refcount must be non-zero.
- unsafe { bindings::drm_dev_put(ptr::addr_of_mut!((*raw_drm.as_ptr()).dev).cast()) };
+ unsafe { bindings::drm_dev_put(drm_dev) };
})?;
// SAFETY: The reference count is one, and now we take ownership of that reference as a
@@ -143,6 +147,14 @@ unsafe fn from_drm_device(ptr: *const bindings::drm_device) -> *mut Self {
unsafe { crate::container_of!(Opaque::cast_from(ptr), Self, dev) }.cast_mut()
}
+ /// # Safety
+ ///
+ /// `ptr` must be a valid pointer to `Self`.
+ unsafe fn into_drm_device(ptr: NonNull<Self>) -> *mut bindings::drm_device {
+ // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`.
+ unsafe { &raw mut (*ptr.as_ptr()).dev }.cast()
+ }
+
/// Not intended to be called externally, except via declare_drm_ioctls!()
///
/// # Safety
@@ -192,8 +204,11 @@ fn inc_ref(&self) {
}
unsafe fn dec_ref(obj: NonNull<Self>) {
+ // SAFETY: `obj` is a valid pointer to `Self`.
+ let drm_dev = unsafe { Self::into_drm_device(obj) };
+
// SAFETY: The safety requirements guarantee that the refcount is non-zero.
- unsafe { bindings::drm_dev_put(obj.cast().as_ptr()) };
+ unsafe { bindings::drm_dev_put(drm_dev) };
}
}
--
2.50.0
On Thu, Jul 31, 2025 at 05:48:09PM +0200, Danilo Krummrich wrote: > In drm_dev_put() call in AlwaysRefCounted::dec_ref() we rely on struct > drm_device to be the first field in drm::Device, whereas everywhere > else we correctly obtain the address of the actual struct drm_device. > > Analogous to the from_drm_device() helper, provide the > into_drm_device() helper in order to address this. > > Fixes: 1e4b8896c0f3 ("rust: drm: add device abstraction") > Signed-off-by: Danilo Krummrich <dakr@kernel.org> > + /// # Safety > + /// > + /// `ptr` must be a valid pointer to `Self`. > + unsafe fn into_drm_device(ptr: NonNull<Self>) -> *mut bindings::drm_device { > + // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`. > + unsafe { &raw mut (*ptr.as_ptr()).dev }.cast() > + } I think it would somewhat more consistent to use the naming raw_get() or cast_into(), but I am ok with this naming too. Reviewed-by: Alice Ryhl <aliceryhl@google.com> Alice
© 2016 - 2025 Red Hat, Inc.