Re: [RFC rdma-next 09/11] RDMA/restrack: Translate from ID to restrack object

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux