diff options
author | Johannes Berg <johannes.berg@intel.com> | 2023-12-08 12:52:15 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-12-11 13:57:16 +0300 |
commit | 9a64d4c93eee6b2efb7a02ec98d9480946424509 (patch) | |
tree | 38bfe2d18efa4cb8ee1a7f34d0a5c89bd3ac3fae /net/core/link_watch.c | |
parent | 18c5c0a845b3fd834e6a3f5d7f2cbf336e23e918 (diff) | |
download | linux-9a64d4c93eee6b2efb7a02ec98d9480946424509.tar.xz |
Revert "net: rtnetlink: remove local list in __linkwatch_run_queue()"
This reverts commit b8dbbbc535a9 ("net: rtnetlink: remove local list
in __linkwatch_run_queue()"). It's evidently broken when there's a
non-urgent work that gets added back, and then the loop can never
finish.
While reverting, add a note about that.
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Fixes: b8dbbbc535a9 ("net: rtnetlink: remove local list in __linkwatch_run_queue()")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/link_watch.c')
-rw-r--r-- | net/core/link_watch.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 7be5b3ab32bd..429571c258da 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c @@ -192,6 +192,11 @@ static void __linkwatch_run_queue(int urgent_only) #define MAX_DO_DEV_PER_LOOP 100 int do_dev = MAX_DO_DEV_PER_LOOP; + /* Use a local list here since we add non-urgent + * events back to the global one when called with + * urgent_only=1. + */ + LIST_HEAD(wrk); /* Give urgent case more budget */ if (urgent_only) @@ -213,11 +218,12 @@ static void __linkwatch_run_queue(int urgent_only) clear_bit(LW_URGENT, &linkwatch_flags); spin_lock_irq(&lweventlist_lock); - while (!list_empty(&lweventlist) && do_dev > 0) { + list_splice_init(&lweventlist, &wrk); + + while (!list_empty(&wrk) && do_dev > 0) { struct net_device *dev; - dev = list_first_entry(&lweventlist, struct net_device, - link_watch_list); + dev = list_first_entry(&wrk, struct net_device, link_watch_list); list_del_init(&dev->link_watch_list); if (!netif_device_present(dev) || @@ -235,6 +241,9 @@ static void __linkwatch_run_queue(int urgent_only) spin_lock_irq(&lweventlist_lock); } + /* Add the remaining work back to lweventlist */ + list_splice_init(&wrk, &lweventlist); + if (!list_empty(&lweventlist)) linkwatch_schedule_work(0); spin_unlock_irq(&lweventlist_lock); |