diff options
author | Eric Dumazet <edumazet@google.com> | 2013-05-20 02:52:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-20 17:00:42 -0400 |
commit | 71cea17ed39fdf1c0634f530ddc6a2c2fc601c2b (patch) | |
tree | ec6ec3929a41948fb7fef76cceaebf2f1681f1d8 /net/ipv4/tcp_ipv4.c | |
parent | 168fc21a971e4bc821a7838ccc39b7bdaf316c11 (diff) |
tcp: md5: remove spinlock usage in fast path
TCP md5 code uses per cpu variables but protects access to them with
a shared spinlock, which is a contention point.
[ tcp_md5sig_pool_lock is locked twice per incoming packet ]
Makes things much simpler, by allocating crypto structures once, first
time a socket needs md5 keys, and not deallocating them as they are
really small.
Next step would be to allow crypto allocations being done in a NUMA
aware way.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
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 | 10 |
1 files changed, 1 insertions, 9 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 719652305a29..d20ede0c9593 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1026,7 +1026,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, | |||
1026 | key = sock_kmalloc(sk, sizeof(*key), gfp); | 1026 | key = sock_kmalloc(sk, sizeof(*key), gfp); |
1027 | if (!key) | 1027 | if (!key) |
1028 | return -ENOMEM; | 1028 | return -ENOMEM; |
1029 | if (hlist_empty(&md5sig->head) && !tcp_alloc_md5sig_pool(sk)) { | 1029 | if (!tcp_alloc_md5sig_pool()) { |
1030 | sock_kfree_s(sk, key, sizeof(*key)); | 1030 | sock_kfree_s(sk, key, sizeof(*key)); |
1031 | return -ENOMEM; | 1031 | return -ENOMEM; |
1032 | } | 1032 | } |
@@ -1044,9 +1044,7 @@ EXPORT_SYMBOL(tcp_md5_do_add); | |||
1044 | 1044 | ||
1045 | int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) | 1045 | int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) |
1046 | { | 1046 | { |
1047 | struct tcp_sock *tp = tcp_sk(sk); | ||
1048 | struct tcp_md5sig_key *key; | 1047 | struct tcp_md5sig_key *key; |
1049 | struct tcp_md5sig_info *md5sig; | ||
1050 | 1048 | ||
1051 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); | 1049 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); |
1052 | if (!key) | 1050 | if (!key) |
@@ -1054,10 +1052,6 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) | |||
1054 | hlist_del_rcu(&key->node); | 1052 | hlist_del_rcu(&key->node); |
1055 | atomic_sub(sizeof(*key), &sk->sk_omem_alloc); | 1053 | atomic_sub(sizeof(*key), &sk->sk_omem_alloc); |
1056 | kfree_rcu(key, rcu); | 1054 | kfree_rcu(key, rcu); |
1057 | md5sig = rcu_dereference_protected(tp->md5sig_info, | ||
1058 | sock_owned_by_user(sk)); | ||
1059 | if (hlist_empty(&md5sig->head)) | ||
1060 | tcp_free_md5sig_pool(); | ||
1061 | return 0; | 1055 | return 0; |
1062 | } | 1056 | } |
1063 | EXPORT_SYMBOL(tcp_md5_do_del); | 1057 | EXPORT_SYMBOL(tcp_md5_do_del); |
@@ -1071,8 +1065,6 @@ static void tcp_clear_md5_list(struct sock *sk) | |||
1071 | 1065 | ||
1072 | md5sig = rcu_dereference_protected(tp->md5sig_info, 1); | 1066 | md5sig = rcu_dereference_protected(tp->md5sig_info, 1); |
1073 | 1067 | ||
1074 | if (!hlist_empty(&md5sig->head)) | ||
1075 | tcp_free_md5sig_pool(); | ||
1076 | hlist_for_each_entry_safe(key, n, &md5sig->head, node) { | 1068 | hlist_for_each_entry_safe(key, n, &md5sig->head, node) { |
1077 | hlist_del_rcu(&key->node); | 1069 | hlist_del_rcu(&key->node); |
1078 | atomic_sub(sizeof(*key), &sk->sk_omem_alloc); | 1070 | atomic_sub(sizeof(*key), &sk->sk_omem_alloc); |