@@ -228,13 +228,27 @@ static void destroy_unused_implicit_child_mr(struct mlx5_ib_mr *mr)
228228 unsigned long idx = ib_umem_start (odp ) >> MLX5_IMR_MTT_SHIFT ;
229229 struct mlx5_ib_mr * imr = mr -> parent ;
230230
231+ /*
232+ * If userspace is racing freeing the parent implicit ODP MR then we can
233+ * loose the race with parent destruction. In this case
234+ * mlx5_ib_free_odp_mr() will free everything in the implicit_children
235+ * xarray so NOP is fine. This child MR cannot be destroyed here because
236+ * we are under its umem_mutex.
237+ */
231238 if (!refcount_inc_not_zero (& imr -> mmkey .usecount ))
232239 return ;
233240
234- xa_erase (& imr -> implicit_children , idx );
241+ xa_lock (& imr -> implicit_children );
242+ if (__xa_cmpxchg (& imr -> implicit_children , idx , mr , NULL , GFP_KERNEL ) !=
243+ mr ) {
244+ xa_unlock (& imr -> implicit_children );
245+ return ;
246+ }
247+
235248 if (MLX5_CAP_ODP (mr_to_mdev (mr )-> mdev , mem_page_fault ))
236- xa_erase (& mr_to_mdev (mr )-> odp_mkeys ,
237- mlx5_base_mkey (mr -> mmkey .key ));
249+ __xa_erase (& mr_to_mdev (mr )-> odp_mkeys ,
250+ mlx5_base_mkey (mr -> mmkey .key ));
251+ xa_unlock (& imr -> implicit_children );
238252
239253 /* Freeing a MR is a sleeping operation, so bounce to a work queue */
240254 INIT_WORK (& mr -> odp_destroy .work , free_implicit_child_mr_work );
@@ -502,18 +516,18 @@ static struct mlx5_ib_mr *implicit_get_child_mr(struct mlx5_ib_mr *imr,
502516 refcount_inc (& ret -> mmkey .usecount );
503517 goto out_lock ;
504518 }
505- xa_unlock (& imr -> implicit_children );
506519
507520 if (MLX5_CAP_ODP (dev -> mdev , mem_page_fault )) {
508- ret = xa_store (& dev -> odp_mkeys , mlx5_base_mkey (mr -> mmkey .key ),
509- & mr -> mmkey , GFP_KERNEL );
521+ ret = __xa_store (& dev -> odp_mkeys , mlx5_base_mkey (mr -> mmkey .key ),
522+ & mr -> mmkey , GFP_KERNEL );
510523 if (xa_is_err (ret )) {
511524 ret = ERR_PTR (xa_err (ret ));
512- xa_erase (& imr -> implicit_children , idx );
513- goto out_mr ;
525+ __xa_erase (& imr -> implicit_children , idx );
526+ goto out_lock ;
514527 }
515528 mr -> mmkey .type = MLX5_MKEY_IMPLICIT_CHILD ;
516529 }
530+ xa_unlock (& imr -> implicit_children );
517531 mlx5_ib_dbg (mr_to_mdev (imr ), "key %x mr %p\n" , mr -> mmkey .key , mr );
518532 return mr ;
519533
0 commit comments