Skip to content

Commit

Permalink
iommu: Add iommu_copy_struct_from_full_user_array helper
Browse files Browse the repository at this point in the history
The iommu_copy_struct_from_user_array helper can be used to copy a single
entry from a user array which might not be efficient if the array is big.

Add a new iommu_copy_struct_from_full_user_array to copy the entire user
array at once. Update the existing iommu_copy_struct_from_user_array kdoc
accordingly.

Link: https://patch.msgid.link/r/5cd773d9c26920c5807d232b21d415ea79172e49.1730836308.git.nicolinc@nvidia.com
Reviewed-by: Kevin Tian <[email protected]>
Reviewed-by: Jason Gunthorpe <[email protected]>
Signed-off-by: Nicolin Chen <[email protected]>
Signed-off-by: Jason Gunthorpe <[email protected]>
  • Loading branch information
jgunthorpe committed Nov 12, 2024
1 parent 54ce69e commit 4f2e59c
Showing 1 changed file with 47 additions and 1 deletion.
48 changes: 47 additions & 1 deletion include/linux/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -493,14 +493,60 @@ static inline int __iommu_copy_struct_from_user_array(
* @index: Index to the location in the array to copy user data from
* @min_last: The last member of the data structure @kdst points in the
* initial version.
* Return 0 for success, otherwise -error.
*
* Copy a single entry from a user array. Return 0 for success, otherwise
* -error.
*/
#define iommu_copy_struct_from_user_array(kdst, user_array, data_type, index, \
min_last) \
__iommu_copy_struct_from_user_array( \
kdst, user_array, data_type, index, sizeof(*(kdst)), \
offsetofend(typeof(*(kdst)), min_last))

/**
* iommu_copy_struct_from_full_user_array - Copy iommu driver specific user
* space data from an iommu_user_data_array
* @kdst: Pointer to an iommu driver specific user data that is defined in
* include/uapi/linux/iommufd.h
* @kdst_entry_size: sizeof(*kdst)
* @user_array: Pointer to a struct iommu_user_data_array for a user space
* array
* @data_type: The data type of the @kdst. Must match with @user_array->type
*
* Copy the entire user array. kdst must have room for kdst_entry_size *
* user_array->entry_num bytes. Return 0 for success, otherwise -error.
*/
static inline int
iommu_copy_struct_from_full_user_array(void *kdst, size_t kdst_entry_size,
struct iommu_user_data_array *user_array,
unsigned int data_type)
{
unsigned int i;
int ret;

if (user_array->type != data_type)
return -EINVAL;
if (!user_array->entry_num)
return -EINVAL;
if (likely(user_array->entry_len == kdst_entry_size)) {
if (copy_from_user(kdst, user_array->uptr,
user_array->entry_num *
user_array->entry_len))
return -EFAULT;
}

/* Copy item by item */
for (i = 0; i != user_array->entry_num; i++) {
ret = copy_struct_from_user(
kdst + kdst_entry_size * i, kdst_entry_size,
user_array->uptr + user_array->entry_len * i,
user_array->entry_len);
if (ret)
return ret;
}
return 0;
}

/**
* struct iommu_ops - iommu ops and capabilities
* @capable: check capability
Expand Down

0 comments on commit 4f2e59c

Please sign in to comment.