aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-08-24 12:42:57 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-24 12:42:57 -0400
commitd3c10db138a9b5d88c475f9e4532003ad35f57c2 (patch)
tree3df00f6697e4a1a1a3027bab8d918381ebd13829 /net
parentd14c800ba64d05f1eceb69924ba3f1aeba829abb (diff)
parentdf5d8bf70f64a2ee34234553eb215418dbc4c8f3 (diff)
Merge tag 'rxrpc-rewrite-20160824-1' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
David Howells says: ==================== rxrpc: More fixes Here are a couple of fix patches: (1) Fix the conn-based retransmission patch posted yesterday. This breaks if it actually has to retransmit. However, it seems the likelihood of this happening is really low, despite the server I'm testing against being located >3000 miles away, and sometime of the time it's handled in the call background processor before we manage to disconnect the call - hence why I didn't spot it. (2) /proc/net/rxrpc_calls can cause a crash it accessed whilst a call is being torn down. The window of opportunity is pretty small, however, as calls don't stay in this state for long. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/rxrpc/ar-internal.h4
-rw-r--r--net/rxrpc/call_object.c3
-rw-r--r--net/rxrpc/conn_client.c1
-rw-r--r--net/rxrpc/conn_event.c1
-rw-r--r--net/rxrpc/input.c2
-rw-r--r--net/rxrpc/proc.c27
6 files changed, 28 insertions, 10 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 7296039c537a..5292bf0bce52 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -407,6 +407,7 @@ enum rxrpc_call_state {
407struct rxrpc_call { 407struct rxrpc_call {
408 struct rcu_head rcu; 408 struct rcu_head rcu;
409 struct rxrpc_connection *conn; /* connection carrying call */ 409 struct rxrpc_connection *conn; /* connection carrying call */
410 struct rxrpc_peer *peer; /* Peer record for remote address */
410 struct rxrpc_sock *socket; /* socket responsible */ 411 struct rxrpc_sock *socket; /* socket responsible */
411 struct timer_list lifetimer; /* lifetime remaining on call */ 412 struct timer_list lifetimer; /* lifetime remaining on call */
412 struct timer_list deadspan; /* reap timer for re-ACK'ing, etc */ 413 struct timer_list deadspan; /* reap timer for re-ACK'ing, etc */
@@ -717,9 +718,10 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *,
717 struct sockaddr_rxrpc *, gfp_t); 718 struct sockaddr_rxrpc *, gfp_t);
718struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t); 719struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t);
719 720
720static inline void rxrpc_get_peer(struct rxrpc_peer *peer) 721static inline struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
721{ 722{
722 atomic_inc(&peer->usage); 723 atomic_inc(&peer->usage);
724 return peer;
723} 725}
724 726
725static inline 727static inline
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 4af01805bfc7..f23432591a0f 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -315,6 +315,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
315 chan = sp->hdr.cid & RXRPC_CHANNELMASK; 315 chan = sp->hdr.cid & RXRPC_CHANNELMASK;
316 candidate->socket = rx; 316 candidate->socket = rx;
317 candidate->conn = conn; 317 candidate->conn = conn;
318 candidate->peer = conn->params.peer;
318 candidate->cid = sp->hdr.cid; 319 candidate->cid = sp->hdr.cid;
319 candidate->call_id = sp->hdr.callNumber; 320 candidate->call_id = sp->hdr.callNumber;
320 candidate->rx_data_post = 0; 321 candidate->rx_data_post = 0;
@@ -384,6 +385,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
384 rcu_assign_pointer(conn->channels[chan].call, call); 385 rcu_assign_pointer(conn->channels[chan].call, call);
385 sock_hold(&rx->sk); 386 sock_hold(&rx->sk);
386 rxrpc_get_connection(conn); 387 rxrpc_get_connection(conn);
388 rxrpc_get_peer(call->peer);
387 spin_unlock(&conn->channel_lock); 389 spin_unlock(&conn->channel_lock);
388 390
389 spin_lock(&conn->params.peer->lock); 391 spin_lock(&conn->params.peer->lock);
@@ -610,6 +612,7 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
610 struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu); 612 struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu);
611 613
612 rxrpc_purge_queue(&call->rx_queue); 614 rxrpc_purge_queue(&call->rx_queue);
615 rxrpc_put_peer(call->peer);
613 kmem_cache_free(rxrpc_call_jar, call); 616 kmem_cache_free(rxrpc_call_jar, call);
614} 617}
615 618
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index fc32cc67c2de..2d43c99e5360 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -280,6 +280,7 @@ attached:
280found_channel: 280found_channel:
281 _debug("found chan"); 281 _debug("found chan");
282 call->conn = conn; 282 call->conn = conn;
283 call->peer = rxrpc_get_peer(conn->params.peer);
283 call->cid = conn->proto.cid | chan; 284 call->cid = conn->proto.cid | chan;
284 call->call_id = ++conn->channels[chan].call_counter; 285 call->call_id = ++conn->channels[chan].call_counter;
285 conn->channels[chan].call_id = call->call_id; 286 conn->channels[chan].call_id = call->call_id;
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index c1c6b7f305d1..6296374df840 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -42,6 +42,7 @@ static void rxrpc_conn_retransmit(struct rxrpc_connection *conn,
42 } abort; 42 } abort;
43 struct { 43 struct {
44 struct rxrpc_ackpacket ack; 44 struct rxrpc_ackpacket ack;
45 u8 padding[3];
45 struct rxrpc_ackinfo info; 46 struct rxrpc_ackinfo info;
46 }; 47 };
47 }; 48 };
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 66cdeb56f44f..5e683dd21ab9 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -732,7 +732,7 @@ void rxrpc_data_ready(struct sock *sk)
732 /* For the previous service call, if completed 732 /* For the previous service call, if completed
733 * successfully, we discard all further packets. 733 * successfully, we discard all further packets.
734 */ 734 */
735 if (rxrpc_conn_is_service(call->conn) && 735 if (rxrpc_conn_is_service(conn) &&
736 (chan->last_type == RXRPC_PACKET_TYPE_ACK || 736 (chan->last_type == RXRPC_PACKET_TYPE_ACK ||
737 sp->hdr.type == RXRPC_PACKET_TYPE_ABORT)) 737 sp->hdr.type == RXRPC_PACKET_TYPE_ABORT))
738 goto discard_unlock; 738 goto discard_unlock;
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 31b7f36a39cb..53872631a66d 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -46,7 +46,9 @@ static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
46 46
47static int rxrpc_call_seq_show(struct seq_file *seq, void *v) 47static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
48{ 48{
49 struct rxrpc_connection *conn; 49 struct rxrpc_local *local;
50 struct rxrpc_sock *rx;
51 struct rxrpc_peer *peer;
50 struct rxrpc_call *call; 52 struct rxrpc_call *call;
51 char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1]; 53 char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
52 54
@@ -60,15 +62,24 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
60 62
61 call = list_entry(v, struct rxrpc_call, link); 63 call = list_entry(v, struct rxrpc_call, link);
62 64
63 sprintf(lbuff, "%pI4:%u", 65 rx = READ_ONCE(call->socket);
64 &call->socket->local->srx.transport.sin.sin_addr, 66 if (rx) {
65 ntohs(call->socket->local->srx.transport.sin.sin_port)); 67 local = READ_ONCE(rx->local);
68 if (local)
69 sprintf(lbuff, "%pI4:%u",
70 &local->srx.transport.sin.sin_addr,
71 ntohs(local->srx.transport.sin.sin_port));
72 else
73 strcpy(lbuff, "no_local");
74 } else {
75 strcpy(lbuff, "no_socket");
76 }
66 77
67 conn = call->conn; 78 peer = call->peer;
68 if (conn) 79 if (peer)
69 sprintf(rbuff, "%pI4:%u", 80 sprintf(rbuff, "%pI4:%u",
70 &conn->params.peer->srx.transport.sin.sin_addr, 81 &peer->srx.transport.sin.sin_addr,
71 ntohs(conn->params.peer->srx.transport.sin.sin_port)); 82 ntohs(peer->srx.transport.sin.sin_port));
72 else 83 else
73 strcpy(rbuff, "no_connection"); 84 strcpy(rbuff, "no_connection");
74 85