drivers: video: rockchip: vcodec_dma_map_sg maybe fail
[firefly-linux-kernel-4.4.55.git] / net / sunrpc / svcsock.c
index 0f679df7d072794094ece1aa48988e834395d849..1413cdcc131c4a7ed49487e4a19691644e0ca65c 100644 (file)
@@ -60,7 +60,7 @@
 
 static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
                                         int flags);
-static void            svc_udp_data_ready(struct sock *, int);
+static void            svc_udp_data_ready(struct sock *);
 static int             svc_udp_recvfrom(struct svc_rqst *);
 static int             svc_udp_sendto(struct svc_rqst *);
 static void            svc_sock_detach(struct svc_xprt *);
@@ -181,7 +181,7 @@ int svc_send_common(struct socket *sock, struct xdr_buf *xdr,
        struct page     **ppage = xdr->pages;
        size_t          base = xdr->page_base;
        unsigned int    pglen = xdr->page_len;
-       unsigned int    flags = MSG_MORE;
+       unsigned int    flags = MSG_MORE | MSG_SENDPAGE_NOTLAST;
        int             slen;
        int             len = 0;
 
@@ -257,7 +257,7 @@ static int svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr)
 
                svc_set_cmsg_data(rqstp, cmh);
 
-               if (sock_sendmsg(sock, &msg, 0) < 0)
+               if (sock_sendmsg(sock, &msg) < 0)
                        goto out;
        }
 
@@ -291,12 +291,14 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
                                &inet_sk(sk)->inet_rcv_saddr,
                                inet_sk(sk)->inet_num);
                break;
+#if IS_ENABLED(CONFIG_IPV6)
        case PF_INET6:
                len = snprintf(buf, remaining, "ipv6 %s %pI6 %d\n",
                                proto_name,
-                               &inet6_sk(sk)->rcv_saddr,
+                               &sk->sk_v6_rcv_saddr,
                                inet_sk(sk)->inet_num);
                break;
+#endif
        default:
                len = snprintf(buf, remaining, "*unknown-%d*\n",
                                sk->sk_family);
@@ -309,19 +311,6 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining)
        return len;
 }
 
-/*
- * Check input queue length
- */
-static int svc_recv_available(struct svc_sock *svsk)
-{
-       struct socket   *sock = svsk->sk_sock;
-       int             avail, err;
-
-       err = kernel_sock_ioctl(sock, TIOCINQ, (unsigned long) &avail);
-
-       return (err >= 0)? avail : err;
-}
-
 /*
  * Generic recvfrom routine.
  */
@@ -337,8 +326,14 @@ static int svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr,
 
        rqstp->rq_xprt_hlen = 0;
 
+       clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
        len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
                                msg.msg_flags);
+       /* If we read a full record, then assume there may be more
+        * data to read (stream based sockets only!)
+        */
+       if (len == buflen)
+               set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
 
        dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
                svsk, iov[0].iov_base, iov[0].iov_len, len);
@@ -398,22 +393,53 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
        release_sock(sock->sk);
 #endif
 }
+
+static int svc_sock_secure_port(struct svc_rqst *rqstp)
+{
+       return svc_port_is_privileged(svc_addr(rqstp));
+}
+
+static bool sunrpc_waitqueue_active(wait_queue_head_t *wq)
+{
+       if (!wq)
+               return false;
+       /*
+        * There should normally be a memory * barrier here--see
+        * wq_has_sleeper().
+        *
+        * It appears that isn't currently necessary, though, basically
+        * because callers all appear to have sufficient memory barriers
+        * between the time the relevant change is made and the
+        * time they call these callbacks.
+        *
+        * The nfsd code itself doesn't actually explicitly wait on
+        * these waitqueues, but it may wait on them for example in
+        * sendpage() or sendmsg() calls.  (And those may be the only
+        * places, since it it uses nonblocking reads.)
+        *
+        * Maybe we should add the memory barriers anyway, but these are
+        * hot paths so we'd need to be convinced there's no sigificant
+        * penalty.
+        */
+       return waitqueue_active(wq);
+}
+
 /*
  * INET callback when data has been received on the socket.
  */
