[PATCH] rust: drm: gem: clean up GEM state in init failure case

Eliot Courtney posted 1 patch 1 month, 3 weeks ago
rust/kernel/drm/gem/mod.rs | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
[PATCH] rust: drm: gem: clean up GEM state in init failure case
Posted by Eliot Courtney 1 month, 3 weeks ago
Currently, if `drm_gem_object_init` fails, the object is freed without
any cleanup. Perform the cleanup in that case.

Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
I looked at `drm_gem_shmem_init` for an example, and it seems like the
correct cleanup here is to do `drm_gem_private_object_fini` if
`drm_gem_object_init` fails. Other C drivers do different things, but
looking at the implementation of `drm_gem_object_init`, this looks like
the only thing we need to clean up.
---
 rust/kernel/drm/gem/mod.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index 75acda7ba500..7b6a085ace27 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -278,7 +278,14 @@ pub fn new(dev: &drm::Device<T::Driver>, size: usize, args: T::Args) -> Result<A
         unsafe { (*obj.as_raw()).funcs = &Self::OBJECT_FUNCS };
 
         // SAFETY: The arguments are all valid per the type invariants.
-        to_result(unsafe { bindings::drm_gem_object_init(dev.as_raw(), obj.obj.get(), size) })?;
+        if let Err(err) =
+            to_result(unsafe { bindings::drm_gem_object_init(dev.as_raw(), obj.obj.get(), size) })
+        {
+            // SAFETY: `drm_gem_object_init()` initializes the private GEM object state before
+            // failing, so `drm_gem_private_object_fini()` is the matching cleanup.
+            unsafe { bindings::drm_gem_private_object_fini(obj.obj.get()) };
+            return Err(err);
+        }
 
         // SAFETY: We will never move out of `Self` as `ARef<Self>` is always treated as pinned.
         let ptr = KBox::into_raw(unsafe { Pin::into_inner_unchecked(obj) });

---
base-commit: a7a080bb4236ebe577b6776d940d1717912ff6dd
change-id: 20260423-fix-gem-1-6c68b9fa0972

Best regards,
--  
Eliot Courtney <ecourtney@nvidia.com>
Re: [PATCH] rust: drm: gem: clean up GEM state in init failure case
Posted by Danilo Krummrich 1 month, 2 weeks ago
On Thu, 23 Apr 2026 21:36:52 +0900, Eliot Courtney wrote:
> [PATCH] rust: drm: gem: clean up GEM state in init failure case

Applied, thanks!

  Branch: drm-rust-fixes
  Tree:   https://gitlab.freedesktop.org/drm/rust/kernel.git

[1/1] rust: drm: gem: clean up GEM state in init failure case
      commit: 2e42a17b8f6b

      [ Move safety comment closer to unsafe block to avoid a clippy warning.
        - Danilo ]

The patch will appear in the next linux-next integration (typically within 24
hours on weekdays).

The patch is queued up for Linus's tree and should land in the next -rc release.
Re: [PATCH] rust: drm: gem: clean up GEM state in init failure case
Posted by Alice Ryhl 1 month, 2 weeks ago
On Thu, Apr 23, 2026 at 2:37 PM Eliot Courtney <ecourtney@nvidia.com> wrote:
>
> Currently, if `drm_gem_object_init` fails, the object is freed without
> any cleanup. Perform the cleanup in that case.
>
> Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>

Tricky stuff. I also concluded that this is correct.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>

This is a bugfix, so:

Cc: stable@vger.kernel.org
Fixes: c284d3e42338 ("rust: drm: gem: Add GEM object abstraction")

Alice
Re: [PATCH] rust: drm: gem: clean up GEM state in init failure case
Posted by Onur Özkan 1 month, 3 weeks ago
On Thu, 23 Apr 2026 21:36:52 +0900
Eliot Courtney <ecourtney@nvidia.com> wrote:

> Currently, if `drm_gem_object_init` fails, the object is freed without
> any cleanup. Perform the cleanup in that case.
> 
> Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
> ---
> I looked at `drm_gem_shmem_init` for an example, and it seems like the
> correct cleanup here is to do `drm_gem_private_object_fini` if
> `drm_gem_object_init` fails. Other C drivers do different things, but
> looking at the implementation of `drm_gem_object_init`, this looks like
> the only thing we need to clean up.
> ---
>  rust/kernel/drm/gem/mod.rs | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
> index 75acda7ba500..7b6a085ace27 100644
> --- a/rust/kernel/drm/gem/mod.rs
> +++ b/rust/kernel/drm/gem/mod.rs
> @@ -278,7 +278,14 @@ pub fn new(dev: &drm::Device<T::Driver>, size: usize, args: T::Args) -> Result<A
>          unsafe { (*obj.as_raw()).funcs = &Self::OBJECT_FUNCS };
>  
>          // SAFETY: The arguments are all valid per the type invariants.
> -        to_result(unsafe { bindings::drm_gem_object_init(dev.as_raw(), obj.obj.get(), size) })?;
> +        if let Err(err) =
> +            to_result(unsafe { bindings::drm_gem_object_init(dev.as_raw(), obj.obj.get(), size) })
> +        {
> +            // SAFETY: `drm_gem_object_init()` initializes the private GEM object state before
> +            // failing, so `drm_gem_private_object_fini()` is the matching cleanup.
> +            unsafe { bindings::drm_gem_private_object_fini(obj.obj.get()) };
> +            return Err(err);
> +        }

I can confirm that this matches the usage on the C side. I think the API could
be improved to avoid relying on developers remembering this pattern. I don't
expect that to happen in this patch, just saying it :).

Reviewed-by: Onur Özkan <work@onurozkan.dev>

>  
>          // SAFETY: We will never move out of `Self` as `ARef<Self>` is always treated as pinned.
>          let ptr = KBox::into_raw(unsafe { Pin::into_inner_unchecked(obj) });
> 
> ---
> base-commit: a7a080bb4236ebe577b6776d940d1717912ff6dd
> change-id: 20260423-fix-gem-1-6c68b9fa0972
> 
> Best regards,
> --  
> Eliot Courtney <ecourtney@nvidia.com>
>