* @ictx: iommufd file descriptor
  * @ops: Driver's ops to associate with the access
  * @data: Opaque data to pass into ops functions
+ * @id: Output ID number to return to userspace for this access
  *
  * An iommufd_access allows a driver to read/write to the IOAS without using
  * DMA. The underlying CPU memory can be accessed using the
  */
 struct iommufd_access *
 iommufd_access_create(struct iommufd_ctx *ictx,
-                     const struct iommufd_access_ops *ops, void *data)
+                     const struct iommufd_access_ops *ops, void *data, u32 *id)
 {
        struct iommufd_access *access;
 
        access->ictx = ictx;
        iommufd_ctx_get(ictx);
        iommufd_object_finalize(ictx, &access->obj);
+       *id = access->obj.id;
        return access;
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
 
        struct iommu_test_cmd *cmd = ucmd->cmd;
        struct selftest_access *staccess;
        struct iommufd_access *access;
+       u32 id;
        int fdno;
        int rc;
 
                (flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ?
                        &selftest_access_ops_pin :
                        &selftest_access_ops,
-               staccess);
+               staccess, &id);
        if (IS_ERR(access)) {
                rc = PTR_ERR(access);
                goto out_put_fdno;
 
 
        lockdep_assert_held(&vdev->dev_set->lock);
 
-       user = iommufd_access_create(ictx, &vfio_user_ops, vdev);
+       user = iommufd_access_create(ictx, &vfio_user_ops, vdev, out_device_id);
        if (IS_ERR(user))
                return PTR_ERR(user);
        vdev->iommufd_access = user;
 
 
 struct iommufd_access *
 iommufd_access_create(struct iommufd_ctx *ictx,
-                     const struct iommufd_access_ops *ops, void *data);
+                     const struct iommufd_access_ops *ops, void *data, u32 *id);
 void iommufd_access_destroy(struct iommufd_access *access);
 int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id);