diff options
| -rw-r--r-- | fs/nfs/inode.c | 11 | ||||
| -rw-r--r-- | net/sunrpc/auth.c | 18 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 58 |
3 files changed, 61 insertions, 26 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index dc52793ff8f8..d22eb383e1cf 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -908,21 +908,16 @@ static int nfs_size_need_update(const struct inode *inode, const struct nfs_fatt | |||
| 908 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | 908 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); |
| 909 | } | 909 | } |
| 910 | 910 | ||
| 911 | static unsigned long nfs_attr_generation_counter; | 911 | static atomic_long_t nfs_attr_generation_counter; |
| 912 | 912 | ||
| 913 | static unsigned long nfs_read_attr_generation_counter(void) | 913 | static unsigned long nfs_read_attr_generation_counter(void) |
| 914 | { | 914 | { |
| 915 | smp_rmb(); | 915 | return atomic_long_read(&nfs_attr_generation_counter); |
| 916 | return nfs_attr_generation_counter; | ||
| 917 | } | 916 | } |
| 918 | 917 | ||
| 919 | unsigned long nfs_inc_attr_generation_counter(void) | 918 | unsigned long nfs_inc_attr_generation_counter(void) |
| 920 | { | 919 | { |
| 921 | unsigned long ret; | 920 | return atomic_long_inc_return(&nfs_attr_generation_counter); |
| 922 | smp_rmb(); | ||
| 923 | ret = ++nfs_attr_generation_counter; | ||
| 924 | smp_wmb(); | ||
| 925 | return ret; | ||
| 926 | } | 921 | } |
| 927 | 922 | ||
| 928 | void nfs_fattr_init(struct nfs_fattr *fattr) | 923 | void nfs_fattr_init(struct nfs_fattr *fattr) |
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 9a288d5eea64..0a50361e3d83 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 | /* |
| @@ -698,8 +699,9 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
| 698 | case -EAGAIN: | 699 | case -EAGAIN: |
| 699 | xs_nospace(task); | 700 | xs_nospace(task); |
| 700 | break; | 701 | break; |
| 701 | case -ECONNREFUSED: | ||
| 702 | case -ECONNRESET: | 702 | case -ECONNRESET: |
| 703 | xs_tcp_shutdown(xprt); | ||
| 704 | case -ECONNREFUSED: | ||
| 703 | case -ENOTCONN: | 705 | case -ENOTCONN: |
| 704 | case -EPIPE: | 706 | case -EPIPE: |
| 705 | status = -ENOTCONN; | 707 | status = -ENOTCONN; |
| @@ -742,6 +744,22 @@ out_release: | |||
| 742 | xprt_release_xprt(xprt, task); | 744 | xprt_release_xprt(xprt, task); |
| 743 | } | 745 | } |
| 744 | 746 | ||
| 747 | static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) | ||
| 748 | { | ||
| 749 | transport->old_data_ready = sk->sk_data_ready; | ||
| 750 | transport->old_state_change = sk->sk_state_change; | ||
| 751 | transport->old_write_space = sk->sk_write_space; | ||
| 752 | transport->old_error_report = sk->sk_error_report; | ||
| 753 | } | ||
| 754 | |||
| 755 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) | ||
| 756 | { | ||
| 757 | sk->sk_data_ready = transport->old_data_ready; | ||
| 758 | sk->sk_state_change = transport->old_state_change; | ||
| 759 | sk->sk_write_space = transport->old_write_space; | ||
| 760 | sk->sk_error_report = transport->old_error_report; | ||
| 761 | } | ||
| 762 | |||
| 745 | /** | 763 | /** |
| 746 | * xs_close - close a socket | 764 | * xs_close - close a socket |
| 747 | * @xprt: transport | 765 | * @xprt: transport |
| @@ -765,9 +783,8 @@ static void xs_close(struct rpc_xprt *xprt) | |||
| 765 | transport->sock = NULL; | 783 | transport->sock = NULL; |
| 766 | 784 | ||
| 767 | sk->sk_user_data = NULL; | 785 | sk->sk_user_data = NULL; |
| 768 | sk->sk_data_ready = transport->old_data_ready; | 786 | |
| 769 | sk->sk_state_change = transport->old_state_change; | 787 | xs_restore_old_callbacks(transport, sk); |
| 770 | sk->sk_write_space = transport->old_write_space; | ||
| 771 | write_unlock_bh(&sk->sk_callback_lock); | 788 | write_unlock_bh(&sk->sk_callback_lock); |
| 772 | 789 | ||
| 773 | sk->sk_no_check = 0; | 790 | sk->sk_no_check = 0; |
| @@ -1180,6 +1197,28 @@ static void xs_tcp_state_change(struct sock *sk) | |||
| 1180 | } | 1197 | } |
| 1181 | 1198 | ||
| 1182 | /** | 1199 | /** |
| 1200 | * xs_tcp_error_report - callback mainly for catching RST events | ||
| 1201 | * @sk: socket | ||
| 1202 | */ | ||
| 1203 | static void xs_tcp_error_report(struct sock *sk) | ||
| 1204 | { | ||
| 1205 | struct rpc_xprt *xprt; | ||
| 1206 | |||
| 1207 | read_lock(&sk->sk_callback_lock); | ||
| 1208 | if (sk->sk_err != ECONNRESET || sk->sk_state != TCP_ESTABLISHED) | ||
| 1209 | goto out; | ||
| 1210 | if (!(xprt = xprt_from_sock(sk))) | ||
| 1211 | goto out; | ||
| 1212 | dprintk("RPC: %s client %p...\n" | ||
| 1213 | "RPC: error %d\n", | ||
| 1214 | __func__, xprt, sk->sk_err); | ||
| 1215 | |||
| 1216 | xprt_force_disconnect(xprt); | ||
| 1217 | out: | ||
| 1218 | read_unlock(&sk->sk_callback_lock); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | /** | ||
| 1183 | * xs_udp_write_space - callback invoked when socket buffer space | 1222 | * xs_udp_write_space - callback invoked when socket buffer space |
| 1184 | * becomes available | 1223 | * becomes available |
| 1185 | * @sk: socket whose state has changed | 1224 | * @sk: socket whose state has changed |
| @@ -1454,10 +1493,9 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
| 1454 | 1493 | ||
| 1455 | write_lock_bh(&sk->sk_callback_lock); | 1494 | write_lock_bh(&sk->sk_callback_lock); |
| 1456 | 1495 | ||
| 1496 | xs_save_old_callbacks(transport, sk); | ||
| 1497 | |||
| 1457 | sk->sk_user_data = xprt; | 1498 | sk->sk_user_data = xprt; |
| 1458 | transport->old_data_ready = sk->sk_data_ready; | ||
| 1459 | transport->old_state_change = sk->sk_state_change; | ||
| 1460 | transport->old_write_space = sk->sk_write_space; | ||
| 1461 | sk->sk_data_ready = xs_udp_data_ready; | 1499 | sk->sk_data_ready = xs_udp_data_ready; |
| 1462 | sk->sk_write_space = xs_udp_write_space; | 1500 | sk->sk_write_space = xs_udp_write_space; |
| 1463 | sk->sk_no_check = UDP_CSUM_NORCV; | 1501 | sk->sk_no_check = UDP_CSUM_NORCV; |
| @@ -1589,13 +1627,13 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
| 1589 | 1627 | ||
| 1590 | write_lock_bh(&sk->sk_callback_lock); | 1628 | write_lock_bh(&sk->sk_callback_lock); |
| 1591 | 1629 | ||
| 1630 | xs_save_old_callbacks(transport, sk); | ||
| 1631 | |||
| 1592 | sk->sk_user_data = xprt; | 1632 | sk->sk_user_data = xprt; |
| 1593 | transport->old_data_ready = sk->sk_data_ready; | ||
| 1594 | transport->old_state_change = sk->sk_state_change; | ||
| 1595 | transport->old_write_space = sk->sk_write_space; | ||
| 1596 | sk->sk_data_ready = xs_tcp_data_ready; | 1633 | sk->sk_data_ready = xs_tcp_data_ready; |
| 1597 | sk->sk_state_change = xs_tcp_state_change; | 1634 | sk->sk_state_change = xs_tcp_state_change; |
| 1598 | sk->sk_write_space = xs_tcp_write_space; | 1635 | sk->sk_write_space = xs_tcp_write_space; |
| 1636 | sk->sk_error_report = xs_tcp_error_report; | ||
| 1599 | sk->sk_allocation = GFP_ATOMIC; | 1637 | sk->sk_allocation = GFP_ATOMIC; |
| 1600 | 1638 | ||
| 1601 | /* socket options */ | 1639 | /* socket options */ |
