Skip to content

Commit 4f2e59c

Browse files
committed
iommu: Add iommu_copy_struct_from_full_user_array helper
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]>
1 parent 54ce69e commit 4f2e59c

File tree

1 file changed

+47
-1
lines changed

1 file changed

+47
-1
lines changed

include/linux/iommu.h

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,14 +493,60 @@ static inline int __iommu_copy_struct_from_user_array(
493493
* @index: Index to the location in the array to copy user data from
494494
* @min_last: The last member of the data structure @kdst points in the
495495
* initial version.
496-
* Return 0 for success, otherwise -error.
496+
*
497+
* Copy a single entry from a user array. Return 0 for success, otherwise
498+
* -error.
497499
*/
498500
#define iommu_copy_struct_from_user_array(kdst, user_array, data_type, index, \
499501
min_last) \
500502
__iommu_copy_struct_from_user_array( \
501503
kdst, user_array, data_type, index, sizeof(*(kdst)), \
502504
offsetofend(typeof(*(kdst)), min_last))
503505

506+
/**
507+
* iommu_copy_struct_from_full_user_array - Copy iommu driver specific user
508+
* space data from an iommu_user_data_array
509+
* @kdst: Pointer to an iommu driver specific user data that is defined in
510+
* include/uapi/linux/iommufd.h
511+
* @kdst_entry_size: sizeof(*kdst)
512+
* @user_array: Pointer to a struct iommu_user_data_array for a user space
513+
* array
514+
* @data_type: The data type of the @kdst. Must match with @user_array->type
515+
*
516+
* Copy the entire user array. kdst must have room for kdst_entry_size *
517+
* user_array->entry_num bytes. Return 0 for success, otherwise -error.
518+
*/
519+
static inline int
520+
iommu_copy_struct_from_full_user_array(void *kdst, size_t kdst_entry_size,
521+
struct iommu_user_data_array *user_array,
522+
unsigned int data_type)
523+
{
524+
unsigned int i;
525+
int ret;
526+
527+
if (user_array->type != data_type)
528+
return -EINVAL;
529+
if (!user_array->entry_num)
530+
return -EINVAL;
531+
if (likely(user_array->entry_len == kdst_entry_size)) {
532+
if (copy_from_user(kdst, user_array->uptr,
533+
user_array->entry_num *
534+
user_array->entry_len))
535+
return -EFAULT;
536+
}
537+
538+
/* Copy item by item */
539+
for (i = 0; i != user_array->entry_num; i++) {
540+
ret = copy_struct_from_user(
541+
kdst + kdst_entry_size * i, kdst_entry_size,
542+
user_array->uptr + user_array->entry_len * i,
543+
user_array->entry_len);
544+
if (ret)
545+
return ret;
546+
}
547+
return 0;
548+
}
549+
504550
/**
505551
* struct iommu_ops - iommu ops and capabilities
506552
* @capable: check capability

0 commit comments

Comments
 (0)