-static void svc_udp_data_ready(struct sock *sk, int count)
+static void svc_udp_data_ready(struct sock *sk)
 {
        struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
        wait_queue_head_t *wq = sk_sleep(sk);
 
        if (svsk) {
-               dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
-                       svsk, sk, count,
+               dprintk("svc: socket %p(inet %p), busy=%d\n",
+                       svsk, sk,
                        test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
                set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
                svc_xprt_enqueue(&svsk->sk_xprt);
        }
-       if (wq && waitqueue_active(wq))
+       if (sunrpc_waitqueue_active(wq))
                wake_up_interruptible(wq);
 }
 
@@ -431,22 +457,50 @@ static void svc_write_space(struct sock *sk)
                svc_xprt_enqueue(&svsk->sk_xprt);
        }
 
-       if (wq && waitqueue_active(wq)) {
+       if (sunrpc_waitqueue_active(wq)) {
                dprintk("RPC svc_write_space: someone sleeping on %p\n",
                       svsk);
                wake_up_interruptible(wq);
        }
 }
 
+static int svc_tcp_has_wspace(struct svc_xprt *xprt)
+{
+       struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
+       struct svc_serv *serv = svsk->sk_xprt.xpt_server;
+       int required;
+
+       if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
+               return 1;
+       required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
+       if (sk_stream_wspace(svsk->sk_sk) >= required ||
+           (sk_stream_min_wspace(svsk->sk_sk) == 0 &&
+            atomic_read(&xprt->xpt_reserved) == 0))
+               return 1;
+       set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
+       return 0;
+}
+
 static void svc_tcp_write_space(struct sock *sk)
 {
+       struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data);
        struct socket *sock = sk->sk_socket;
 
-       if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock)
+       if (!sk_stream_is_writeable(sk) || !sock)
+               return;
+       if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt))
                clear_bit(SOCK_NOSPACE, &sock->flags);
        svc_write_space(sk);
 }
 
+static void svc_tcp_adjust_wspace(struct svc_xprt *xprt)
+{
+       struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
+
+       if (svc_tcp_has_wspace(xprt))
+               clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
+}
+
 /*
  * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo
  */
@@ -676,6 +730,7 @@ static struct svc_xprt_ops svc_udp_ops = {
        .xpo_prep_reply_hdr = svc_udp_prep_reply_hdr,
        .xpo_has_wspace = svc_udp_has_wspace,
        .xpo_accept = svc_udp_accept,
+       .xpo_secure_port = svc_sock_secure_port,
 };
 
 static struct svc_xprt_class svc_udp_class = {
@@ -683,6 +738,7 @@ static struct svc_xprt_class svc_udp_class = {
        .xcl_owner = THIS_MODULE,
        .xcl_ops = &svc_udp_ops,
        .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP,
+       .xcl_ident = XPRT_TRANSPORT_UDP,
 };
 
 static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
@@ -729,7 +785,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
  * A data_ready event on a listening socket means there's a connection
  * pending. Do not use state_change as a substitute for it.
  */
-static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
+static void svc_tcp_listen_data_ready(struct sock *sk)
 {
        struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
        wait_queue_head_t *wq;
@@ -756,7 +812,7 @@ static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
        }
 
        wq = sk_sleep(sk);
-       if (wq && waitqueue_active(wq))
+       if (sunrpc_waitqueue_active(wq))
                wake_up_interruptible_all(wq);
 }
 
@@ -777,11 +833,11 @@ static void svc_tcp_state_change(struct sock *sk)
                set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
                svc_xprt_enqueue(&svsk->sk_xprt);
        }
-       if (wq && waitqueue_active(wq))
+       if (sunrpc_waitqueue_active(wq))
                wake_up_interruptible_all(wq);
 }
 
