From 45256dd8882182ee47dfcb67d012ed29f407e6ac Mon Sep 17 00:00:00 2001 From: Israel Rukshin Date: Wed, 17 Aug 2016 07:28:20 +0000 Subject: [PATCH] isert: fix isert connection kref leak To avoid rare cases when checking ISERT_CONNECTION_EST bit may lead to kref leak, we now take the third refcount earlier before calling to rdma_accept. Signed-off-by: Israel Rukshin git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6951 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/isert-scst/iser.h | 7 +++---- iscsi-scst/kernel/isert-scst/iser_rdma.c | 19 ++++++------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/iscsi-scst/kernel/isert-scst/iser.h b/iscsi-scst/kernel/isert-scst/iser.h index a72cedc4b..07f8b881a 100644 --- a/iscsi-scst/kernel/isert-scst/iser.h +++ b/iscsi-scst/kernel/isert-scst/iser.h @@ -159,10 +159,9 @@ struct isert_cq { #define ISERT_CONNECTION_ABORTED 0 #define ISERT_DRAIN_POSTED 1 #define ISERT_DISCON_CALLED 2 -#define ISERT_CONNECTION_EST 3 -#define ISERT_DRAINED_RQ 4 -#define ISERT_DRAINED_SQ 5 -#define ISERT_CONNECTION_CLOSE 6 +#define ISERT_DRAINED_RQ 3 +#define ISERT_DRAINED_SQ 4 +#define ISERT_CONNECTION_CLOSE 5 struct isert_connection { struct iscsi_conn iscsi ____cacheline_aligned; diff --git a/iscsi-scst/kernel/isert-scst/iser_rdma.c b/iscsi-scst/kernel/isert-scst/iser_rdma.c index b01748c31..70d3e2aef 100644 --- a/iscsi-scst/kernel/isert-scst/iser_rdma.c +++ b/iscsi-scst/kernel/isert-scst/iser_rdma.c @@ -639,10 +639,7 @@ static void isert_conn_closed_do_work(struct work_struct *work) if (!test_bit(ISERT_CONNECTION_ABORTED, &isert_conn->flags)) isert_connection_abort(&isert_conn->iscsi); - /* if connection established we have another refcount */ - if (test_bit(ISERT_CONNECTION_EST, &isert_conn->flags)) { - isert_conn_free(isert_conn); - } + isert_conn_free(isert_conn); } static void isert_sched_conn_closed(struct isert_connection *isert_conn) @@ -1406,11 +1403,12 @@ static void isert_immediate_conn_close(struct isert_connection* isert_conn) set_bit(ISERT_CONNECTION_CLOSE, &isert_conn->flags); isert_conn->state = ISER_CONN_CLOSING; /* - * reaching here must be with the isert_conn refcount of 2, - * one from the init and one from the connect request, + * reaching here must be with the isert_conn refcount of 3, + * one from the init and two from the connect request, * thus it is safe to deref directly before the sched_conn_free. */ isert_conn_free(isert_conn); + isert_conn_free(isert_conn); isert_sched_conn_free(isert_conn); } @@ -1481,6 +1479,7 @@ static int isert_cm_conn_req_handler(struct rdma_cm_id *cm_id, tgt_conn_param.private_data = &cm_hdr; cm_hdr.flags = ISER_ZBVA_NOT_SUPPORTED | ISER_SEND_W_INV_NOT_SUPPORTED; + kref_get(&isert_conn->kref); kref_get(&isert_conn->kref); err = rdma_accept(cm_id, &tgt_conn_param); @@ -1527,6 +1526,7 @@ out: fail_accept: set_bit(ISERT_CONNECTION_ABORTED, &isert_conn->flags); isert_conn_free(isert_conn); + isert_conn_free(isert_conn); isert_sched_conn_free(isert_conn); err = 0; goto out; @@ -1564,21 +1564,14 @@ static int isert_cm_connect_handler(struct rdma_cm_id *cm_id, if (unlikely(ret)) goto out; - /* check if already started teardown */ - if (!unlikely(kref_get_unless_zero(&isert_conn->kref))) - goto out; - /* notify upper layer */ ret = isert_conn_established(&isert_conn->iscsi, (struct sockaddr *)&isert_conn->peer_addr, isert_conn->peer_addrsz); if (unlikely(ret)) { - isert_conn_free(isert_conn); goto out; } - set_bit(ISERT_CONNECTION_EST, &isert_conn->flags); - if (push_saved_pdu) { PRINT_INFO("iser push saved rx pdu"); isert_recv_completion_handler(isert_conn->saved_wr);