Skip to content

Commit f20bef6

Browse files
committed
RDMA/odp: Make the three ways to create a umem_odp clear
The three paths to build the umem_odps are kind of muddled, they are: - As a normal ib_mr umem - As a child in an implicit ODP umem tree - As the root of an implicit ODP umem tree Only the first two are actually umem's, the last is an abuse. The implicit case can only be triggered by explicit driver request, it should never be co-mingled with the normal case. While we are here, make sensible function names and add some comments to make this clearer. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 22d79c9 commit f20bef6

File tree

3 files changed

+89
-20
lines changed

3 files changed

+89
-20
lines changed

drivers/infiniband/core/umem_odp.c

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
#include <rdma/ib_umem.h>
4747
#include <rdma/ib_umem_odp.h>
4848

49+
#include "uverbs.h"
50+
4951
static void ib_umem_notifier_start_account(struct ib_umem_odp *umem_odp)
5052
{
5153
mutex_lock(&umem_odp->umem_mutex);
@@ -344,8 +346,67 @@ static inline int ib_init_umem_odp(struct ib_umem_odp *umem_odp,
344346
return ret;
345347
}
346348

347-
struct ib_umem_odp *ib_alloc_odp_umem(struct ib_umem_odp *root,
348-
unsigned long addr, size_t size)
349+
/**
350+
* ib_umem_odp_alloc_implicit - Allocate a parent implicit ODP umem
351+
*
352+
* Implicit ODP umems do not have a VA range and do not have any page lists.
353+
* They exist only to hold the per_mm reference to help the driver create
354+
* children umems.
355+
*
356+
* @udata: udata from the syscall being used to create the umem
357+
* @access: ib_reg_mr access flags
358+
*/
359+
struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_udata *udata,
360+
int access)
361+
{
362+
struct ib_ucontext *context =
363+
container_of(udata, struct uverbs_attr_bundle, driver_udata)
364+
->context;
365+
struct ib_umem *umem;
366+
struct ib_umem_odp *umem_odp;
367+
int ret;
368+
369+
if (access & IB_ACCESS_HUGETLB)
370+
return ERR_PTR(-EINVAL);
371+
372+
if (!context)
373+
return ERR_PTR(-EIO);
374+
if (WARN_ON_ONCE(!context->invalidate_range))
375+
return ERR_PTR(-EINVAL);
376+
377+
umem_odp = kzalloc(sizeof(*umem_odp), GFP_KERNEL);
378+
if (!umem_odp)
379+
return ERR_PTR(-ENOMEM);
380+
umem = &umem_odp->umem;
381+
umem->context = context;
382+
umem->writable = ib_access_writable(access);
383+
umem->owning_mm = current->mm;
384+
umem_odp->is_implicit_odp = 1;
385+
umem_odp->page_shift = PAGE_SHIFT;
386+
387+
ret = ib_init_umem_odp(umem_odp, NULL);
388+
if (ret) {
389+
kfree(umem_odp);
390+
return ERR_PTR(ret);
391+
}
392+
393+
mmgrab(umem->owning_mm);
394+
395+
return umem_odp;
396+
}
397+
EXPORT_SYMBOL(ib_umem_odp_alloc_implicit);
398+
399+
/**
400+
* ib_umem_odp_alloc_child - Allocate a child ODP umem under an implicit
401+
* parent ODP umem
402+
*
403+
* @root: The parent umem enclosing the child. This must be allocated using
404+
* ib_alloc_implicit_odp_umem()
405+
* @addr: The starting userspace VA
406+
* @size: The length of the userspace VA
407+
*/
408+
struct ib_umem_odp *ib_umem_odp_alloc_child(struct ib_umem_odp *root,
409+
unsigned long addr, size_t size)
349410
{
350411
/*
351412
* Caller must ensure that root cannot be freed during the call to
@@ -355,6 +416,9 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_umem_odp *root,
355416
struct ib_umem *umem;
356417
int ret;
357418

419+
if (WARN_ON(!root->is_implicit_odp))
420+
return ERR_PTR(-EINVAL);
421+
358422
odp_data = kzalloc(sizeof(*odp_data), GFP_KERNEL);
359423
if (!odp_data)
360424
return ERR_PTR(-ENOMEM);
@@ -376,8 +440,15 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_umem_odp *root,
376440

377441
return odp_data;
378442
}
379-
EXPORT_SYMBOL(ib_alloc_odp_umem);
443+
EXPORT_SYMBOL(ib_umem_odp_alloc_child);
380444

445+
/**
446+
* ib_umem_odp_get - Complete ib_umem_get()
447+
*
448+
* @umem_odp: The partially configured umem from ib_umem_get()
449+
* @addr: The starting userspace VA
450+
* @access: ib_reg_mr access flags
451+
*/
381452
int ib_umem_odp_get(struct ib_umem_odp *umem_odp, int access)
382453
{
383454
/*
@@ -386,9 +457,6 @@ int ib_umem_odp_get(struct ib_umem_odp *umem_odp, int access)
386457
*/
387458
struct mm_struct *mm = umem_odp->umem.owning_mm;
388459

389-
if (umem_odp->umem.address == 0 && umem_odp->umem.length == 0)
390-
umem_odp->is_implicit_odp = 1;
391-
392460
umem_odp->page_shift = PAGE_SHIFT;
393461
if (access & IB_ACCESS_HUGETLB) {
394462
struct vm_area_struct *vma;

drivers/infiniband/hw/mlx5/odp.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ static void mlx5_ib_page_fault_resume(struct mlx5_ib_dev *dev,
384384
}
385385

386386
static struct mlx5_ib_mr *implicit_mr_alloc(struct ib_pd *pd,
387-
struct ib_umem *umem,
387+
struct ib_umem_odp *umem_odp,
388388
bool ksm, int access_flags)
389389
{
390390
struct mlx5_ib_dev *dev = to_mdev(pd->device);
@@ -402,7 +402,7 @@ static struct mlx5_ib_mr *implicit_mr_alloc(struct ib_pd *pd,
402402
mr->dev = dev;
403403
mr->access_flags = access_flags;
404404
mr->mmkey.iova = 0;
405-
mr->umem = umem;
405+
mr->umem = &umem_odp->umem;
406406

407407
if (ksm) {
408408
err = mlx5_ib_update_xlt(mr, 0,
@@ -462,14 +462,13 @@ static struct ib_umem_odp *implicit_mr_get_data(struct mlx5_ib_mr *mr,
462462
if (nentries)
463463
nentries++;
464464
} else {
465-
odp = ib_alloc_odp_umem(odp_mr, addr,
466-
MLX5_IMR_MTT_SIZE);
465+
odp = ib_umem_odp_alloc_child(odp_mr, addr, MLX5_IMR_MTT_SIZE);
467466
if (IS_ERR(odp)) {
468467
mutex_unlock(&odp_mr->umem_mutex);
469468
return ERR_CAST(odp);
470469
}
471470

472-
mtt = implicit_mr_alloc(mr->ibmr.pd, &odp->umem, 0,
471+
mtt = implicit_mr_alloc(mr->ibmr.pd, odp, 0,
473472
mr->access_flags);
474473
if (IS_ERR(mtt)) {
475474
mutex_unlock(&odp_mr->umem_mutex);
@@ -519,19 +518,19 @@ struct mlx5_ib_mr *mlx5_ib_alloc_implicit_mr(struct mlx5_ib_pd *pd,
519518
int access_flags)
520519
{
521520
struct mlx5_ib_mr *imr;
522-
struct ib_umem *umem;
521+
struct ib_umem_odp *umem_odp;
523522

524-
umem = ib_umem_get(udata, 0, 0, access_flags, 0);
525-
if (IS_ERR(umem))
526-
return ERR_CAST(umem);
523+
umem_odp = ib_umem_odp_alloc_implicit(udata, access_flags);
524+
if (IS_ERR(umem_odp))
525+
return ERR_CAST(umem_odp);
527526

528-
imr = implicit_mr_alloc(&pd->ibpd, umem, 1, access_flags);
527+
imr = implicit_mr_alloc(&pd->ibpd, umem_odp, 1, access_flags);
529528
if (IS_ERR(imr)) {
530-
ib_umem_release(umem);
529+
ib_umem_release(&umem_odp->umem);
531530
return ERR_CAST(imr);
532531
}
533532

534-
imr->umem = umem;
533+
imr->umem = &umem_odp->umem;
535534
init_waitqueue_head(&imr->q_leaf_free);
536535
atomic_set(&imr->num_leaf_free, 0);
537536
atomic_set(&imr->num_pending_prefetch, 0);

include/rdma/ib_umem_odp.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,10 @@ struct ib_ucontext_per_mm {
140140
};
141141

142142
int ib_umem_odp_get(struct ib_umem_odp *umem_odp, int access);
143-
struct ib_umem_odp *ib_alloc_odp_umem(struct ib_umem_odp *root_umem,
144-
unsigned long addr, size_t size);
143+
struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_udata *udata,
144+
int access);
145+
struct ib_umem_odp *ib_umem_odp_alloc_child(struct ib_umem_odp *root_umem,
146+
unsigned long addr, size_t size);
145147
void ib_umem_odp_release(struct ib_umem_odp *umem_odp);
146148

147149
int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, u64 start_offset,

0 commit comments

Comments
 (0)