diff options
Diffstat (limited to 'net/ipv4/tcp_cong.c')
-rw-r--r-- | net/ipv4/tcp_cong.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index fde983f6376b..421ea1b918da 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -189,8 +189,8 @@ void tcp_init_congestion_control(struct sock *sk) | |||
189 | INET_ECN_dontxmit(sk); | 189 | INET_ECN_dontxmit(sk); |
190 | } | 190 | } |
191 | 191 | ||
192 | void tcp_reinit_congestion_control(struct sock *sk, | 192 | static void tcp_reinit_congestion_control(struct sock *sk, |
193 | const struct tcp_congestion_ops *ca) | 193 | const struct tcp_congestion_ops *ca) |
194 | { | 194 | { |
195 | struct inet_connection_sock *icsk = inet_csk(sk); | 195 | struct inet_connection_sock *icsk = inet_csk(sk); |
196 | 196 | ||
@@ -338,7 +338,7 @@ out: | |||
338 | * tcp_reinit_congestion_control (if the current congestion control was | 338 | * tcp_reinit_congestion_control (if the current congestion control was |
339 | * already initialized. | 339 | * already initialized. |
340 | */ | 340 | */ |
341 | int tcp_set_congestion_control(struct sock *sk, const char *name, bool load) | 341 | int tcp_set_congestion_control(struct sock *sk, const char *name, bool load, bool reinit) |
342 | { | 342 | { |
343 | struct inet_connection_sock *icsk = inet_csk(sk); | 343 | struct inet_connection_sock *icsk = inet_csk(sk); |
344 | const struct tcp_congestion_ops *ca; | 344 | const struct tcp_congestion_ops *ca; |
@@ -360,9 +360,18 @@ int tcp_set_congestion_control(struct sock *sk, const char *name, bool load) | |||
360 | if (!ca) { | 360 | if (!ca) { |
361 | err = -ENOENT; | 361 | err = -ENOENT; |
362 | } else if (!load) { | 362 | } else if (!load) { |
363 | icsk->icsk_ca_ops = ca; | 363 | const struct tcp_congestion_ops *old_ca = icsk->icsk_ca_ops; |
364 | if (!try_module_get(ca->owner)) | 364 | |
365 | if (try_module_get(ca->owner)) { | ||
366 | if (reinit) { | ||
367 | tcp_reinit_congestion_control(sk, ca); | ||
368 | } else { | ||
369 | icsk->icsk_ca_ops = ca; | ||
370 | module_put(old_ca->owner); | ||
371 | } | ||
372 | } else { | ||
365 | err = -EBUSY; | 373 | err = -EBUSY; |
374 | } | ||
366 | } else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || | 375 | } else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || |
367 | ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))) { | 376 | ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))) { |
368 | err = -EPERM; | 377 | err = -EPERM; |