diff options
author | Judy Hsiao <judyhsiao@chromium.org> | 2023-12-06 03:38:33 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-01-25 14:52:29 -0800 |
commit | 6511772fc0bcd1542a6c1b809b6a702c9a93c1fd (patch) | |
tree | 2727865f8a5ef660bc0d975c8e3d2a5fc2bf889d /net/core | |
parent | 2e1846b0c044ce8a5f36edd07a66881dc93f923e (diff) |
neighbour: Don't let neigh_forced_gc() disable preemption for long
[ Upstream commit e5dc5afff62f3e97e86c3643ec9fcad23de4f2d3 ]
We are seeing cases where neigh_cleanup_and_release() is called by
neigh_forced_gc() many times in a row with preemption turned off.
When running on a low powered CPU at a low CPU frequency, this has
been measured to keep preemption off for ~10 ms. That's not great on a
system with HZ=1000 which expects tasks to be able to schedule in
with ~1ms latency.
Suggested-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Judy Hsiao <judyhsiao@chromium.org>
Reviewed-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/neighbour.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 927c4db2703f..5829477efbba 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -225,9 +225,11 @@ static int neigh_forced_gc(struct neigh_table *tbl) { int max_clean = atomic_read(&tbl->gc_entries) - READ_ONCE(tbl->gc_thresh2); + u64 tmax = ktime_get_ns() + NSEC_PER_MSEC; unsigned long tref = jiffies - 5 * HZ; struct neighbour *n, *tmp; int shrunk = 0; + int loop = 0; NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs); @@ -250,11 +252,16 @@ static int neigh_forced_gc(struct neigh_table *tbl) shrunk++; if (shrunk >= max_clean) break; + if (++loop == 16) { + if (ktime_get_ns() > tmax) + goto unlock; + loop = 0; + } } } WRITE_ONCE(tbl->last_flush, jiffies); - +unlock: write_unlock_bh(&tbl->lock); return shrunk; |