[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 28 Oct 2009 21:57:38 -0700 (PDT)
From: David Miller <davem@...emloft.net>
To: eric.dumazet@...il.com
Cc: schen@...sta.com, netdev@...r.kernel.org
Subject: Re: [PATCH] Multicast packet reassembly can fail
From: Eric Dumazet <eric.dumazet@...il.com>
Date: Wed, 28 Oct 2009 11:18:24 +0100
> Check line 219 of net/ipv4/inet_fragment.c
>
> #ifdef CONFIG_SMP
> /* With SMP race we have to recheck hash table, because
> * such entry could be created on other cpu, while we
> * promoted read lock to write lock.
> */
> hlist_for_each_entry(qp, n, &f->hash[hash], list) {
> if (qp->net == nf && f->match(qp, arg)) {
> atomic_inc(&qp->refcnt);
> write_unlock(&f->lock);
> qp_in->last_in |= INET_FRAG_COMPLETE; <<< HERE >>>
> inet_frag_put(qp_in, f);
> return qp;
> }
> }
> #endif
>
> I really wonder why we set INET_FRAG_COMPLETE here
What has happened here is that another cpu created an identical
frag entry before we took the write lock.
So we're letting that other cpu's entry stand, and will release
our local one and not use it at all.
Setting INET_FRAG_COMPLETE does two things:
1) It makes sure input frag processing skips this entry if such
code paths happen to see it for some reason.
2) INET_FRAG_COMPLETE must be set when inet_frag_destroy() gets
called by inet_frag_put() when it drops the refcount to zero.
There is an assertion on INET_FRAG_COMPLETE in inet_frag_destroy.
Hope that clears things up.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists