mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 10:41:26 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user