From patchwork Sat Mar 26 15:27:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bob Copeland X-Patchwork-Id: 8674621 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 3E1A4C0553 for ; Sat, 26 Mar 2016 15:27:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1619C20218 for ; Sat, 26 Mar 2016 15:27:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 04CEE20211 for ; Sat, 26 Mar 2016 15:27:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752726AbcCZP1h (ORCPT ); Sat, 26 Mar 2016 11:27:37 -0400 Received: from mail-qg0-f68.google.com ([209.85.192.68]:35523 "EHLO mail-qg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752470AbcCZP1e (ORCPT ); Sat, 26 Mar 2016 11:27:34 -0400 Received: by mail-qg0-f68.google.com with SMTP id c67so8755661qgc.2 for ; Sat, 26 Mar 2016 08:27:33 -0700 (PDT) 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=RdsbwuQfv0YltklKCXZZClXqBR6gbl5jbYQ2AGEwK9E=; b=qCY15jxgcdZbZLN3Hto+1fNx+ZfleY5M9+gIxcF3pW373uHId98lJ7EdyZCVza9WVm 9lFHM2UNTzmKlMhwJD5DxHpjhPdhbrmJ8T4kkOSwPIz1WqpVJDVAQ6d9IFNyuzJllqUE P4r69/Otvjjf3lYugiO9kJmo/a1k3wwLzHZXdQt6NGefKF4BXUvyv6re+NaOU2acyg3y mCmhacYaY8EKm24Kgf0QLT6XCXiq/EixAby1kKykqOi+e2uVXufV5LxcRlOpeanZ0nr2 dWCgfjs3mfRjDCgWkNaGujpkyAzfjptyFcPqrLkSd/+9U0Cs2ADGboL10VJnIMGhEtJQ 03vA== 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=RdsbwuQfv0YltklKCXZZClXqBR6gbl5jbYQ2AGEwK9E=; b=QfBxPtv7Uy/E6fqfO6S8J7NVSqzhNIR1CoTrCJ91YL/X6Ixt+PY6KaG26Uk2kDDQnz FGLszGlqnIgikEwgsihLx3bxiK1ZTeuBGd+dpHFn5pBIHBqN2PPxgMoMi+OWGDZyMyqQ HJrjN9zDK0lckKpnbbJy4ScW3QtEVlz9C5jliNVMi8SazaNBotPNfePNvqYUFzu+cSxJ yQdBRw/Bz3uhOqxxaNehsE87sXxSFbdc7LLaKi/xqwsAiAi9NWMekdvpKuNKRs/yz+qz 5RTcq0yfQoij1RdvPVnb/oTTSjfWQoKxCVcKheGGD7AVSj9HlTRa47JHtW+Sg0woUA0h aJvA== X-Gm-Message-State: AD7BkJK+UskljjPcvUKivItlWKEin5uOVEIGtKpKor39tDq7qQ37v80ynuyAdKMP/x5zSA== X-Received: by 10.141.6.9 with SMTP id i9mr25316137qhd.21.1459006053409; Sat, 26 Mar 2016 08:27:33 -0700 (PDT) Received: from hash ([2001:470:1d:6db:230:48ff:fe9d:9c89]) by smtp.gmail.com with ESMTPSA id b34sm7860205qgb.31.2016.03.26.08.27.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 26 Mar 2016 08:27:32 -0700 (PDT) Received: from glass.lan ([192.168.1.51] helo=glass) by hash with esmtp (Exim 4.84_2) (envelope-from ) id 1ajq7g-0001JF-4T; Sat, 26 Mar 2016 11:27:32 -0400 Received: from bob by glass with local (Exim 4.86) (envelope-from ) id 1ajq7g-0001BF-4i; Sat, 26 Mar 2016 11:27:32 -0400 From: Bob Copeland To: Johannes Berg Cc: linux-wireless@vger.kernel.org, Bob Copeland Subject: [PATCH 2/2] mac80211: mesh: flush paths outside of plink lock Date: Sat, 26 Mar 2016 11:27:19 -0400 Message-Id: <1459006039-4493-2-git-send-email-me@bobcopeland.com> X-Mailer: git-send-email 2.6.1 In-Reply-To: <1459006039-4493-1-git-send-email-me@bobcopeland.com> References: <1459006039-4493-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=-7.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 Lockdep warned of a lock dependency between the mesh_plink lock and the internal lock for the rhashtable. The problem is that the rhashtable code uses a spin lock with softirqs enabled, while mesh_plink_timer executes a walk (to flush paths on a state change) inside a softirq with the plink lock held. This leads to the following deadlock if the timer fires while rht lock is held on this CPU, and plink lock is held on another CPU: CPU0 CPU1 ---- ---- lock(&(&ht->lock)->rlock); local_irq_disable(); lock(&(&sta->mesh->plink_lock)->rlock); lock(&(&ht->lock)->rlock); lock(&(&sta->mesh->plink_lock)->rlock); *** DEADLOCK *** Fix by waiting until we drop the plink lock to flush paths. Fixes: d48a1b7cd439 ("mac80211: mesh: convert path table to rhashtable") Signed-off-by: Bob Copeland --- net/mac80211/mesh_plink.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index a07e93c21c9e..ecfba8ad29e4 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -331,7 +331,9 @@ free: * * @sta: mesh peer link to deactivate * - * All mesh paths with this peer as next hop will be flushed + * Mesh paths with this peer as next hop should be flushed + * by the caller outside of plink_lock. + * * Returns beacon changed flag if the beacon content changed. * * Locking: the caller must hold sta->mesh->plink_lock @@ -346,7 +348,6 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta) if (sta->mesh->plink_state == NL80211_PLINK_ESTAB) changed = mesh_plink_dec_estab_count(sdata); sta->mesh->plink_state = NL80211_PLINK_BLOCKED; - mesh_path_flush_by_nexthop(sta); ieee80211_mps_sta_status_update(sta); changed |= ieee80211_mps_set_sta_local_pm(sta, @@ -374,6 +375,7 @@ u32 mesh_plink_deactivate(struct sta_info *sta) sta->sta.addr, sta->mesh->llid, sta->mesh->plid, sta->mesh->reason); spin_unlock_bh(&sta->mesh->plink_lock); + mesh_path_flush_by_nexthop(sta); return changed; } @@ -748,6 +750,7 @@ u32 mesh_plink_block(struct sta_info *sta) changed = __mesh_plink_deactivate(sta); sta->mesh->plink_state = NL80211_PLINK_BLOCKED; spin_unlock_bh(&sta->mesh->plink_lock); + mesh_path_flush_by_nexthop(sta); return changed; } @@ -797,6 +800,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; enum ieee80211_self_protected_actioncode action = 0; u32 changed = 0; + bool flush = false; mpl_dbg(sdata, "peer %pM in state %s got event %s\n", sta->sta.addr, mplstates[sta->mesh->plink_state], mplevents[event]); @@ -885,6 +889,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, changed |= mesh_set_short_slot_time(sdata); mesh_plink_close(sdata, sta, event); action = WLAN_SP_MESH_PEERING_CLOSE; + flush = true; break; case OPN_ACPT: action = WLAN_SP_MESH_PEERING_CONFIRM; @@ -916,6 +921,8 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, break; } spin_unlock_bh(&sta->mesh->plink_lock); + if (flush) + mesh_path_flush_by_nexthop(sta); if (action) { mesh_plink_frame_tx(sdata, sta, action, sta->sta.addr, sta->mesh->llid, sta->mesh->plid,