Andrey reported a kernel warning for the blocking ops in between prepare_to_wait() and schedule(), that is alloc_tx().
Of course, the logic itself is suspicious, other sendmsg() could handle skb allocation failure very well, not sure why ATM has to wait for a successful one here. But probably it is too late to change since the errno and behavior is visible to user-space. So just leave the logic as it is. Reported-by: Andrey Konovalov <andreyk...@google.com> Tested-by: Andrey Konovalov <andreyk...@google.com> Signed-off-by: Cong Wang <xiyou.wangc...@gmail.com> --- net/atm/common.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/atm/common.c b/net/atm/common.c index 7ec3bbc..b672231 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -572,8 +572,8 @@ int vcc_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) { + DEFINE_WAIT_FUNC(wait, woken_wake_function); struct sock *sk = sock->sk; - DEFINE_WAIT(wait); struct atm_vcc *vcc; struct sk_buff *skb; int eff, error; @@ -605,14 +605,14 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) } eff = (size+3) & ~3; /* align to word boundary */ - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + add_wait_queue(sk_sleep(sk), &wait); error = 0; while (!(skb = alloc_tx(vcc, eff))) { if (m->msg_flags & MSG_DONTWAIT) { error = -EAGAIN; break; } - schedule(); + wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); if (signal_pending(current)) { error = -ERESTARTSYS; break; @@ -624,9 +624,8 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) send_sig(SIGPIPE, current, 0); break; } - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); } - finish_wait(sk_sleep(sk), &wait); + remove_wait_queue(sk_sleep(sk), &wait); if (error) goto out; skb->dev = NULL; /* for paths shared with net_device interfaces */ -- 2.5.5