From: sashiko-bot@kernel.org
To: "Danilo Krummrich" <dakr@kernel.org>
Cc: "Danilo Krummrich" <dakr@kernel.org>,
ojeda@kernel.org, "Alexandre Courbot" <acourbot@nvidia.com>,
dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 6/7] rust: drm: make Driver::File lifetime-parameterized
Date: Fri, 14 Aug 2026 23:23:42 +0000 [thread overview]
Message-ID: <20260814232342.C6E9A1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260814230923.1292966-7-dakr@kernel.org>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Lock inversion in Registration::drop() when freeing file data under filelist_mutex
- [Low] Missing #[inline] annotations on small abstraction functions
--
--- Patch [6]: [PATCH 6/7] rust: drm: make Driver::File lifetime-parameterized ---
commit f0644f05187ec5973de59ac9760eaeeee5140b6a
Author: Danilo Krummrich <dakr@kernel.org>
rust: drm: make Driver::File lifetime-parameterized
Make the DRM file private data lifetime-parameterized, allowing drivers
to borrow from RegistrationData in their per-file data.
> diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs
> --- a/rust/kernel/drm/driver.rs
> +++ b/rust/kernel/drm/driver.rs
[ ... ]
> @@ -221,6 +237,51 @@ fn drop(&mut self) {
> unsafe { bindings::drm_dev_unplug(self.drm.as_raw()) };
> // After drm_dev_unplug(), the SRCU barrier guarantees that all RegistrationGuard critical
> // sections have completed, so no one holds a reference to reg_data anymore.
> - // reg_data is dropped here automatically.
> +
> + // Drop all remaining file private data before dropping registration data. This guarantees
> + // that file data (which may borrow from RegistrationData) is always dropped first.
> + let raw = self.drm.as_raw();
> +
> + // SAFETY: `filelist_mutex` is initialized by `drm_dev_init()` and remains valid for
> + // the lifetime of the `struct drm_device`.
> + let filelist_mutex = unsafe { Mutex::from_raw(&raw mut (*raw).filelist_mutex) };
> + {
> + let _guard = filelist_mutex.lock();
> +
> + // SAFETY: `filelist` is a valid, initialized sentinel `list_head`; the mutex
> + // guard prevents concurrent modification.
> + let filelist = unsafe {
> + clist_create!(
> + &raw mut (*raw).filelist,
> + drm::File<T>,
> + bindings::drm_file,
> + lhead
> + )
> + };
> +
> + for file in filelist.iter() {
> + // SAFETY: `file` is a valid `drm_file` on this device's filelist.
> + let priv_ptr = unsafe { (*file.as_raw()).driver_priv };
> +
> + // SAFETY: Setting `driver_priv` to NULL is visible to `postclose_callback()`
> + // through the `filelist_mutex` acquire/release chain in `drm_close_helper()`.
> + unsafe { (*file.as_raw()).driver_priv = core::ptr::null_mut() };
> +
> + // SAFETY: `driver_priv` was created by `open_callback()` via `KBox::into_raw` and
> + // has not yet been freed (the file is still in the list, so `postclose_callback()`
> + // has not run).
> + drop(unsafe { KBox::from_raw(priv_ptr.cast::<<T::File as ForLt>::Of<'static>>()) });
[Severity: High]
Does dropping the file data while holding `filelist_mutex` introduce a lock
inversion risk?
If the driver's File Drop implementation acquires a driver-specific lock, this
creates a `filelist_mutex` -> driver lock dependency.
Since VFS operations routinely take driver locks before the DRM core takes
`filelist_mutex` (e.g., in `drm_file_free`), this could violate core kernel
locking rules and cause an AB-BA deadlock on device unplug.
> +
> + self.drm.open_count.fetch_sub(1, Release);
> + }
> + }
> +
> + // Wait for in-flight `postclose_callback()` calls to complete. After `drm_dev_unplug()`, no
> + // new opens can succeed, so `open_count` is monotonically decreasing.
> + self.drm
> + .open_count_wq
> + .wait_event(|| self.drm.open_count.load(Acquire) == 0);
> +
> + // `_reg_data` is dropped here automatically, after all file data has been dropped.
> }
> }
> diff --git a/rust/kernel/drm/file.rs b/rust/kernel/drm/file.rs
> --- a/rust/kernel/drm/file.rs
> +++ b/rust/kernel/drm/file.rs
[ ... ]
> @@ -45,59 +62,94 @@ pub(super) fn as_raw(&self) -> *mut bindings::drm_file {
> self.0.get()
> }
>
> - fn driver_priv(&self) -> *mut T {
> - // SAFETY: By the type invariants of `Self`, `self.as_raw()` is always valid.
> - unsafe { (*self.as_raw()).driver_priv }.cast()
> + /// Return a pinned reference to the driver file data.
> + ///
> + /// Only available when `D::File` implements [`trait@CovariantForLt`]. For invariant types, use
> + /// [`inner_with()`](Self::inner_with).
> + pub fn inner(&self) -> Pin<&<D::File as ForLt>::Of<'_>>
> + where
> + D::File: CovariantForLt,
[Severity: Low]
This isn't a bug, but shouldn't this small accessor abstraction function be
annotated with #[inline]?
> + {
> + // SAFETY: `driver_priv` was initialized by `open_callback()`. `CovariantForLt` guarantees
> + // the lifetime shortening from `'static` to `'_` is sound.
> + unsafe { Pin::new_unchecked(&*(*self.as_raw()).driver_priv.cast_const().cast()) }
> }
>
> - /// Return a pinned reference to the driver file structure.
> - pub fn inner(&self) -> Pin<&T> {
> - // SAFETY: By the type invariant the pointer `self.as_raw()` points to a valid and opened
> - // `struct drm_file`, hence `driver_priv` has been properly initialized by `open_callback`.
> - unsafe { Pin::new_unchecked(&*(self.driver_priv())) }
> + /// Access the driver file data through a closure.
> + ///
> + /// This works for all file data types, including invariant ones. For covariant types,
> + /// [`inner()`](Self::inner) provides direct access without a closure.
> + pub fn inner_with<R, F>(&self, f: F) -> R
> + where
> + F: for<'a> FnOnce(Pin<&'a <D::File as ForLt>::Of<'a>>) -> R,
[Severity: Low]
This isn't a bug, but shouldn't this abstraction function also be annotated
with #[inline]?
> + {
> + // SAFETY: `driver_priv` was initialized by `open_callback()`. The HRTB `for<'a>` prevents
> + // the caller from choosing a concrete lifetime, making the lifetime shortening sound
> + // regardless of variance.
> + f(unsafe { Pin::new_unchecked(&*(*self.as_raw()).driver_priv.cast_const().cast()) })
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260814230923.1292966-1-dakr@kernel.org?part=6
next prev parent reply other threads:[~2026-08-14 23:23 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-14 23:08 [PATCH 0/7] lifetime-parameterized DRM File private data Danilo Krummrich
2026-08-14 23:08 ` [PATCH 1/7] rust: drm: rename Ioctl device context to Userspace Danilo Krummrich
2026-08-14 23:09 ` [PATCH 2/7] rust: drm: gem: gate open/close callbacks with RegistrationGuard Danilo Krummrich
2026-08-14 23:21 ` sashiko-bot
2026-08-14 23:09 ` [PATCH 3/7] rust: drm: move file_operations from gem to device Danilo Krummrich
2026-08-14 23:22 ` sashiko-bot
2026-08-14 23:09 ` [PATCH 4/7] rust: fs: add iminor() helper Danilo Krummrich
2026-08-14 23:09 ` [PATCH 5/7] rust: drm: wrap fops open with RegistrationGuard Danilo Krummrich
2026-08-14 23:29 ` sashiko-bot
2026-08-14 23:09 ` [PATCH 6/7] rust: drm: make Driver::File lifetime-parameterized Danilo Krummrich
2026-08-14 23:23 ` sashiko-bot [this message]
2026-08-14 23:09 ` [PATCH 7/7] rust: drm: return impl PinInit from DriverFile::open() Danilo Krummrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260814232342.C6E9A1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=acourbot@nvidia.com \
--cc=dakr@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=ojeda@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.