rxrpc: Rewrite the data and ack handling code
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / net / rxrpc / af_rxrpc.c
index 1e8cf3ded81f3fcd29117089f8f8d4da9db69701..caa226dd436e9015cff166e3b5ffdaf3a47c4e7f 100644 (file)
@@ -155,7 +155,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
        }
 
        if (rx->srx.srx_service) {
-               write_lock_bh(&local->services_lock);
+               write_lock(&local->services_lock);
                hlist_for_each_entry(prx, &local->services, listen_link) {
                        if (prx->srx.srx_service == rx->srx.srx_service)
                                goto service_in_use;
@@ -163,7 +163,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
 
                rx->local = local;
                hlist_add_head_rcu(&rx->listen_link, &local->services);
-               write_unlock_bh(&local->services_lock);
+               write_unlock(&local->services_lock);
 
                rx->sk.sk_state = RXRPC_SERVER_BOUND;
        } else {
@@ -176,7 +176,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
        return 0;
 
 service_in_use:
-       write_unlock_bh(&local->services_lock);
+       write_unlock(&local->services_lock);
        rxrpc_put_local(local);
        ret = -EADDRINUSE;
 error_unlock:
@@ -515,15 +515,16 @@ error:
 static unsigned int rxrpc_poll(struct file *file, struct socket *sock,
                               poll_table *wait)
 {
-       unsigned int mask;
        struct sock *sk = sock->sk;
+       struct rxrpc_sock *rx = rxrpc_sk(sk);
+       unsigned int mask;
 
        sock_poll_wait(file, sk_sleep(sk), wait);
        mask = 0;
 
        /* the socket is readable if there are any messages waiting on the Rx
         * queue */
-       if (!skb_queue_empty(&sk->sk_receive_queue))
+       if (!list_empty(&rx->recvmsg_q))
                mask |= POLLIN | POLLRDNORM;
 
        /* the socket is writable if there is space to add new data to the
@@ -575,8 +576,11 @@ static int rxrpc_create(struct net *net, struct socket *sock, int protocol,
        rx->calls = RB_ROOT;
 
        INIT_HLIST_NODE(&rx->listen_link);
-       INIT_LIST_HEAD(&rx->secureq);
-       INIT_LIST_HEAD(&rx->acceptq);
+       spin_lock_init(&rx->incoming_lock);
+       INIT_LIST_HEAD(&rx->sock_calls);
+       INIT_LIST_HEAD(&rx->to_be_accepted);
+       INIT_LIST_HEAD(&rx->recvmsg_q);
+       rwlock_init(&rx->recvmsg_lock);
        rwlock_init(&rx->call_lock);
        memset(&rx->srx, 0, sizeof(rx->srx));
 
@@ -584,6 +588,39 @@ static int rxrpc_create(struct net *net, struct socket *sock, int protocol,
        return 0;
 }
 
+/*
+ * Kill all the calls on a socket and shut it down.
+ */
+static int rxrpc_shutdown(struct socket *sock, int flags)
+{
+       struct sock *sk = sock->sk;
+       struct rxrpc_sock *rx = rxrpc_sk(sk);
+       int ret = 0;
+
+       _enter("%p,%d", sk, flags);
+
+       if (flags != SHUT_RDWR)
+               return -EOPNOTSUPP;
+       if (sk->sk_state == RXRPC_CLOSE)
+               return -ESHUTDOWN;
+
+       lock_sock(sk);
+
+       spin_lock_bh(&sk->sk_receive_queue.lock);
+       if (sk->sk_state < RXRPC_CLOSE) {
+               sk->sk_state = RXRPC_CLOSE;
+               sk->sk_shutdown = SHUTDOWN_MASK;
+       } else {
+               ret = -ESHUTDOWN;
+       }
+       spin_unlock_bh(&sk->sk_receive_queue.lock);
+
+       rxrpc_discard_prealloc(rx);
+
+       release_sock(sk);
+       return ret;
+}
+
 /*
  * RxRPC socket destructor
  */
@@ -623,9 +660,9 @@ static int rxrpc_release_sock(struct sock *sk)
        ASSERTCMP(rx->listen_link.next, !=, LIST_POISON1);
 
        if (!hlist_unhashed(&rx->listen_link)) {
-               write_lock_bh(&rx->local->services_lock);
+               write_lock(&rx->local->services_lock);
                hlist_del_rcu(&rx->listen_link);
-               write_unlock_bh(&rx->local->services_lock);
+               write_unlock(&rx->local->services_lock);
        }
 
        /* try to flush out this socket */
@@ -678,7 +715,7 @@ static const struct proto_ops rxrpc_rpc_ops = {
        .poll           = rxrpc_poll,
        .ioctl          = sock_no_ioctl,
        .listen         = rxrpc_listen,
-       .shutdown       = sock_no_shutdown,
+       .shutdown       = rxrpc_shutdown,
        .setsockopt     = rxrpc_setsockopt,
        .getsockopt     = sock_no_getsockopt,
        .sendmsg        = rxrpc_sendmsg,