Commit a5600024 authored by Kirill Tkhai's avatar Kirill Tkhai Committed by David S. Miller

net: Fix hlist corruptions in inet_evict_bucket()

inet_evict_bucket() iterates global list, and
several tasks may call it in parallel. All of
them hash the same fq->list_evictor to different
lists, which leads to list corruption.

This patch makes fq be hashed to expired list
only if this has not been made yet by another
task. Since inet_frag_alloc() allocates fq
using kmem_cache_zalloc(), we may rely on
list_evictor is initially unhashed.

The problem seems to exist before async
pernet_operations, as there was possible to have
exit method to be executed in parallel with
inet_frags::frags_work, so I add two Fixes tags.
This also may go to stable.

Fixes: d1fe1944 "inet: frag: don't re-use chainlist for evictor"
Fixes: f84c6821 "net: Convert pernet_subsys, registered from inet_init()"
Signed-off-by: default avatarKirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e06513d7
...@@ -119,6 +119,9 @@ static void inet_frag_secret_rebuild(struct inet_frags *f) ...@@ -119,6 +119,9 @@ static void inet_frag_secret_rebuild(struct inet_frags *f)
static bool inet_fragq_should_evict(const struct inet_frag_queue *q) static bool inet_fragq_should_evict(const struct inet_frag_queue *q)
{ {
if (!hlist_unhashed(&q->list_evictor))
return false;
return q->net->low_thresh == 0 || return q->net->low_thresh == 0 ||
frag_mem_limit(q->net) >= q->net->low_thresh; frag_mem_limit(q->net) >= q->net->low_thresh;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment