summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-10-03 12:52:19 -0700
committerDavid S. Miller <davem@davemloft.net>2014-10-03 12:52:19 -0700
commitfba7516303c1f6bb45fcc3df888978d0b34202c4 (patch)
tree5ce5ea7eed46aa59ff245a02ababb35a6b2b1d44
parentee042ec88022249b848306dd6e87ffd2fd88a839 (diff)
parent593cbb3ec6a3f2424966832727f394b1696d0d72 (diff)
downloadtalos-op-linux-fba7516303c1f6bb45fcc3df888978d0b34202c4.tar.gz
talos-op-linux-fba7516303c1f6bb45fcc3df888978d0b34202c4.zip
Merge branch 'rds-net'
Herton R. Krzesinski says: ==================== Small fixes/changes for RDS I got a report of one issue within RDS (after investigation it was a double free), and I'm sending the fix (patch 3/3) which reporter said it works (no more WARNING triggered on a specially instrumented kernel). The report/test was done on a very old kernel (RHEL 5, 2.6.18 based with backports), but the problem the patch handles still exists and should not change. Besides that, while reviewing some of the code but being unable to reproduce with rds_tcp, I noticed two small improvements/fixes which are in patches 1 and 2. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/rds/send.c11
-rw-r--r--net/rds/tcp_connect.c5
-rw-r--r--net/rds/threads.c3
3 files changed, 12 insertions, 7 deletions
diff --git a/net/rds/send.c b/net/rds/send.c
index 23718160d71e..0a64541020b0 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -593,8 +593,11 @@ static void rds_send_remove_from_sock(struct list_head *messages, int status)
sock_put(rds_rs_to_sk(rs));
}
rs = rm->m_rs;
- sock_hold(rds_rs_to_sk(rs));
+ if (rs)
+ sock_hold(rds_rs_to_sk(rs));
}
+ if (!rs)
+ goto unlock_and_drop;
spin_lock(&rs->rs_lock);
if (test_and_clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) {
@@ -638,9 +641,6 @@ unlock_and_drop:
* queue. This means that in the TCP case, the message may not have been
* assigned the m_ack_seq yet - but that's fine as long as tcp_is_acked
* checks the RDS_MSG_HAS_ACK_SEQ bit.
- *
- * XXX It's not clear to me how this is safely serialized with socket
- * destruction. Maybe it should bail if it sees SOCK_DEAD.
*/
void rds_send_drop_acked(struct rds_connection *conn, u64 ack,
is_acked_func is_acked)
@@ -711,6 +711,9 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest)
*/
if (!test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags)) {
spin_unlock_irqrestore(&conn->c_lock, flags);
+ spin_lock_irqsave(&rm->m_rs_lock, flags);
+ rm->m_rs = NULL;
+ spin_unlock_irqrestore(&rm->m_rs_lock, flags);
continue;
}
list_del_init(&rm->m_conn_item);
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c
index a65ee78db0c5..f9f564a6c960 100644
--- a/net/rds/tcp_connect.c
+++ b/net/rds/tcp_connect.c
@@ -106,11 +106,14 @@ int rds_tcp_conn_connect(struct rds_connection *conn)
rds_tcp_set_callbacks(sock, conn);
ret = sock->ops->connect(sock, (struct sockaddr *)&dest, sizeof(dest),
O_NONBLOCK);
- sock = NULL;
rdsdebug("connect to address %pI4 returned %d\n", &conn->c_faddr, ret);
if (ret == -EINPROGRESS)
ret = 0;
+ if (ret == 0)
+ sock = NULL;
+ else
+ rds_tcp_restore_callbacks(sock, conn->c_transport_data);
out:
if (sock)
diff --git a/net/rds/threads.c b/net/rds/threads.c
index 65eaefcab241..dc2402e871fd 100644
--- a/net/rds/threads.c
+++ b/net/rds/threads.c
@@ -78,8 +78,7 @@ void rds_connect_complete(struct rds_connection *conn)
"current state is %d\n",
__func__,
atomic_read(&conn->c_state));
- atomic_set(&conn->c_state, RDS_CONN_ERROR);
- queue_work(rds_wq, &conn->c_down_w);
+ rds_conn_drop(conn);
return;
}
OpenPOWER on IntegriCloud