aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2017-05-11 14:28:15 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-11 22:19:30 -0400
commit844cf763fba654436d3a4279b6a672c196cf1901 (patch)
tree60dc21eb9e82310b9267805b12f88fa07ae9f925 /net/tipc
parentad990dbe6d3ac3af1f5f4484b1126b9fc601e98a (diff)
tipc: make macro tipc_wait_for_cond() smp safe
The macro tipc_wait_for_cond() is embedding the macro sk_wait_event() to fulfil its task. The latter, in turn, is evaluating the stated condition outside the socket lock context. This is problematic if the condition is accessing non-trivial data structures which may be altered by incoming interrupts, as is the case with the cong_links() linked list, used by socket to keep track of the current set of congested links. We sometimes see crashes when this list is accessed by a condition function at the same time as a SOCK_WAKEUP interrupt is removing an element from the list. We fix this by expanding selected parts of sk_wait_event() into the outer macro, while ensuring that all evaluations of a given condition are performed under socket lock protection. Fixes: commit 365ad353c256 ("tipc: reduce risk of user starvation during link congestion") Reviewed-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/socket.c38
1 files changed, 19 insertions, 19 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 0d4f2f455a7c..1b92b72e812f 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -362,25 +362,25 @@ static int tipc_sk_sock_err(struct socket *sock, long *timeout)
362 return 0; 362 return 0;
363} 363}
364 364
365#define tipc_wait_for_cond(sock_, timeout_, condition_) \ 365#define tipc_wait_for_cond(sock_, timeo_, condition_) \
366({ \ 366({ \
367 int rc_ = 0; \ 367 struct sock *sk_; \
368 int done_ = 0; \ 368 int rc_; \
369 \ 369 \
370 while (!(condition_) && !done_) { \ 370 while ((rc_ = !(condition_))) { \
371 struct sock *sk_ = sock->sk; \ 371 DEFINE_WAIT_FUNC(wait_, woken_wake_function); \
372 DEFINE_WAIT_FUNC(wait_, woken_wake_function); \ 372 sk_ = (sock_)->sk; \
373 \ 373 rc_ = tipc_sk_sock_err((sock_), timeo_); \
374 rc_ = tipc_sk_sock_err(sock_, timeout_); \ 374 if (rc_) \
375 if (rc_) \ 375 break; \
376 break; \ 376 prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE); \
377 prepare_to_wait(sk_sleep(sk_), &wait_, \ 377 release_sock(sk_); \
378 TASK_INTERRUPTIBLE); \ 378 *(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \
379 done_ = sk_wait_event(sk_, timeout_, \ 379 sched_annotate_sleep(); \
380 (condition_), &wait_); \ 380 lock_sock(sk_); \
381 remove_wait_queue(sk_sleep(sk_), &wait_); \ 381 remove_wait_queue(sk_sleep(sk_), &wait_); \
382 } \ 382 } \
383 rc_; \ 383 rc_; \
384}) 384})
385 385
386/** 386/**