lkml.org 
[lkml]   [2019]   [Mar]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.0 191/238] svcrpc: fix UDP on servers with lots of threads
    Date
    5.0-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: J. Bruce Fields <bfields@redhat.com>

    commit b7e5034cbecf5a65b7bfdc2b20a8378039577706 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>

    ---
    net/sunrpc/svcsock.c | 20 ++++++++++----------
    1 file changed, 10 insertions(+), 10 deletions(-)

    --- a/net/sunrpc/svcsock.c
    +++ b/net/sunrpc/svcsock.c
    @@ -349,12 +349,16 @@ static ssize_t svc_recvfrom(struct svc_r
    /*
    * 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);
    }
    @@ -516,9 +520,7 @@ static int svc_udp_recvfrom(struct svc_r
    * 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;
    @@ -681,9 +683,7 @@ static void svc_udp_init(struct svc_sock
    * 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);

    \
     
     \ /
      Last update: 2019-03-22 13:25    [W:4.291 / U:0.104 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site