diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2016-09-01 12:33:46 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-09-01 12:33:46 -0400 |
commit | 0cb7bf61b1e9f05027de58c80f9b46a714d24e35 (patch) | |
tree | 41fb55cf62d07b425122f9a8b96412c0d8eb99c5 /net/sunrpc | |
parent | aa877175e7a9982233ed8f10cb4bfddd78d82741 (diff) | |
parent | 3eab887a55424fc2c27553b7bfe32330df83f7b8 (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.c | 8 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 24 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 26 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 60 |
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 | ||
342 | static struct gss_upcall_msg * | 342 | static 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 | } |
2674 | EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt); | 2677 | EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt); |
2675 | 2678 | ||
2679 | static int | ||
2680 | rpc_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 | |||
2691 | void | ||
2692 | rpc_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 | } | ||
2698 | EXPORT_SYMBOL_GPL(rpc_cap_max_reconnect_timeout); | ||
2699 | |||
2676 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 2700 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
2677 | static void rpc_show_header(void) | 2701 | static 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 | ||
683 | static bool | ||
684 | xprt_has_timer(const struct rpc_xprt *xprt) | ||
685 | { | ||
686 | return xprt->idle_timeout != 0; | ||
687 | } | ||
688 | |||
689 | static void | ||
690 | xprt_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 | |||
683 | static void | 697 | static void |
684 | xprt_init_autodisconnect(unsigned long data) | 698 | xprt_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); | ||
728 | out: | 745 | out: |
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 | ||
891 | static 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 | ||
2178 | static void xs_udp_setup_socket(struct work_struct *work) | 2179 | static 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 | } |
2299 | out: | 2315 | out: |
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 | ||
2388 | static 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 | |||
2398 | static 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: | |||
2386 | static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task) | 2421 | static 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 | ||