Re: [PATCH for-rc 2/2] IB/mlx5: Fix how advise_mr() launches async work

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

 



On Fri, Jan 11, 2019 at 07:31:24PM -0700, Jason Gunthorpe wrote:
> From: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
>
> Work must hold a kref on the ib_device otherwise the dev pointer can
> become free before the work runs.

How can it occur exactly?

"dev" will be released after mlx5_ib will exist, mlx5_ib exist will
drain advise_mr queue before it. Such drain will ensure that no works
are running.

>
> Remove the bogus use of 'reg_state':
>  - While in uverbs the reg_state is guaranteed to always be
>    REGISTERED
>  - Testing reg_state with no locking is bogus. Use ib_device_try_get()
>    to get back into a region that prevents unregistration.
>
> Fixes: 813e90b1aeaa ("IB/mlx5: Add advise_mr() support")
> Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
> ---
>  drivers/infiniband/hw/mlx5/odp.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c
> index 8d46b1dc56580f..a241a65834d4ca 100644
> --- a/drivers/infiniband/hw/mlx5/odp.c
> +++ b/drivers/infiniband/hw/mlx5/odp.c
> @@ -1595,10 +1595,12 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work)
>  	struct prefetch_mr_work *w =
>  		container_of(work, struct prefetch_mr_work, work);
>
> -	if (w->dev->ib_dev.reg_state == IB_DEV_REGISTERED)
> +	if (ib_device_try_get(&w->dev->ib_dev)) {
>  		mlx5_ib_prefetch_sg_list(w->dev, w->pf_flags, w->sg_list,
>  					 w->num_sge);
> -
> +		ib_device_put(&w->dev->ib_dev);
> +	}
> +	put_device(&w->dev->ib_dev.dev);
>  	kfree(w);
>  }
>
> @@ -1617,15 +1619,13 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
>  		return mlx5_ib_prefetch_sg_list(dev, pf_flags, sg_list,
>  						num_sge);
>
> -	if (dev->ib_dev.reg_state != IB_DEV_REGISTERED)
> -		return -ENODEV;
> -
>  	work = kvzalloc(struct_size(work, sg_list, num_sge), GFP_KERNEL);
>  	if (!work)
>  		return -ENOMEM;
>
>  	memcpy(work->sg_list, sg_list, num_sge * sizeof(struct ib_sge));
>
> +	get_device(&dev->ib_dev.dev);

It looks extremely wrong to sprinkle driver code with general
get_device/put_device.

>  	work->dev = dev;
>  	work->pf_flags = pf_flags;
>  	work->num_sge = num_sge;
> --
> 2.20.1
>

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux