On Wed, 14 Jul 2021 21:20:38 -0300
Jason Gunthorpe <j...@nvidia.com> wrote:
> +/*
> + * We need to get memory_lock for each device, but devices can share 
> mmap_lock,
> + * therefore we need to zap and hold the vma_lock for each device, and only 
> then
> + * get each memory_lock.
> + */
> +static int vfio_hot_reset_device_set(struct vfio_pci_device *vdev,
> +                                  struct vfio_pci_group_info *groups)
> +{
> +     struct vfio_device_set *dev_set = vdev->vdev.dev_set;
> +     struct vfio_pci_device *cur_mem =
> +             list_first_entry(&dev_set->device_list, struct vfio_pci_device,
> +                              vdev.dev_set_list);

We shouldn't be looking at the list outside of the lock, if the first
entry got removed we'd break our unwind code.

> +     struct vfio_pci_device *cur_vma;
> +     struct vfio_pci_device *cur;
> +     bool is_mem = true;
> +     int ret;
>  
> -     if (pci_dev_driver(pdev) != &vfio_pci_driver) {
> -             vfio_device_put(device);
> -             return -EBUSY;
> +     mutex_lock(&dev_set->lock);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^

> +
> +     /* All devices in the group to be reset need VFIO devices */
> +     if (vfio_pci_for_each_slot_or_bus(
> +                 vdev->pdev, vfio_pci_check_all_devices_bound, dev_set,
> +                 !pci_probe_reset_slot(vdev->pdev->slot))) {
> +             ret = -EINVAL;
> +             goto err_unlock;
>       }
>  
> -     vdev = container_of(device, struct vfio_pci_device, vdev);
> +     list_for_each_entry(cur_vma, &dev_set->device_list, vdev.dev_set_list) {
> +             /*
> +              * Test whether all the affected devices are contained by the
> +              * set of groups provided by the user.
> +              */
> +             if (!vfio_dev_in_groups(cur_vma, groups)) {
> +                     ret = -EINVAL;
> +                     goto err_undo;
> +             }
>  
> -     /*
> -      * Locking multiple devices is prone to deadlock, runaway and
> -      * unwind if we hit contention.
> -      */
> -     if (!vfio_pci_zap_and_vma_lock(vdev, true)) {
> -             vfio_device_put(device);
> -             return -EBUSY;
> +             /*
> +              * Locking multiple devices is prone to deadlock, runaway and
> +              * unwind if we hit contention.
> +              */
> +             if (!vfio_pci_zap_and_vma_lock(cur_vma, true)) {
> +                     ret = -EBUSY;
> +                     goto err_undo;
> +             }
>       }
>  
> -     devs->devices[devs->cur_index++] = vdev;
> -     return 0;
> +     list_for_each_entry(cur_mem, &dev_set->device_list, vdev.dev_set_list) {
> +             if (!down_write_trylock(&cur_mem->memory_lock)) {
> +                     ret = -EBUSY;
> +                     goto err_undo;
> +             }
> +             mutex_unlock(&cur_mem->vma_lock);
> +     }
> +
> +     ret = pci_reset_bus(vdev->pdev);
> +


> +     list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list)
> +             up_write(&cur->memory_lock);
> +     mutex_unlock(&dev_set->lock);
> +
> +     return ret;


Isn't the above section actually redundant to below, ie. we could just
fall through after the pci_reset_bus()?  Thanks,

Alex

> +
> +err_undo:
> +     list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) {
> +             if (cur == cur_mem)
> +                     is_mem = false;
> +             if (cur == cur_vma)
> +                     break;
> +             if (is_mem)
> +                     up_write(&cur->memory_lock);
> +             else
> +                     mutex_unlock(&cur->vma_lock);
> +     }
> +err_unlock:
> +     mutex_unlock(&dev_set->lock);
> +     return ret;
>  }
>  
>  /*

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to