From 68399ac37e571c2d695ea3b08aa82235874b5158 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Wed, 27 Mar 2013 05:55:25 +0000 Subject: net: frag, avoid several CPUs grabbing same frag queue during LRU evictor loop The LRU list is protected by its own lock, since commit 3ef0eb0db4 (net: frag, move LRU list maintenance outside of rwlock), and no-longer by a read_lock. This makes it possible, to remove the inet_frag_queue, which is about to be "evicted", from the LRU list head. This avoids the problem, of several CPUs grabbing the same frag queue. Note, cannot remove the inet_frag_lru_del() call in fq_unlink() called by inet_frag_kill(), because inet_frag_kill() is also used in other situations. Thus, we use list_del_init() to allow this double list_del to work. Signed-off-by: Jesper Dangaard Brouer Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_fragment.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/ipv4/inet_fragment.c') diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 2bff045bec60..8ba548a8efce 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -204,6 +204,9 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force) q = list_first_entry(&nf->lru_list, struct inet_frag_queue, lru_list); atomic_inc(&q->refcnt); + /* Remove q from list to avoid several CPUs grabbing it */ + list_del_init(&q->lru_list); + spin_unlock(&nf->lru_lock); spin_lock(&q->lock); -- cgit v1.2.3-59-g8ed1b