diff mbox

[RFC,ABI,V2,6/8] RDMA/core: Add initialize and cleanup of common types

Message ID 1468941812-32286-7-git-send-email-matanb@mellanox.com (mailing list archive)
State RFC
Headers show

Commit Message

Matan Barak July 19, 2016, 3:23 p.m. UTC
The new ABI infrastructure introduced types per driver. Since current
drivers use common types, we mimics the current release ucontext
process using the new process.

Signed-off-by: Matan Barak <matanb@mellanox.com>
---
 drivers/infiniband/core/uverbs.h           |   9 +-
 drivers/infiniband/core/uverbs_ioctl_cmd.c | 130 +++++++++++++++++++++++++++++
 drivers/infiniband/core/uverbs_main.c      | 101 +---------------------
 include/rdma/uverbs_ioctl_cmd.h            |  15 ++++
 4 files changed, 156 insertions(+), 99 deletions(-)

Comments

Jason Gunthorpe July 20, 2016, 5:40 p.m. UTC | #1
On Tue, Jul 19, 2016 at 06:23:30PM +0300, Matan Barak wrote:
> @@ -210,103 +211,9 @@ static void ib_uverbs_detach_umcast(struct ib_qp *qp,
>  static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
>  				      struct ib_ucontext *context)
>  {
> +	ib_uverbs_uobject_type_initialize_ucontext(context, &file->device->ib_dev->type_list);

There is a certain dissonance to having an initialize function called
inside a cleanup function - is that right (it doesn't look that
right)? If it is right, find a better name...

Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Matan Barak July 21, 2016, 11:40 a.m. UTC | #2
On 20/07/2016 20:40, Jason Gunthorpe wrote:
> On Tue, Jul 19, 2016 at 06:23:30PM +0300, Matan Barak wrote:
>> @@ -210,103 +211,9 @@ static void ib_uverbs_detach_umcast(struct ib_qp *qp,
>>  static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
>>  				      struct ib_ucontext *context)
>>  {
>> +	ib_uverbs_uobject_type_initialize_ucontext(context, &file->device->ib_dev->type_list);
>
> There is a certain dissonance to having an initialize function called
> inside a cleanup function - is that right (it doesn't look that
> right)? If it is right, find a better name...
>

That's a bug, thanks.

> Jason
>

Matan
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 86be861..b65a865 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -174,8 +174,6 @@  struct ib_ucq_object {
 	u32			async_events_reported;
 };
 
-void idr_remove_uobj(struct ib_uobject *uobj);
-
 struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
 					struct ib_device *ib_dev,
 					int is_async);
@@ -197,6 +195,13 @@  void ib_uverbs_event_handler(struct ib_event_handler *handler,
 void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev, struct ib_xrcd *xrcd);
 
 int uverbs_dealloc_mw(struct ib_mw *mw);
+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
+			   struct ib_uverbs_event_file *ev_file,
+			   struct ib_ucq_object *uobj);
+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
+			      struct ib_uevent_object *uobj);
+void ib_uverbs_detach_umcast(struct ib_qp *qp,
+			     struct ib_uqp_object *uobj);
 
 struct ib_uverbs_flow_spec {
 	union {
diff --git a/drivers/infiniband/core/uverbs_ioctl_cmd.c b/drivers/infiniband/core/uverbs_ioctl_cmd.c
index 4c2d30e4..ea50c08 100644
--- a/drivers/infiniband/core/uverbs_ioctl_cmd.c
+++ b/drivers/infiniband/core/uverbs_ioctl_cmd.c
@@ -31,8 +31,11 @@ 
  */
 
 #include <rdma/uverbs_ioctl_cmd.h>
+#include <rdma/ib_user_verbs.h>
 #include <rdma/ib_verbs.h>
 #include <linux/bug.h>
+#include <linux/file.h>
+#include "rdma_core.h"
 #include "uverbs.h"
 
 #define IB_UVERBS_VENDOR_FLAG	0x8000
@@ -76,3 +79,130 @@  int uverbs_action_std_ctx_handle(struct ib_device *ib_dev,
 }
 EXPORT_SYMBOL(uverbs_action_std_ctx_handle);
 
+static void free_ah(struct uverbs_uobject_type *uobject_type,
+		    struct ib_uobject *uobject,
+		    struct ib_ucontext *ucontext)
+{
+	ib_destroy_ah((struct ib_ah *)uobject->object);
+}
+
+static void free_flow(struct uverbs_uobject_type *uobject_type,
+		      struct ib_uobject *uobject,
+		      struct ib_ucontext *ucontext)
+{
+	ib_destroy_flow((struct ib_flow *)uobject->object);
+}
+
+static void free_mw(struct uverbs_uobject_type *uobject_type,
+		    struct ib_uobject *uobject,
+		    struct ib_ucontext *ucontext)
+{
+	uverbs_dealloc_mw((struct ib_mw *)uobject->object);
+}
+
+static void free_qp(struct uverbs_uobject_type *uobject_type,
+		    struct ib_uobject *uobject,
+		    struct ib_ucontext *ucontext)
+{
+	struct ib_qp *qp = uobject->object;
+	struct ib_uqp_object *uqp =
+		container_of(uobject, struct ib_uqp_object, uevent.uobject);
+
+	if (qp != qp->real_qp) {
+		ib_close_qp(qp);
+	} else {
+		ib_uverbs_detach_umcast(qp, uqp);
+		ib_destroy_qp(qp);
+	}
+	ib_uverbs_release_uevent(ucontext->ufile, &uqp->uevent);
+}
+
+static void free_srq(struct uverbs_uobject_type *uobject_type,
+		     struct ib_uobject *uobject,
+		     struct ib_ucontext *ucontext)
+{
+	struct ib_srq *srq = uobject->object;
+	struct ib_uevent_object *uevent =
+		container_of(uobject, struct ib_uevent_object, uobject);
+
+	ib_destroy_srq(srq);
+	ib_uverbs_release_uevent(ucontext->ufile, uevent);
+}
+
+static void free_cq(struct uverbs_uobject_type *uobject_type,
+		    struct ib_uobject *uobject,
+		    struct ib_ucontext *ucontext)
+{
+	struct ib_cq *cq = uobject->object;
+	struct ib_uverbs_event_file *ev_file = cq->cq_context;
+	struct ib_ucq_object *ucq =
+		container_of(uobject, struct ib_ucq_object, uobject);
+
+	ib_destroy_cq(cq);
+	ib_uverbs_release_ucq(ucontext->ufile, ev_file, ucq);
+}
+
+static void free_mr(struct uverbs_uobject_type *uobject_type,
+		    struct ib_uobject *uobject,
+		    struct ib_ucontext *ucontext)
+{
+	ib_dereg_mr((struct ib_mr *)uobject);
+}
+
+static void free_xrcd(struct uverbs_uobject_type *uobject_type,
+		      struct ib_uobject *uobject,
+		      struct ib_ucontext *ucontext)
+{
+	struct ib_xrcd *xrcd = uobject->object;
+
+	mutex_lock(&ucontext->ufile->device->xrcd_tree_mutex);
+	ib_uverbs_dealloc_xrcd(ucontext->ufile->device, xrcd);
+	mutex_unlock(&ucontext->ufile->device->xrcd_tree_mutex);
+}
+
+static void free_pd(struct uverbs_uobject_type *uobject_type,
+		    struct ib_uobject *uobject,
+		    struct ib_ucontext *ucontext)
+{
+	ib_dealloc_pd((struct ib_pd *)uobject);
+}
+
+int rdma_initialize_common_types(struct ib_device *ib_dev, unsigned int types)
+{
+	static const struct
+	{
+		enum uverbs_common_types type;
+		void (*free)(struct uverbs_uobject_type *uobject_type,
+			     struct ib_uobject *uobject,
+			     struct ib_ucontext *ucontext);
+
+	} common_types[] = { /* by release order */
+		{.type = UVERBS_TYPE_AH,	.free = free_ah},
+		{.type = UVERBS_TYPE_MW,	.free = free_mw},
+		{.type = UVERBS_TYPE_FLOW,	.free = free_flow},
+		{.type = UVERBS_TYPE_QP,	.free = free_qp},
+		{.type = UVERBS_TYPE_SRQ,	.free = free_srq},
+		{.type = UVERBS_TYPE_CQ,	.free = free_cq},
+		{.type = UVERBS_TYPE_MR,	.free = free_mr},
+		{.type = UVERBS_TYPE_XRCD,	.free = free_xrcd},
+		{.type = UVERBS_TYPE_PD,	.free = free_pd},
+	};
+	int ret = 0;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(common_types); i++) {
+		if (types & common_types[i].type) {
+			ret = ib_uverbs_uobject_type_add(&ib_dev->type_list,
+							 common_types[i].free,
+							 common_types[i].type);
+			if (ret)
+				goto free;
+		}
+	}
+
+free:
+	ib_uverbs_uobject_types_remove(ib_dev);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_initialize_common_types);
+
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index fa51568..9137698 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -52,6 +52,7 @@ 
 #include <rdma/rdma_ioctl.h>
 
 #include "uverbs.h"
+#include "rdma_core.h"
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand userspace verbs access");
@@ -195,8 +196,8 @@  void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
 	spin_unlock_irq(&file->async_file->lock);
 }
 
