RDMA/rxe: Prevent double freeing rxe_map_set()

The same rxe_map_set could be freed twice:

rxe_reg_user_mr()
  -> rxe_mr_init_user()
    -> rxe_mr_free_map_set() # 1st

  -> rxe_drop_ref()
   ...
    -> rxe_mr_cleanup()
      -> rxe_mr_free_map_set() # 2nd

Follow normal convection and put resource cleanup either in the error
unwind of the allocator, or the overall free function. Leave the object
unchanged with a NULL cur_map_set on failure and remove the unncessary
free in rxe_mr_init_user().

Link: https://lore.kernel.org/r/20211228014406.1033444-1-lizhijian@cn.fujitsu.com
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Acked-by: Zhu Yanjun <zyjzyj2000@gmail.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
Li Zhijian 2021-12-28 09:44:06 +08:00 committed by Jason Gunthorpe
parent c9e6606c7f
commit 8ff5f5d9d8

View File

@ -135,19 +135,19 @@ static int rxe_mr_alloc(struct rxe_mr *mr, int num_buf, int both)
ret = rxe_mr_alloc_map_set(num_map, &mr->cur_map_set); ret = rxe_mr_alloc_map_set(num_map, &mr->cur_map_set);
if (ret) if (ret)
goto err_out; return -ENOMEM;
if (both) { if (both) {
ret = rxe_mr_alloc_map_set(num_map, &mr->next_map_set); ret = rxe_mr_alloc_map_set(num_map, &mr->next_map_set);
if (ret) { if (ret)
rxe_mr_free_map_set(mr->num_map, mr->cur_map_set); goto err_free;
goto err_out;
}
} }
return 0; return 0;
err_out: err_free:
rxe_mr_free_map_set(mr->num_map, mr->cur_map_set);
mr->cur_map_set = NULL;
return -ENOMEM; return -ENOMEM;
} }
@ -214,7 +214,7 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova,
pr_warn("%s: Unable to get virtual address\n", pr_warn("%s: Unable to get virtual address\n",
__func__); __func__);
err = -ENOMEM; err = -ENOMEM;
goto err_cleanup_map; goto err_release_umem;
} }
buf->addr = (uintptr_t)vaddr; buf->addr = (uintptr_t)vaddr;
@ -237,8 +237,6 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova,
return 0; return 0;
err_cleanup_map:
rxe_mr_free_map_set(mr->num_map, mr->cur_map_set);
err_release_umem: err_release_umem:
ib_umem_release(umem); ib_umem_release(umem);
err_out: err_out: