mac80211: return new mpath from mesh_path_add()
authorBob Copeland <me@bobcopeland.com>
Fri, 29 Mar 2013 13:38:39 +0000 (09:38 -0400)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 8 Apr 2013 07:16:59 +0000 (09:16 +0200)
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>
net/mac80211/cfg.c
net/mac80211/mesh.h
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_pathtbl.c

index 6e43feb49a7697d5d870d6e5a46f338d1f42503c..edca2a288abde7a60d20e7bb0a922ed605d1f5d6 100644 (file)
@@ -1540,7 +1540,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata;
        struct mesh_path *mpath;
        struct sta_info *sta;
-       int err;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -1551,17 +1550,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
                return -ENOENT;
        }
 
-       err = mesh_path_add(sdata, dst);
-       if (err) {
+       mpath = mesh_path_add(sdata, dst);
+       if (IS_ERR(mpath)) {
                rcu_read_unlock();
-               return err;
+               return PTR_ERR(mpath);
        }
 
-       mpath = mesh_path_lookup(sdata, dst);
-       if (!mpath) {
-               rcu_read_unlock();
-               return -ENXIO;
-       }
        mesh_path_fix_nexthop(mpath, sta);
 
        rcu_read_unlock();
index 6ffabbe99c4633989b2a45ab7f8bf18c376b75c2..da158774eebb69eac8abf0a23472f766532cf00a 100644 (file)
@@ -275,7 +275,8 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
                            struct ieee80211_mgmt *mgmt, size_t len);
-int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
+struct mesh_path *
+mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst);
 
 int mesh_path_add_gate(struct mesh_path *mpath);
 int mesh_path_send_to_gates(struct mesh_path *mpath);
index 94904337784c671e0a729ed4caf4e29bf1835e61..c82d5e6a24c03977ee40d7fbdf0e98ab6a210318 100644 (file)
@@ -445,9 +445,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
                                }
                        }
                } else {
-                       mesh_path_add(sdata, orig_addr);
-                       mpath = mesh_path_lookup(sdata, orig_addr);
-                       if (!mpath) {
+                       mpath = mesh_path_add(sdata, orig_addr);
+                       if (IS_ERR(mpath)) {
                                rcu_read_unlock();
                                return 0;
                        }
@@ -486,9 +485,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
                                        (last_hop_metric > mpath->metric)))
                                fresh_info = false;
                } else {
-                       mesh_path_add(sdata, ta);
-                       mpath = mesh_path_lookup(sdata, ta);
-                       if (!mpath) {
+                       mpath = mesh_path_add(sdata, ta);
+                       if (IS_ERR(mpath)) {
                                rcu_read_unlock();
                                return 0;
                        }
@@ -804,9 +802,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 
        mpath = mesh_path_lookup(sdata, orig_addr);
        if (!mpath) {
-               mesh_path_add(sdata, orig_addr);
-               mpath = mesh_path_lookup(sdata, orig_addr);
-               if (!mpath) {
+               mpath = mesh_path_add(sdata, orig_addr);
+               if (IS_ERR(mpath)) {
                        rcu_read_unlock();
                        sdata->u.mesh.mshstats.dropped_frames_no_route++;
                        return;
@@ -1098,11 +1095,10 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata,
        /* no nexthop found, start resolving */
        mpath = mesh_path_lookup(sdata, target_addr);
        if (!mpath) {
-               mesh_path_add(sdata, target_addr);
-               mpath = mesh_path_lookup(sdata, target_addr);
-               if (!mpath) {
+               mpath = mesh_path_add(sdata, target_addr);
+               if (IS_ERR(mpath)) {
                        mesh_path_discard_frame(sdata, skb);
-                       err = -ENOSPC;
+                       err = PTR_ERR(mpath);
                        goto endlookup;
                }
        }
index dc7c8df40c2c3093c0ec81c7af1fbeeac973ecd9..89aacfd2756d627287ce4d381e7038d0b0ebdd5e 100644 (file)
@@ -493,7 +493,8 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata)
  *
  * State: the initial state of the new path is set to 0
  */
-int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
+struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
+                               const u8 *dst)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct ieee80211_local *local = sdata->local;
@@ -502,18 +503,33 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
        struct mpath_node *node, *new_node;
        struct hlist_head *bucket;
        int grow = 0;
-       int err = 0;
+       int err;
        u32 hash_idx;
 
        if (ether_addr_equal(dst, sdata->vif.addr))
                /* never add ourselves as neighbours */
-               return -ENOTSUPP;
+               return ERR_PTR(-ENOTSUPP);
 
        if (is_multicast_ether_addr(dst))
-               return -ENOTSUPP;
+               return ERR_PTR(-ENOTSUPP);
 
        if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
-               return -ENOSPC;
+               return ERR_PTR(-ENOSPC);
+
+       read_lock_bh(&pathtbl_resize_lock);
+       tbl = resize_dereference_mesh_paths();
+
+       hash_idx = mesh_table_hash(dst, sdata, tbl);
+       bucket = &tbl->hash_buckets[hash_idx];
+
+       spin_lock(&tbl->hashwlock[hash_idx]);
+
+       hlist_for_each_entry(node, bucket, list) {
+               mpath = node->mpath;
+               if (mpath->sdata == sdata &&
+                   ether_addr_equal(dst, mpath->dst))
+                       goto found;
+       }
 
        err = -ENOMEM;
        new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
@@ -524,7 +540,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
        if (!new_node)
                goto err_node_alloc;
 
-       read_lock_bh(&pathtbl_resize_lock);
        memcpy(new_mpath->dst, dst, ETH_ALEN);
        eth_broadcast_addr(new_mpath->rann_snd_addr);
        new_mpath->is_root = false;
@@ -538,21 +553,6 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
        spin_lock_init(&new_mpath->state_lock);
        init_timer(&new_mpath->timer);
 
-       tbl = resize_dereference_mesh_paths();
-
-       hash_idx = mesh_table_hash(dst, sdata, tbl);
-       bucket = &tbl->hash_buckets[hash_idx];
-
-       spin_lock(&tbl->hashwlock[hash_idx]);
-
-       err = -EEXIST;
-       hlist_for_each_entry(node, bucket, list) {
-               mpath = node->mpath;
-               if (mpath->sdata == sdata &&
-                   ether_addr_equal(dst, mpath->dst))
-                       goto err_exists;
-       }
-
        hlist_add_head_rcu(&new_node->list, bucket);
        if (atomic_inc_return(&tbl->entries) >=
            tbl->mean_chain_len * (tbl->hash_mask + 1))
@@ -560,23 +560,23 @@ int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst)
 
        mesh_paths_generation++;
 
-       spin_unlock(&tbl->hashwlock[hash_idx]);
-       read_unlock_bh(&pathtbl_resize_lock);
        if (grow) {
                set_bit(MESH_WORK_GROW_MPATH_TABLE,  &ifmsh->wrkq_flags);
                ieee80211_queue_work(&local->hw, &sdata->work);
        }
-       return 0;
-
-err_exists:
+       mpath = new_mpath;
+found:
        spin_unlock(&tbl->hashwlock[hash_idx]);
        read_unlock_bh(&pathtbl_resize_lock);
-       kfree(new_node);
+       return mpath;
+
 err_node_alloc:
        kfree(new_mpath);
 err_path_alloc:
        atomic_dec(&sdata->u.mesh.mpaths);
-       return err;
+       spin_unlock(&tbl->hashwlock[hash_idx]);
+       read_unlock_bh(&pathtbl_resize_lock);
+       return ERR_PTR(err);
 }
 
 static void mesh_table_free_rcu(struct rcu_head *rcu)