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 <israelr@mellanox.com>

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6951 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Israel Rukshin
2016-08-17 07:28:20 +00:00
parent 87902c8722
commit 45256dd888
2 changed files with 9 additions and 17 deletions

View File

@@ -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;

View File

@@ -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);