From patchwork Mon Feb 29 01:03:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bob Copeland X-Patchwork-Id: 8448251 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 696EAC0553 for ; Mon, 29 Feb 2016 01:04:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 45F2A20272 for ; Mon, 29 Feb 2016 01:04:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 279B02027D for ; Mon, 29 Feb 2016 01:04:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752738AbcB2BEP (ORCPT ); Sun, 28 Feb 2016 20:04:15 -0500 Received: from mail-qg0-f66.google.com ([209.85.192.66]:35911 "EHLO mail-qg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752265AbcB2BEJ (ORCPT ); Sun, 28 Feb 2016 20:04:09 -0500 Received: by mail-qg0-f66.google.com with SMTP id 14so9664194qgg.3 for ; Sun, 28 Feb 2016 17:04:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bobcopeland-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7XIIHbN8BnmEySQzZ/D1WT/b/lvHYoAXn+LKyLzoD1U=; b=Q2eqVeVCYgK07lZdVrt1lW7QmV4wwgUZn1/rUV6oI9+jZOrkU6nLGNO+mrB7d5vb4m m4sZCujgJjMzBIvBVwOR2XJUXdW67G09B8Oo/qm6Dv5OFRcBUADOsgHA4UYyn+sMRQol VvJtuHzNL718OfNVKsrHUbVZ91swQVCN2rPi/akBRX2hQ8aBDZf5hoeCJKi64J7oTzFZ DfoM+Xk12Bu2UY8igP+7azSzyZO7ztFXg7DbyZ6OlPl49IOVTgo8gNJklZfjXFsTiM8g +aXimqAOSuBBFk+bnPEpl+82w0CjV5WYpfgIrcuG0M6O6oVoYp56F5vdVhC88qQ+rS/g UcaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7XIIHbN8BnmEySQzZ/D1WT/b/lvHYoAXn+LKyLzoD1U=; b=QWPNYvQXsHdxB6wLg54WMdDQV57re+9TAazG3iFC8Jwy93kj/1iZwjNObodI4oqfK1 gjqjuML/0QXUBK6RG1Qe7Km7MLwd9oE/Q63JMf4a5dDUR/06a1f3EUnnd9WRIkLyTYbt Rgo41iN3aRZ9ZdUO6xwtKyaP22wyv2qyPc1zKvWraS9sEAvxjvn9+1Tp8fIEk88Um3UX EQEdHwZ9aUcP5F63Uw980ezN78lexMrP/A6ziRsCn30ce3ZFzPtAFtOOweqJRDSIVtqu s3qUK6/tB4q3MXAqEK5mfXC34/MfzL9aiVpdbEhu3uCCW4sU8+OWim8tni7LyS+9zWVm omvw== X-Gm-Message-State: AD7BkJLRR1ah6BHC+n079zxuc13MkAqQj8v+EV5attQA/FBGOP7FzPfUCbwMx5EOsOrG6w== X-Received: by 10.140.21.232 with SMTP id 95mr16077966qgl.12.1456707847745; Sun, 28 Feb 2016 17:04:07 -0800 (PST) Received: from hash ([2001:470:1d:6db:230:48ff:fe9d:9c89]) by smtp.gmail.com with ESMTPSA id i14sm10025167qkh.6.2016.02.28.17.04.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 28 Feb 2016 17:04:06 -0800 (PST) Received: from glass.lan ([192.168.1.51] helo=glass) by hash with esmtp (Exim 4.84) (envelope-from ) id 1aaCFj-0005qL-HY; Sun, 28 Feb 2016 20:03:59 -0500 Received: from bob by glass with local (Exim 4.86) (envelope-from ) id 1aaCFp-00054x-4B; Sun, 28 Feb 2016 20:04:05 -0500 From: Bob Copeland To: linux-wireless@vger.kernel.org Cc: Johannes Berg , Bob Copeland Subject: [PATCH 4/4] mac80211: mesh: embed known gates list in struct mesh_path Date: Sun, 28 Feb 2016 20:03:59 -0500 Message-Id: <1456707839-19469-4-git-send-email-me@bobcopeland.com> X-Mailer: git-send-email 2.6.1 In-Reply-To: <1456707839-19469-1-git-send-email-me@bobcopeland.com> References: <1456707839-19469-1-git-send-email-me@bobcopeland.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The mesh path table uses a struct mesh_node in its hlists in order to support a resizable hash table: the mesh_node provides an indirection to the actual mesh path so that two different bucket lists can point to the same path entry. However, for the known gates list, we don't need this indirection because there is ever only one list. So we can just embed the hlist_node in the mesh path itself, which simplifies things a bit and saves a linear search whenever we need to find an item in the list. Signed-off-by: Bob Copeland --- net/mac80211/mesh.h | 1 + net/mac80211/mesh_pathtbl.c | 100 +++++++++++++++++++------------------------- 2 files changed, 45 insertions(+), 56 deletions(-) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 601992b6cd8a..f3cc3917e048 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -105,6 +105,7 @@ enum mesh_deferred_task_flags { struct mesh_path { u8 dst[ETH_ALEN]; u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ + struct hlist_node gate_list; struct ieee80211_sub_if_data *sdata; struct sta_info __rcu *next_hop; struct timer_list timer; diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 4794240e8f94..e4daf4b94eaf 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -119,10 +119,18 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) { struct hlist_head *mesh_hash; struct hlist_node *p, *q; - struct mpath_node *gate; + struct mesh_path *gate; int i; mesh_hash = tbl->hash_buckets; + if (free_leafs) { + spin_lock_bh(&tbl->gates_lock); + hlist_for_each_entry_safe(gate, q, + tbl->known_gates, gate_list) + hlist_del(&gate->gate_list); + kfree(tbl->known_gates); + spin_unlock_bh(&tbl->gates_lock); + } for (i = 0; i <= tbl->hash_mask; i++) { spin_lock_bh(&tbl->hashwlock[i]); hlist_for_each_safe(p, q, &mesh_hash[i]) { @@ -131,16 +139,6 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) } spin_unlock_bh(&tbl->hashwlock[i]); } - if (free_leafs) { - spin_lock_bh(&tbl->gates_lock); - hlist_for_each_entry_safe(gate, q, - tbl->known_gates, list) { - hlist_del(&gate->list); - kfree(gate); - } - kfree(tbl->known_gates); - spin_unlock_bh(&tbl->gates_lock); - } __mesh_table_free(tbl); } @@ -431,30 +429,26 @@ mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) int mesh_path_add_gate(struct mesh_path *mpath) { struct mesh_table *tbl; - struct mpath_node *gate, *new_gate; int err; rcu_read_lock(); tbl = rcu_dereference(mpath->sdata->u.mesh.mesh_paths); - hlist_for_each_entry_rcu(gate, tbl->known_gates, list) - if (gate->mpath == mpath) { - err = -EEXIST; - goto err_rcu; - } - - new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC); - if (!new_gate) { - err = -ENOMEM; + spin_lock_bh(&mpath->state_lock); + if (mpath->is_gate) { + err = -EEXIST; + spin_unlock_bh(&mpath->state_lock); goto err_rcu; } - mpath->is_gate = true; mpath->sdata->u.mesh.num_gates++; - new_gate->mpath = mpath; - spin_lock_bh(&tbl->gates_lock); - hlist_add_head_rcu(&new_gate->list, tbl->known_gates); - spin_unlock_bh(&tbl->gates_lock); + + spin_lock(&tbl->gates_lock); + hlist_add_head_rcu(&mpath->gate_list, tbl->known_gates); + spin_unlock(&tbl->gates_lock); + + spin_unlock_bh(&mpath->state_lock); + mpath_dbg(mpath->sdata, "Mesh path: Recorded new gate: %pM. %d known gates\n", mpath->dst, mpath->sdata->u.mesh.num_gates); @@ -468,28 +462,22 @@ err_rcu: * mesh_gate_del - remove a mesh gate from the list of known gates * @tbl: table which holds our list of known gates * @mpath: gate mpath - * - * Locking: must be called inside rcu_read_lock() section */ static void mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) { - struct mpath_node *gate; - struct hlist_node *q; + lockdep_assert_held(&mpath->state_lock); + if (!mpath->is_gate) + return; - hlist_for_each_entry_safe(gate, q, tbl->known_gates, list) { - if (gate->mpath != mpath) - continue; - spin_lock_bh(&tbl->gates_lock); - hlist_del_rcu(&gate->list); - kfree_rcu(gate, rcu); - spin_unlock_bh(&tbl->gates_lock); - mpath->sdata->u.mesh.num_gates--; - mpath->is_gate = false; - mpath_dbg(mpath->sdata, - "Mesh path: Deleted gate: %pM. %d known gates\n", - mpath->dst, mpath->sdata->u.mesh.num_gates); - break; - } + mpath->is_gate = false; + spin_lock_bh(&tbl->gates_lock); + hlist_del_rcu(&mpath->gate_list); + mpath->sdata->u.mesh.num_gates--; + spin_unlock_bh(&tbl->gates_lock); + + mpath_dbg(mpath->sdata, + "Mesh path: Deleted gate: %pM. %d known gates\n", + mpath->dst, mpath->sdata->u.mesh.num_gates); } /** @@ -781,13 +769,13 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node) struct mesh_path *mpath = node->mpath; struct ieee80211_sub_if_data *sdata = node->mpath->sdata; - spin_lock(&mpath->state_lock); + spin_lock_bh(&mpath->state_lock); mpath->flags |= MESH_PATH_RESOLVING; if (mpath->is_gate) mesh_gate_del(tbl, mpath); hlist_del_rcu(&node->list); call_rcu(&node->rcu, mesh_path_node_reclaim); - spin_unlock(&mpath->state_lock); + spin_unlock_bh(&mpath->state_lock); atomic_dec(&sdata->u.mesh.mpaths); atomic_dec(&tbl->entries); } @@ -999,7 +987,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) struct ieee80211_sub_if_data *sdata = mpath->sdata; struct mesh_table *tbl; struct mesh_path *from_mpath = mpath; - struct mpath_node *gate = NULL; + struct mesh_path *gate = NULL; bool copy = false; struct hlist_head *known_gates; @@ -1011,22 +999,22 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) if (!known_gates) return -EHOSTUNREACH; - hlist_for_each_entry_rcu(gate, known_gates, list) { - if (gate->mpath->flags & MESH_PATH_ACTIVE) { - mpath_dbg(sdata, "Forwarding to %pM\n", gate->mpath->dst); - mesh_path_move_to_queue(gate->mpath, from_mpath, copy); - from_mpath = gate->mpath; + hlist_for_each_entry_rcu(gate, known_gates, gate_list) { + if (gate->flags & MESH_PATH_ACTIVE) { + mpath_dbg(sdata, "Forwarding to %pM\n", gate->dst); + mesh_path_move_to_queue(gate, from_mpath, copy); + from_mpath = gate; copy = true; } else { mpath_dbg(sdata, "Not forwarding to %pM (flags %#x)\n", - gate->mpath->dst, gate->mpath->flags); + gate->dst, gate->flags); } } - hlist_for_each_entry_rcu(gate, known_gates, list) { - mpath_dbg(sdata, "Sending to %pM\n", gate->mpath->dst); - mesh_path_tx_pending(gate->mpath); + hlist_for_each_entry_rcu(gate, known_gates, gate_list) { + mpath_dbg(sdata, "Sending to %pM\n", gate->dst); + mesh_path_tx_pending(gate); } return (from_mpath == mpath) ? -EHOSTUNREACH : 0;