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.fran...@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.