[PATCH 2/2] rust: drm: gpuvm: call drm_gpuvm_bo_destroy_not_in_lists() in Drop
From: Daniel Pesic
Date: Mon Jul 27 2026 - 17:18:21 EST
GpuVmBoAlloc's type invariant guarantees a refcount of one and absence
from the gem, extobj, and evict lists for as long as the value exists as
itself. The only way to consume it is via obtain(), which moves it out
via ManuallyDrop, so the invariant holds when Drop::drop runs. Since
this is the required precondition for
drm_gpuvm_bo_destroy_not_in_lists(), call it directly rather than going
through the deferred put, and drop the TODO.
The GEM's gpuva lock must not be held when this runs, since freeing the
last reference to the GEM object would free the lock embedded in it.
Drop::drop has a fixed safe signature, so this precondition cannot be
enforced by the type system and is documented instead, matching the
existing note on GpuVmBoAlloc::obtain(). It currently holds as
lock_gpuva()'s two call sites, in sm_ops.rs, operate on a GpuVmBo that
is already obtained and never construct or drop a GpuVmBoAlloc.
Suggested-by: Alice Ryhl <aliceryhl@xxxxxxxxxx>
Signed-off-by: Daniel Pesic <danny.pesic@xxxxxxxxx>
---
rust/kernel/drm/gpuvm/vm_bo.rs | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/drm/gpuvm/vm_bo.rs b/rust/kernel/drm/gpuvm/vm_bo.rs
index a30f838c11b8..7c0f5846cf39 100644
--- a/rust/kernel/drm/gpuvm/vm_bo.rs
+++ b/rust/kernel/drm/gpuvm/vm_bo.rs
@@ -249,10 +249,14 @@ fn deref(&self) -> &GpuVmBo<T> {
}
impl<T: DriverGpuVm> Drop for GpuVmBoAlloc<T> {
+ /// Must not be dropped while holding the `drm_gem_object` gpuva lock.
#[inline]
fn drop(&mut self) {
- // TODO: Call drm_gpuvm_bo_destroy_not_in_lists() directly.
- // SAFETY: It's safe to perform a deferred put in any context.
- unsafe { bindings::drm_gpuvm_bo_put_deferred(self.as_raw()) };
+ // SAFETY: By the type invariant, `drm_gpuvm_bo` has a refcount
+ // of one and is absent from the gem, extobj, and evict lists.
+ // Per the precondition documented in impl, the caller does not
+ // hold the object's gpuva lock. Therefore, the preconditions of
+ // `drm_gpuvm_bo_destroy_not_in_lists()` are satisfied.
+ unsafe { bindings::drm_gpuvm_bo_destroy_not_in_lists(self.as_raw()) };
}
}
--
2.55.0