aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-09-01 12:33:46 -0400
committerThomas Gleixner <tglx@linutronix.de>2016-09-01 12:33:46 -0400
commit0cb7bf61b1e9f05027de58c80f9b46a714d24e35 (patch)
tree41fb55cf62d07b425122f9a8b96412c0d8eb99c5 /net/sunrpc
parentaa877175e7a9982233ed8f10cb4bfddd78d82741 (diff)
parent3eab887a55424fc2c27553b7bfe32330df83f7b8 (diff)
Merge branch 'linus' into smp/hotplug
Apply upstream changes to avoid conflicts with pending patches.
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c8
-rw-r--r--net/sunrpc/clnt.c24
-rw-r--r--net/sunrpc/xprt.c26
-rw-r--r--net/sunrpc/xprtsock.c60
4 files changed, 94 insertions, 24 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 23c8e7c39656..976c7812bbd5 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -340,12 +340,14 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
340} 340}
341 341
342static struct gss_upcall_msg * 342static struct gss_upcall_msg *
343__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid) 343__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth)
344{ 344{
345 struct gss_upcall_msg *pos; 345 struct gss_upcall_msg *pos;
346 list_for_each_entry(pos, &pipe->in_downcall, list) { 346 list_for_each_entry(pos, &pipe->in_downcall, list) {
347 if (!uid_eq(pos->uid, uid)) 347 if (!uid_eq(pos->uid, uid))
348 continue; 348 continue;
349 if (auth && pos->auth->service != auth->service)
350 continue;
349 atomic_inc(&pos->count); 351 atomic_inc(&pos->count);
350 dprintk("RPC: %s found msg %p\n", __func__, pos); 352 dprintk("RPC: %s found msg %p\n", __func__, pos);
351 return pos; 353 return pos;
@@ -365,7 +367,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg)
365 struct gss_upcall_msg *old; 367 struct gss_upcall_msg *old;
366 368
367 spin_lock(&pipe->lock); 369 spin_lock(&pipe->lock);
368 old = __gss_find_upcall(pipe, gss_msg->uid); 370 old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth);
369 if (old == NULL) { 371 if (old == NULL) {
370 atomic_inc(&gss_msg->count); 372 atomic_inc(&gss_msg->count);
371 list_add(&gss_msg->list, &pipe->in_downcall); 373 list_add(&gss_msg->list, &pipe->in_downcall);
@@ -714,7 +716,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
714 err = -ENOENT; 716 err = -ENOENT;
715 /* Find a matching upcall */ 717 /* Find a matching upcall */
716 spin_lock(&pipe->lock); 718 spin_lock(&pipe->lock);
717 gss_msg = __gss_find_upcall(pipe, uid); 719 gss_msg = __gss_find_upcall(pipe, uid, NULL);
718 if (gss_msg == NULL) { 720 if (gss_msg == NULL) {
719 spin_unlock(&pipe->lock); 721 spin_unlock(&pipe->lock);
720 goto err_put_ctx; 722 goto err_put_ctx;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index cb49898a5a58..7f79fb7dc6a0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2638,6 +2638,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
2638{ 2638{
2639 struct rpc_xprt_switch *xps; 2639 struct rpc_xprt_switch *xps;
2640 struct rpc_xprt *xprt; 2640 struct rpc_xprt *xprt;
2641 unsigned long reconnect_timeout;
2641 unsigned char resvport; 2642 unsigned char resvport;
2642 int ret = 0; 2643 int ret = 0;
2643 2644
@@ -2649,6 +2650,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
2649 return -EAGAIN; 2650 return -EAGAIN;
2650 } 2651 }
2651 resvport = xprt->resvport; 2652 resvport = xprt->resvport;
2653 reconnect_timeout = xprt->max_reconnect_timeout;
2652 rcu_read_unlock(); 2654 rcu_read_unlock();
2653 2655
2654 xprt = xprt_create_transport(xprtargs); 2656 xprt = xprt_create_transport(xprtargs);
@@ -2657,6 +2659,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
2657 goto out_put_switch; 2659 goto out_put_switch;
2658 } 2660 }
2659 xprt->resvport = resvport; 2661 xprt->resvport = resvport;
2662 xprt->max_reconnect_timeout = reconnect_timeout;
2660 2663
2661 rpc_xprt_switch_set_roundrobin(xps); 2664 rpc_xprt_switch_set_roundrobin(xps);
2662 if (setup) { 2665 if (setup) {
@@ -2673,6 +2676,27 @@ out_put_switch:
2673} 2676}
2674EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt); 2677EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt);
2675 2678
2679static int
2680rpc_xprt_cap_max_reconnect_timeout(struct rpc_clnt *clnt,
2681 struct rpc_xprt *xprt,
2682 void *data)
2683{
2684 unsigned long timeout = *((unsigned long *)data);
2685
2686 if (timeout < xprt->max_reconnect_timeout)
2687 xprt->max_reconnect_timeout = timeout;
2688 return 0;
2689}
2690
2691void
2692rpc_cap_max_reconnect_timeout(struct rpc_clnt *clnt, unsigned long timeo)
2693{
2694 rpc_clnt_iterate_for_each_xprt(clnt,
2695 rpc_xprt_cap_max_reconnect_timeout,
2696 &timeo);
2697}
2698EXPORT_SYMBOL_GPL(rpc_cap_max_reconnect_timeout);
2699
2676#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 2700#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
2677static void rpc_show_header(void) 2701static void rpc_show_header(void)
2678{ 2702{
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 8313960cac52..ea244b29138b 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -680,6 +680,20 @@ out:
680 spin_unlock_bh(&xprt->transport_lock); 680 spin_unlock_bh(&xprt->transport_lock);
681} 681}
682 682
683static bool
684xprt_has_timer(const struct rpc_xprt *xprt)
685{
686 return xprt->idle_timeout != 0;
687}
688
689static void
690xprt_schedule_autodisconnect(struct rpc_xprt *xprt)
691 __must_hold(&xprt->transport_lock)
692{
693 if (list_empty(&xprt->recv) && xprt_has_timer(xprt))
694 mod_timer(&xprt->timer, xprt->last_used + xprt->idle_timeout);
695}
696
683static void 697static void
684xprt_init_autodisconnect(unsigned long data) 698xprt_init_autodisconnect(unsigned long data)
685{ 699{
@@ -688,6 +702,8 @@ xprt_init_autodisconnect(unsigned long data)
688 spin_lock(&xprt->transport_lock); 702 spin_lock(&xprt->transport_lock);
689 if (!list_empty(&xprt->recv)) 703 if (!list_empty(&xprt->recv))
690 goto out_abort; 704 goto out_abort;
705 /* Reset xprt->last_used to avoid connect/autodisconnect cycling */
706 xprt->last_used = jiffies;
691 if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) 707 if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
692 goto out_abort; 708 goto out_abort;
693 spin_unlock(&xprt->transport_lock); 709 spin_unlock(&xprt->transport_lock);
@@ -725,6 +741,7 @@ void xprt_unlock_connect(struct rpc_xprt *xprt, void *cookie)
725 goto out; 741 goto out;
726 xprt->snd_task =NULL; 742 xprt->snd_task =NULL;
727 xprt->ops->release_xprt(xprt, NULL); 743 xprt->ops->release_xprt(xprt, NULL);
744 xprt_schedule_autodisconnect(xprt);
728out: 745out:
729 spin_unlock_bh(&xprt->transport_lock); 746 spin_unlock_bh(&xprt->transport_lock);
730 wake_up_bit(&xprt->state, XPRT_LOCKED); 747 wake_up_bit(&xprt->state, XPRT_LOCKED);
@@ -888,11 +905,6 @@ static void xprt_timer(struct rpc_task *task)
888 spin_unlock_bh(&xprt->transport_lock); 905 spin_unlock_bh(&xprt->transport_lock);
889} 906}
890 907
891static inline int xprt_has_timer(struct rpc_xprt *xprt)
892{
893 return xprt->idle_timeout != 0;
894}
895
896/** 908/**
897 * xprt_prepare_transmit - reserve the transport before sending a request 909 * xprt_prepare_transmit - reserve the transport before sending a request
898 * @task: RPC task about to send a request 910 * @task: RPC task about to send a request
@@ -1280,9 +1292,7 @@ void xprt_release(struct rpc_task *task)
1280 if (!list_empty(&req->rq_list)) 1292 if (!list_empty(&req->rq_list))
1281 list_del(&req->rq_list); 1293 list_del(&req->rq_list);
1282 xprt->last_used = jiffies; 1294 xprt->last_used = jiffies;
1283 if (list_empty(&xprt->recv) && xprt_has_timer(xprt)) 1295 xprt_schedule_autodisconnect(xprt);
1284 mod_timer(&xprt->timer,
1285 xprt->last_used + xprt->idle_timeout);
1286 spin_unlock_bh(&xprt->transport_lock); 1296 spin_unlock_bh(&xprt->transport_lock);
1287 if (req->rq_buffer) 1297 if (req->rq_buffer)
1288 xprt->ops->buf_free(req->rq_buffer); 1298 xprt->ops->buf_free(req->rq_buffer);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 111767ab124a..8ede3bc52481 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -177,7 +177,6 @@ static struct ctl_table sunrpc_table[] = {
177 * increase over time if the server is down or not responding. 177 * increase over time if the server is down or not responding.
178 */ 178 */
179#define XS_TCP_INIT_REEST_TO (3U * HZ) 179#define XS_TCP_INIT_REEST_TO (3U * HZ)
180#define XS_TCP_MAX_REEST_TO (5U * 60 * HZ)
181 180
182/* 181/*
183 * TCP idle timeout; client drops the transport socket if it is idle 182 * TCP idle timeout; client drops the transport socket if it is idle
@@ -2173,6 +2172,8 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
2173 write_unlock_bh(&sk->sk_callback_lock); 2172 write_unlock_bh(&sk->sk_callback_lock);
2174 } 2173 }
2175 xs_udp_do_set_buffer_size(xprt); 2174 xs_udp_do_set_buffer_size(xprt);
2175
2176 xprt->stat.connect_start = jiffies;
2176} 2177}
2177 2178
2178static void xs_udp_setup_socket(struct work_struct *work) 2179static void xs_udp_setup_socket(struct work_struct *work)
@@ -2236,6 +2237,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
2236 unsigned int keepcnt = xprt->timeout->to_retries + 1; 2237 unsigned int keepcnt = xprt->timeout->to_retries + 1;
2237 unsigned int opt_on = 1; 2238 unsigned int opt_on = 1;
2238 unsigned int timeo; 2239 unsigned int timeo;
2240 unsigned int addr_pref = IPV6_PREFER_SRC_PUBLIC;
2239 2241
2240 /* TCP Keepalive options */ 2242 /* TCP Keepalive options */
2241 kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, 2243 kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
@@ -2247,6 +2249,16 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
2247 kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT, 2249 kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
2248 (char *)&keepcnt, sizeof(keepcnt)); 2250 (char *)&keepcnt, sizeof(keepcnt));
2249 2251
2252 /* Avoid temporary address, they are bad for long-lived
2253 * connections such as NFS mounts.
2254 * RFC4941, section 3.6 suggests that:
2255 * Individual applications, which have specific
2256 * knowledge about the normal duration of connections,
2257 * MAY override this as appropriate.
2258 */
2259 kernel_setsockopt(sock, SOL_IPV6, IPV6_ADDR_PREFERENCES,
2260 (char *)&addr_pref, sizeof(addr_pref));
2261
2250 /* TCP user timeout (see RFC5482) */ 2262 /* TCP user timeout (see RFC5482) */
2251 timeo = jiffies_to_msecs(xprt->timeout->to_initval) * 2263 timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
2252 (xprt->timeout->to_retries + 1); 2264 (xprt->timeout->to_retries + 1);
@@ -2295,6 +2307,10 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
2295 /* SYN_SENT! */ 2307 /* SYN_SENT! */
2296 if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) 2308 if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
2297 xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; 2309 xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
2310 break;
2311 case -EADDRNOTAVAIL:
2312 /* Source port number is unavailable. Try a new one! */
2313 transport->srcport = 0;
2298 } 2314 }
2299out: 2315out:
2300 return ret; 2316 return ret;
@@ -2369,6 +2385,25 @@ out:
2369 xprt_wake_pending_tasks(xprt, status); 2385 xprt_wake_pending_tasks(xprt, status);
2370} 2386}
2371 2387
2388static unsigned long xs_reconnect_delay(const struct rpc_xprt *xprt)
2389{
2390 unsigned long start, now = jiffies;
2391
2392 start = xprt->stat.connect_start + xprt->reestablish_timeout;
2393 if (time_after(start, now))
2394 return start - now;
2395 return 0;
2396}
2397
2398static void xs_reconnect_backoff(struct rpc_xprt *xprt)
2399{
2400 xprt->reestablish_timeout <<= 1;
2401 if (xprt->reestablish_timeout > xprt->max_reconnect_timeout)
2402 xprt->reestablish_timeout = xprt->max_reconnect_timeout;
2403 if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
2404 xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
2405}
2406
2372/** 2407/**
2373 * xs_connect - connect a socket to a remote endpoint 2408 * xs_connect - connect a socket to a remote endpoint
2374 * @xprt: pointer to transport structure 2409 * @xprt: pointer to transport structure
@@ -2386,6 +2421,7 @@ out:
2386static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task) 2421static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
2387{ 2422{
2388 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); 2423 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
2424 unsigned long delay = 0;
2389 2425
2390 WARN_ON_ONCE(!xprt_lock_connect(xprt, task, transport)); 2426 WARN_ON_ONCE(!xprt_lock_connect(xprt, task, transport));
2391 2427
@@ -2397,19 +2433,15 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
2397 /* Start by resetting any existing state */ 2433 /* Start by resetting any existing state */
2398 xs_reset_transport(transport); 2434 xs_reset_transport(transport);
2399 2435
2400 queue_delayed_work(xprtiod_workqueue, 2436 delay = xs_reconnect_delay(xprt);
2401 &transport->connect_worker, 2437 xs_reconnect_backoff(xprt);
2402 xprt->reestablish_timeout); 2438
2403 xprt->reestablish_timeout <<= 1; 2439 } else
2404 if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
2405 xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
2406 if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
2407 xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
2408 } else {
2409 dprintk("RPC: xs_connect scheduled xprt %p\n", xprt); 2440 dprintk("RPC: xs_connect scheduled xprt %p\n", xprt);
2410 queue_delayed_work(xprtiod_workqueue, 2441
2411 &transport->connect_worker, 0); 2442 queue_delayed_work(xprtiod_workqueue,
2412 } 2443 &transport->connect_worker,
2444 delay);
2413} 2445}
2414 2446
2415/** 2447/**
@@ -2961,6 +2993,8 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
2961 xprt->ops = &xs_tcp_ops; 2993 xprt->ops = &xs_tcp_ops;
2962 xprt->timeout = &xs_tcp_default_timeout; 2994 xprt->timeout = &xs_tcp_default_timeout;
2963 2995
2996 xprt->max_reconnect_timeout = xprt->timeout->to_maxval;
2997
2964 INIT_WORK(&transport->recv_worker, xs_tcp_data_receive_workfn); 2998 INIT_WORK(&transport->recv_worker, xs_tcp_data_receive_workfn);
2965 INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_setup_socket); 2999 INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_setup_socket);
2966 3000