Re: [PATCH rdma-next 2/2] IB/mlx5: Validate correct PD before prefetch MR

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

 



On Mon, Feb 04, 2019 at 10:13:48AM +0200, Leon Romanovsky wrote:
> From: Moni Shoua <monis@xxxxxxxxxxxx>
> 
> When prefetching odp mr it is required to verify that pd of the mr is
> identical to the pd for which the advise_mr request arrived with.
> 
> This check was missing from synchronous flow and is added now.
> 
> Fixes: 813e90b1aeaa ("IB/mlx5: Add advise_mr() support")
> Reported-by: Parav Pandit <parav@xxxxxxxxxxxx>
> Signed-off-by: Moni Shoua <monis@xxxxxxxxxxxx>
> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
>  drivers/infiniband/hw/mlx5/odp.c | 43 +++++++++++++++++++-------------
>  1 file changed, 26 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c
> index 977d8f5d1e0f..b520178272bd 100644
> +++ b/drivers/infiniband/hw/mlx5/odp.c
> @@ -737,7 +737,8 @@ static int get_indirect_num_descs(struct mlx5_core_mkey *mmkey)
>   * -EFAULT when there's an error mapping the requested pages. The caller will
>   *  abort the page fault handling.
>   */
> -static int pagefault_single_data_segment(struct mlx5_ib_dev *dev, u32 key,
> +static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
> +					 struct ib_pd *pd, u32 key,
>  					 u64 io_virt, size_t bcnt,
>  					 u32 *bytes_committed,
>  					 u32 *bytes_mapped, u32 flags)
> @@ -787,9 +788,15 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev, u32 key,
>  			goto srcu_unlock;
>  		}
>  
> -		if (prefetch && !is_odp_mr(mr)) {
> -			ret = -EINVAL;
> -			goto srcu_unlock;
> +		if (prefetch) {
> +			if (!is_odp_mr(mr) ||
> +			    mr->ibmr.pd != pd) {
> +				mlx5_ib_dbg(dev, "Invalid prefetch request: %s\n",
> +					    is_odp_mr(mr) ?  "MR is not ODP" :
> +					    "PD is not of the MR");
> +				ret = -EINVAL;
> +				goto srcu_unlock;
> +			}
>  		}
>  
>  		if (!is_odp_mr(mr)) {
> @@ -972,7 +979,8 @@ static int pagefault_data_segments(struct mlx5_ib_dev *dev,
>  			continue;
>  		}
>  
> -		ret = pagefault_single_data_segment(dev, key, io_virt, bcnt,
> +		ret = pagefault_single_data_segment(dev, NULL, key,
> +						    io_virt, bcnt,
>  						    &pfault->bytes_committed,
>  						    bytes_mapped, 0);
>  		if (ret < 0)
> @@ -1339,7 +1347,7 @@ static void mlx5_ib_mr_rdma_pfault_handler(struct mlx5_ib_dev *dev,
>  		prefetch_len = min(MAX_PREFETCH_LEN, prefetch_len);
>  	}
>  
> -	ret = pagefault_single_data_segment(dev, rkey, address, length,
> +	ret = pagefault_single_data_segment(dev, NULL, rkey, address, length,
>  					    &pfault->bytes_committed, NULL,
>  					    0);
>  	if (ret == -EAGAIN) {
> @@ -1366,7 +1374,7 @@ static void mlx5_ib_mr_rdma_pfault_handler(struct mlx5_ib_dev *dev,
>  	if (prefetch_activated) {
>  		u32 bytes_committed = 0;
>  
> -		ret = pagefault_single_data_segment(dev, rkey, address,
> +		ret = pagefault_single_data_segment(dev, NULL, rkey, address,
>  						    prefetch_len,
>  						    &bytes_committed, NULL,
>  						    0);
> @@ -1663,23 +1671,24 @@ int mlx5_ib_odp_init(void)
>  
>  struct prefetch_mr_work {
>  	struct work_struct work;
> -	struct mlx5_ib_dev *dev;
> +	struct ib_pd *pd;
>  	u32 pf_flags;
>  	u32 num_sge;
>  	struct ib_sge sg_list[0];
>  };
>  
> -static int mlx5_ib_prefetch_sg_list(struct mlx5_ib_dev *dev, u32 pf_flags,
> +static int mlx5_ib_prefetch_sg_list(struct ib_pd *pd, u32 pf_flags,
>  				    struct ib_sge *sg_list, u32 num_sge)
>  {
>  	int i;
>  	int ret = 0;
> +	struct mlx5_ib_dev *dev = to_mdev(pd->device);
>  
>  	for (i = 0; i < num_sge; ++i) {
>  		struct ib_sge *sg = &sg_list[i];
>  		int bytes_committed = 0;
>  
> -		ret = pagefault_single_data_segment(dev, sg->lkey, sg->addr,
> +		ret = pagefault_single_data_segment(dev, pd, sg->lkey, sg->addr,
>  						    sg->length,
>  						    &bytes_committed, NULL,
>  						    pf_flags);
> @@ -1715,9 +1724,9 @@ 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)
> -		mlx5_ib_prefetch_sg_list(w->dev, w->pf_flags, w->sg_list,
> -					 w->num_sge);
> +	if (w->pd->device->reg_state == IB_DEV_REGISTERED)
> +		mlx5_ib_prefetch_sg_list(w->pd, w->pf_flags,
> +					 w->sg_list, w->num_sge);
>  
>  	kfree(w);
>  }
> @@ -1738,10 +1747,10 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
>  		pf_flags |= MLX5_PF_FLAGS_DOWNGRADE;
>  
>  	if (flags & IB_UVERBS_ADVISE_MR_FLAG_FLUSH)
> -		return mlx5_ib_prefetch_sg_list(dev, pf_flags, sg_list,
> -						num_sge);
> +		return mlx5_ib_prefetch_sg_list(pd, pf_flags,
> +						sg_list, num_sge);
>  
> -	if (dev->ib_dev.reg_state != IB_DEV_REGISTERED)
> +	if (pd->device->reg_state != IB_DEV_REGISTERED)
>  		return -ENODEV;

This needs to be rebased onto a rc5 merge'd tree.

>  	work = kvzalloc(struct_size(work, sg_list, num_sge), GFP_KERNEL);
> @@ -1750,7 +1759,7 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
>  
>  	memcpy(work->sg_list, sg_list, num_sge * sizeof(struct ib_sge));
>  
> -	work->dev = dev;
> +	work->pd = pd;

This deserves a comment that it is safe to have this pointer because
MR destruction flushes the WQ, and the PD can't be destroyed while it
has MRs

Jason




[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