| From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> |
| Date: Fri, 8 Sep 2017 11:35:21 -0300 |
| Subject: [PATCH] sctp: fix missing wake ups in some situations |
| References: bnc#1060662 |
| Patch-mainline: v4.12.14 |
| Git-commit: 7906b00f5cd1cd484fced7fcda892176e3202c8a |
| |
| [ Upstream commit 7906b00f5cd1cd484fced7fcda892176e3202c8a ] |
| |
| Commit fb586f25300f ("sctp: delay calls to sk_data_ready() as much as |
| possible") minimized the number of wake ups that are triggered in case |
| the association receives a packet with multiple data chunks on it and/or |
| when io_events are enabled and then commit 0970f5b36659 ("sctp: signal |
| sk_data_ready earlier on data chunks reception") moved the wake up to as |
| soon as possible. It thus relies on the state machine running later to |
| clean the flag that the event was already generated. |
| |
| The issue is that there are 2 call paths that calls |
| sctp_ulpq_tail_event() outside of the state machine, causing the flag to |
| linger and possibly omitting a needed wake up in the sequence. |
| |
| One of the call paths is when enabling SCTP_SENDER_DRY_EVENTS via |
| setsockopt(SCTP_EVENTS), as noticed by Harald Welte. The other is when |
| partial reliability triggers removal of chunks from the send queue when |
| the application calls sendmsg(). |
| |
| This commit fixes it by not setting the flag in case the socket is not |
| owned by the user, as it won't be cleaned later. This works for |
| user-initiated calls and also for rx path processing. |
| |
| Fixes: fb586f25300f ("sctp: delay calls to sk_data_ready() as much as possible") |
| Reported-by: Harald Welte <laforge@gnumonks.org> |
| Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Jiri Slaby <jslaby@suse.cz> |
| |
| net/sctp/ulpqueue.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c |
| index aa3624d50278..8354479178b9 100644 |
| |
| |
| @@ -265,7 +265,8 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) |
| sctp_ulpq_clear_pd(ulpq); |
| |
| if (queue == &sk->sk_receive_queue && !sp->data_ready_signalled) { |
| - sp->data_ready_signalled = 1; |
| + if (!sock_owned_by_user(sk)) |
| + sp->data_ready_signalled = 1; |
| sk->sk_data_ready(sk); |
| } |
| return 1; |
| -- |
| 2.14.2 |
| |