On Thu, 22 Oct 2020 13:12:04 -0400
Tony Krowiak <akrow...@linux.ibm.com> wrote:

> +static int vfio_ap_mdev_validate_masks(struct ap_matrix_mdev *matrix_mdev,
> +                                    unsigned long *mdev_apm,
> +                                    unsigned long *mdev_aqm)
> +{
> +     if (ap_apqn_in_matrix_owned_by_def_drv(mdev_apm, mdev_aqm))
> +             return -EADDRNOTAVAIL;
> +
> +     return vfio_ap_mdev_verify_no_sharing(matrix_mdev, mdev_apm, mdev_aqm);
> +}
> +
>  static bool vfio_ap_mdev_matrixes_equal(struct ap_matrix *matrix1,
>                                       struct ap_matrix *matrix2)
>  {
> @@ -840,33 +734,21 @@ static ssize_t assign_adapter_store(struct device *dev,
>       if (apid > matrix_mdev->matrix.apm_max)
>               return -ENODEV;
>  
> -     /*
> -      * Set the bit in the AP mask (APM) corresponding to the AP adapter
> -      * number (APID). The bits in the mask, from most significant to least
> -      * significant bit, correspond to APIDs 0-255.
> -      */
> -     mutex_lock(&matrix_dev->lock);
> -
> -     ret = vfio_ap_mdev_verify_queues_reserved_for_apid(matrix_mdev, apid);
> -     if (ret)
> -             goto done;
> -
>       memset(apm, 0, sizeof(apm));
>       set_bit_inv(apid, apm);
>  
> -     ret = vfio_ap_mdev_verify_no_sharing(matrix_mdev, apm,
> -                                          matrix_mdev->matrix.aqm);
> -     if (ret)
> -             goto done;
> -
> +     mutex_lock(&matrix_dev->lock);
> +     ret = vfio_ap_mdev_validate_masks(matrix_mdev, apm,
> +                                       matrix_mdev->matrix.aqm);

Is this a potential deadlock?

Consider following scenario 
1) apmask_store() takes ap_perms_mutex
2) assign_adapter_store() takes matrix_dev->lock
3) apmask_store() calls vfio_ap_mdev_resource_in_use() which tries
   to take matrix_dev->lock
4) assign_adapter_store() calls ap_apqn_in_matrix_owned_by_def_drv
   which tries to take ap_perms_mutex

BANG!

I think using mutex_trylock(&matrix_dev->lock) and bailing out with busy
if we don't manage to acquire the lock would be a good idea anyway, to
prevent a bunch of mdev management operations piling up on the mutex
and starving in_use().

Regards,
Halil

 
> +     if (ret) {
> +             mutex_unlock(&matrix_dev->lock);
> +             return ret;
> +     }
>       set_bit_inv(apid, matrix_mdev->matrix.apm);
>       vfio_ap_mdev_link_queues(matrix_mdev, LINK_APID, apid);
> -     ret = count;
> -
> -done:
>       mutex_unlock(&matrix_dev->lock);
>  
> -     return ret;
> +     return count;

Reply via email to