RDMA: During rereg_mr ensure that REREG_ACCESS is compatible
If IB_MR_REREG_ACCESS changes from RO to RW then the umem has to be
re-evaluated to ensure it is properly pinned as RW. Since the umem is
hidden inside each driver's mr struct add a ib_umem_check_rereg() function
that each driver has to call before processing IB_MR_REREG_ACCESS.
mlx4 has to retain its duplicate ib_access_writable check because it
implements IB_MR_REREG_ACCESS | IB_MR_REREG_TRANS by changing both items
in place sequentially while the MR is live, so it will continue to not
support this combination.
Cc: stable@vger.kernel.org
Fixes: b40656aa7d ("RDMA/umem: remove FOLL_FORCE usage")
Link: https://patch.msgid.link/r/0-v1-06fb1a2d6cf5+107-rereg_access_jgg@nvidia.com
Reported-by: Philip Tsukerman <philiptsukerman@gmail.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
323c98a4ff
commit
badad6fad6
7 changed files with 45 additions and 0 deletions
|
|
@ -332,3 +332,19 @@ int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_umem_copy_from);
|
||||
|
||||
/*
|
||||
* Called during rereg mr if the driver is able to re-use a umem for
|
||||
* IB_MR_REREG_ACCESS.
|
||||
*/
|
||||
int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags)
|
||||
{
|
||||
if (!umem)
|
||||
return 0;
|
||||
|
||||
if ((flags & IB_MR_REREG_ACCESS) && !(flags & IB_MR_REREG_TRANS))
|
||||
if (ib_access_writable(new_access_flags) && !umem->writable)
|
||||
return -EACCES;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_umem_check_rereg);
|
||||
|
|
|
|||
|
|
@ -300,6 +300,10 @@ struct ib_mr *hns_roce_rereg_user_mr(struct ib_mr *ibmr, int flags, u64 start,
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
ret = ib_umem_check_rereg(mr->pbl_mtr.umem, flags, mr_access_flags);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
|
||||
mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
|
||||
ret = PTR_ERR_OR_ZERO(mailbox);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -3803,6 +3803,10 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags,
|
|||
if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
ret = ib_umem_check_rereg(iwmr->region, flags, new_access);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (dmabuf_revocable) {
|
||||
umem_dmabuf = to_ib_umem_dmabuf(iwmr->region);
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,10 @@ struct ib_mr *mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, u64 start,
|
|||
struct mlx4_mpt_entry **pmpt_entry = &mpt_entry;
|
||||
int err;
|
||||
|
||||
err = ib_umem_check_rereg(mmr->umem, flags, mr_access_flags);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
/* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs,
|
||||
* we assume that the calls can't run concurrently. Otherwise, a
|
||||
* race exists.
|
||||
|
|
|
|||
|
|
@ -1179,6 +1179,10 @@ struct ib_mr *mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
|
|||
if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
err = ib_umem_check_rereg(mr->umem, flags, new_access_flags);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (!(flags & IB_MR_REREG_ACCESS))
|
||||
new_access_flags = mr->access_flags;
|
||||
if (!(flags & IB_MR_REREG_PD))
|
||||
|
|
|
|||
|
|
@ -1319,6 +1319,7 @@ static struct ib_mr *rxe_rereg_user_mr(struct ib_mr *ibmr, int flags,
|
|||
struct rxe_mr *mr = to_rmr(ibmr);
|
||||
struct rxe_pd *old_pd = to_rpd(ibmr->pd);
|
||||
struct rxe_pd *pd = to_rpd(ibpd);
|
||||
int err;
|
||||
|
||||
/* for now only support the two easy cases:
|
||||
* rereg_pd and rereg_access
|
||||
|
|
@ -1328,6 +1329,10 @@ static struct ib_mr *rxe_rereg_user_mr(struct ib_mr *ibmr, int flags,
|
|||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
err = ib_umem_check_rereg(mr->umem, flags, access);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (flags & IB_MR_REREG_PD) {
|
||||
rxe_put(old_pd);
|
||||
rxe_get(pd);
|
||||
|
|
|
|||
|
|
@ -156,6 +156,8 @@ void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf);
|
|||
void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf);
|
||||
void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf);
|
||||
|
||||
int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags);
|
||||
|
||||
#else /* CONFIG_INFINIBAND_USER_MEM */
|
||||
|
||||
#include <linux/err.h>
|
||||
|
|
@ -230,5 +232,11 @@ static inline void ib_umem_dmabuf_revoke_lock(struct ib_umem_dmabuf *umem_dmabuf
|
|||
static inline void ib_umem_dmabuf_revoke_unlock(struct ib_umem_dmabuf *umem_dmabuf) {}
|
||||
static inline void ib_umem_dmabuf_revoke(struct ib_umem_dmabuf *umem_dmabuf) {}
|
||||
|
||||
static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags,
|
||||
int new_access_flags)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_INFINIBAND_USER_MEM */
|
||||
#endif /* IB_UMEM_H */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue