mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
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 365ad353c2
("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>
This commit is contained in:
parent
ad990dbe6d
commit
844cf763fb
@ -362,25 +362,25 @@ static int tipc_sk_sock_err(struct socket *sock, long *timeout)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define tipc_wait_for_cond(sock_, timeout_, condition_) \
|
||||
({ \
|
||||
int rc_ = 0; \
|
||||
int done_ = 0; \
|
||||
\
|
||||
while (!(condition_) && !done_) { \
|
||||
struct sock *sk_ = sock->sk; \
|
||||
DEFINE_WAIT_FUNC(wait_, woken_wake_function); \
|
||||
\
|
||||
rc_ = tipc_sk_sock_err(sock_, timeout_); \
|
||||
if (rc_) \
|
||||
break; \
|
||||
prepare_to_wait(sk_sleep(sk_), &wait_, \
|
||||
TASK_INTERRUPTIBLE); \
|
||||
done_ = sk_wait_event(sk_, timeout_, \
|
||||
(condition_), &wait_); \
|
||||
remove_wait_queue(sk_sleep(sk_), &wait_); \
|
||||
} \
|
||||
rc_; \
|
||||
#define tipc_wait_for_cond(sock_, timeo_, condition_) \
|
||||
({ \
|
||||
struct sock *sk_; \
|
||||
int rc_; \
|
||||
\
|
||||
while ((rc_ = !(condition_))) { \
|
||||
DEFINE_WAIT_FUNC(wait_, woken_wake_function); \
|
||||
sk_ = (sock_)->sk; \
|
||||
rc_ = tipc_sk_sock_err((sock_), timeo_); \
|
||||
if (rc_) \
|
||||
break; \
|
||||
prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE); \
|
||||
release_sock(sk_); \
|
||||
*(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \
|
||||
sched_annotate_sleep(); \
|
||||
lock_sock(sk_); \
|
||||
remove_wait_queue(sk_sleep(sk_), &wait_); \
|
||||
} \
|
||||
rc_; \
|
||||
})
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user