On Thu, Oct 26, 2023 at 10:49:28AM +0800, Lu Baolu wrote:
+static ssize_t hwpt_fault_fops_write(struct file *filep,
const char __user *buf,size_t count, loff_t *ppos)+{
- size_t response_size = sizeof(struct iommu_hwpt_page_response);
 - struct hw_pgtable_fault *fault = filep->private_data;
 - struct iommu_hwpt_page_response response;
 - struct iommufd_hw_pagetable *hwpt;
 - struct iopf_group *iter, *group;
 - struct iommufd_device *idev;
 - size_t done = 0;
 - int rc = 0;
 - if (*ppos || count % response_size)
 return -ESPIPE;- mutex_lock(&fault->mutex);
 - while (!list_empty(&fault->response) && count > done) {
 rc = copy_from_user(&response, buf + done, response_size);if (rc)break;/* Get the device that this response targets at. */idev = container_of(iommufd_get_object(fault->ictx,response.dev_id,IOMMUFD_OBJ_DEVICE),struct iommufd_device, obj);if (IS_ERR(idev)) {rc = PTR_ERR(idev);break;}
See here it might be better to have a per-fd list of outstanding faults per-fd and then the cookie would just index that list, then you get everything in one shot instead of having to do a xarray looking and then a linear list search
+static const struct file_operations hwpt_fault_fops = {
- .owner = THIS_MODULE,
 - .read = hwpt_fault_fops_read,
 - .write = hwpt_fault_fops_write,
 +};
nonseekable_open() behavior should be integrated into this
+static int hw_pagetable_get_fault_fd(struct hw_pgtable_fault *fault) +{
- struct file *filep;
 - int fdno;
 - fdno = get_unused_fd_flags(O_CLOEXEC);
 - if (fdno < 0)
 return fdno;- filep = anon_inode_getfile("[iommufd-pgfault]", &hwpt_fault_fops,
 fault, O_RDWR);- if (IS_ERR(filep)) {
 put_unused_fd(fdno);return PTR_ERR(filep);- }
 - fd_install(fdno, filep);
 - fault->fault_file = filep;
 - fault->fault_fd = fdno;
 
fd_install must be the very last thing before returning success from a system call because we cannot undo it.
There are other failure paths before here and the final return
Jason