]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/rxrpc/call_accept.c
rxrpc: Implement service upgrade
[mirror_ubuntu-artful-kernel.git] / net / rxrpc / call_accept.c
index 1752fcf8e8f1dd85866004a2ee38c8bbaa040138..0d4d84e8c074da699898d1fab3f4b936e1f04a9c 100644 (file)
@@ -38,6 +38,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
 {
        const void *here = __builtin_return_address(0);
        struct rxrpc_call *call;
+       struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
        int max, tmp;
        unsigned int size = RXRPC_BACKLOG_MAX;
        unsigned int head, tail, call_head, call_tail;
@@ -79,7 +80,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
        if (CIRC_CNT(head, tail, size) < max) {
                struct rxrpc_connection *conn;
 
-               conn = rxrpc_prealloc_service_connection(gfp);
+               conn = rxrpc_prealloc_service_connection(rxnet, gfp);
                if (!conn)
                        return -ENOMEM;
                b->conn_backlog[head] = conn;
@@ -136,9 +137,9 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
 
        write_unlock(&rx->call_lock);
 
-       write_lock(&rxrpc_call_lock);
-       list_add_tail(&call->link, &rxrpc_calls);
-       write_unlock(&rxrpc_call_lock);
+       write_lock(&rxnet->call_lock);
+       list_add_tail(&call->link, &rxnet->calls);
+       write_unlock(&rxnet->call_lock);
 
        b->call_backlog[call_head] = call;
        smp_store_release(&b->call_backlog_head, (call_head + 1) & (size - 1));
@@ -185,6 +186,7 @@ int rxrpc_service_prealloc(struct rxrpc_sock *rx, gfp_t gfp)
 void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
 {
        struct rxrpc_backlog *b = rx->backlog;
+       struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
        unsigned int size = RXRPC_BACKLOG_MAX, head, tail;
 
        if (!b)
@@ -209,10 +211,10 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
        tail = b->conn_backlog_tail;
        while (CIRC_CNT(head, tail, size) > 0) {
                struct rxrpc_connection *conn = b->conn_backlog[tail];
-               write_lock(&rxrpc_connection_lock);
+               write_lock(&rxnet->conn_lock);
                list_del(&conn->link);
                list_del(&conn->proc_link);
-               write_unlock(&rxrpc_connection_lock);
+               write_unlock(&rxnet->conn_lock);
                kfree(conn);
                tail = (tail + 1) & (size - 1);
        }
@@ -294,7 +296,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
                conn->params.local = local;
                conn->params.peer = peer;
                rxrpc_see_connection(conn);
-               rxrpc_new_incoming_connection(conn, skb);
+               rxrpc_new_incoming_connection(rx, conn, skb);
        } else {
                rxrpc_get_connection(conn);
        }
@@ -339,7 +341,8 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
 
        /* Get the socket providing the service */
        rx = rcu_dereference(local->service);
-       if (rx && service_id == rx->srx.srx_service)
+       if (rx && (service_id == rx->srx.srx_service ||
+                  service_id == rx->second_service))
                goto found_service;
 
        trace_rxrpc_abort("INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,