On Wed, 30 Aug 2006 03:21:26 +0400
Alexey Kuznetsov <[EMAIL PROTECTED]> wrote:
> Hello!
>
> > This should not be any more racy than the existing code.
>
> Existing code is not racy.
Race 1: w/o RCU
Cpu 0: is in neigh_lookup
gets read_lock()
finds entry
++refcount to 2
updates it
Cpu 1: is in forced_gc()
waits at write_lock()
releases read_lock()
drops ref count to 1.
sees ref count is 1
deletes it
Race 1: w RCU
Cpu 0: is in __neigh_lookup
updates it
Cpu 1: is in forced_gc()
leaves refcount=1
sees ref count is 1
deletes it
>
> Critical place is interpretation of refcnt==1. Current code assumes,
> that when refcnt=1 and entry is in hash table, nobody can take this
> entry (table is locked). So, it can be unlinked from the table.
>
> See? __neigh_lookup()/__neigh_lookup_errno() _MUST_ return alive
> and hashed entry. And will stay hashed until the reference is held.
> Or until neigh entry is forced for destruction by device going down,
> in this case referring dst entries will die as well.
Why must it be hashed, it could always get zapped just after the update.
> If dst cache grabs an entry, which is purged from table because for some
> time it had refcnt==1, you got a valid dst entry referring to dead
> neighbour entry.
Hmm.. Since this is a slow path, grabbing the write_lock on the neighbour
entry would block the gc from zapping it.
in __neigh_lookup()
neigh_hold();
write_lock(&n->lock);
if (n->dead) {
write_unlock()
neigh_release()
goto rescan;
}
write_unlock()
--
Stephen Hemminger <[EMAIL PROTECTED]>
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html