iommufd: Introduce iommufd_object_alloc_ucmd helper

An object allocator needs to call either iommufd_object_finalize() upon a
success or iommufd_object_abort_and_destroy() upon an error code.

To reduce duplication, store a new_obj in the struct iommufd_ucmd and call
iommufd_object_finalize/iommufd_object_abort_and_destroy() accordingly in
the main function.

Similar to iommufd_object_alloc() and __iommufd_object_alloc(), add a pair
of helpers: __iommufd_object_alloc_ucmd() and iommufd_object_alloc_ucmd().

Link: https://patch.msgid.link/r/e7206d4227844887cc8dbf0cc7b0242580fafd9d.1749882255.git.nicolinc@nvidia.com
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Acked-by: Pranjal Shrivastava <praan@google.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
Nicolin Chen 2025-06-13 23:35:25 -07:00 committed by Jason Gunthorpe
parent 17a93473a5
commit c0d498a1b9
2 changed files with 51 additions and 0 deletions

View File

@ -135,6 +135,7 @@ struct iommufd_ucmd {
void __user *ubuffer;
u32 user_size;
void *cmd;
struct iommufd_object *new_obj;
};
int iommufd_vfio_ioctl(struct iommufd_ctx *ictx, unsigned int cmd,
@ -230,6 +231,11 @@ iommufd_object_put_and_try_destroy(struct iommufd_ctx *ictx,
iommufd_object_remove(ictx, obj, obj->id, 0);
}
/*
* Callers of these normal object allocators must call iommufd_object_finalize()
* to finalize the object, or call iommufd_object_abort_and_destroy() to revert
* the allocation.
*/
struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
size_t size,
enum iommufd_object_type type);
@ -246,6 +252,26 @@ struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
#define iommufd_object_alloc(ictx, ptr, type) \
__iommufd_object_alloc(ictx, ptr, type, obj)
/*
* Callers of these _ucmd allocators should not call iommufd_object_finalize()
* or iommufd_object_abort_and_destroy(), as the core automatically does that.
*/
struct iommufd_object *
_iommufd_object_alloc_ucmd(struct iommufd_ucmd *ucmd, size_t size,
enum iommufd_object_type type);
#define __iommufd_object_alloc_ucmd(ucmd, ptr, type, obj) \
container_of(_iommufd_object_alloc_ucmd( \
ucmd, \
sizeof(*(ptr)) + BUILD_BUG_ON_ZERO( \
offsetof(typeof(*(ptr)), \
obj) != 0), \
type), \
typeof(*(ptr)), obj)
#define iommufd_object_alloc_ucmd(ucmd, ptr, type) \
__iommufd_object_alloc_ucmd(ucmd, ptr, type, obj)
/*
* The IO Address Space (IOAS) pagetable is a virtual page table backed by the
* io_pagetable object. It is a user controlled mapping of IOVA -> PFNs. The

View File

@ -61,6 +61,24 @@ struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
return ERR_PTR(rc);
}
struct iommufd_object *_iommufd_object_alloc_ucmd(struct iommufd_ucmd *ucmd,
size_t size,
enum iommufd_object_type type)
{
struct iommufd_object *new_obj;
/* Something is coded wrong if this is hit */
if (WARN_ON(ucmd->new_obj))
return ERR_PTR(-EBUSY);
new_obj = _iommufd_object_alloc(ucmd->ictx, size, type);
if (IS_ERR(new_obj))
return new_obj;
ucmd->new_obj = new_obj;
return new_obj;
}
/*
* Allow concurrent access to the object.
*
@ -448,6 +466,13 @@ static long iommufd_fops_ioctl(struct file *filp, unsigned int cmd,
if (ret)
return ret;
ret = op->execute(&ucmd);
if (ucmd.new_obj) {
if (ret)
iommufd_object_abort_and_destroy(ictx, ucmd.new_obj);
else
iommufd_object_finalize(ictx, ucmd.new_obj);
}
return ret;
}