|
@@ -249,11 +249,11 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
|
|
|
*/
|
|
|
static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
|
|
|
struct rxrpc_local *local,
|
|
|
+ struct rxrpc_peer *peer,
|
|
|
struct rxrpc_connection *conn,
|
|
|
struct sk_buff *skb)
|
|
|
{
|
|
|
struct rxrpc_backlog *b = rx->backlog;
|
|
|
- struct rxrpc_peer *peer, *xpeer;
|
|
|
struct rxrpc_call *call;
|
|
|
unsigned short call_head, conn_head, peer_head;
|
|
|
unsigned short call_tail, conn_tail, peer_tail;
|
|
@@ -276,21 +276,18 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
|
|
|
return NULL;
|
|
|
|
|
|
if (!conn) {
|
|
|
- /* No connection. We're going to need a peer to start off
|
|
|
- * with. If one doesn't yet exist, use a spare from the
|
|
|
- * preallocation set. We dump the address into the spare in
|
|
|
- * anticipation - and to save on stack space.
|
|
|
- */
|
|
|
- xpeer = b->peer_backlog[peer_tail];
|
|
|
- if (rxrpc_extract_addr_from_skb(local, &xpeer->srx, skb) < 0)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- peer = rxrpc_lookup_incoming_peer(local, xpeer);
|
|
|
- if (peer == xpeer) {
|
|
|
+ if (peer && !rxrpc_get_peer_maybe(peer))
|
|
|
+ peer = NULL;
|
|
|
+ if (!peer) {
|
|
|
+ peer = b->peer_backlog[peer_tail];
|
|
|
+ if (rxrpc_extract_addr_from_skb(local, &peer->srx, skb) < 0)
|
|
|
+ return NULL;
|
|
|
b->peer_backlog[peer_tail] = NULL;
|
|
|
smp_store_release(&b->peer_backlog_tail,
|
|
|
(peer_tail + 1) &
|
|
|
(RXRPC_BACKLOG_MAX - 1));
|
|
|
+
|
|
|
+ rxrpc_new_incoming_peer(local, peer);
|
|
|
}
|
|
|
|
|
|
/* Now allocate and set up the connection */
|
|
@@ -335,30 +332,16 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
|
|
|
* The call is returned with the user access mutex held.
|
|
|
*/
|
|
|
struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
|
|
|
+ struct rxrpc_sock *rx,
|
|
|
+ struct rxrpc_peer *peer,
|
|
|
struct rxrpc_connection *conn,
|
|
|
struct sk_buff *skb)
|
|
|
{
|
|
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
|
|
- struct rxrpc_sock *rx;
|
|
|
struct rxrpc_call *call;
|
|
|
- u16 service_id = sp->hdr.serviceId;
|
|
|
|
|
|
_enter("");
|
|
|
|
|
|
- /* Get the socket providing the service */
|
|
|
- rx = rcu_dereference(local->service);
|
|
|
- if (rx && (service_id == rx->srx.srx_service ||
|
|
|
- service_id == rx->second_service))
|
|
|
- goto found_service;
|
|
|
-
|
|
|
- trace_rxrpc_abort(0, "INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
|
|
|
- RX_INVALID_OPERATION, EOPNOTSUPP);
|
|
|
- skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
|
|
|
- skb->priority = RX_INVALID_OPERATION;
|
|
|
- _leave(" = NULL [service]");
|
|
|
- return NULL;
|
|
|
-
|
|
|
-found_service:
|
|
|
spin_lock(&rx->incoming_lock);
|
|
|
if (rx->sk.sk_state == RXRPC_SERVER_LISTEN_DISABLED ||
|
|
|
rx->sk.sk_state == RXRPC_CLOSE) {
|
|
@@ -371,7 +354,7 @@ found_service:
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- call = rxrpc_alloc_incoming_call(rx, local, conn, skb);
|
|
|
+ call = rxrpc_alloc_incoming_call(rx, local, peer, conn, skb);
|
|
|
if (!call) {
|
|
|
skb->mark = RXRPC_SKB_MARK_REJECT_BUSY;
|
|
|
_leave(" = NULL [busy]");
|