mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Tung Quang Nguyen <tung.quang.nguyen@est.tech>
To: "bsdhenrymartin@gmail.com" <bsdhenrymartin@gmail.com>,
	"netdev-bot+sashiko@kernel.org" <netdev-bot+sashiko@kernel.org>
Cc: "jmaloy@redhat.com" <jmaloy@redhat.com>,
	"davem@davemloft.net" <davem@davemloft.net>,
	"kuba@kernel.org" <kuba@kernel.org>,
	"edumazet@kernel.org" <edumazet@kernel.org>,
	"pabeni@redhat.com" <pabeni@redhat.com>,
	"horms@kernel.org" <horms@kernel.org>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	"tipc-discussion@lists.sourceforge.net"
	<tipc-discussion@lists.sourceforge.net>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"stable@vger.kernel.org" <stable@vger.kernel.org>
Subject: RE: [PATCH net v2] tipc: fix broadcast sender hang on last acker departure
Date: Wed, 14 Oct 2026 13:40:15 +0000	[thread overview]
Message-ID: <AM7P189MB11376F05ED2439EDBC2AEE65C69D2@AM7P189MB1137.EURP189.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <179190865919.434549.2450236888091417368@kernel.org>

>Subject: Re: [PATCH net v2] tipc: fix broadcast sender hang on last acker
>departure
>
>Thank you for your contribution! Sashiko AI review found 2 potential
>issue(s) to consider.
>
>Critical: 0 · High: 0 · Medium: 1 · Low: 1
>
>If you believe none of the issues are legitimate, please reply to each issue of
>Medium severity or higher and explain why the AI is wrong.
>If any of them are legitimate and you plan to respin, please let patchwork
>know by including "pw-bot: cr" as a separate line at the end of your reply (one
>such reply per series is enough).
>
>- [Medium] The patch adds m->bc_pending so that only members counted for
>  the current replicast can reduce grp->bc_ackers, but it checks the…
>- [Low] The commit message gives the wrong reason why blocked writers
>  stay asleep, and it overstates when the blocking sendmsg() hang…
>
>--
>
>tipc: fix broadcast sender hang on last acker departure
>
>This patch restores *grp->open when the last member that owes a replicast ack
>is deleted. It also calls sk->sk_write_space() from tipc_sk_filter_rcv() when the
>group becomes writable again. A new per-member bc_pending flag limits the
>bc_ackers decrement in the delete path to members that were counted for the
>current replicast.
>
>> TIPC group broadcast senders are blocked while a replicast still has
>> outstanding member acks: poll(EPOLLOUT) only fires when
>> tsk->group_is_open, and writers keep re-sleeping on every unrelated
>> data-ready wakeup because tipc_group_bc_cong() keeps seeing *grp->open
>> == false (the default sk_sndtimeo is MAX_SCHEDULE_TIMEOUT, so there is
>> no bounded send timeout either).
>
>[Severity: Low]
>Is this description of the mechanism accurate? tipc_group_bc_cong() only
>writes *grp->open and never reads it:
>
>net/tipc/group.c:tipc_group_bc_cong() {
>	if (grp->bc_ackers) {
>		*grp->open = false;
>		return true;
>	}
>	if (list_empty(&grp->small_win))
>		return false;
>	...
>}
>
>Its return value depends only on grp->bc_ackers and the head of
>grp->small_win.
>
>> When the last outstanding acker departs before acking,
>> tipc_group_delete_member() decrements grp->bc_ackers but never
>> restores *grp->open, and the blocked senders are never woken.
>
>The old delete path already brought bc_ackers to 0 when the last owing
>member left. That member has bc_acked == S-1 and bc_snd_nxt == S+1, so the
>less() test matches.
>
>tipc_wait_for_cond() waits with woken_wake_function, which ignores the poll
>key, and tipc_data_ready() wakes every sleeper on sk_wq.
>
>So with group member events enabled, the sk_data_ready() after the leave
>event is delivered already woke the writer in tipc_send_group_bcast().
>tipc_group_bc_cong() then returned false and sendmsg() went on, returning
>EHOSTUNREACH if the group was now empty.
>
>The poll(EPOLLOUT) hang does look real in every case, because tipc_poll() only
>sets EPOLLOUT when tsk->group_is_open is true.
>
>The blocking sendmsg() hang seems to happen only when nothing wakes the
>writer after the deletion. One example is group member events being disabled.
>In that case TIPC_GRP_MEMBER_EVT is freed with deliver = false and
>sk_data_ready() is never called.
>
>The code change itself looks correct. Since this is tagged for stable, could the
>changelog describe the actual wakeup path and say when the
>sendmsg() hang occurs?

Please rewrite the changelog.

