diff options
author | Wu Fengguang <fengguang.wu@intel.com> | 2009-09-03 02:45:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-03 02:45:45 -0400 |
commit | aa1330766c49199bdab4d4a9096d98b072df9044 (patch) | |
tree | 98787478dbef0faa7caee09c4996abcda723a608 /net/ipv4/tcp_ipv4.c | |
parent | 05c6a8d7a7d778f26d8eb821556988993b766092 (diff) |
tcp: replace hard coded GFP_KERNEL with sk_allocation
This fixed a lockdep warning which appeared when doing stress
memory tests over NFS:
inconsistent {RECLAIM_FS-ON-W} -> {IN-RECLAIM_FS-W} usage.
page reclaim => nfs_writepage => tcp_sendmsg => lock sk_lock
mount_root => nfs_root_data => tcp_close => lock sk_lock =>
tcp_send_fin => alloc_skb_fclone => page reclaim
David raised a concern that if the allocation fails in tcp_send_fin(), and it's
GFP_ATOMIC, we are going to yield() (which sleeps) and loop endlessly waiting
for the allocation to succeed.
But fact is, the original GFP_KERNEL also sleeps. GFP_ATOMIC+yield() looks
weird, but it is no worse the implicit sleep inside GFP_KERNEL. Both could
loop endlessly under memory pressure.
CC: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
CC: David S. Miller <davem@davemloft.net>
CC: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ce7d3b021ffc..0543561da999 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -886,7 +886,7 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
886 | } | 886 | } |
887 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 887 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
888 | } | 888 | } |
889 | if (tcp_alloc_md5sig_pool() == NULL) { | 889 | if (tcp_alloc_md5sig_pool(sk) == NULL) { |
890 | kfree(newkey); | 890 | kfree(newkey); |
891 | return -ENOMEM; | 891 | return -ENOMEM; |
892 | } | 892 | } |
@@ -1007,8 +1007,9 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1007 | 1007 | ||
1008 | if (!tcp_sk(sk)->md5sig_info) { | 1008 | if (!tcp_sk(sk)->md5sig_info) { |
1009 | struct tcp_sock *tp = tcp_sk(sk); | 1009 | struct tcp_sock *tp = tcp_sk(sk); |
1010 | struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL); | 1010 | struct tcp_md5sig_info *p; |
1011 | 1011 | ||
1012 | p = kzalloc(sizeof(*p), sk->sk_allocation); | ||
1012 | if (!p) | 1013 | if (!p) |
1013 | return -EINVAL; | 1014 | return -EINVAL; |
1014 | 1015 | ||
@@ -1016,7 +1017,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1016 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1017 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
1017 | } | 1018 | } |
1018 | 1019 | ||
1019 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); | 1020 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation); |
1020 | if (!newkey) | 1021 | if (!newkey) |
1021 | return -ENOMEM; | 1022 | return -ENOMEM; |
1022 | return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, | 1023 | return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, |