Skip to content

Commit b7e5034

Browse files
author
J. Bruce Fields
committed
svcrpc: fix UDP on servers with lots of threads
James Pearson found that an NFS server stopped responding to UDP requests if started with more than 1017 threads. sv_max_mesg is about 2^20, so that is probably where the calculation performed by svc_sock_setbufsize(svsk->sk_sock, (serv->sv_nrthreads+3) * serv->sv_max_mesg, (serv->sv_nrthreads+3) * serv->sv_max_mesg); starts to overflow an int. Reported-by: James Pearson <jcpearson@gmail.com> Tested-by: James Pearson <jcpearson@gmail.com> Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields <bfields@redhat.com>
1 parent 8820bca commit b7e5034

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

net/sunrpc/svcsock.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,16 @@ static ssize_t svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov,
349349
/*
350350
* Set socket snd and rcv buffer lengths
351351
*/
352-
static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
353-
unsigned int rcv)
352+
static void svc_sock_setbufsize(struct svc_sock *svsk, unsigned int nreqs)
354353
{
354+
unsigned int max_mesg = svsk->sk_xprt.xpt_server->sv_max_mesg;
355+
struct socket *sock = svsk->sk_sock;
356+
357+
nreqs = min(nreqs, INT_MAX / 2 / max_mesg);
358+
355359
lock_sock(sock->sk);
356-
sock->sk->sk_sndbuf = snd * 2;
357-
sock->sk->sk_rcvbuf = rcv * 2;
360+
sock->sk->sk_sndbuf = nreqs * max_mesg * 2;
361+
sock->sk->sk_rcvbuf = nreqs * max_mesg * 2;
358362
sock->sk->sk_write_space(sock->sk);
359363
release_sock(sock->sk);
360364
}
@@ -516,9 +520,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
516520
* provides an upper bound on the number of threads
517521
* which will access the socket.
518522
*/
519-
svc_sock_setbufsize(svsk->sk_sock,
520-
(serv->sv_nrthreads+3) * serv->sv_max_mesg,
521-
(serv->sv_nrthreads+3) * serv->sv_max_mesg);
523+
svc_sock_setbufsize(svsk, serv->sv_nrthreads + 3);
522524

523525
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
524526
skb = NULL;
@@ -681,9 +683,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
681683
* receive and respond to one request.
682684
* svc_udp_recvfrom will re-adjust if necessary
683685
*/
684-
svc_sock_setbufsize(svsk->sk_sock,
685-
3 * svsk->sk_xprt.xpt_server->sv_max_mesg,
686-
3 * svsk->sk_xprt.xpt_server->sv_max_mesg);
686+
svc_sock_setbufsize(svsk, 3);
687687

688688
/* data might have come in before data_ready set up */
689689
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);

0 commit comments

Comments
 (0)