Re: [PATCH v7 03/14] vdpa: Sync calls set/get config/status with cf_mutex

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jan 11, 2022 at 9:30 AM Si-Wei Liu <si-wei.liu@xxxxxxxxxx> wrote:
>
>
>
> On 1/9/2022 10:05 PM, Jason Wang wrote:
> >
> > 在 2022/1/8 上午9:23, Si-Wei Liu 写道:
> >>
> >>
> >> On 1/6/2022 9:08 PM, Jason Wang wrote:
> >>>
> >>> 在 2022/1/7 上午8:33, Si-Wei Liu 写道:
> >>>>
> >>>>
> >>>> On 1/5/2022 3:46 AM, Eli Cohen wrote:
> >>>>> Add wrappers to get/set status and protect these operations with
> >>>>> cf_mutex to serialize these operations with respect to get/set config
> >>>>> operations.
> >>>>>
> >>>>> Signed-off-by: Eli Cohen <elic@xxxxxxxxxx>
> >>>>> ---
> >>>>>   drivers/vdpa/vdpa.c          | 19 +++++++++++++++++++
> >>>>>   drivers/vhost/vdpa.c         |  7 +++----
> >>>>>   drivers/virtio/virtio_vdpa.c |  3 +--
> >>>>>   include/linux/vdpa.h         |  3 +++
> >>>>>   4 files changed, 26 insertions(+), 6 deletions(-)
> >>>>>
> >>>>> diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
> >>>>> index 42d71d60d5dc..5134c83c4a22 100644
> >>>>> --- a/drivers/vdpa/vdpa.c
> >>>>> +++ b/drivers/vdpa/vdpa.c
> >>>>> @@ -21,6 +21,25 @@ static LIST_HEAD(mdev_head);
> >>>>>   static DEFINE_MUTEX(vdpa_dev_mutex);
> >>>>>   static DEFINE_IDA(vdpa_index_ida);
> >>>>>   +u8 vdpa_get_status(struct vdpa_device *vdev)
> >>>>> +{
> >>>>> +    u8 status;
> >>>>> +
> >>>>> +    mutex_lock(&vdev->cf_mutex);
> >>>>> +    status = vdev->config->get_status(vdev);
> >>>>> +    mutex_unlock(&vdev->cf_mutex);
> >>>>> +    return status;
> >>>>> +}
> >>>>> +EXPORT_SYMBOL(vdpa_get_status);
> >>>>> +
> >>>>> +void vdpa_set_status(struct vdpa_device *vdev, u8 status)
> >>>>> +{
> >>>>> +    mutex_lock(&vdev->cf_mutex);
> >>>>> +    vdev->config->set_status(vdev, status);
> >>>>> +    mutex_unlock(&vdev->cf_mutex);
> >>>>> +}
> >>>>> +EXPORT_SYMBOL(vdpa_set_status);
> >>>>> +
> >>>>>   static struct genl_family vdpa_nl_family;
> >>>>>     static int vdpa_dev_probe(struct device *d)
> >>>>> diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
> >>>>> index ebaa373e9b82..d9d499465e2e 100644
> >>>>> --- a/drivers/vhost/vdpa.c
> >>>>> +++ b/drivers/vhost/vdpa.c
> >>>>> @@ -142,10 +142,9 @@ static long vhost_vdpa_get_device_id(struct
> >>>>> vhost_vdpa *v, u8 __user *argp)
> >>>>>   static long vhost_vdpa_get_status(struct vhost_vdpa *v, u8
> >>>>> __user *statusp)
> >>>>>   {
> >>>>>       struct vdpa_device *vdpa = v->vdpa;
> >>>>> -    const struct vdpa_config_ops *ops = vdpa->config;
> >>>>>       u8 status;
> >>>>>   -    status = ops->get_status(vdpa);
> >>>>> +    status = vdpa_get_status(vdpa);
> >>>> Not sure why we need to take cf_mutex here. Appears to me only
> >>>> setters (set_status and reset) need to take the lock in this function.
> >>>
> >>>
> >>> You may be right but it doesn't harm and it is guaranteed to be
> >>> correct if we protect it with mutex here.
> >> Is it more for future proof?
> >
> >
> > I think so.
>
> I guess in this situation it would be better defer to the future patch
> to add such locking or wrapper, although right now there are just two
> additional calls taking the lock needlessly when vhost_vdpa_get_status
> is called. Maybe it's just me but I'm worried some future patch may
> calls the locked API wrapper thousands of times unintendedly, then the
> overhead becomes quite obvious.

I'm fine to remove this if others agree on this.

>
> >
> >
> >> Ok, but IMHO it might be better to get some comment here, otherwise
> >> it's quite confusing why the lock needs to be held. vhost_vdpa had
> >> done its own serialization in vhost_vdpa_unlocked_ioctl() through
> >> vhost_dev`mutex.
> >
> >
> > Right, but they are done for different levels, one is for vhost_dev
> > antoher is for vdpa_dev.
> The cf_mutex is introduced to serialize the command line configure
> thread (via netlink) and the upstream driver calls from either the
> vhost_dev or virtio_dev. I don't see a case, even in future, where the
> netlink thread needs to update the virtio status on the fly. Can you
> enlighten me why that is at all possible?

After some thought I don't see a case. I can think of NEEDS_RESET but
it should come with a config interrupt so we're probably fine without
the mutex here.

Thanks

>
> Thanks,
> -Siwei
> >
> > Thanks
> >
> >
> >>
> >> -Siwei
> >>
> >>>
> >>> Thanks
> >>>
> >>>
> >>>>
> >>>>>         if (copy_to_user(statusp, &status, sizeof(status)))
> >>>>>           return -EFAULT;
> >>>>> @@ -164,7 +163,7 @@ static long vhost_vdpa_set_status(struct
> >>>>> vhost_vdpa *v, u8 __user *statusp)
> >>>>>       if (copy_from_user(&status, statusp, sizeof(status)))
> >>>>>           return -EFAULT;
> >>>>>   -    status_old = ops->get_status(vdpa);
> >>>>> +    status_old = vdpa_get_status(vdpa);
> >>>> Ditto.
> >>>>
> >>>>>         /*
> >>>>>        * Userspace shouldn't remove status bits unless reset the
> >>>>> @@ -182,7 +181,7 @@ static long vhost_vdpa_set_status(struct
> >>>>> vhost_vdpa *v, u8 __user *statusp)
> >>>>>           if (ret)
> >>>>>               return ret;
> >>>>>       } else
> >>>>> -        ops->set_status(vdpa, status);
> >>>>> +        vdpa_set_status(vdpa, status);
> >>>> The reset() call in the if branch above needs to take the cf_mutex,
> >>>> the same way as that for set_status(). The reset() is effectively
> >>>> set_status(vdpa, 0).
> >>>>
> >>>> Thanks,
> >>>> -Siwei
> >>>>
> >>>>>         if ((status & VIRTIO_CONFIG_S_DRIVER_OK) && !(status_old &
> >>>>> VIRTIO_CONFIG_S_DRIVER_OK))
> >>>>>           for (i = 0; i < nvqs; i++)
> >>>>> diff --git a/drivers/virtio/virtio_vdpa.c
> >>>>> b/drivers/virtio/virtio_vdpa.c
> >>>>> index a84b04ba3195..76504559bc25 100644
> >>>>> --- a/drivers/virtio/virtio_vdpa.c
> >>>>> +++ b/drivers/virtio/virtio_vdpa.c
> >>>>> @@ -91,9 +91,8 @@ static u8 virtio_vdpa_get_status(struct
> >>>>> virtio_device *vdev)
> >>>>>   static void virtio_vdpa_set_status(struct virtio_device *vdev,
> >>>>> u8 status)
> >>>>>   {
> >>>>>       struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> >>>>> -    const struct vdpa_config_ops *ops = vdpa->config;
> >>>>>   -    return ops->set_status(vdpa, status);
> >>>>> +    return vdpa_set_status(vdpa, status);
> >>>>>   }
> >>>>>     static void virtio_vdpa_reset(struct virtio_device *vdev)
> >>>>> diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h
> >>>>> index 9cc4291a79b3..ae047fae2603 100644
> >>>>> --- a/include/linux/vdpa.h
> >>>>> +++ b/include/linux/vdpa.h
> >>>>> @@ -408,6 +408,9 @@ void vdpa_get_config(struct vdpa_device *vdev,
> >>>>> unsigned int offset,
> >>>>>                void *buf, unsigned int len);
> >>>>>   void vdpa_set_config(struct vdpa_device *dev, unsigned int offset,
> >>>>>                const void *buf, unsigned int length);
> >>>>> +u8 vdpa_get_status(struct vdpa_device *vdev);
> >>>>> +void vdpa_set_status(struct vdpa_device *vdev, u8 status);
> >>>>> +
> >>>>>   /**
> >>>>>    * struct vdpa_mgmtdev_ops - vdpa device ops
> >>>>>    * @dev_add: Add a vdpa device using alloc and register
> >>>>
> >>>
> >>
> >
>

_______________________________________________
Virtualization mailing list
Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linuxfoundation.org/mailman/listinfo/virtualization




[Index of Archives]     [KVM Development]     [Libvirt Development]     [Libvirt Users]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux