Message ID | 1295635976.2609.23.camel@edumazet-laptop |
---|---|
State | Rejected, archived |
Delegated to: | David Miller |
Headers | show |
From: Eric Dumazet <eric.dumazet@gmail.com> Date: Fri, 21 Jan 2011 19:52:56 +0100 > Here is how I fixed this, thanks again Jamie ! > > [PATCH] net: neighbour: pneigh_lookup() doesnt need RTNL Eric, I don't think we can do this. Fundamentally, any time a user operation changes the configuration of the networking, we must hold the RTNL. Eliding the RTNL for lookups is fine, but for things that change state it is not. I therefore think you'll need to rework the arp_ioctl() portions of the commit that introduced this regression. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Le vendredi 21 janvier 2011 à 13:06 -0800, David Miller a écrit : > From: Eric Dumazet <eric.dumazet@gmail.com> > Date: Fri, 21 Jan 2011 19:52:56 +0100 > > > Here is how I fixed this, thanks again Jamie ! > > > > [PATCH] net: neighbour: pneigh_lookup() doesnt need RTNL > > Eric, I don't think we can do this. > > Fundamentally, any time a user operation changes the configuration > of the networking, we must hold the RTNL. > > Eliding the RTNL for lookups is fine, but for things that change > state it is not. > > I therefore think you'll need to rework the arp_ioctl() portions > of the commit that introduced this regression. > Hmm, I'll think about it, no problem. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 799f06e..6b96b2c 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -578,17 +578,18 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, int key_len = tbl->key_len; u32 hash_val = pneigh_hash(pkey, key_len); - read_lock_bh(&tbl->lock); + if (creat) + write_lock_bh(&tbl->lock); + else + read_lock_bh(&tbl->lock); + n = __pneigh_lookup_1(tbl->phash_buckets[hash_val], net, pkey, key_len, dev); - read_unlock_bh(&tbl->lock); if (n || !creat) goto out; - ASSERT_RTNL(); - - n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); + n = kmalloc(sizeof(*n) + key_len, GFP_ATOMIC); if (!n) goto out; @@ -607,11 +608,13 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, goto out; } - write_lock_bh(&tbl->lock); n->next = tbl->phash_buckets[hash_val]; tbl->phash_buckets[hash_val] = n; - write_unlock_bh(&tbl->lock); out: + if (creat) + write_unlock_bh(&tbl->lock); + else + read_unlock_bh(&tbl->lock); return n; } EXPORT_SYMBOL(pneigh_lookup);