Commit 801df68d authored by Varun Prakash's avatar Varun Prakash Committed by Martin K. Petersen

scsi: target: iscsi: cxgbit: fix csk leak

csk leak can happen if a new TCP connection gets established after
cxgbit_accept_np() returns, to fix this leak free remaining csk in
cxgbit_free_np().
Signed-off-by: default avatarVarun Prakash <varun@chelsio.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent b90cd6f2
...@@ -598,9 +598,12 @@ static void cxgbit_free_cdev_np(struct cxgbit_np *cnp) ...@@ -598,9 +598,12 @@ static void cxgbit_free_cdev_np(struct cxgbit_np *cnp)
mutex_unlock(&cdev_list_lock); mutex_unlock(&cdev_list_lock);
} }
static void __cxgbit_free_conn(struct cxgbit_sock *csk);
void cxgbit_free_np(struct iscsi_np *np) void cxgbit_free_np(struct iscsi_np *np)
{ {
struct cxgbit_np *cnp = np->np_context; struct cxgbit_np *cnp = np->np_context;
struct cxgbit_sock *csk, *tmp;
cnp->com.state = CSK_STATE_DEAD; cnp->com.state = CSK_STATE_DEAD;
if (cnp->com.cdev) if (cnp->com.cdev)
...@@ -608,6 +611,13 @@ void cxgbit_free_np(struct iscsi_np *np) ...@@ -608,6 +611,13 @@ void cxgbit_free_np(struct iscsi_np *np)
else else
cxgbit_free_all_np(cnp); cxgbit_free_all_np(cnp);
spin_lock_bh(&cnp->np_accept_lock);
list_for_each_entry_safe(csk, tmp, &cnp->np_accept_list, accept_node) {
list_del_init(&csk->accept_node);
__cxgbit_free_conn(csk);
}
spin_unlock_bh(&cnp->np_accept_lock);
np->np_context = NULL; np->np_context = NULL;
cxgbit_put_cnp(cnp); cxgbit_put_cnp(cnp);
} }
...@@ -705,9 +715,9 @@ void cxgbit_abort_conn(struct cxgbit_sock *csk) ...@@ -705,9 +715,9 @@ void cxgbit_abort_conn(struct cxgbit_sock *csk)
csk->tid, 600, __func__); csk->tid, 600, __func__);
} }
void cxgbit_free_conn(struct iscsi_conn *conn) static void __cxgbit_free_conn(struct cxgbit_sock *csk)
{ {
struct cxgbit_sock *csk = conn->context; struct iscsi_conn *conn = csk->conn;
bool release = false; bool release = false;
pr_debug("%s: state %d\n", pr_debug("%s: state %d\n",
...@@ -716,7 +726,7 @@ void cxgbit_free_conn(struct iscsi_conn *conn) ...@@ -716,7 +726,7 @@ void cxgbit_free_conn(struct iscsi_conn *conn)
spin_lock_bh(&csk->lock); spin_lock_bh(&csk->lock);
switch (csk->com.state) { switch (csk->com.state) {
case CSK_STATE_ESTABLISHED: case CSK_STATE_ESTABLISHED:
if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) { if (conn && (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT)) {
csk->com.state = CSK_STATE_CLOSING; csk->com.state = CSK_STATE_CLOSING;
cxgbit_send_halfclose(csk); cxgbit_send_halfclose(csk);
} else { } else {
...@@ -741,6 +751,11 @@ void cxgbit_free_conn(struct iscsi_conn *conn) ...@@ -741,6 +751,11 @@ void cxgbit_free_conn(struct iscsi_conn *conn)
cxgbit_put_csk(csk); cxgbit_put_csk(csk);
} }
void cxgbit_free_conn(struct iscsi_conn *conn)
{
__cxgbit_free_conn(conn->context);
}
static void cxgbit_set_emss(struct cxgbit_sock *csk, u16 opt) static void cxgbit_set_emss(struct cxgbit_sock *csk, u16 opt)
{ {
csk->emss = csk->com.cdev->lldi.mtus[TCPOPT_MSS_G(opt)] - csk->emss = csk->com.cdev->lldi.mtus[TCPOPT_MSS_G(opt)] -
...@@ -803,6 +818,7 @@ void _cxgbit_free_csk(struct kref *kref) ...@@ -803,6 +818,7 @@ void _cxgbit_free_csk(struct kref *kref)
spin_unlock_bh(&cdev->cskq.lock); spin_unlock_bh(&cdev->cskq.lock);
cxgbit_free_skb(csk); cxgbit_free_skb(csk);
cxgbit_put_cnp(csk->cnp);
cxgbit_put_cdev(cdev); cxgbit_put_cdev(cdev);
kfree(csk); kfree(csk);
...@@ -1351,6 +1367,7 @@ cxgbit_pass_accept_req(struct cxgbit_device *cdev, struct sk_buff *skb) ...@@ -1351,6 +1367,7 @@ cxgbit_pass_accept_req(struct cxgbit_device *cdev, struct sk_buff *skb)
goto rel_skb; goto rel_skb;
} }
cxgbit_get_cnp(cnp);
cxgbit_get_cdev(cdev); cxgbit_get_cdev(cdev);
spin_lock(&cdev->cskq.lock); spin_lock(&cdev->cskq.lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment