Skip to content

Commit 7196dbb

Browse files
trondmypdamschuma-ntap
authored andcommitted
SUNRPC: Allow changing of the TCP timeout parameters on the fly
When the NFSv4 server tells us the lease period, we usually want to adjust down the timeout parameters on the TCP connection to ensure that we don't miss lease renewals due to a faulty connection. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
1 parent 8d1b8c6 commit 7196dbb

File tree

4 files changed

+77
-11
lines changed

4 files changed

+77
-11
lines changed

include/linux/sunrpc/xprt.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ struct rpc_xprt_ops {
137137
void (*release_request)(struct rpc_task *task);
138138
void (*close)(struct rpc_xprt *xprt);
139139
void (*destroy)(struct rpc_xprt *xprt);
140+
void (*set_connect_timeout)(struct rpc_xprt *xprt,
141+
unsigned long connect_timeout,
142+
unsigned long reconnect_timeout);
140143
void (*print_stats)(struct rpc_xprt *xprt, struct seq_file *seq);
141144
int (*enable_swap)(struct rpc_xprt *xprt);
142145
void (*disable_swap)(struct rpc_xprt *xprt);
@@ -221,6 +224,7 @@ struct rpc_xprt {
221224
struct timer_list timer;
222225
unsigned long last_used,
223226
idle_timeout,
227+
connect_timeout,
224228
max_reconnect_timeout;
225229

226230
/*

include/linux/sunrpc/xprtsock.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ struct sock_xprt {
5555
size_t rcvsize,
5656
sndsize;
5757

58+
struct rpc_timeout tcp_timeout;
59+
5860
/*
5961
* Saved socket callback addresses
6062
*/
@@ -81,6 +83,7 @@ struct sock_xprt {
8183

8284
#define XPRT_SOCK_CONNECTING 1U
8385
#define XPRT_SOCK_DATA_READY (2)
86+
#define XPRT_SOCK_UPD_TIMEOUT (3)
8487

8588
#endif /* __KERNEL__ */
8689

net/sunrpc/clnt.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2684,6 +2684,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
26842684
{
26852685
struct rpc_xprt_switch *xps;
26862686
struct rpc_xprt *xprt;
2687+
unsigned long connect_timeout;
26872688
unsigned long reconnect_timeout;
26882689
unsigned char resvport;
26892690
int ret = 0;
@@ -2696,6 +2697,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
26962697
return -EAGAIN;
26972698
}
26982699
resvport = xprt->resvport;
2700+
connect_timeout = xprt->connect_timeout;
26992701
reconnect_timeout = xprt->max_reconnect_timeout;
27002702
rcu_read_unlock();
27012703

@@ -2705,7 +2707,10 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
27052707
goto out_put_switch;
27062708
}
27072709
xprt->resvport = resvport;
2708-
xprt->max_reconnect_timeout = reconnect_timeout;
2710+
if (xprt->ops->set_connect_timeout != NULL)
2711+
xprt->ops->set_connect_timeout(xprt,
2712+
connect_timeout,
2713+
reconnect_timeout);
27092714

27102715
rpc_xprt_switch_set_roundrobin(xps);
27112716
if (setup) {
@@ -2722,24 +2727,35 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
27222727
}
27232728
EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt);
27242729

2730+
struct connect_timeout_data {
2731+
unsigned long connect_timeout;
2732+
unsigned long reconnect_timeout;
2733+
};
2734+
27252735
static int
2726-
rpc_xprt_cap_max_reconnect_timeout(struct rpc_clnt *clnt,
2736+
rpc_xprt_set_connect_timeout(struct rpc_clnt *clnt,
27272737
struct rpc_xprt *xprt,
27282738
void *data)
27292739
{
2730-
unsigned long timeout = *((unsigned long *)data);
2740+
struct connect_timeout_data *timeo = data;
27312741

2732-
if (timeout < xprt->max_reconnect_timeout)
2733-
xprt->max_reconnect_timeout = timeout;
2742+
if (xprt->ops->set_connect_timeout)
2743+
xprt->ops->set_connect_timeout(xprt,
2744+
timeo->connect_timeout,
2745+
timeo->reconnect_timeout);
27342746
return 0;
27352747
}
27362748

27372749
void
27382750
rpc_cap_max_reconnect_timeout(struct rpc_clnt *clnt, unsigned long timeo)
27392751
{
2752+
struct connect_timeout_data timeout = {
2753+
.connect_timeout = timeo,
2754+
.reconnect_timeout = timeo,
2755+
};
27402756
rpc_clnt_iterate_for_each_xprt(clnt,
2741-
rpc_xprt_cap_max_reconnect_timeout,
2742-
&timeo);
2757+
rpc_xprt_set_connect_timeout,
2758+
&timeout);
27432759
}
27442760
EXPORT_SYMBOL_GPL(rpc_cap_max_reconnect_timeout);
27452761

net/sunrpc/xprtsock.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
#include "sunrpc.h"
5353

5454
static void xs_close(struct rpc_xprt *xprt);
55+
static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
56+
struct socket *sock);
5557

