diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_cong.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 5c8caf4a1244..34ae3f13483a 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -77,18 +77,19 @@ void tcp_init_congestion_control(struct sock *sk) | |||
77 | struct inet_connection_sock *icsk = inet_csk(sk); | 77 | struct inet_connection_sock *icsk = inet_csk(sk); |
78 | struct tcp_congestion_ops *ca; | 78 | struct tcp_congestion_ops *ca; |
79 | 79 | ||
80 | if (icsk->icsk_ca_ops != &tcp_init_congestion_ops) | 80 | /* if no choice made yet assign the current value set as default */ |
81 | return; | 81 | if (icsk->icsk_ca_ops == &tcp_init_congestion_ops) { |
82 | rcu_read_lock(); | ||
83 | list_for_each_entry_rcu(ca, &tcp_cong_list, list) { | ||
84 | if (try_module_get(ca->owner)) { | ||
85 | icsk->icsk_ca_ops = ca; | ||
86 | break; | ||
87 | } | ||
82 | 88 | ||
83 | rcu_read_lock(); | 89 | /* fallback to next available */ |
84 | list_for_each_entry_rcu(ca, &tcp_cong_list, list) { | ||
85 | if (try_module_get(ca->owner)) { | ||
86 | icsk->icsk_ca_ops = ca; | ||
87 | break; | ||
88 | } | 90 | } |
89 | 91 | rcu_read_unlock(); | |
90 | } | 92 | } |
91 | rcu_read_unlock(); | ||
92 | 93 | ||
93 | if (icsk->icsk_ca_ops->init) | 94 | if (icsk->icsk_ca_ops->init) |
94 | icsk->icsk_ca_ops->init(sk); | 95 | icsk->icsk_ca_ops->init(sk); |
@@ -236,6 +237,7 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
236 | 237 | ||
237 | rcu_read_lock(); | 238 | rcu_read_lock(); |
238 | ca = tcp_ca_find(name); | 239 | ca = tcp_ca_find(name); |
240 | |||
239 | /* no change asking for existing value */ | 241 | /* no change asking for existing value */ |
240 | if (ca == icsk->icsk_ca_ops) | 242 | if (ca == icsk->icsk_ca_ops) |
241 | goto out; | 243 | goto out; |
@@ -261,7 +263,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name) | |||
261 | else { | 263 | else { |
262 | tcp_cleanup_congestion_control(sk); | 264 | tcp_cleanup_congestion_control(sk); |
263 | icsk->icsk_ca_ops = ca; | 265 | icsk->icsk_ca_ops = ca; |
264 | if (icsk->icsk_ca_ops->init) | 266 | |
267 | if (sk->sk_state != TCP_CLOSE && icsk->icsk_ca_ops->init) | ||
265 | icsk->icsk_ca_ops->init(sk); | 268 | icsk->icsk_ca_ops->init(sk); |
266 | } | 269 | } |
267 | out: | 270 | out: |