-static void svc_tcp_data_ready(struct sock *sk, int count)
+static void svc_tcp_data_ready(struct sock *sk)
 {
        struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
        wait_queue_head_t *wq = sk_sleep(sk);
@@ -792,7 +848,7 @@ static void svc_tcp_data_ready(struct sock *sk, int count)
                set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
                svc_xprt_enqueue(&svsk->sk_xprt);
        }
-       if (wq && waitqueue_active(wq))
+       if (sunrpc_waitqueue_active(wq))
                wake_up_interruptible(wq);
 }
 
@@ -840,8 +896,7 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
         * tell us anything.  For now just warn about unpriv connections.
         */
        if (!svc_port_is_privileged(sin)) {
-               dprintk(KERN_WARNING
-                       "%s: connect from unprivileged port: %s\n",
+               dprintk("%s: connect from unprivileged port: %s\n",
                        serv->sv_name,
                        __svc_print_addr(sin, buf, sizeof(buf)));
        }
@@ -865,6 +920,10 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
        }
        svc_xprt_set_local(&newsvsk->sk_xprt, sin, slen);
 
+       if (sock_is_loopback(newsock->sk))
+               set_bit(XPT_LOCAL, &newsvsk->sk_xprt.xpt_flags);
+       else
+               clear_bit(XPT_LOCAL, &newsvsk->sk_xprt.xpt_flags);
        if (serv->sv_stats)
                serv->sv_stats->nettcpconn++;
 
@@ -917,7 +976,10 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
        len = svsk->sk_datalen;
        npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        for (i = 0; i < npages; i++) {
-               BUG_ON(svsk->sk_pages[i] == NULL);
+               if (svsk->sk_pages[i] == NULL) {
+                       WARN_ON_ONCE(1);
+                       continue;
+               }
                put_page(svsk->sk_pages[i]);
                svsk->sk_pages[i] = NULL;
        }
@@ -936,8 +998,6 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
        unsigned int want;
        int len;
 
-       clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
-
        if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
                struct kvec     iov;
 
@@ -984,17 +1044,12 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
        xid = *p++;
        calldir = *p;
 
-       if (bc_xprt)
-               req = xprt_lookup_rqst(bc_xprt, xid);
-
-       if (!req) {
-               printk(KERN_NOTICE
-                       "%s: Got unrecognized reply: "
-                       "calldir 0x%x xpt_bc_xprt %p xid %08x\n",
-                       __func__, ntohl(calldir),
-                       bc_xprt, xid);
+       if (!bc_xprt)
                return -EAGAIN;
-       }
+       spin_lock_bh(&bc_xprt->transport_lock);
+       req = xprt_lookup_rqst(bc_xprt, xid);
+       if (!req)
+               goto unlock_notfound;
 
        memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf));
        /*
@@ -1005,11 +1060,21 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
        dst = &req->rq_private_buf.head[0];
        src = &rqstp->rq_arg.head[0];
        if (dst->iov_len < src->iov_len)
-               return -EAGAIN; /* whatever; just giving up. */
+               goto unlock_eagain; /* whatever; just giving up. */
        memcpy(dst->iov_base, src->iov_base, src->iov_len);
        xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len);
        rqstp->rq_arg.len = 0;
+       spin_unlock_bh(&bc_xprt->transport_lock);
        return 0;
+unlock_notfound:
+       printk(KERN_NOTICE
+               "%s: Got unrecognized reply: "
+               "calldir 0x%x xpt_bc_xprt %p xid %08x\n",
+               __func__, ntohl(calldir),
+               bc_xprt, ntohl(xid));
+unlock_eagain:
+       spin_unlock_bh(&bc_xprt->transport_lock);
+       return -EAGAIN;
 }
 
 static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)
@@ -1029,8 +1094,6 @@ static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)
 static void svc_tcp_fragment_received(struct svc_sock *svsk)
 {
        /* If we have more data, signal svc_xprt_enqueue() to try again */
-       if (svc_recv_available(svsk) > sizeof(rpc_fraghdr))
-               set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
        dprintk("svc: TCP %s record (%d bytes)\n",
                svc_sock_final_rec(svsk) ? "final" : "nonfinal",
                svc_sock_reclen(svsk));
@@ -1092,8 +1155,10 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
                goto err_noclose;
        }
 
