]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommufd: Introduce iommufd_object_alloc_ucmd helper
authorNicolin Chen <nicolinc@nvidia.com>
Sat, 14 Jun 2025 06:35:25 +0000 (23:35 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Thu, 19 Jun 2025 18:43:29 +0000 (15:43 -0300)
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>
drivers/iommu/iommufd/iommufd_private.h
drivers/iommu/iommufd/main.c

index ec5b499d139cd87839cefa93bf435bfc0d106665..4f5e8cd99c9655e1304fdc962be1ab1bd76fe62d 100644 (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
index 85ad2853da0b737c3927cda7a0fe977065de668f..778694d7c2075ed423a33adcffdf4125ae9f5c77 100644 (file)
@@ -61,6 +61,24 @@ out_free:
        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;
 }