>
>> diff --git a/net/tipc/group.c b/net/tipc/group.c index
>> 74f6d3dac0784..e9c77f12c9819 100644
>> --- a/net/tipc/group.c
>> +++ b/net/tipc/group.c
>
>[ ... ]
>
>> @@ -340,9 +341,12 @@ static void tipc_group_delete_member(struct
>tipc_group *grp,
>>  	rb_erase(&m->tree_node, &grp->members);
>>  	grp->member_cnt--;
>>
>> -	/* Check if we were waiting for replicast ack from this member */
>> -	if (grp->bc_ackers && less(m->bc_acked, grp->bc_snd_nxt - 1))
>> -		grp->bc_ackers--;
>> +	/* If this member owed an ack for the current replicast and it
>> +	 * was the last one, restore the open state so blocked broadcast
>> +	 * senders can proceed.
>> +	 */
>> +	if (grp->bc_ackers && m->bc_pending && !--grp->bc_ackers)
>> +		*grp->open = true;
>>
>>  	list_del_init(&m->list);
>>  	list_del_init(&m->small_win);
>> @@ -406,6 +410,8 @@ void tipc_group_update_bc_members(struct
>tipc_group *grp, int len, bool ack)
>>  			m->bc_acked = prev;
>>  			ackers++;
>>  		}
>> +		if (ack)
>> +			m->bc_pending = tipc_group_is_receiver(m);
>>  	}
>>
>>  	/* Mark number of acknowledges to expect, if any */ @@ -803,6
>+809,7
>> @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
>>  		if (acked != grp->bc_snd_nxt || m->bc_acked == acked)
>>  			return;
>>  		m->bc_acked = acked;
>> +		m->bc_pending = false;
>>  		if (--grp->bc_ackers)
>>  			return;
>>  		list_del_init(&m->small_win);
>
>[Severity: Medium]
>Should the GRP_ACK_MSG handler also check m->bc_pending before it
>decrements grp->bc_ackers?
>
>The new test in tipc_group_delete_member() assumes bc_ackers equals the
>number of members with bc_pending set.
>
>This handler still decrements bc_ackers for any member that passes the acked
>== grp->bc_snd_nxt and m->bc_acked != acked checks.
>
>Two kinds of member can pass those checks without having been counted:
>
>- Members that were MBR_JOINING or MBR_LEAVING when
>  tipc_group_update_bc_members() ran keep a stale bc_acked and get
>  bc_pending = false.
>- Members created after the replicast have bc_pending = false and
>  bc_acked = bc_snd_nxt - 1 from tipc_group_create_member().
>
>For both, a GRP_ACK_MSG carrying acked == bc_snd_nxt passes every check
>here.
>
>For example, with bc_ackers == 2 for counted members A and B:
>
>  ack from uncounted member X     bc_ackers 2 -> 1
>  B acks, or B is deleted         bc_ackers 1 -> 0, *grp->open = true
>
>A still has bc_pending == true and has never acked.
>
>Isn't this the case the commit message gives as the reason for adding
>bc_pending, where a non-counted member "could silently void a still-
>outstanding ack from a real acker"?
>
>A cluster peer can trigger this. It sends GRP_JOIN_MSG, which makes
>tipc_group_proto_rcv() create an MBR_JOINING member for any port. It then
>sends GRP_ACK_MSG with acked == bc_snd_nxt. I could not find a benign
>protocol sequence that ends up here.
>
>Would something like this close the gap?
>
>	if (acked != grp->bc_snd_nxt || !m->bc_pending)
>		return;
>

Looks right. Please use this approach (Perhaps, bc_acked field of tipc_member needs to be removed).

  reply	other threads:[~2026-10-14 13:40 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-09  5:56 [PATCH] tipc: fix broadcast sender hang and leak " Henry Martin
2026-10-09  6:00 ` netdev-bot+sinfo
2026-10-10  5:59 ` netdev-bot+sashiko
2026-10-12 11:45   ` Tung Quang Nguyen
2026-10-12 15:33     ` [PATCH net v2] tipc: fix broadcast sender hang " Henry Martin
2026-10-13 16:24       ` netdev-bot+sashiko
2026-10-14 13:40         ` Tung Quang Nguyen [this message]
2026-10-15  2:20           ` [PATCH net v3] " Henry Martin
2026-10-14 13:37       ` [PATCH net v2] " Tung Quang Nguyen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=AM7P189MB11376F05ED2439EDBC2AEE65C69D2@AM7P189MB1137.EURP189.PROD.OUTLOOK.COM \
    --to=tung.quang.nguyen@est.tech \
    --cc=bsdhenrymartin@gmail.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=jmaloy@redhat.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev-bot+sashiko@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=stable@vger.kernel.org \
    --cc=tipc-discussion@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®