RxRPC rewrite

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIVAwUAV72yZ/Sw1s6N8H32AQITcQ//Tj+QPw2wnc6p6CAXSQ4CJAgprZP25dEY
 11aaLsKBsBpJXyGjRWVxHJeoNnfVO05ATyZU1AjIlALDUY2Kq1IyNJWmmxZbx0M/
 oaRN4kB41jKyJRGWnPdvQb7KL0SvjlyiEWNV9ztEk4W5Ik7UInAYl2sdovwzvgL0
 Nw7KClg2lTLE8Nu4v0GYFxz5bCUw3M4a0+C5oXCSIpXwLOMQezAmXRhYNhlxHwmZ
 phuvJrP7xH0Z2G4MgVwvyOsQzzKptWoo3c5YxTWlhUl2qk1ZUKcu+eMv9ir/T3mD
 exiiMgDLd74Wb9J9U1AEmGp9NgfxM20MGR7O/ARZ8K8FUrxMWbEifjv/eqMl0YGr
 Wk/df+VwUsp3nfOMe7/UZaBCx5ZSV7x8WT6p6lRIQAIrJj1CFbo5pxHLgG/SPt5x
 EPniDw/oC+0G7sc3BjqTLZZP7qh27TuvuUVqAdgM7lJCpozk37Qnq4C0jwheJ7ct
 MvB1mGkfiHVnq3F0UL7emazmlYBULPTJvj7fN9iPAsvNYBbdENCbjfNP0T2YKNlW
 1B08pUtMfHiS3/+LkFQ9yl0lhWnkApm++pNcOM1nLANi49Th92ch8lpfD6poAUBl
 vRWHcMeeqevnydl57WQJ40gtmJr1/5pKgVQwRY/sSBQztr/uqtM811dkNwlF3szw
 es7wA7HkKlI=
 =mirU
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
David S. Miller 2016-08-24 09:42:57 -07:00
commit d3c10db138
6 changed files with 28 additions and 10 deletions

View File

@ -407,6 +407,7 @@ enum rxrpc_call_state {
struct rxrpc_call {
struct rcu_head rcu;
struct rxrpc_connection *conn; /* connection carrying call */
struct rxrpc_peer *peer; /* Peer record for remote address */
struct rxrpc_sock *socket; /* socket responsible */
struct timer_list lifetimer; /* lifetime remaining on call */
struct timer_list deadspan; /* reap timer for re-ACK'ing, etc */
@ -717,9 +718,10 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *,
struct sockaddr_rxrpc *, gfp_t);
struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t);
static inline void rxrpc_get_peer(struct rxrpc_peer *peer)
static inline struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
{
atomic_inc(&peer->usage);
return peer;
}
static inline

View File

@ -315,6 +315,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
chan = sp->hdr.cid & RXRPC_CHANNELMASK;
candidate->socket = rx;
candidate->conn = conn;
candidate->peer = conn->params.peer;
candidate->cid = sp->hdr.cid;
candidate->call_id = sp->hdr.callNumber;
candidate->rx_data_post = 0;
@ -384,6 +385,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
rcu_assign_pointer(conn->channels[chan].call, call);
sock_hold(&rx->sk);
rxrpc_get_connection(conn);
rxrpc_get_peer(call->peer);
spin_unlock(&conn->channel_lock);
spin_lock(&conn->params.peer->lock);
@ -610,6 +612,7 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu);
rxrpc_purge_queue(&call->rx_queue);
rxrpc_put_peer(call->peer);
kmem_cache_free(rxrpc_call_jar, call);
}

View File

@ -280,6 +280,7 @@ attached:
found_channel:
_debug("found chan");
call->conn = conn;
call->peer = rxrpc_get_peer(conn->params.peer);
call->cid = conn->proto.cid | chan;
call->call_id = ++conn->channels[chan].call_counter;
conn->channels[chan].call_id = call->call_id;

View File

@ -42,6 +42,7 @@ static void rxrpc_conn_retransmit(struct rxrpc_connection *conn,
} abort;
struct {
struct rxrpc_ackpacket ack;
u8 padding[3];
struct rxrpc_ackinfo info;
};
};

View File

@ -732,7 +732,7 @@ void rxrpc_data_ready(struct sock *sk)
/* For the previous service call, if completed
* successfully, we discard all further packets.
*/
if (rxrpc_conn_is_service(call->conn) &&
if (rxrpc_conn_is_service(conn) &&
(chan->last_type == RXRPC_PACKET_TYPE_ACK ||
sp->hdr.type == RXRPC_PACKET_TYPE_ABORT))
goto discard_unlock;

View File

@ -46,7 +46,9 @@ static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
{
struct rxrpc_connection *conn;
struct rxrpc_local *local;
struct rxrpc_sock *rx;
struct rxrpc_peer *peer;
struct rxrpc_call *call;
char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
@ -60,15 +62,24 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
call = list_entry(v, struct rxrpc_call, link);
sprintf(lbuff, "%pI4:%u",
&call->socket->local->srx.transport.sin.sin_addr,
ntohs(call->socket->local->srx.transport.sin.sin_port));
rx = READ_ONCE(call->socket);
if (rx) {
local = READ_ONCE(rx->local);
if (local)
sprintf(lbuff, "%pI4:%u",
&local->srx.transport.sin.sin_addr,
ntohs(local->srx.transport.sin.sin_port));
else
strcpy(lbuff, "no_local");
} else {
strcpy(lbuff, "no_socket");
}
conn = call->conn;
if (conn)
peer = call->peer;
if (peer)
sprintf(rbuff, "%pI4:%u",
&conn->params.peer->srx.transport.sin.sin_addr,
ntohs(conn->params.peer->srx.transport.sin.sin_port));
&peer->srx.transport.sin.sin_addr,
ntohs(peer->srx.transport.sin.sin_port));
else
strcpy(rbuff, "no_connection");