diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth.c | 18 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 58 |
2 files changed, 58 insertions, 18 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 436bf1b4b76c..cb216b2df666 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -228,19 +228,21 @@ static int | |||
228 | rpcauth_prune_expired(struct list_head *free, int nr_to_scan) | 228 | rpcauth_prune_expired(struct list_head *free, int nr_to_scan) |
229 | { | 229 | { |
230 | spinlock_t *cache_lock; | 230 | spinlock_t *cache_lock; |
231 | struct rpc_cred *cred; | 231 | struct rpc_cred *cred, *next; |
232 | unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM; | 232 | unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM; |
233 | 233 | ||
234 | while (!list_empty(&cred_unused)) { | 234 | list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) { |
235 | cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru); | 235 | |
236 | /* Enforce a 60 second garbage collection moratorium */ | ||
237 | if (time_in_range(cred->cr_expire, expired, jiffies) && | ||
238 | test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) | ||
239 | continue; | ||
240 | |||
236 | list_del_init(&cred->cr_lru); | 241 | list_del_init(&cred->cr_lru); |
237 | number_cred_unused--; | 242 | number_cred_unused--; |
238 | if (atomic_read(&cred->cr_count) != 0) | 243 | if (atomic_read(&cred->cr_count) != 0) |
239 | continue; | 244 | continue; |
240 | /* Enforce a 5 second garbage collection moratorium */ | 245 | |
241 | if (time_in_range(cred->cr_expire, expired, jiffies) && | ||
242 | test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) | ||
243 | continue; | ||
244 | cache_lock = &cred->cr_auth->au_credcache->lock; | 246 | cache_lock = &cred->cr_auth->au_credcache->lock; |
245 | spin_lock(cache_lock); | 247 | spin_lock(cache_lock); |
246 | if (atomic_read(&cred->cr_count) == 0) { | 248 | if (atomic_read(&cred->cr_count) == 0) { |
@@ -453,7 +455,7 @@ need_lock: | |||
453 | } | 455 | } |
454 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) | 456 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) |
455 | rpcauth_unhash_cred(cred); | 457 | rpcauth_unhash_cred(cred); |
456 | else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { | 458 | if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { |
457 | cred->cr_expire = jiffies; | 459 | cred->cr_expire = jiffies; |
458 | list_add_tail(&cred->cr_lru, &cred_unused); | 460 | list_add_tail(&cred->cr_lru, &cred_unused); |
459 | number_cred_unused++; | 461 | number_cred_unused++; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index f9ce3c9949d5..82a9b6286dd3 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -249,6 +249,7 @@ struct sock_xprt { | |||
249 | void (*old_data_ready)(struct sock *, int); | 249 | void (*old_data_ready)(struct sock *, int); |
250 | void (*old_state_change)(struct sock *); | 250 | void (*old_state_change)(struct sock *); |
251 | void (*old_write_space)(struct sock *); | 251 | void (*old_write_space)(struct sock *); |
252 | void (*old_error_report)(struct sock *); | ||
252 | }; | 253 | }; |
253 | 254 | ||
254 | /* | 255 | /* |
@@ -696,8 +697,9 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
696 | case -EAGAIN: | 697 | case -EAGAIN: |
697 | xs_nospace(task); | 698 | xs_nospace(task); |
698 | break; | 699 | break; |
699 | case -ECONNREFUSED: | ||
700 | case -ECONNRESET: | 700 | case -ECONNRESET: |
701 | xs_tcp_shutdown(xprt); | ||
702 | case -ECONNREFUSED: | ||
701 | case -ENOTCONN: | 703 | case -ENOTCONN: |
702 | case -EPIPE: | 704 | case -EPIPE: |
703 | status = -ENOTCONN; | 705 | status = -ENOTCONN; |
@@ -740,6 +742,22 @@ out_release: | |||
740 | xprt_release_xprt(xprt, task); | 742 | xprt_release_xprt(xprt, task); |
741 | } | 743 | } |
742 | 744 | ||
745 | static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) | ||
746 | { | ||
747 | transport->old_data_ready = sk->sk_data_ready; | ||
748 | transport->old_state_change = sk->sk_state_change; | ||
749 | transport->old_write_space = sk->sk_write_space; | ||
750 | transport->old_error_report = sk->sk_error_report; | ||
751 | } | ||
752 | |||
753 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) | ||
754 | { | ||
755 | sk->sk_data_ready = transport->old_data_ready; | ||
756 | sk->sk_state_change = transport->old_state_change; | ||
757 | sk->sk_write_space = transport->old_write_space; | ||
758 | sk->sk_error_report = transport->old_error_report; | ||
759 | } | ||
760 | |||
743 | /** | 761 | /** |
744 | * xs_close - close a socket | 762 | * xs_close - close a socket |
745 | * @xprt: transport | 763 | * @xprt: transport |
@@ -763,9 +781,8 @@ static void xs_close(struct rpc_xprt *xprt) | |||
763 | transport->sock = NULL; | 781 | transport->sock = NULL; |
764 | 782 | ||
765 | sk->sk_user_data = NULL; | 783 | sk->sk_user_data = NULL; |
766 | sk->sk_data_ready = transport->old_data_ready; | 784 | |
767 | sk->sk_state_change = transport->old_state_change; | 785 | xs_restore_old_callbacks(transport, sk); |
768 | sk->sk_write_space = transport->old_write_space; | ||
769 | write_unlock_bh(&sk->sk_callback_lock); | 786 | write_unlock_bh(&sk->sk_callback_lock); |
770 | 787 | ||
771 | sk->sk_no_check = 0; | 788 | sk->sk_no_check = 0; |
@@ -1178,6 +1195,28 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1178 | } | 1195 | } |
1179 | 1196 | ||
1180 | /** | 1197 | /** |
1198 | * xs_tcp_error_report - callback mainly for catching RST events | ||
1199 | * @sk: socket | ||
1200 | */ | ||
1201 | static void xs_tcp_error_report(struct sock *sk) | ||
1202 | { | ||
1203 | struct rpc_xprt *xprt; | ||
1204 | |||
1205 | read_lock(&sk->sk_callback_lock); | ||
1206 | if (sk->sk_err != ECONNRESET || sk->sk_state != TCP_ESTABLISHED) | ||
1207 | goto out; | ||
1208 | if (!(xprt = xprt_from_sock(sk))) | ||
1209 | goto out; | ||
1210 | dprintk("RPC: %s client %p...\n" | ||
1211 | "RPC: error %d\n", | ||
1212 | __func__, xprt, sk->sk_err); | ||
1213 | |||
1214 | xprt_force_disconnect(xprt); | ||
1215 | out: | ||
1216 | read_unlock(&sk->sk_callback_lock); | ||
1217 | } | ||
1218 | |||
1219 | /** | ||
1181 | * xs_udp_write_space - callback invoked when socket buffer space | 1220 | * xs_udp_write_space - callback invoked when socket buffer space |
1182 | * becomes available | 1221 | * becomes available |
1183 | * @sk: socket whose state has changed | 1222 | * @sk: socket whose state has changed |
@@ -1452,10 +1491,9 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1452 | 1491 | ||
1453 | write_lock_bh(&sk->sk_callback_lock); | 1492 | write_lock_bh(&sk->sk_callback_lock); |
1454 | 1493 | ||
1494 | xs_save_old_callbacks(transport, sk); | ||
1495 | |||
1455 | sk->sk_user_data = xprt; | 1496 | sk->sk_user_data = xprt; |
1456 | transport->old_data_ready = sk->sk_data_ready; | ||
1457 | transport->old_state_change = sk->sk_state_change; | ||
1458 | transport->old_write_space = sk->sk_write_space; | ||
1459 | sk->sk_data_ready = xs_udp_data_ready; | 1497 | sk->sk_data_ready = xs_udp_data_ready; |
1460 | sk->sk_write_space = xs_udp_write_space; | 1498 | sk->sk_write_space = xs_udp_write_space; |
1461 | sk->sk_no_check = UDP_CSUM_NORCV; | 1499 | sk->sk_no_check = UDP_CSUM_NORCV; |
@@ -1587,13 +1625,13 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1587 | 1625 | ||
1588 | write_lock_bh(&sk->sk_callback_lock); | 1626 | write_lock_bh(&sk->sk_callback_lock); |
1589 | 1627 | ||
1628 | xs_save_old_callbacks(transport, sk); | ||
1629 | |||
1590 | sk->sk_user_data = xprt; | 1630 | sk->sk_user_data = xprt; |
1591 | transport->old_data_ready = sk->sk_data_ready; | ||
1592 | transport->old_state_change = sk->sk_state_change; | ||
1593 | transport->old_write_space = sk->sk_write_space; | ||
1594 | sk->sk_data_ready = xs_tcp_data_ready; | 1631 | sk->sk_data_ready = xs_tcp_data_ready; |
1595 | sk->sk_state_change = xs_tcp_state_change; | 1632 | sk->sk_state_change = xs_tcp_state_change; |
1596 | sk->sk_write_space = xs_tcp_write_space; | 1633 | sk->sk_write_space = xs_tcp_write_space; |
1634 | sk->sk_error_report = xs_tcp_error_report; | ||
1597 | sk->sk_allocation = GFP_ATOMIC; | 1635 | sk->sk_allocation = GFP_ATOMIC; |
1598 | 1636 | ||
1599 | /* socket options */ | 1637 | /* socket options */ |