From: Taehee Yoo <ap420073@gmail.com>
To: Eric Dumazet <edumazet@google.com>
Cc: David Miller <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>,
David Ahern <dsahern@kernel.org>, netdev <netdev@vger.kernel.org>
Subject: Re: [PATCH net] net: mld: do not use system_wq in the mld
Date: Fri, 22 Jul 2022 02:53:09 +0900 [thread overview]
Message-ID: <ea287ba8-89d6-8175-0ebb-3269328a79b4@gmail.com> (raw)
In-Reply-To: <CANn89iJjc+jcyWZS1L+EfSkZYRaeVSmUHAkLKAFDRN4bCOcVyg@mail.gmail.com>
Hi Eric,
Thank you so much for your review!
On 7/21/22 23:04, Eric Dumazet wrote:
> On Thu, Jul 21, 2022 at 2:03 PM Taehee Yoo <ap420073@gmail.com> wrote:
>>
>> mld works are supposed to be executed in mld_wq.
>> But mld_{query | report}_work() calls schedule_delayed_work().
>> schedule_delayed_work() internally uses system_wq.
>> So, this would cause the reference count leak.
>
> I do not think the changelog is accurate.
> At least I do not understand it yet.
>
> We can not unload the ipv6 module, so destroy_workqueue(mld_wq) is
never used.
>
>
>
>>
>> splat looks like:
>> unregister_netdevice: waiting for br1 to become free. Usage count = 2
>> leaked reference.
>> ipv6_add_dev+0x3a5/0x1070
>> addrconf_notify+0x4f3/0x1760
>> notifier_call_chain+0x9e/0x180
>> register_netdevice+0xd10/0x11e0
>> br_dev_newlink+0x27/0x100 [bridge]
>> __rtnl_newlink+0xd85/0x14e0
>> rtnl_newlink+0x5f/0x90
>> rtnetlink_rcv_msg+0x335/0x9a0
>> netlink_rcv_skb+0x121/0x350
>> netlink_unicast+0x439/0x710
>> netlink_sendmsg+0x75f/0xc00
>> ____sys_sendmsg+0x694/0x860
>> ___sys_sendmsg+0xe9/0x160
>> __sys_sendmsg+0xbe/0x150
>> do_syscall_64+0x3b/0x90
>> entry_SYSCALL_64_after_hwframe+0x63/0xcd
>>
>> Fixes: f185de28d9ae ("mld: add new workqueues for process mld events")
>> Signed-off-by: Taehee Yoo <ap420073@gmail.com>
>> ---
>> net/ipv6/mcast.c | 14 ++++++++------
>> 1 file changed, 8 insertions(+), 6 deletions(-)
>>
>> diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
>> index 7f695c39d9a8..87c699d57b36 100644
>> --- a/net/ipv6/mcast.c
>> +++ b/net/ipv6/mcast.c
>> @@ -1522,7 +1522,6 @@ static void mld_query_work(struct work_struct
*work)
>>
>> if (++cnt >= MLD_MAX_QUEUE) {
>> rework = true;
>> - schedule_delayed_work(&idev->mc_query_work, 0);
>> break;
>> }
>> }
>> @@ -1533,8 +1532,10 @@ static void mld_query_work(struct work_struct
*work)
>> __mld_query_work(skb);
>> mutex_unlock(&idev->mc_lock);
>>
>> - if (!rework)
>> - in6_dev_put(idev);
>> + if (rework && queue_delayed_work(mld_wq,
&idev->mc_query_work, 0))
>
> It seems the 'real issue' was that
> schedule_delayed_work(&idev->mc_query_work, 0) could be a NOP
> because the work queue was already scheduled ?
>
I think your assumption is right.
I tested the below scenario, which occurs the real issue.
THREAD0 THREAD1
mld_report_work()
spin_lock_bh()
if (!mod_delayed_work()) <-- queued
in6_dev_hold();
spin_unlock_bh()
spin_lock_bh()
schedule_delayed_work() <-- return false, already queued by THREAD1
spin_unlock_bh()
return;
//no in6_dev_put() regardless return value of schedule_delayed_work().
In order to check, I added printk like below.
if (++cnt >= MLD_MAX_QUEUE) {
rework = true;
if (!schedule_delayed_work(&idev->mc_report_work, 0))
printk("[TEST]%s %u \n", __func__, __LINE__);
break;
If the TEST log message is printed, work is already queued by other logic.
So, it indicates a reference count is leaked.
The result is that I can see log messages only when the reference count
leak occurs.
So, although I tested it only for 1 hour, I'm sure that this bug comes
from missing check a return value of schedule_delayed_work().
As you said, this changelog is not correct.
system_wq and mld_wq are not related to this issue.
I would like to send a v2 patch after some more tests.
The v2 patch will change the commit message.
>
>
>> + return;
>> +
>> + in6_dev_put(idev);
>> }
>>
>> /* called with rcu_read_lock() */
>> @@ -1624,7 +1625,6 @@ static void mld_report_work(struct work_struct
*work)
>>
>> if (++cnt >= MLD_MAX_QUEUE) {
>> rework = true;
>> - schedule_delayed_work(&idev->mc_report_work, 0);
>> break;
>> }
>> }
>> @@ -1635,8 +1635,10 @@ static void mld_report_work(struct
work_struct *work)
>> __mld_report_work(skb);
>> mutex_unlock(&idev->mc_lock);
>>
>> - if (!rework)
>> - in6_dev_put(idev);
>> + if (rework && queue_delayed_work(mld_wq,
&idev->mc_report_work, 0))
>> + return;
>> +
>> + in6_dev_put(idev);
>> }
>>
>> static bool is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf,
int type,
>> --
>> 2.17.1
>>
Thanks a lot!
Taehee Yoo
next prev parent reply other threads:[~2022-07-21 17:53 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-21 12:03 [PATCH net] net: mld: do not use system_wq in the mld Taehee Yoo
2022-07-21 14:04 ` Eric Dumazet
2022-07-21 17:53 ` Taehee Yoo [this message]
2022-07-21 18:34 ` Eric Dumazet
2022-07-21 19:01 ` Taehee Yoo
2022-07-22 2:35 ` Hangbin Liu
2022-07-22 4:23 ` Hangbin Liu
2022-07-22 4:50 ` Taehee Yoo
2022-07-22 6:16 ` Hangbin Liu
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=ea287ba8-89d6-8175-0ebb-3269328a79b4@gmail.com \
--to=ap420073@gmail.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=yoshfuji@linux-ipv6.org \
/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;
as well as URLs for NNTP newsgroup(s).