]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/sunrpc/xprtsock.c
Merge tag 'nfs-for-4.11-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
[karo-tx-linux.git] / net / sunrpc / xprtsock.c
index c8ac649a51cba98464dfadcd2849b648dab79520..16aff8ddc16f8f3e66e31a86ce227b3ac49857bf 100644 (file)
@@ -52,6 +52,8 @@
 #include "sunrpc.h"
 
 static void xs_close(struct rpc_xprt *xprt);
+static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
+               struct socket *sock);
 
 /*
  * xprtsock tunables
@@ -666,6 +668,9 @@ static int xs_tcp_send_request(struct rpc_task *task)
        if (task->tk_flags & RPC_TASK_SENT)
                zerocopy = false;
 
+       if (test_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state))
+               xs_tcp_set_socket_timeouts(xprt, transport->sock);
+
        /* Continue transmitting the packet/record. We must be careful
         * to cope with writespace callbacks arriving _after_ we have
         * called sendmsg(). */
@@ -1188,7 +1193,7 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r
        char *p;
 
        len = sizeof(transport->tcp_xid) - transport->tcp_offset;
-       dprintk("RPC:       reading XID (%Zu bytes)\n", len);
+       dprintk("RPC:       reading XID (%zu bytes)\n", len);
        p = ((char *) &transport->tcp_xid) + transport->tcp_offset;
        used = xdr_skb_read_bits(desc, p, len);
        transport->tcp_offset += used;
@@ -1219,7 +1224,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
         */
        offset = transport->tcp_offset - sizeof(transport->tcp_xid);
        len = sizeof(transport->tcp_calldir) - offset;
-       dprintk("RPC:       reading CALL/REPLY flag (%Zu bytes)\n", len);
+       dprintk("RPC:       reading CALL/REPLY flag (%zu bytes)\n", len);
        p = ((char *) &transport->tcp_calldir) + offset;
        used = xdr_skb_read_bits(desc, p, len);
        transport->tcp_offset += used;
@@ -1310,7 +1315,7 @@ static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
                return;
        }
 
-       dprintk("RPC:       XID %08x read %Zd bytes\n",
+       dprintk("RPC:       XID %08x read %zd bytes\n",
                        ntohl(transport->tcp_xid), r);
        dprintk("RPC:       xprt = %p, tcp_copied = %lu, tcp_offset = %u, "
                        "tcp_reclen = %u\n", xprt, transport->tcp_copied,
@@ -1456,7 +1461,7 @@ static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_s
        desc->count -= len;
        desc->offset += len;
        transport->tcp_offset += len;
-       dprintk("RPC:       discarded %Zu bytes\n", len);
+       dprintk("RPC:       discarded %zu bytes\n", len);
        xs_tcp_check_fraghdr(transport);
 }
 
@@ -1734,7 +1739,9 @@ static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t
  */
 static void xs_udp_timer(struct rpc_xprt *xprt, struct rpc_task *task)
 {
+       spin_lock_bh(&xprt->transport_lock);
        xprt_adjust_cwnd(xprt, task, -ETIMEDOUT);
+       spin_unlock_bh(&xprt->transport_lock);
 }
 
 static unsigned short xs_get_random_port(void)
@@ -2238,11 +2245,20 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt)
 static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
                struct socket *sock)
 {
-       unsigned int keepidle = DIV_ROUND_UP(xprt->timeout->to_initval, HZ);
-       unsigned int keepcnt = xprt->timeout->to_retries + 1;
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       unsigned int keepidle;
+       unsigned int keepcnt;
        unsigned int opt_on = 1;
        unsigned int timeo;
 
+       spin_lock_bh(&xprt->transport_lock);
+       keepidle = DIV_ROUND_UP(xprt->timeout->to_initval, HZ);
+       keepcnt = xprt->timeout->to_retries + 1;
+       timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
+               (xprt->timeout->to_retries + 1);
+       clear_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state);
+       spin_unlock_bh(&xprt->transport_lock);
+
        /* TCP Keepalive options */
        kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
                        (char *)&opt_on, sizeof(opt_on));
@@ -2254,12 +2270,38 @@ static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
                        (char *)&keepcnt, sizeof(keepcnt));
 
        /* TCP user timeout (see RFC5482) */
-       timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
-               (xprt->timeout->to_retries + 1);
        kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
                        (char *)&timeo, sizeof(timeo));
 }
 
+static void xs_tcp_set_connect_timeout(struct rpc_xprt *xprt,
+               unsigned long connect_timeout,
+               unsigned long reconnect_timeout)
+{
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+       struct rpc_timeout to;
+       unsigned long initval;
+
+       spin_lock_bh(&xprt->transport_lock);
+       if (reconnect_timeout < xprt->max_reconnect_timeout)
+               xprt->max_reconnect_timeout = reconnect_timeout;
+       if (connect_timeout < xprt->connect_timeout) {
+               memcpy(&to, xprt->timeout, sizeof(to));
+               initval = DIV_ROUND_UP(connect_timeout, to.to_retries + 1);
+               /* Arbitrary lower limit */
+               if (initval <  XS_TCP_INIT_REEST_TO << 1)
+                       initval = XS_TCP_INIT_REEST_TO << 1;
+               to.to_initval = initval;
+               to.to_maxval = initval;
+               memcpy(&transport->tcp_timeout, &to,
+                               sizeof(transport->tcp_timeout));
+               xprt->timeout = &transport->tcp_timeout;
+               xprt->connect_timeout = connect_timeout;
+       }
+       set_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state);
+       spin_unlock_bh(&xprt->transport_lock);
+}
+
 static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
 {
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -2728,6 +2770,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
        .set_retrans_timeout    = xprt_set_retrans_timeout_def,
        .close                  = xs_tcp_shutdown,
        .destroy                = xs_destroy,
+       .set_connect_timeout    = xs_tcp_set_connect_timeout,
        .print_stats            = xs_tcp_print_stats,
        .enable_swap            = xs_enable_swap,
        .disable_swap           = xs_disable_swap,
@@ -3014,6 +3057,8 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
        xprt->timeout = &xs_tcp_default_timeout;
 
        xprt->max_reconnect_timeout = xprt->timeout->to_maxval;
+       xprt->connect_timeout = xprt->timeout->to_initval *
+               (xprt->timeout->to_retries + 1);
 
        INIT_WORK(&transport->recv_worker, xs_tcp_data_receive_workfn);
        INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_setup_socket);
@@ -3216,7 +3261,9 @@ static int param_set_uint_minmax(const char *val,
        if (!val)
                return -EINVAL;
        ret = kstrtouint(val, 0, &num);
-       if (ret == -EINVAL || num < min || num > max)
+       if (ret)
+               return ret;
+       if (num < min || num > max)
                return -EINVAL;
        *((unsigned int *)kp->arg) = num;
        return 0;