aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/nldev.c
diff options
context:
space:
mode:
authorLeon Romanovsky <leonro@mellanox.com>2019-02-18 22:25:48 +0200
committerJason Gunthorpe <jgg@mellanox.com>2019-02-19 10:13:38 -0700
commit7c77c6a9bf9d71711dd3f89858bb0f5157a11919 (patch)
tree8c7f62c751d056b92cad308589fbb04089a65853 /drivers/infiniband/core/nldev.c
parentRDMA/restrack: Hide restrack DB from IB/core (diff)
downloadlinux-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/nldev.c')
-rw-r--r--drivers/infiniband/core/nldev.c41
1 files changed, 16 insertions, 25 deletions
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 54312f9626a1..9b4f891771c4 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1018,6 +1018,7 @@ static int res_get_common_dumpit(struct sk_buff *skb,
const struct nldev_fill_res_entry *fe = &fill_entries[res_type];
struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
struct rdma_restrack_entry *res;
+ struct rdma_restrack_root *rt;
int err, ret = 0, idx = 0;
struct nlattr *table_attr;
struct nlattr *entry_attr;
@@ -1028,7 +1029,6 @@ static int res_get_common_dumpit(struct sk_buff *skb,
unsigned long id;
u32 index, port = 0;
bool filled = false;
- struct xarray *xa;
err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
nldev_policy, NULL);
@@ -1076,14 +1076,14 @@ static int res_get_common_dumpit(struct sk_buff *skb,
has_cap_net_admin = netlink_capable(cb->skb, CAP_NET_ADMIN);
- xa = &device->res->xa[res_type];
- down_read(&device->res->rwsem);
+ rt = &device->res[res_type];
+ xa_lock(&rt->xa);
/*
* FIXME: if the skip ahead is something common this loop should
* use xas_for_each & xas_pause to optimize, we can have a lot of
* objects.
*/
- xa_for_each(xa, id, res) {
+ xa_for_each(&rt->xa, id, res) {
if (idx < start)
goto next;
@@ -1091,45 +1091,37 @@ static int res_get_common_dumpit(struct sk_buff *skb,
goto next;
if (!rdma_restrack_get(res))
- /*
- * Resource is under release now, but we are not
- * relesing lock now, so it will be released in
- * our next pass, once we will get ->next pointer.
- */
goto next;
+ xa_unlock(&rt->xa);
+
filled = true;
entry_attr = nla_nest_start(skb, fe->entry);
if (!entry_attr) {
ret = -EMSGSIZE;
rdma_restrack_put(res);
- up_read(&device->res->rwsem);
- break;
+ goto msg_full;
}
- up_read(&device->res->rwsem);
ret = fe->fill_res_func(skb, has_cap_net_admin, res, port);
- down_read(&device->res->rwsem);
- /*
- * Return resource back, but it won't be released till
- * the &device->res.rwsem will be released for write.
- */
rdma_restrack_put(res);
- if (ret)
+ if (ret) {
nla_nest_cancel(skb, entry_attr);
- if (ret == -EMSGSIZE)
- break;
- if (ret == -EAGAIN)
- goto next;
- if (ret)
+ if (ret == -EMSGSIZE)
+ goto msg_full;
+ if (ret == -EAGAIN)
+ goto again;
goto res_err;
+ }
nla_nest_end(skb, entry_attr);
+again: xa_lock(&rt->xa);
next: idx++;
}
- up_read(&device->res->rwsem);
+ xa_unlock(&rt->xa);
+msg_full:
nla_nest_end(skb, table_attr);
nlmsg_end(skb, nlh);
cb->args[0] = idx;
@@ -1146,7 +1138,6 @@ next: idx++;
res_err:
nla_nest_cancel(skb, table_attr);
- up_read(&device->res->rwsem);
err:
nlmsg_cancel(skb, nlh);