mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
svcrpc: fix UDP on servers with lots of threads
commit b7e5034cbe upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
4af185feb9
commit
43bceddcd7
@@ -381,12 +381,16 @@ static int svc_partial_recvfrom(struct svc_rqst *rqstp,
|
||||
/*
|
||||
* Set socket snd and rcv buffer lengths
|
||||
*/
|
||||
static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
|
||||
unsigned int rcv)
|
||||
static void svc_sock_setbufsize(struct svc_sock *svsk, unsigned int nreqs)
|
||||
{
|
||||
unsigned int max_mesg = svsk->sk_xprt.xpt_server->sv_max_mesg;
|
||||
struct socket *sock = svsk->sk_sock;
|
||||
|
||||
nreqs = min(nreqs, INT_MAX / 2 / max_mesg);
|
||||
|
||||
lock_sock(sock->sk);
|
||||
sock->sk->sk_sndbuf = snd * 2;
|
||||
sock->sk->sk_rcvbuf = rcv * 2;
|
||||
sock->sk->sk_sndbuf = nreqs * max_mesg * 2;
|
||||
sock->sk->sk_rcvbuf = nreqs * max_mesg * 2;
|
||||
sock->sk->sk_write_space(sock->sk);
|
||||
release_sock(sock->sk);
|
||||
}
|
||||
@@ -548,9 +552,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
|
||||
* provides an upper bound on the number of threads
|
||||
* which will access the socket.
|
||||
*/
|
||||
svc_sock_setbufsize(svsk->sk_sock,
|
||||
(serv->sv_nrthreads+3) * serv->sv_max_mesg,
|
||||
(serv->sv_nrthreads+3) * serv->sv_max_mesg);
|
||||
svc_sock_setbufsize(svsk, serv->sv_nrthreads + 3);
|
||||
|
||||
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
||||
skb = NULL;
|
||||
@@ -718,9 +720,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
|
||||
* receive and respond to one request.
|
||||
* svc_udp_recvfrom will re-adjust if necessary
|
||||
*/
|
||||
svc_sock_setbufsize(svsk->sk_sock,
|
||||
3 * svsk->sk_xprt.xpt_server->sv_max_mesg,
|
||||
3 * svsk->sk_xprt.xpt_server->sv_max_mesg);
|
||||
svc_sock_setbufsize(svsk, 3);
|
||||
|
||||
/* data might have come in before data_ready set up */
|
||||
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
|
||||
|
||||
Reference in New Issue
Block a user