Commit 41eda65c authored by Leon Romanovsky's avatar Leon Romanovsky Committed by Jason Gunthorpe

RDMA/restrack: Hide restrack DB from IB/core

There is no need to expose internals of restrack DB to IB/core.
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 48118527
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <rdma/ib_cache.h> #include <rdma/ib_cache.h>
#include "core_priv.h" #include "core_priv.h"
#include "restrack.h"
MODULE_AUTHOR("Roland Dreier"); MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("core kernel InfiniBand API"); MODULE_DESCRIPTION("core kernel InfiniBand API");
...@@ -338,7 +339,10 @@ struct ib_device *_ib_alloc_device(size_t size) ...@@ -338,7 +339,10 @@ struct ib_device *_ib_alloc_device(size_t size)
if (!device) if (!device)
return NULL; return NULL;
rdma_restrack_init(device); if (rdma_restrack_init(device)) {
kfree(device);
return NULL;
}
device->dev.class = &ib_class; device->dev.class = &ib_class;
device->groups[0] = &ib_dev_attr_group; device->groups[0] = &ib_dev_attr_group;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "core_priv.h" #include "core_priv.h"
#include "cma_priv.h" #include "cma_priv.h"
#include "restrack.h"
static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = { static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
[RDMA_NLDEV_ATTR_DEV_INDEX] = { .type = NLA_U32 }, [RDMA_NLDEV_ATTR_DEV_INDEX] = { .type = NLA_U32 },
...@@ -1027,6 +1028,7 @@ static int res_get_common_dumpit(struct sk_buff *skb, ...@@ -1027,6 +1028,7 @@ static int res_get_common_dumpit(struct sk_buff *skb,
unsigned long id; unsigned long id;
u32 index, port = 0; u32 index, port = 0;
bool filled = false; bool filled = false;
struct xarray *xa;
err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
nldev_policy, NULL); nldev_policy, NULL);
...@@ -1074,13 +1076,14 @@ static int res_get_common_dumpit(struct sk_buff *skb, ...@@ -1074,13 +1076,14 @@ static int res_get_common_dumpit(struct sk_buff *skb,
has_cap_net_admin = netlink_capable(cb->skb, CAP_NET_ADMIN); has_cap_net_admin = netlink_capable(cb->skb, CAP_NET_ADMIN);
down_read(&device->res.rwsem); xa = &device->res->xa[res_type];
down_read(&device->res->rwsem);
/* /*
* FIXME: if the skip ahead is something common this loop should * 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 * use xas_for_each & xas_pause to optimize, we can have a lot of
* objects. * objects.
*/ */
xa_for_each(&device->res.xa[res_type], id, res) { xa_for_each(xa, id, res) {
if (idx < start) if (idx < start)
goto next; goto next;
...@@ -1101,13 +1104,13 @@ static int res_get_common_dumpit(struct sk_buff *skb, ...@@ -1101,13 +1104,13 @@ static int res_get_common_dumpit(struct sk_buff *skb,
if (!entry_attr) { if (!entry_attr) {
ret = -EMSGSIZE; ret = -EMSGSIZE;
rdma_restrack_put(res); rdma_restrack_put(res);
up_read(&device->res.rwsem); up_read(&device->res->rwsem);
break; break;
} }
up_read(&device->res.rwsem);
up_read(&device->res->rwsem);
ret = fe->fill_res_func(skb, has_cap_net_admin, res, port); ret = fe->fill_res_func(skb, has_cap_net_admin, res, port);
down_read(&device->res.rwsem); down_read(&device->res->rwsem);
/* /*
* Return resource back, but it won't be released till * Return resource back, but it won't be released till
* the &device->res.rwsem will be released for write. * the &device->res.rwsem will be released for write.
...@@ -1125,7 +1128,7 @@ static int res_get_common_dumpit(struct sk_buff *skb, ...@@ -1125,7 +1128,7 @@ static int res_get_common_dumpit(struct sk_buff *skb,
nla_nest_end(skb, entry_attr); nla_nest_end(skb, entry_attr);
next: idx++; next: idx++;
} }
up_read(&device->res.rwsem); up_read(&device->res->rwsem);
nla_nest_end(skb, table_attr); nla_nest_end(skb, table_attr);
nlmsg_end(skb, nlh); nlmsg_end(skb, nlh);
...@@ -1143,7 +1146,7 @@ next: idx++; ...@@ -1143,7 +1146,7 @@ next: idx++;
res_err: res_err:
nla_nest_cancel(skb, table_attr); nla_nest_cancel(skb, table_attr);
up_read(&device->res.rwsem); up_read(&device->res->rwsem);
err: err:
nlmsg_cancel(skb, nlh); nlmsg_cancel(skb, nlh);
......
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/sched/task.h> #include <linux/sched/task.h>
#include <linux/pid_namespace.h> #include <linux/pid_namespace.h>
#include <linux/rwsem.h>
#include "cma_priv.h" #include "cma_priv.h"
#include "restrack.h"
static int rt_xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry, static int rt_xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry,
u32 *next) u32 *next)
...@@ -35,18 +37,27 @@ static int rt_xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry, ...@@ -35,18 +37,27 @@ static int rt_xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry,
} }
/** /**
* rdma_restrack_init() - initialize resource tracking * rdma_restrack_init() - initialize and allocate resource tracking
* @dev: IB device * @dev: IB device
*
* Return: 0 on success
*/ */
void rdma_restrack_init(struct ib_device *dev) int rdma_restrack_init(struct ib_device *dev)
{ {
struct rdma_restrack_root *res = &dev->res; struct rdma_restrack_root *rt;
int i; int i;
dev->res = kzalloc(sizeof(*rt), GFP_KERNEL);
if (!dev->res)
return -ENOMEM;
rt = dev->res;
for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) for (i = 0 ; i < RDMA_RESTRACK_MAX; i++)
xa_init_flags(&res->xa[i], XA_FLAGS_ALLOC); xa_init_flags(&rt->xa[i], XA_FLAGS_ALLOC);
init_rwsem(&rt->rwsem);
init_rwsem(&res->rwsem); return 0;
} }
static const char *type2str(enum rdma_restrack_type type) static const char *type2str(enum rdma_restrack_type type)
...@@ -69,7 +80,7 @@ static const char *type2str(enum rdma_restrack_type type) ...@@ -69,7 +80,7 @@ static const char *type2str(enum rdma_restrack_type type)
*/ */
void rdma_restrack_clean(struct ib_device *dev) void rdma_restrack_clean(struct ib_device *dev)
{ {
struct rdma_restrack_root *res = &dev->res; struct rdma_restrack_root *rt = dev->res;
struct rdma_restrack_entry *e; struct rdma_restrack_entry *e;
char buf[TASK_COMM_LEN]; char buf[TASK_COMM_LEN];
bool found = false; bool found = false;
...@@ -77,14 +88,16 @@ void rdma_restrack_clean(struct ib_device *dev) ...@@ -77,14 +88,16 @@ void rdma_restrack_clean(struct ib_device *dev)
int i; int i;
for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) { for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) {
if (!xa_empty(&res->xa[i])) { struct xarray *xa = &dev->res->xa[i];
if (!xa_empty(xa)) {
unsigned long index; unsigned long index;
if (!found) { if (!found) {
pr_err("restrack: %s", CUT_HERE); pr_err("restrack: %s", CUT_HERE);
dev_err(&dev->dev, "BUG: RESTRACK detected leak of resources\n"); dev_err(&dev->dev, "BUG: RESTRACK detected leak of resources\n");
} }
xa_for_each(&res->xa[i], index, e) { xa_for_each(xa, index, e) {
if (rdma_is_kernel_res(e)) { if (rdma_is_kernel_res(e)) {
owner = e->kern_name; owner = e->kern_name;
} else { } else {
...@@ -104,10 +117,12 @@ void rdma_restrack_clean(struct ib_device *dev) ...@@ -104,10 +117,12 @@ void rdma_restrack_clean(struct ib_device *dev)
} }
found = true; found = true;
} }
xa_destroy(&res->xa[i]); xa_destroy(xa);
} }
if (found) if (found)
pr_err("restrack: %s", CUT_HERE); pr_err("restrack: %s", CUT_HERE);
kfree(rt);
} }
/** /**
...@@ -119,19 +134,19 @@ void rdma_restrack_clean(struct ib_device *dev) ...@@ -119,19 +134,19 @@ void rdma_restrack_clean(struct ib_device *dev)
int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type, int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type,
struct pid_namespace *ns) struct pid_namespace *ns)
{ {
struct rdma_restrack_root *res = &dev->res; struct xarray *xa = &dev->res->xa[type];
struct rdma_restrack_entry *e; struct rdma_restrack_entry *e;
unsigned long index = 0; unsigned long index = 0;
u32 cnt = 0; u32 cnt = 0;
down_read(&res->rwsem); down_read(&dev->res->rwsem);
xa_for_each(&res->xa[type], index, e) { xa_for_each(xa, index, e) {
if (ns == &init_pid_ns || if (ns == &init_pid_ns ||
(!rdma_is_kernel_res(e) && (!rdma_is_kernel_res(e) &&
ns == task_active_pid_ns(e->task))) ns == task_active_pid_ns(e->task)))
cnt++; cnt++;
} }
up_read(&res->rwsem); up_read(&dev->res->rwsem);
return cnt; return cnt;
} }
EXPORT_SYMBOL(rdma_restrack_count); EXPORT_SYMBOL(rdma_restrack_count);
...@@ -202,17 +217,19 @@ EXPORT_SYMBOL(rdma_restrack_set_task); ...@@ -202,17 +217,19 @@ EXPORT_SYMBOL(rdma_restrack_set_task);
static void rdma_restrack_add(struct rdma_restrack_entry *res) static void rdma_restrack_add(struct rdma_restrack_entry *res)
{ {
struct ib_device *dev = res_to_dev(res); struct ib_device *dev = res_to_dev(res);
struct rdma_restrack_root *rt;
struct xarray *xa;
int ret; int ret;
if (!dev) if (!dev)
return; return;
rt = dev->res;
xa = &dev->res->xa[res->type];
kref_init(&res->kref); kref_init(&res->kref);
init_completion(&res->comp); init_completion(&res->comp);
ret = rt_xa_alloc_cyclic(xa, &res->id, res, &rt->next_id[res->type]);
ret = rt_xa_alloc_cyclic(&dev->res.xa[res->type], &res->id, res,
&dev->res.next_id[res->type]);
if (!ret) if (!ret)
res->valid = true; res->valid = true;
} }
...@@ -266,14 +283,14 @@ struct rdma_restrack_entry * ...@@ -266,14 +283,14 @@ struct rdma_restrack_entry *
rdma_restrack_get_byid(struct ib_device *dev, rdma_restrack_get_byid(struct ib_device *dev,
enum rdma_restrack_type type, u32 id) enum rdma_restrack_type type, u32 id)
{ {
struct rdma_restrack_root *rt = &dev->res; struct xarray *xa = &dev->res->xa[type];
struct rdma_restrack_entry *res; struct rdma_restrack_entry *res;
down_read(&dev->res.rwsem); down_read(&dev->res->rwsem);
res = xa_load(&rt->xa[type], id); res = xa_load(xa, id);
if (!res || !rdma_restrack_get(res)) if (!res || !rdma_restrack_get(res))
res = ERR_PTR(-ENOENT); res = ERR_PTR(-ENOENT);
up_read(&dev->res.rwsem); up_read(&dev->res->rwsem);
return res; return res;
} }
...@@ -295,19 +312,33 @@ EXPORT_SYMBOL(rdma_restrack_put); ...@@ -295,19 +312,33 @@ EXPORT_SYMBOL(rdma_restrack_put);
void rdma_restrack_del(struct rdma_restrack_entry *res) void rdma_restrack_del(struct rdma_restrack_entry *res)
{ {
struct ib_device *dev; struct ib_device *dev = res_to_dev(res);
struct xarray *xa;
if (!res->valid) if (!res->valid)
goto out; goto out;
dev = res_to_dev(res); /*
* 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) if (!dev)
return; return;
down_write(&dev->res.rwsem); xa = &dev->res->xa[res->type];
xa_erase(&dev->res.xa[res->type], res->id); down_write(&dev->res->rwsem);
xa_erase(xa, res->id);
res->valid = false; res->valid = false;
up_write(&dev->res.rwsem); up_write(&dev->res->rwsem);
rdma_restrack_put(res); rdma_restrack_put(res);
wait_for_completion(&res->comp); wait_for_completion(&res->comp);
......
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/*
* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved.
*/
#ifndef _RDMA_CORE_RESTRACK_H_
#define _RDMA_CORE_RESTRACK_H_
#include <linux/mutex.h>
#include <linux/rwsem.h>
/**
* struct rdma_restrack_root - main resource tracking management
* entity, per-device
*/
struct rdma_restrack_root {
/*
* @rwsem: Read/write lock to protect erase of entry.
* Lists and insertions are protected by XArray internal lock.
*/
struct rw_semaphore rwsem;
/**
* @xa: Array of XArray structures to hold restrack entries.
* We want to use array of XArrays because insertion is type
* dependent. For types with xisiting unique ID (like QPN),
* we will insert to that unique index. For other types,
* we insert based on pointers and auto-allocate unique index.
*/
struct xarray xa[RDMA_RESTRACK_MAX];
/**
* @next_id: Next ID to support cyclic allocation
*/
u32 next_id[RDMA_RESTRACK_MAX];
};
int rdma_restrack_init(struct ib_device *dev);
void rdma_restrack_clean(struct ib_device *dev);
#endif /* _RDMA_CORE_RESTRACK_H_ */
...@@ -2533,6 +2533,8 @@ struct ib_device_ops { ...@@ -2533,6 +2533,8 @@ struct ib_device_ops {
DECLARE_RDMA_OBJ_SIZE(ib_pd); DECLARE_RDMA_OBJ_SIZE(ib_pd);
}; };
struct rdma_restrack_root;
struct ib_device { struct ib_device {
/* Do not access @dma_device directly from ULP nor from HW drivers. */ /* Do not access @dma_device directly from ULP nor from HW drivers. */
struct device *dma_device; struct device *dma_device;
...@@ -2589,10 +2591,7 @@ struct ib_device { ...@@ -2589,10 +2591,7 @@ struct ib_device {
#endif #endif
u32 index; u32 index;
/* struct rdma_restrack_root *res;
* Implementation details of the RDMA core, don't use in drivers
*/
struct rdma_restrack_root res;
const struct uapi_definition *driver_def; const struct uapi_definition *driver_def;
enum rdma_driver_id driver_id; enum rdma_driver_id driver_id;
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#define _RDMA_RESTRACK_H_ #define _RDMA_RESTRACK_H_
#include <linux/typecheck.h> #include <linux/typecheck.h>
#include <linux/rwsem.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/completion.h> #include <linux/completion.h>
...@@ -50,31 +49,6 @@ enum rdma_restrack_type { ...@@ -50,31 +49,6 @@ enum rdma_restrack_type {
}; };
struct ib_device; struct ib_device;
struct rdma_restrack_entry;
/**
* struct rdma_restrack_root - main resource tracking management
* entity, per-device
*/
struct rdma_restrack_root {
/*
* @rwsem: Read/write lock to protect erase of entry.
* Lists and insertions are protected by XArray internal lock.
*/
struct rw_semaphore rwsem;
/**
* @xa: Array of XArray structures to hold restrack entries.
* We want to use array of XArrays because insertion is type
* dependent. For types with xisiting unique ID (like QPN),
* we will insert to that unique index. For other types,
* we insert based on pointers and auto-allocate unique index.
*/
struct xarray xa[RDMA_RESTRACK_MAX];
/**
* @next_id: Next ID to support cyclic allocation
*/
u32 next_id[RDMA_RESTRACK_MAX];
};
/** /**
* struct rdma_restrack_entry - metadata per-entry * struct rdma_restrack_entry - metadata per-entry
...@@ -125,8 +99,6 @@ struct rdma_restrack_entry { ...@@ -125,8 +99,6 @@ struct rdma_restrack_entry {
u32 id; u32 id;
}; };
void rdma_restrack_init(struct ib_device *dev);
void rdma_restrack_clean(struct ib_device *dev);
int rdma_restrack_count(struct ib_device *dev, int rdma_restrack_count(struct ib_device *dev,
enum rdma_restrack_type type, enum rdma_restrack_type type,
struct pid_namespace *ns); struct pid_namespace *ns);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment