[PATCH 1/3] drm: Add DRM prime interfaces to reassign GEM handle

Christian König christian.koenig at amd.com
Mon May 19 12:29:21 UTC 2025


On 5/16/25 21:33, David Francis wrote:
> CRIU restore of drm buffer objects requires the ability to create
> or import a buffer object with a specific gem handle.
> 
> Add new drm ioctl DRM_IOCTL_PRIME_CHANGE_GEM_HANDLE, which takes
> the gem handle of an object and moves that object to a
> specified new gem handle.
> 
> This ioctl needs to call drm_prime_remove_buf_handle,
> but that function acquires the prime lock, which the ioctl
> needs to hold for other purposes.
> 
> Make drm_prime_remove_buf_handle not acquire the prime lock,
> and change its other caller to reflect this.
> 
> Signed-off-by: David Francis <David.Francis at amd.com>

First of all you need to add more people and the dri-devel mailing list for review.

A few more comments below.

> ---
>  drivers/gpu/drm/drm_gem.c      |  5 ++++
>  drivers/gpu/drm/drm_internal.h |  2 ++
>  drivers/gpu/drm/drm_ioctl.c    |  1 +
>  drivers/gpu/drm/drm_prime.c    | 43 ++++++++++++++++++++++++++++++----
>  include/uapi/drm/drm.h         |  7 ++++++
>  5 files changed, 54 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index ee811764c3df..f56eeed808d2 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -282,7 +282,12 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
>  	if (obj->funcs->close)
>  		obj->funcs->close(obj, file_priv);
>  
> +	mutex_lock(&file_priv->prime.lock);
> +
>  	drm_prime_remove_buf_handle(&file_priv->prime, id);
> +
> +	mutex_unlock(&file_priv->prime.lock);
> +
>  	drm_vma_node_revoke(&obj->vma_node, file_priv);
>  
>  	drm_gem_object_handle_put_unlocked(obj);
> diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
> index b2b6a8e49dda..7437e5eaf8db 100644
> --- a/drivers/gpu/drm/drm_internal.h
> +++ b/drivers/gpu/drm/drm_internal.h
> @@ -82,6 +82,8 @@ int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
>  				 struct drm_file *file_priv);
>  int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
>  				 struct drm_file *file_priv);
> +int drm_prime_change_gem_handle_ioctl(struct drm_device *dev, void *data,
> +				 struct drm_file *file_priv);
>  
>  void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
>  void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index f593dc569d31..f9b531311aac 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -658,6 +658,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
>  
>  	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_RENDER_ALLOW),
>  	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_RENDER_ALLOW),

> +	DRM_IOCTL_DEF(DRM_IOCTL_PRIME_CHANGE_GEM_HANDLE, drm_prime_change_gem_handle_ioctl, DRM_RENDER_ALLOW),

>  
>  	DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_NAME, drm_set_client_name, DRM_RENDER_ALLOW),
>  
> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
> index 0e3f8adf162f..8f3317fcae49 100644
> --- a/drivers/gpu/drm/drm_prime.c
> +++ b/drivers/gpu/drm/drm_prime.c
> @@ -190,8 +190,6 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
>  {
>  	struct rb_node *rb;
>  
> -	mutex_lock(&prime_fpriv->lock);
> -
>  	rb = prime_fpriv->handles.rb_node;
>  	while (rb) {
>  		struct drm_prime_member *member;
> @@ -210,8 +208,6 @@ void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
>  			rb = rb->rb_left;
>  		}
>  	}
> -
> -	mutex_unlock(&prime_fpriv->lock);
>  }
>  
>  void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
> @@ -1084,3 +1080,42 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
>  	dma_buf_put(dma_buf);
>  }
>  EXPORT_SYMBOL(drm_prime_gem_destroy);
> +
> +int drm_prime_change_gem_handle_ioctl(struct drm_device *dev, void *data,
> +				 struct drm_file *file_priv)

This is not a prime function, but rather a GEM function. So the new code should go into drm_gem.c, I suggest close to the drm_gem_open_ioctl() function.

> +{
> +	struct drm_prime_change_gem_handle *args = data;
> +	struct drm_gem_object *obj;
> +	int ret;
> +
> +	obj = drm_gem_object_lookup(file_priv, args->handle);
> +
> +	if (!obj)
> +		return -ENOENT;
> +
> +	get_dma_buf(obj->dma_buf);
> +
> +	mutex_lock(&file_priv->prime.lock);
> +
> +	drm_prime_remove_buf_handle(&file_priv->prime, args->handle);
> +
> +	spin_lock(&file_priv->table_lock);
> +
> +	idr_remove(&file_priv->object_idr, args->handle);
> +	ret = idr_alloc(&file_priv->object_idr, obj, args->new_handle, args->new_handle + 1, GFP_NOWAIT);

This needs to be reordered.

First call idr_alloc() to check if the new handle is actually available.

Then call drm_prime_add_buf_handle() when the GEM object actually has a DMA-buf associated with it.

When that worked call drm_prime_remove_buf_handle() and finally idr_remove().

Regards,
Christian.

> +
> +	spin_unlock(&file_priv->table_lock);
> +
> +	if (ret < 0)
> +		goto out_unlock;
> +
> +	ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf, args->new_handle);
> +	if (ret < 0)
> +		goto out_unlock;
> +
> +out_unlock:
> +	mutex_unlock(&file_priv->prime.lock);
> +	dma_buf_put(obj->dma_buf);
> +
> +	return ret;
> +}
> diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
> index 7fba37b94401..ae701b8f9314 100644
> --- a/include/uapi/drm/drm.h
> +++ b/include/uapi/drm/drm.h
> @@ -625,6 +625,11 @@ struct drm_gem_open {
>  	__u64 size;
>  };
>  
> +struct drm_prime_change_gem_handle {
> +	__u32 handle;
> +	__u32 new_handle;
> +};
> +
>  /**
>   * DRM_CAP_DUMB_BUFFER
>   *
> @@ -1305,6 +1310,8 @@ extern "C" {
>   */
>  #define DRM_IOCTL_SET_CLIENT_NAME	DRM_IOWR(0xD1, struct drm_set_client_name)
>  
> +#define DRM_IOCTL_PRIME_CHANGE_GEM_HANDLE    DRM_IOWR(0xD2, struct drm_prime_change_gem_handle)
> +
>  /*
>   * Device specific ioctls should only be in their respective headers
>   * The device specific ioctl range is from 0x40 to 0x9f.



More information about the dri-devel mailing list