diff options
| author | stephen hemminger <shemminger@vyatta.com> | 2011-04-04 10:03:29 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-04-04 20:22:26 -0400 |
| commit | 664de48bb6c4e167fcdf92a4bddf880030fbfbb3 (patch) | |
| tree | 3da0ad964f1ad79f567ed04a5e5b32c201687787 | |
| parent | 7cd8861ab0d907430bbea0af93bc41aee0437efc (diff) | |
bridge: split rcu and no-rcu cases of fdb lookup
In some cases, look up of forward database entry is done with RCU;
and for others no RCU is needed because of locking. Split the two
cases into two differnt loops (and take off inline).
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/bridge/br_fdb.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index b39135285f83..a839a5d9d2c7 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
| @@ -305,8 +305,21 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, | |||
| 305 | return num; | 305 | return num; |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, | 308 | static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, |
| 309 | const unsigned char *addr) | 309 | const unsigned char *addr) |
| 310 | { | ||
| 311 | struct hlist_node *h; | ||
| 312 | struct net_bridge_fdb_entry *fdb; | ||
| 313 | |||
| 314 | hlist_for_each_entry(fdb, h, head, hlist) { | ||
| 315 | if (!compare_ether_addr(fdb->addr.addr, addr)) | ||
| 316 | return fdb; | ||
| 317 | } | ||
| 318 | return NULL; | ||
| 319 | } | ||
| 320 | |||
| 321 | static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head, | ||
| 322 | const unsigned char *addr) | ||
| 310 | { | 323 | { |
| 311 | struct hlist_node *h; | 324 | struct hlist_node *h; |
| 312 | struct net_bridge_fdb_entry *fdb; | 325 | struct net_bridge_fdb_entry *fdb; |
| @@ -393,7 +406,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
| 393 | source->state == BR_STATE_FORWARDING)) | 406 | source->state == BR_STATE_FORWARDING)) |
| 394 | return; | 407 | return; |
| 395 | 408 | ||
| 396 | fdb = fdb_find(head, addr); | 409 | fdb = fdb_find_rcu(head, addr); |
| 397 | if (likely(fdb)) { | 410 | if (likely(fdb)) { |
| 398 | /* attempt to update an entry for a local interface */ | 411 | /* attempt to update an entry for a local interface */ |
| 399 | if (unlikely(fdb->is_local)) { | 412 | if (unlikely(fdb->is_local)) { |
