Re: [PATCH v1 2/4] vduse: Add file operation for mmap

From: Jason Wang
Date: Tue Oct 17 2023 - 23:07:38 EST


On Wed, Oct 11, 2023 at 2:42 PM Cindy Lu <lulu@xxxxxxxxxx> wrote:
>
> Add the operation for mmap, The user space APP will
> use this function to map the pages to userspace
>
> Signed-off-by: Cindy Lu <lulu@xxxxxxxxxx>
> ---
> drivers/vdpa/vdpa_user/vduse_dev.c | 66 ++++++++++++++++++++++++++++++
> 1 file changed, 66 insertions(+)
>
> diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
> index 565126a9ab01..05e72d752fb6 100644
> --- a/drivers/vdpa/vdpa_user/vduse_dev.c
> +++ b/drivers/vdpa/vdpa_user/vduse_dev.c
> @@ -1380,6 +1380,70 @@ static struct vduse_dev *vduse_dev_get_from_minor(int minor)
> return dev;
> }
>
> +static vm_fault_t vduse_vm_fault(struct vm_fault *vmf)
> +{
> + struct vduse_dev *dev = vmf->vma->vm_file->private_data;
> + struct vm_area_struct *vma = vmf->vma;
> + u16 index = vma->vm_pgoff;
> + struct vduse_virtqueue *vq;
> + struct vdpa_reconnect_info *info;
> +
> + /* index 0 page reserved for vduse status*/
> + if (index == 0) {
> + info = &dev->reconnect_status;
> + } else {
> + /* index 1+vq_number page reserved for vduse vqs*/
> + vq = &dev->vqs[index - 1];
> + info = &vq->reconnect_info;
> + }
> + if (remap_pfn_range(vma, vmf->address & PAGE_MASK,
> + PFN_DOWN(virt_to_phys((void *)info->vaddr)),
> + PAGE_SIZE, vma->vm_page_prot))
> + return VM_FAULT_SIGBUS;
> + return VM_FAULT_NOPAGE;
> +}
> +
> +static const struct vm_operations_struct vduse_vm_ops = {
> + .fault = vduse_vm_fault,
> +};
> +
> +static int vduse_dev_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> + struct vduse_dev *dev = file->private_data;
> + struct vdpa_reconnect_info *info;
> + unsigned long index = vma->vm_pgoff;
> + struct vduse_virtqueue *vq;
> +
> + if (vma->vm_end - vma->vm_start != PAGE_SIZE)
> + return -EINVAL;
> + if ((vma->vm_flags & VM_SHARED) == 0)
> + return -EINVAL;
> +
> + if (index > dev->vq_num + 1)
> + return -EINVAL;
> +
> + /* index 0 page reserved for vduse status*/
> + if (index == 0) {
> + info = &dev->reconnect_status;
> + } else {
> + /* index 1+vq_number page reserved for vduse vqs*/
> + vq = &dev->vqs[index - 1];
> + info = &vq->reconnect_info;
> + }
> + if (info->vaddr == 0)
> + return -ENOTSUPP;

Under which condition could we meet this?

> +
> + if (virt_to_phys((void *)info->vaddr) & (PAGE_SIZE - 1))
> + return -EINVAL;

And this?

> + if (vma->vm_end - vma->vm_start != info->size)
> + return -EOPNOTSUPP;
> +
> + vm_flags_set(vma, VM_IO | VM_DONTDUMP);

I still don't understand the flags here. Or at least it requires some
comment to explain why they are needed here.

Please refer to the kernel sources which explains their use cases.

Thanks

> + vma->vm_ops = &vduse_vm_ops;
> +
> + return 0;
> +}
> +
> static int vduse_dev_open(struct inode *inode, struct file *file)
> {
> int ret;
> @@ -1412,6 +1476,8 @@ static const struct file_operations vduse_dev_fops = {
> .unlocked_ioctl = vduse_dev_ioctl,
> .compat_ioctl = compat_ptr_ioctl,
> .llseek = noop_llseek,
> + .mmap = vduse_dev_mmap,
> +
> };
>
> static struct vduse_dev *vduse_dev_create(void)
> --
> 2.34.3
>