On Thu, Jan 03, 2019 at 10:27:52PM +0000, Jason Gunthorpe wrote: > On Thu, Jan 03, 2019 at 10:05:57AM +0200, Leon Romanovsky wrote: > > From: Leon Romanovsky <leonro@xxxxxxxxxxxx> > > > > Add new general helper to get restrack entry given by ID and > > their respective type. > > > > Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> > > drivers/infiniband/core/restrack.c | 13 +++++++++++++ > > include/rdma/restrack.h | 11 +++++++++++ > > 2 files changed, 24 insertions(+) > > > > diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c > > index 473422da0856..d65758a3a7b6 100644 > > +++ b/drivers/infiniband/core/restrack.c > > @@ -249,6 +249,19 @@ int __must_check rdma_restrack_get(struct rdma_restrack_entry *res) > > } > > EXPORT_SYMBOL(rdma_restrack_get); > > > > +struct rdma_restrack_entry * > > +rdma_restrack_get_byid(struct rdma_restrack_root *rt, > > + enum rdma_restrack_type type, u32 id) > > +{ > > + struct rdma_restrack_entry *res; > > + > > + res = xa_load(&rt->xa[type], id); > > the previous patch did: > > + id = res_to_id(res); > + ret = xa_insert(&dev->res.xa[res->type], id, res, GFP_KERNEL); > > Where res_to_id() returns a pointer casted to an unsigned long - so > the use of 'u32 id' is wrong here. I "removed" from this RFC patches which added software ID generation for drivers without relevant HW/FW and their conversion to use that ID. At the time of final submission res_to_id() won't return pointers. > > Also, it seems to expose kernel pointers to user space, which is a > security no-no. We are not, see introduction of ".id" field in nldev.c. It is added once all drivers are capable to return some unique ID and not pointer. > > I think this needs actual device-unique IDs for all objects, no use of > pointers. It exists, I didn't post it as part of RFC. > > Probably better to use the xarray in the IDR mode and have it generate > unique ID's for all the cases where a HW ID is not already present. I'm attaching this patch for your convenience. From c3cca57ebf246c268b60be9ad364a0275cedb1de Mon Sep 17 00:00:00 2001 From: Leon Romanovsky <leonro@xxxxxxxxxxxx> Date: Thu, 3 Jan 2019 18:19:43 +0200 Subject: [PATCH 24/25] RDMA/restrack: Implement software ID interface Provide basic functionality to safely get and put software IDs for devices which don't do it in HW. Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> --- drivers/infiniband/core/restrack.c | 94 +++++++++++++++++++++++++++++- include/rdma/restrack.h | 39 +++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c index bd3c37ca7829..f687dffb042a 100644 --- a/drivers/infiniband/core/restrack.c +++ b/drivers/infiniband/core/restrack.c @@ -12,6 +12,24 @@ #include "cma_priv.h" +struct sw_id { + /** + * @id: Bitmap to keep SW genrated IDs for devices which + * don't have relevant hW/FW to generate them on their own. + * It is used for types without other unique identification + * available, for example QPs have unique QPN built-in. + */ + unsigned long *bitmap; + /** + * @max: Maximal value of entry in ids bitmap + */ + u32 max; + /** + * @bitmap_lock: Protect concurent ID updates + */ + spinlock_t bitmap_lock; +}; + static int fill_res_noop(struct sk_buff *msg, struct rdma_restrack_entry *entry) { @@ -26,7 +44,7 @@ void rdma_restrack_init(struct rdma_restrack_root *res) xa_init(&res->xa[i]); res->fill_res_entry = fill_res_noop; - + res->priv = NULL; } static const char *type2str(enum rdma_restrack_type type) @@ -85,6 +103,8 @@ void rdma_restrack_clean(struct rdma_restrack_root *res) } if (!found) pr_err("restrack: %s", CUT_HERE); + + kfree(res->priv); } int rdma_restrack_count(struct rdma_restrack_root *res, @@ -300,3 +320,75 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) } } EXPORT_SYMBOL(rdma_restrack_del); + +int rdma_restrack_alloc_ids(struct rdma_restrack_root *rt, + enum rdma_restrack_type type, u32 max) +{ + struct sw_id *id; + + if (!rt->priv) + /* Possible optimization: allocate only specific type */ + rt->priv = kcalloc(RDMA_RESTRACK_MAX, sizeof(struct sw_id), + GFP_KERNEL); + + if (!rt->priv) + return -ENOMEM; + + id = rt->priv + type * sizeof(struct sw_id); + id->max = max; + spin_lock_init(&id->bitmap_lock); + id->bitmap = kcalloc(BITS_TO_LONGS(max), sizeof(long), GFP_KERNEL); + if (!id->bitmap) { + kfree(rt->priv); + return -ENOMEM; + } + + return 0; +} +EXPORT_SYMBOL(rdma_restrack_alloc_ids); + +void rdma_restrack_free_ids(struct rdma_restrack_root *rt, + enum rdma_restrack_type type) +{ + struct sw_id *id; + + id = rt->priv + type * sizeof(struct sw_id); + id->max = 0; + kfree(id->bitmap); +} +EXPORT_SYMBOL(rdma_restrack_free_ids); + +int rdma_restrack_get_id(struct rdma_restrack_root *rt, + enum rdma_restrack_type type, u32 *val) +{ + struct sw_id *id; + int ret = 0; + + id = rt->priv + type * sizeof(struct sw_id); + spin_lock(&id->bitmap_lock); + *val = find_first_zero_bit(id->bitmap, id->max); + if (*val == id->max) { + *val = 0; + ret = -EINVAL; + goto out; + } + + __set_bit(*val, id->bitmap); + +out: spin_unlock(&id->bitmap_lock); + return ret; + +} +EXPORT_SYMBOL(rdma_restrack_get_id); + +void rdma_restrack_put_id(struct rdma_restrack_root *rt, + enum rdma_restrack_type type, u32 val) +{ + struct sw_id *id; + + id = rt->priv + type * sizeof(struct sw_id); + spin_lock(&id->bitmap_lock); + __clear_bit(val, id->bitmap); + spin_unlock(&id->bitmap_lock); +} +EXPORT_SYMBOL(rdma_restrack_put_id); diff --git a/include/rdma/restrack.h b/include/rdma/restrack.h index 33108b6a509f..cf74b1176e6f 100644 --- a/include/rdma/restrack.h +++ b/include/rdma/restrack.h @@ -70,6 +70,12 @@ struct rdma_restrack_root { */ int (*fill_res_entry)(struct sk_buff *msg, struct rdma_restrack_entry *entry); + + /** + * @priv: Private data used internally by restrack and + * not supposed to be seen and used by users. + */ + void *priv; }; /** @@ -199,4 +205,37 @@ int rdma_nl_put_driver_u64_hex(struct sk_buff *msg, const char *name, struct rdma_restrack_entry * rdma_restrack_get_byid(struct rdma_restrack_root *rt, enum rdma_restrack_type type, u32 id); +/** + * rdma_restrack_alloc_ids() - allocate software IDs bitmap + * @rt: root table to work + * @type: resource track type + * @max: maximal possible value + * + * Return: 0 on success + */ +int rdma_restrack_alloc_ids(struct rdma_restrack_root *rt, + enum rdma_restrack_type type, u32 max); +/** + * rdma_restrack_free_ids() - free software IDs bitmap + * @rt: root table to work + * @type: resource track type + */ +void rdma_restrack_free_ids(struct rdma_restrack_root *rt, + enum rdma_restrack_type type); +/** + * rdma_restrack_get_id() - get software ID + * @rt: root table to work + * @type: resource track type + * @val: returned value + */ +int rdma_restrack_get_id(struct rdma_restrack_root *rt, + enum rdma_restrack_type type, u32 *val); +/** + * rdma_restrack_put_id() - return software ID + * @rt: root table to work + * @type: resource track type + * @val: Id to return + */ +void rdma_restrack_put_id(struct rdma_restrack_root *rt, + enum rdma_restrack_type type, u32 val); #endif /* _RDMA_RESTRACK_H_ */ -- 2.19.1 > > Jason
Attachment:
signature.asc
Description: PGP signature