-       if (svc_sock_reclen(svsk) < 8)
+       if (svsk->sk_datalen < 8) {
+               svsk->sk_datalen = 0;
                goto err_delete; /* client is nuts. */
+       }
 
        rqstp->rq_arg.len = svsk->sk_datalen;
        rqstp->rq_arg.page_base = 0;
@@ -1105,6 +1170,10 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
 
        rqstp->rq_xprt_ctxt   = NULL;
        rqstp->rq_prot        = IPPROTO_TCP;
+       if (test_bit(XPT_LOCAL, &svsk->sk_xprt.xpt_flags))
+               set_bit(RQ_LOCAL, &rqstp->rq_flags);
+       else
+               clear_bit(RQ_LOCAL, &rqstp->rq_flags);
 
        p = (__be32 *)rqstp->rq_arg.head[0].iov_base;
        calldir = p[1];
@@ -1179,21 +1248,6 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
        svc_putnl(resv, 0);
 }
 
-static int svc_tcp_has_wspace(struct svc_xprt *xprt)
-{
-       struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
-       struct svc_serv *serv = svsk->sk_xprt.xpt_server;
-       int required;
-
-       if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
-               return 1;
-       required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
-       if (sk_stream_wspace(svsk->sk_sk) >= required)
-               return 1;
-       set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
-       return 0;
-}
-
 static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
                                       struct net *net,
                                       struct sockaddr *sa, int salen,
@@ -1225,6 +1279,7 @@ static struct svc_xprt_ops svc_tcp_bc_ops = {
        .xpo_detach = svc_bc_tcp_sock_detach,
        .xpo_free = svc_bc_sock_free,
        .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr,
+       .xpo_secure_port = svc_sock_secure_port,
 };
 
 static struct svc_xprt_class svc_tcp_bc_class = {
@@ -1263,6 +1318,8 @@ static struct svc_xprt_ops svc_tcp_ops = {
        .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr,
        .xpo_has_wspace = svc_tcp_has_wspace,
        .xpo_accept = svc_tcp_accept,
+       .xpo_secure_port = svc_sock_secure_port,
+       .xpo_adjust_wspace = svc_tcp_adjust_wspace,
 };
 
 static struct svc_xprt_class svc_tcp_class = {
@@ -1270,6 +1327,7 @@ static struct svc_xprt_class svc_tcp_class = {
        .xcl_owner = THIS_MODULE,
        .xcl_ops = &svc_tcp_ops,
        .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP,
+       .xcl_ident = XPRT_TRANSPORT_TCP,
 };
 
 void svc_init_xprt_sock(void)
@@ -1334,7 +1392,6 @@ EXPORT_SYMBOL_GPL(svc_sock_update_bufs);
 
 /*
  * Initialize socket for RPC use and create svc_sock struct
- * XXX: May want to setsockopt SO_SNDBUF and SO_RCVBUF.
  */
 static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
                                                struct socket *sock,
@@ -1388,6 +1445,22 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
        return svsk;
 }
 
+bool svc_alien_sock(struct net *net, int fd)
+{
+       int err;
+       struct socket *sock = sockfd_lookup(fd, &err);
+       bool ret = false;
+
+       if (!sock)
+               goto out;
+       if (sock_net(sock->sk) != net)
+               ret = true;
+       sockfd_put(sock);
+out:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(svc_alien_sock);
+
 /**
  * svc_addsock - add a listener socket to an RPC service
  * @serv: pointer to RPC service to which to add a new listener
@@ -1545,7 +1618,7 @@ static void svc_sock_detach(struct svc_xprt *xprt)
        sk->sk_write_space = svsk->sk_owspace;
 
        wq = sk_sleep(sk);
-       if (wq && waitqueue_active(wq))
+       if (sunrpc_waitqueue_active(wq))
                wake_up_interruptible(wq);
 }