Skip to content

Commit

Permalink
net: fix sleeping for sk_wait_event()
Browse files Browse the repository at this point in the history
Similar to commit 14135f3 ("inet: fix sleeping inside inet_wait_for_connect()"),
sk_wait_event() needs to fix too, because release_sock() is blocking,
it changes the process state back to running after sleep, which breaks
the previous prepare_to_wait().

Switch to the new wait API.

Cc: Eric Dumazet <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Signed-off-by: Cong Wang <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
congwang authored and davem330 committed Nov 14, 2016
1 parent 7d38484 commit d9dc8b0
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 77 deletions.
9 changes: 4 additions & 5 deletions crypto/algif_aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,28 +132,27 @@ static void aead_wmem_wakeup(struct sock *sk)

static int aead_wait_for_data(struct sock *sk, unsigned flags)
{
DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct alg_sock *ask = alg_sk(sk);
struct aead_ctx *ctx = ask->private;
long timeout;
DEFINE_WAIT(wait);
int err = -ERESTARTSYS;

if (flags & MSG_DONTWAIT)
return -EAGAIN;

sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);

add_wait_queue(sk_sleep(sk), &wait);
for (;;) {
if (signal_pending(current))
break;
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
timeout = MAX_SCHEDULE_TIMEOUT;
if (sk_wait_event(sk, &timeout, !ctx->more)) {
if (sk_wait_event(sk, &timeout, !ctx->more, &wait)) {
err = 0;
break;
}
}
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);

sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);

Expand Down
18 changes: 9 additions & 9 deletions crypto/algif_skcipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,26 +199,26 @@ static void skcipher_free_sgl(struct sock *sk)

static int skcipher_wait_for_wmem(struct sock *sk, unsigned flags)
{
long timeout;
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);
int err = -ERESTARTSYS;
long timeout;

if (flags & MSG_DONTWAIT)
return -EAGAIN;

sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);

add_wait_queue(sk_sleep(sk), &wait);
for (;;) {
if (signal_pending(current))
break;
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
timeout = MAX_SCHEDULE_TIMEOUT;
if (sk_wait_event(sk, &timeout, skcipher_writable(sk))) {
if (sk_wait_event(sk, &timeout, skcipher_writable(sk), &wait)) {
err = 0;
break;
}
}
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);

return err;
}
Expand All @@ -242,10 +242,10 @@ static void skcipher_wmem_wakeup(struct sock *sk)

static int skcipher_wait_for_data(struct sock *sk, unsigned flags)
{
DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct alg_sock *ask = alg_sk(sk);
struct skcipher_ctx *ctx = ask->private;
long timeout;
DEFINE_WAIT(wait);
int err = -ERESTARTSYS;

if (flags & MSG_DONTWAIT) {
Expand All @@ -254,17 +254,17 @@ static int skcipher_wait_for_data(struct sock *sk, unsigned flags)

sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);

add_wait_queue(sk_sleep(sk), &wait);
for (;;) {
if (signal_pending(current))
break;
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
timeout = MAX_SCHEDULE_TIMEOUT;
if (sk_wait_event(sk, &timeout, ctx->used)) {
if (sk_wait_event(sk, &timeout, ctx->used, &wait)) {
err = 0;
break;
}
}
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);

sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);

Expand Down
8 changes: 5 additions & 3 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -915,14 +915,16 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
#endif
}

#define sk_wait_event(__sk, __timeo, __condition) \
#define sk_wait_event(__sk, __timeo, __condition, __wait) \
({ int __rc; \
release_sock(__sk); \
__rc = __condition; \
if (!__rc) { \
*(__timeo) = schedule_timeout(*(__timeo)); \
*(__timeo) = wait_woken(__wait, \
TASK_INTERRUPTIBLE, \
*(__timeo)); \
} \
sched_annotate_sleep(); \
sched_annotate_sleep(); \
lock_sock(__sk); \
__rc = __condition; \
__rc; \
Expand Down
8 changes: 4 additions & 4 deletions net/core/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -2078,14 +2078,14 @@ void __sk_flush_backlog(struct sock *sk)
*/
int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb)
{
DEFINE_WAIT_FUNC(wait, woken_wake_function);
int rc;
DEFINE_WAIT(wait);

prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
add_wait_queue(sk_sleep(sk), &wait);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb);
rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb, &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
return rc;
}
EXPORT_SYMBOL(sk_wait_data);
Expand Down
28 changes: 14 additions & 14 deletions net/core/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ void sk_stream_write_space(struct sock *sk)
*/
int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
{
DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct task_struct *tsk = current;
DEFINE_WAIT(wait);
int done;

do {
Expand All @@ -68,13 +68,13 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
if (signal_pending(tsk))
return sock_intr_errno(*timeo_p);

prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
add_wait_queue(sk_sleep(sk), &wait);
sk->sk_write_pending++;
done = sk_wait_event(sk, timeo_p,
!sk->sk_err &&
!((1 << sk->sk_state) &
~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)));
finish_wait(sk_sleep(sk), &wait);
~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
sk->sk_write_pending--;
} while (!done);
return 0;
Expand All @@ -94,16 +94,16 @@ static inline int sk_stream_closing(struct sock *sk)
void sk_stream_wait_close(struct sock *sk, long timeout)
{
if (timeout) {
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);

add_wait_queue(sk_sleep(sk), &wait);

do {
prepare_to_wait(sk_sleep(sk), &wait,
TASK_INTERRUPTIBLE);
if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk)))
if (sk_wait_event(sk, &timeout, !sk_stream_closing(sk), &wait))
break;
} while (!signal_pending(current) && timeout);

finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
}
}
EXPORT_SYMBOL(sk_stream_wait_close);
Expand All @@ -119,16 +119,16 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
long vm_wait = 0;
long current_timeo = *timeo_p;
bool noblock = (*timeo_p ? false : true);
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);

if (sk_stream_memory_free(sk))
current_timeo = vm_wait = (prandom_u32() % (HZ / 5)) + 2;

add_wait_queue(sk_sleep(sk), &wait);

while (1) {
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);

prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);

if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
goto do_error;
if (!*timeo_p) {
Expand All @@ -147,7 +147,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
sk_wait_event(sk, &current_timeo, sk->sk_err ||
(sk->sk_shutdown & SEND_SHUTDOWN) ||
(sk_stream_memory_free(sk) &&
!vm_wait));
!vm_wait), &wait);
sk->sk_write_pending--;

if (vm_wait) {
Expand All @@ -161,7 +161,7 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
*timeo_p = current_timeo;
}
out:
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
return err;

do_error:
Expand Down
16 changes: 8 additions & 8 deletions net/decnet/af_decnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1718,7 +1718,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
* See if there is data ready to read, sleep if there isn't
*/
for(;;) {
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);

if (sk->sk_err)
goto out;
Expand Down Expand Up @@ -1749,11 +1749,11 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
goto out;
}

prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
add_wait_queue(sk_sleep(sk), &wait);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target));
sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target), &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
}

skb_queue_walk_safe(queue, skb, n) {
Expand Down Expand Up @@ -1999,19 +1999,19 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
* size.
*/
if (dn_queue_too_long(scp, queue, flags)) {
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);

if (flags & MSG_DONTWAIT) {
err = -EWOULDBLOCK;
goto out;
}

prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
add_wait_queue(sk_sleep(sk), &wait);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
sk_wait_event(sk, &timeo,
!dn_queue_too_long(scp, queue, flags));
!dn_queue_too_long(scp, queue, flags), &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
continue;
}

Expand Down
24 changes: 12 additions & 12 deletions net/llc/af_llc.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,12 +532,12 @@ static int llc_ui_listen(struct socket *sock, int backlog)

static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
{
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);
int rc = 0;

add_wait_queue(sk_sleep(sk), &wait);
while (1) {
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE))
if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE, &wait))
break;
rc = -ERESTARTSYS;
if (signal_pending(current))
Expand All @@ -547,39 +547,39 @@ static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
break;
rc = 0;
}
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
return rc;
}

static bool llc_ui_wait_for_conn(struct sock *sk, long timeout)
{
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);

add_wait_queue(sk_sleep(sk), &wait);
while (1) {
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT))
if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT, &wait))
break;
if (signal_pending(current) || !timeout)
break;
}
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
return timeout;
}

static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
{
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);
struct llc_sock *llc = llc_sk(sk);
int rc;

add_wait_queue(sk_sleep(sk), &wait);
while (1) {
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
rc = 0;
if (sk_wait_event(sk, &timeout,
(sk->sk_shutdown & RCV_SHUTDOWN) ||
(!llc_data_accept_state(llc->state) &&
!llc->remote_busy_flag &&
!llc->p_flag)))
!llc->p_flag), &wait))
break;
rc = -ERESTARTSYS;
if (signal_pending(current))
Expand All @@ -588,7 +588,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
if (!timeout)
break;
}
finish_wait(sk_sleep(sk), &wait);
remove_wait_queue(sk_sleep(sk), &wait);
return rc;
}

Expand Down
9 changes: 4 additions & 5 deletions net/phonet/pep.c
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@ static int pep_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
/* Wait until flow control allows TX */
done = atomic_read(&pn->tx_credits);
while (!done) {
DEFINE_WAIT(wait);
DEFINE_WAIT_FUNC(wait, woken_wake_function);

if (!timeo) {
err = -EAGAIN;
Expand All @@ -1178,10 +1178,9 @@ static int pep_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
goto out;
}

prepare_to_wait(sk_sleep(sk), &wait,
TASK_INTERRUPTIBLE);
done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits));
finish_wait(sk_sleep(sk), &wait);
add_wait_queue(sk_sleep(sk), &wait);
done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits), &wait);
remove_wait_queue(sk_sleep(sk), &wait);

if (sk->sk_state != TCP_ESTABLISHED)
goto disabled;
Expand Down
Loading

0 comments on commit d9dc8b0

Please sign in to comment.