Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: return new mpath from mesh_path_add()

Most times that mesh_path_add() is called, it is followed by
a lookup to get the just-added mpath. We can instead just
return the new mpath in the case that we allocated one (or the
existing one if already there), so do that. Also, reorder the
code in mesh_path_add a bit so that we don't need to allocate
in the pre-existing case.

Signed-off-by: Bob Copeland <bob@cozybit.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Bob Copeland and committed by
Johannes Berg
ae76eef0 0f71651f

+42 -51
+3 -9
net/mac80211/cfg.c
··· 1540 1540 struct ieee80211_sub_if_data *sdata; 1541 1541 struct mesh_path *mpath; 1542 1542 struct sta_info *sta; 1543 - int err; 1544 1543 1545 1544 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1546 1545 ··· 1550 1551 return -ENOENT; 1551 1552 } 1552 1553 1553 - err = mesh_path_add(sdata, dst); 1554 - if (err) { 1554 + mpath = mesh_path_add(sdata, dst); 1555 + if (IS_ERR(mpath)) { 1555 1556 rcu_read_unlock(); 1556 - return err; 1557 + return PTR_ERR(mpath); 1557 1558 } 1558 1559 1559 - mpath = mesh_path_lookup(sdata, dst); 1560 - if (!mpath) { 1561 - rcu_read_unlock(); 1562 - return -ENXIO; 1563 - } 1564 1560 mesh_path_fix_nexthop(mpath, sta); 1565 1561 1566 1562 rcu_read_unlock();
+2 -1
net/mac80211/mesh.h
··· 275 275 void mesh_path_expire(struct ieee80211_sub_if_data *sdata); 276 276 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, 277 277 struct ieee80211_mgmt *mgmt, size_t len); 278 - int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); 278 + struct mesh_path * 279 + mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); 279 280 280 281 int mesh_path_add_gate(struct mesh_path *mpath); 281 282 int mesh_path_send_to_gates(struct mesh_path *mpath);
+9 -13
net/mac80211/mesh_hwmp.c
··· 445 445 } 446 446 } 447 447 } else { 448 - mesh_path_add(sdata, orig_addr); 449 - mpath = mesh_path_lookup(sdata, orig_addr); 450 - if (!mpath) { 448 + mpath = mesh_path_add(sdata, orig_addr); 449 + if (IS_ERR(mpath)) { 451 450 rcu_read_unlock(); 452 451 return 0; 453 452 } ··· 485 486 (last_hop_metric > mpath->metric))) 486 487 fresh_info = false; 487 488 } else { 488 - mesh_path_add(sdata, ta); 489 - mpath = mesh_path_lookup(sdata, ta); 490 - if (!mpath) { 489 + mpath = mesh_path_add(sdata, ta); 490 + if (IS_ERR(mpath)) { 491 491 rcu_read_unlock(); 492 492 return 0; 493 493 } ··· 802 804 803 805 mpath = mesh_path_lookup(sdata, orig_addr); 804 806 if (!mpath) { 805 - mesh_path_add(sdata, orig_addr); 806 - mpath = mesh_path_lookup(sdata, orig_addr); 807 - if (!mpath) { 807 + mpath = mesh_path_add(sdata, orig_addr); 808 + if (IS_ERR(mpath)) { 808 809 rcu_read_unlock(); 809 810 sdata->u.mesh.mshstats.dropped_frames_no_route++; 810 811 return; ··· 1095 1098 /* no nexthop found, start resolving */ 1096 1099 mpath = mesh_path_lookup(sdata, target_addr); 1097 1100 if (!mpath) { 1098 - mesh_path_add(sdata, target_addr); 1099 - mpath = mesh_path_lookup(sdata, target_addr); 1100 - if (!mpath) { 1101 + mpath = mesh_path_add(sdata, target_addr); 1102 + if (IS_ERR(mpath)) { 1101 1103 mesh_path_discard_frame(sdata, skb); 1102 - err = -ENOSPC; 1104 + err = PTR_ERR(mpath); 1103 1105 goto endlookup; 1104 1106 } 1105 1107 }
+28 -28
net/mac80211/mesh_pathtbl.c
··· 493 493 * 494 494 * State: the initial state of the new path is set to 0 495 495 */ 496 - int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) 496 + struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata, 497 + const u8 *dst) 497 498 { 498 499 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 499 500 struct ieee80211_local *local = sdata->local; ··· 503 502 struct mpath_node *node, *new_node; 504 503 struct hlist_head *bucket; 505 504 int grow = 0; 506 - int err = 0; 505 + int err; 507 506 u32 hash_idx; 508 507 509 508 if (ether_addr_equal(dst, sdata->vif.addr)) 510 509 /* never add ourselves as neighbours */ 511 - return -ENOTSUPP; 510 + return ERR_PTR(-ENOTSUPP); 512 511 513 512 if (is_multicast_ether_addr(dst)) 514 - return -ENOTSUPP; 513 + return ERR_PTR(-ENOTSUPP); 515 514 516 515 if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) 517 - return -ENOSPC; 516 + return ERR_PTR(-ENOSPC); 517 + 518 + read_lock_bh(&pathtbl_resize_lock); 519 + tbl = resize_dereference_mesh_paths(); 520 + 521 + hash_idx = mesh_table_hash(dst, sdata, tbl); 522 + bucket = &tbl->hash_buckets[hash_idx]; 523 + 524 + spin_lock(&tbl->hashwlock[hash_idx]); 525 + 526 + hlist_for_each_entry(node, bucket, list) { 527 + mpath = node->mpath; 528 + if (mpath->sdata == sdata && 529 + ether_addr_equal(dst, mpath->dst)) 530 + goto found; 531 + } 518 532 519 533 err = -ENOMEM; 520 534 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC); ··· 540 524 if (!new_node) 541 525 goto err_node_alloc; 542 526 543 - read_lock_bh(&pathtbl_resize_lock); 544 527 memcpy(new_mpath->dst, dst, ETH_ALEN); 545 528 eth_broadcast_addr(new_mpath->rann_snd_addr); 546 529 new_mpath->is_root = false; ··· 553 538 spin_lock_init(&new_mpath->state_lock); 554 539 init_timer(&new_mpath->timer); 555 540 556 - tbl = resize_dereference_mesh_paths(); 557 - 558 - hash_idx = mesh_table_hash(dst, sdata, tbl); 559 - bucket = &tbl->hash_buckets[hash_idx]; 560 - 561 - spin_lock(&tbl->hashwlock[hash_idx]); 562 - 563 - err = -EEXIST; 564 - hlist_for_each_entry(node, bucket, list) { 565 - mpath = node->mpath; 566 - if (mpath->sdata == sdata && 567 - ether_addr_equal(dst, mpath->dst)) 568 - goto err_exists; 569 - } 570 - 571 541 hlist_add_head_rcu(&new_node->list, bucket); 572 542 if (atomic_inc_return(&tbl->entries) >= 573 543 tbl->mean_chain_len * (tbl->hash_mask + 1)) ··· 560 560 561 561 mesh_paths_generation++; 562 562 563 - spin_unlock(&tbl->hashwlock[hash_idx]); 564 - read_unlock_bh(&pathtbl_resize_lock); 565 563 if (grow) { 566 564 set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); 567 565 ieee80211_queue_work(&local->hw, &sdata->work); 568 566 } 569 - return 0; 570 - 571 - err_exists: 567 + mpath = new_mpath; 568 + found: 572 569 spin_unlock(&tbl->hashwlock[hash_idx]); 573 570 read_unlock_bh(&pathtbl_resize_lock); 574 - kfree(new_node); 571 + return mpath; 572 + 575 573 err_node_alloc: 576 574 kfree(new_mpath); 577 575 err_path_alloc: 578 576 atomic_dec(&sdata->u.mesh.mpaths); 579 - return err; 577 + spin_unlock(&tbl->hashwlock[hash_idx]); 578 + read_unlock_bh(&pathtbl_resize_lock); 579 + return ERR_PTR(err); 580 580 } 581 581 582 582 static void mesh_table_free_rcu(struct rcu_head *rcu)