-static void ib_uverbs_detach_umcast(struct ib_qp *qp,
-				    struct ib_uqp_object *uobj)
+void ib_uverbs_detach_umcast(struct ib_qp *qp,
+			     struct ib_uqp_object *uobj)
 {
 	struct ib_uverbs_mcast_entry *mcast, *tmp;
 
@@ -210,103 +211,9 @@  static void ib_uverbs_detach_umcast(struct ib_qp *qp,
 static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
 				      struct ib_ucontext *context)
 {
-	struct ib_uobject *uobj, *tmp;
-
 	down_write(&file->close_sem);
 	context->closing = 1;
-
-	list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
-		struct ib_ah *ah = uobj->object;
-
-		idr_remove_uobj(uobj);
-		ib_destroy_ah(ah);
-		kfree(uobj);
-	}
-
-	/* Remove MWs before QPs, in order to support type 2A MWs. */
-	list_for_each_entry_safe(uobj, tmp, &context->mw_list, list) {
-		struct ib_mw *mw = uobj->object;
-
-		idr_remove_uobj(uobj);
-		uverbs_dealloc_mw(mw);
-		kfree(uobj);
-	}
-
-	list_for_each_entry_safe(uobj, tmp, &context->rule_list, list) {
-		struct ib_flow *flow_id = uobj->object;
-
-		idr_remove_uobj(uobj);
-		ib_destroy_flow(flow_id);
-		kfree(uobj);
-	}
-
-	list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
-		struct ib_qp *qp = uobj->object;
-		struct ib_uqp_object *uqp =
-			container_of(uobj, struct ib_uqp_object, uevent.uobject);
-
-		idr_remove_uobj(uobj);
-		if (qp != qp->real_qp) {
-			ib_close_qp(qp);
-		} else {
-			ib_uverbs_detach_umcast(qp, uqp);
-			ib_destroy_qp(qp);
-		}
-		ib_uverbs_release_uevent(file, &uqp->uevent);
-		kfree(uqp);
-	}
-
-	list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
-		struct ib_srq *srq = uobj->object;
-		struct ib_uevent_object *uevent =
-			container_of(uobj, struct ib_uevent_object, uobject);
-
-		idr_remove_uobj(uobj);
-		ib_destroy_srq(srq);
-		ib_uverbs_release_uevent(file, uevent);
-		kfree(uevent);
-	}
-
-	list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
-		struct ib_cq *cq = uobj->object;
-		struct ib_uverbs_event_file *ev_file = cq->cq_context;
-		struct ib_ucq_object *ucq =
-			container_of(uobj, struct ib_ucq_object, uobject);
-
-		idr_remove_uobj(uobj);
-		ib_destroy_cq(cq);
-		ib_uverbs_release_ucq(file, ev_file, ucq);
-		kfree(ucq);
-	}
-
-	list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
-		struct ib_mr *mr = uobj->object;
-
-		idr_remove_uobj(uobj);
-		ib_dereg_mr(mr);
-		kfree(uobj);
-	}
-
-	mutex_lock(&file->device->xrcd_tree_mutex);
-	list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
-		struct ib_xrcd *xrcd = uobj->object;
-		struct ib_uxrcd_object *uxrcd =
-			container_of(uobj, struct ib_uxrcd_object, uobject);
-
-		idr_remove_uobj(uobj);
-		ib_uverbs_dealloc_xrcd(file->device, xrcd);
-		kfree(uxrcd);
-	}
-	mutex_unlock(&file->device->xrcd_tree_mutex);
-
-	list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
-		struct ib_pd *pd = uobj->object;
-
-		idr_remove_uobj(uobj);
-		ib_dealloc_pd(pd);
-		kfree(uobj);
-	}
-
+	ib_uverbs_uobject_type_initialize_ucontext(context, &file->device->ib_dev->type_list);
 	put_pid(context->tgid);
 	up_write(&file->close_sem);
 
diff --git a/include/rdma/uverbs_ioctl_cmd.h b/include/rdma/uverbs_ioctl_cmd.h
index 19806df..18e652d 100644
--- a/include/rdma/uverbs_ioctl_cmd.h
+++ b/include/rdma/uverbs_ioctl_cmd.h
@@ -64,5 +64,20 @@  struct uverbs_action_std_ctx_handler {
 	void *priv;
 };
 
+int rdma_initialize_common_types(struct ib_device *ib_dev, unsigned int types);
+
+enum uverbs_common_types {
+	UVERBS_TYPE_DEVICE, /* Don't use IDRs here */
+	UVERBS_TYPE_PD,
+	UVERBS_TYPE_CQ,
+	UVERBS_TYPE_QP,
+	UVERBS_TYPE_SRQ,
+	UVERBS_TYPE_AH,
+	UVERBS_TYPE_MR,
+	UVERBS_TYPE_MW,
+	UVERBS_TYPE_FLOW,
+	UVERBS_TYPE_XRCD,
+};
+
 #endif