|
@@ -449,24 +449,6 @@ static void ucma_cleanup_multicast(struct ucma_context *ctx)
|
|
|
mutex_unlock(&mut);
|
|
|
}
|
|
|
|
|
|
-static void ucma_cleanup_events(struct ucma_context *ctx)
|
|
|
-{
|
|
|
- struct ucma_event *uevent, *tmp;
|
|
|
-
|
|
|
- list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list) {
|
|
|
- if (uevent->ctx != ctx)
|
|
|
- continue;
|
|
|
-
|
|
|
- list_del(&uevent->list);
|
|
|
-
|
|
|
- /* clear incoming connections. */
|
|
|
- if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST)
|
|
|
- rdma_destroy_id(uevent->cm_id);
|
|
|
-
|
|
|
- kfree(uevent);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
static void ucma_cleanup_mc_events(struct ucma_multicast *mc)
|
|
|
{
|
|
|
struct ucma_event *uevent, *tmp;
|
|
@@ -480,9 +462,16 @@ static void ucma_cleanup_mc_events(struct ucma_multicast *mc)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * We cannot hold file->mut when calling rdma_destroy_id() or we can
|
|
|
+ * deadlock. We also acquire file->mut in ucma_event_handler(), and
|
|
|
+ * rdma_destroy_id() will wait until all callbacks have completed.
|
|
|
+ */
|
|
|
static int ucma_free_ctx(struct ucma_context *ctx)
|
|
|
{
|
|
|
int events_reported;
|
|
|
+ struct ucma_event *uevent, *tmp;
|
|
|
+ LIST_HEAD(list);
|
|
|
|
|
|
/* No new events will be generated after destroying the id. */
|
|
|
rdma_destroy_id(ctx->cm_id);
|
|
@@ -491,10 +480,20 @@ static int ucma_free_ctx(struct ucma_context *ctx)
|
|
|
|
|
|
/* Cleanup events not yet reported to the user. */
|
|
|
mutex_lock(&ctx->file->mut);
|
|
|
- ucma_cleanup_events(ctx);
|
|
|
+ list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list) {
|
|
|
+ if (uevent->ctx == ctx)
|
|
|
+ list_move_tail(&uevent->list, &list);
|
|
|
+ }
|
|
|
list_del(&ctx->list);
|
|
|
mutex_unlock(&ctx->file->mut);
|
|
|
|
|
|
+ list_for_each_entry_safe(uevent, tmp, &list, list) {
|
|
|
+ list_del(&uevent->list);
|
|
|
+ if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST)
|
|
|
+ rdma_destroy_id(uevent->cm_id);
|
|
|
+ kfree(uevent);
|
|
|
+ }
|
|
|
+
|
|
|
events_reported = ctx->events_reported;
|
|
|
kfree(ctx);
|
|
|
return events_reported;
|