]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.19/svcrpc-fix-udp-on-servers-with-lots-of-threads.patch
Linux 4.14.108
[thirdparty/kernel/stable-queue.git] / queue-4.19 / svcrpc-fix-udp-on-servers-with-lots-of-threads.patch
1 From b7e5034cbecf5a65b7bfdc2b20a8378039577706 Mon Sep 17 00:00:00 2001
2 From: "J. Bruce Fields" <bfields@redhat.com>
3 Date: Wed, 20 Feb 2019 12:54:50 -0500
4 Subject: svcrpc: fix UDP on servers with lots of threads
5
6 From: J. Bruce Fields <bfields@redhat.com>
7
8 commit b7e5034cbecf5a65b7bfdc2b20a8378039577706 upstream.
9
10 James Pearson found that an NFS server stopped responding to UDP
11 requests if started with more than 1017 threads.
12
13 sv_max_mesg is about 2^20, so that is probably where the calculation
14 performed by
15
16 svc_sock_setbufsize(svsk->sk_sock,
17 (serv->sv_nrthreads+3) * serv->sv_max_mesg,
18 (serv->sv_nrthreads+3) * serv->sv_max_mesg);
19
20 starts to overflow an int.
21
22 Reported-by: James Pearson <jcpearson@gmail.com>
23 Tested-by: James Pearson <jcpearson@gmail.com>
24 Cc: stable@vger.kernel.org
25 Signed-off-by: J. Bruce Fields <bfields@redhat.com>
26 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
27
28 ---
29 net/sunrpc/svcsock.c | 20 ++++++++++----------
30 1 file changed, 10 insertions(+), 10 deletions(-)
31
32 --- a/net/sunrpc/svcsock.c
33 +++ b/net/sunrpc/svcsock.c
34 @@ -381,12 +381,16 @@ static int svc_partial_recvfrom(struct s
35 /*
36 * Set socket snd and rcv buffer lengths
37 */
38 -static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
39 - unsigned int rcv)
40 +static void svc_sock_setbufsize(struct svc_sock *svsk, unsigned int nreqs)
41 {
42 + unsigned int max_mesg = svsk->sk_xprt.xpt_server->sv_max_mesg;
43 + struct socket *sock = svsk->sk_sock;
44 +
45 + nreqs = min(nreqs, INT_MAX / 2 / max_mesg);
46 +
47 lock_sock(sock->sk);
48 - sock->sk->sk_sndbuf = snd * 2;
49 - sock->sk->sk_rcvbuf = rcv * 2;
50 + sock->sk->sk_sndbuf = nreqs * max_mesg * 2;
51 + sock->sk->sk_rcvbuf = nreqs * max_mesg * 2;
52 sock->sk->sk_write_space(sock->sk);
53 release_sock(sock->sk);
54 }
55 @@ -548,9 +552,7 @@ static int svc_udp_recvfrom(struct svc_r
56 * provides an upper bound on the number of threads
57 * which will access the socket.
58 */
59 - svc_sock_setbufsize(svsk->sk_sock,
60 - (serv->sv_nrthreads+3) * serv->sv_max_mesg,
61 - (serv->sv_nrthreads+3) * serv->sv_max_mesg);
62 + svc_sock_setbufsize(svsk, serv->sv_nrthreads + 3);
63
64 clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
65 skb = NULL;
66 @@ -718,9 +720,7 @@ static void svc_udp_init(struct svc_sock
67 * receive and respond to one request.
68 * svc_udp_recvfrom will re-adjust if necessary
69 */
70 - svc_sock_setbufsize(svsk->sk_sock,
71 - 3 * svsk->sk_xprt.xpt_server->sv_max_mesg,
72 - 3 * svsk->sk_xprt.xpt_server->sv_max_mesg);
73 + svc_sock_setbufsize(svsk, 3);
74
75 /* data might have come in before data_ready set up */
76 set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);