diff options
author | Leon Romanovsky <leonro@mellanox.com> | 2019-02-18 22:25:48 +0200 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2019-02-19 10:13:38 -0700 |
commit | 7c77c6a9bf9d71711dd3f89858bb0f5157a11919 (patch) | |
tree | 8c7f62c751d056b92cad308589fbb04089a65853 /drivers/infiniband/core/restrack.c | |
parent | RDMA/restrack: Hide restrack DB from IB/core (diff) | |
download | linux-dev-7c77c6a9bf9d71711dd3f89858bb0f5157a11919.tar.xz linux-dev-7c77c6a9bf9d71711dd3f89858bb0f5157a11919.zip |
RDMA/restrack: Prepare restrack_root to addition of extra fields per-type
As a preparation to extension of rdma_restrack_root to provide software
IDs, which will be per-type too. We convert the rdma_restrack_root from
struct with arrays to array of structs.
Such conversion allows us to drop rwsem lock in favour of internal XArray
lock.
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Diffstat (limited to 'drivers/infiniband/core/restrack.c')
-rw-r--r-- | drivers/infiniband/core/restrack.c | 63 |
1 files changed, 24 insertions, 39 deletions
diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c index 6a4b76c66bcb..a5ea3988b4c3 100644 --- a/drivers/infiniband/core/restrack.c +++ b/drivers/infiniband/core/restrack.c @@ -9,7 +9,6 @@ #include <linux/mutex.h> #include <linux/sched/task.h> #include <linux/pid_namespace.h> -#include <linux/rwsem.h> #include "cma_priv.h" #include "restrack.h" @@ -47,15 +46,14 @@ int rdma_restrack_init(struct ib_device *dev) struct rdma_restrack_root *rt; int i; - dev->res = kzalloc(sizeof(*rt), GFP_KERNEL); + dev->res = kcalloc(RDMA_RESTRACK_MAX, sizeof(*rt), GFP_KERNEL); if (!dev->res) return -ENOMEM; rt = dev->res; - for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) - xa_init_flags(&rt->xa[i], XA_FLAGS_ALLOC); - init_rwsem(&rt->rwsem); + for (i = 0; i < RDMA_RESTRACK_MAX; i++) + xa_init_flags(&rt[i].xa, XA_FLAGS_ALLOC); return 0; } @@ -88,7 +86,7 @@ void rdma_restrack_clean(struct ib_device *dev) int i; for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) { - struct xarray *xa = &dev->res->xa[i]; + struct xarray *xa = &dev->res[i].xa; if (!xa_empty(xa)) { unsigned long index; @@ -134,19 +132,19 @@ void rdma_restrack_clean(struct ib_device *dev) int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type, struct pid_namespace *ns) { - struct xarray *xa = &dev->res->xa[type]; + struct rdma_restrack_root *rt = &dev->res[type]; struct rdma_restrack_entry *e; - unsigned long index = 0; + XA_STATE(xas, &rt->xa, 0); u32 cnt = 0; - down_read(&dev->res->rwsem); - xa_for_each(xa, index, e) { + xa_lock(&rt->xa); + xas_for_each(&xas, e, U32_MAX) { if (ns == &init_pid_ns || (!rdma_is_kernel_res(e) && ns == task_active_pid_ns(e->task))) cnt++; } - up_read(&dev->res->rwsem); + xa_unlock(&rt->xa); return cnt; } EXPORT_SYMBOL(rdma_restrack_count); @@ -218,18 +216,16 @@ static void rdma_restrack_add(struct rdma_restrack_entry *res) { struct ib_device *dev = res_to_dev(res); struct rdma_restrack_root *rt; - struct xarray *xa; int ret; if (!dev) return; - rt = dev->res; - xa = &dev->res->xa[res->type]; + rt = &dev->res[res->type]; kref_init(&res->kref); init_completion(&res->comp); - ret = rt_xa_alloc_cyclic(xa, &res->id, res, &rt->next_id[res->type]); + ret = rt_xa_alloc_cyclic(&rt->xa, &res->id, res, &rt->next_id); if (!ret) res->valid = true; } @@ -283,14 +279,14 @@ struct rdma_restrack_entry * rdma_restrack_get_byid(struct ib_device *dev, enum rdma_restrack_type type, u32 id) { - struct xarray *xa = &dev->res->xa[type]; + struct rdma_restrack_root *rt = &dev->res[type]; struct rdma_restrack_entry *res; - down_read(&dev->res->rwsem); - res = xa_load(xa, id); + xa_lock(&rt->xa); + res = xa_load(&rt->xa, id); if (!res || !rdma_restrack_get(res)) res = ERR_PTR(-ENOENT); - up_read(&dev->res->rwsem); + xa_unlock(&rt->xa); return res; } @@ -312,33 +308,22 @@ EXPORT_SYMBOL(rdma_restrack_put); void rdma_restrack_del(struct rdma_restrack_entry *res) { - struct ib_device *dev = res_to_dev(res); - struct xarray *xa; + struct rdma_restrack_entry *old; + struct rdma_restrack_root *rt; + struct ib_device *dev; if (!res->valid) goto out; - /* - * All objects except CM_ID set valid device immediately - * after new object is created, it means that for not valid - * objects will still have "dev". - * - * It is not the case for CM_ID, newly created object has - * this field set to NULL and it is set in _cma_attach_to_dev() - * only. - * - * Because we don't want to add any conditions on call - * to rdma_restrack_del(), the check below protects from - * NULL-dereference. - */ - if (!dev) + dev = res_to_dev(res); + if (WARN_ON(!dev)) return; - xa = &dev->res->xa[res->type]; - down_write(&dev->res->rwsem); - xa_erase(xa, res->id); + rt = &dev->res[res->type]; + + old = xa_erase(&rt->xa, res->id); + WARN_ON(old != res); res->valid = false; - up_write(&dev->res->rwsem); rdma_restrack_put(res); wait_for_completion(&res->comp); |