On Sat, Apr 11, 2020 at 08:28:13PM +0200, Pavel Machek wrote:
Hi!
The following case cause the bug: for the trouble SKB, it was in outq->transmitted list
Ok... but this is one hell of "interesting" code.
--- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -165,29 +165,44 @@ static void sctp_clear_owner_w(struct sc skb_orphan(chunk->skb); } +#define traverse_and_process() \ +do { \
- msg = chunk->msg; \
- if (msg == prev_msg) \
continue; \
- list_for_each_entry(c, &msg->chunks, frag_list) { \
if ((clear && asoc->base.sk == c->skb->sk) || \
(!clear && asoc->base.sk != c->skb->sk)) \
cb(c); \
- } \
- prev_msg = msg; \
+} while (0)
Should this be function?
Do you see how it does "continue"? But the do {} while(0) wrapper eats the continue. "break" would be more clear here, but they are really equivalent due to way this macro is used.
It is just very, very confusing.
Agree. The 'continue' itself slipped in on a refactoring and I didn't notice the confusing aspect of it. Initially, the code was written without the macro, and the continue refererred to the outter list_for_each_entry().
Marcelo