5658
/*
5759
* xprtsock tunables
@@ -666,6 +668,9 @@ static int xs_tcp_send_request(struct rpc_task *task)
666668
if (task->tk_flags & RPC_TASK_SENT)
667669
zerocopy = false;
668670

671+
if (test_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state))
672+
xs_tcp_set_socket_timeouts(xprt, transport->sock);
673+
669674
/* Continue transmitting the packet/record. We must be careful
670675
* to cope with writespace callbacks arriving _after_ we have
671676
* called sendmsg(). */
@@ -2238,11 +2243,20 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt)
22382243
static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
22392244
struct socket *sock)
22402245
{
2241-
unsigned int keepidle = DIV_ROUND_UP(xprt->timeout->to_initval, HZ);
2242-
unsigned int keepcnt = xprt->timeout->to_retries + 1;
2246+
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
2247+
unsigned int keepidle;
2248+
unsigned int keepcnt;
22432249
unsigned int opt_on = 1;
22442250
unsigned int timeo;
22452251

2252+
spin_lock_bh(&xprt->transport_lock);
2253+
keepidle = DIV_ROUND_UP(xprt->timeout->to_initval, HZ);
2254+
keepcnt = xprt->timeout->to_retries + 1;
2255+
timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
2256+
(xprt->timeout->to_retries + 1);
2257+
clear_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state);
2258+
spin_unlock_bh(&xprt->transport_lock);
2259+
22462260
/* TCP Keepalive options */
22472261
kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
22482262
(char *)&opt_on, sizeof(opt_on));
@@ -2254,12 +2268,38 @@ static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
22542268
(char *)&keepcnt, sizeof(keepcnt));
22552269

22562270
/* TCP user timeout (see RFC5482) */
2257-
timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
2258-
(xprt->timeout->to_retries + 1);
22592271
kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
22602272
(char *)&timeo, sizeof(timeo));
22612273
}
22622274

2275+
static void xs_tcp_set_connect_timeout(struct rpc_xprt *xprt,
2276+
unsigned long connect_timeout,
2277+
unsigned long reconnect_timeout)
2278+
{
2279+
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
2280+
struct rpc_timeout to;
2281+
unsigned long initval;
2282+
2283+
spin_lock_bh(&xprt->transport_lock);
2284+
if (reconnect_timeout < xprt->max_reconnect_timeout)
2285+
xprt->max_reconnect_timeout = reconnect_timeout;
2286+
if (connect_timeout < xprt->connect_timeout) {
2287+
memcpy(&to, xprt->timeout, sizeof(to));
2288+
initval = DIV_ROUND_UP(connect_timeout, to.to_retries + 1);
2289+
/* Arbitrary lower limit */
2290+
if (initval < XS_TCP_INIT_REEST_TO << 1)
2291+
initval = XS_TCP_INIT_REEST_TO << 1;
2292+
to.to_initval = initval;
2293+
to.to_maxval = initval;
2294+
memcpy(&transport->tcp_timeout, &to,
2295+
sizeof(transport->tcp_timeout));
2296+
xprt->timeout = &transport->tcp_timeout;
2297+
xprt->connect_timeout = connect_timeout;
2298+
}
2299+
set_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state);
2300+
spin_unlock_bh(&xprt->transport_lock);
2301+
}
2302+
22632303
static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
22642304
{
22652305
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -2728,6 +2768,7 @@ static struct rpc_xprt_ops xs_tcp_ops = {
27282768
.set_retrans_timeout = xprt_set_retrans_timeout_def,
27292769
.close = xs_tcp_shutdown,
27302770
.destroy = xs_destroy,
2771+
.set_connect_timeout = xs_tcp_set_connect_timeout,
27312772
.print_stats = xs_tcp_print_stats,
27322773
.enable_swap = xs_enable_swap,
27332774
.disable_swap = xs_disable_swap,
@@ -3014,6 +3055,8 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
30143055
xprt->timeout = &xs_tcp_default_timeout;
30153056

30163057
xprt->max_reconnect_timeout = xprt->timeout->to_maxval;
3058+
xprt->connect_timeout = xprt->timeout->to_initval *
3059+
(xprt->timeout->to_retries + 1);
30173060

30183061
INIT_WORK(&transport->recv_worker, xs_tcp_data_receive_workfn);
30193062
INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_setup_socket);

0 commit comments

Comments
 (0)