From patchwork Thu Dec 17 12:11:55 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Eckelmann X-Patchwork-Id: 5205 Return-Path: Received: from mail.gmx.net (mail.gmx.net [213.165.64.20]) by open-mesh.net (Postfix) with SMTP id 42E0115423E for ; Thu, 17 Dec 2009 12:57:42 +0000 (UTC) Received: (qmail invoked by alias); 17 Dec 2009 12:11:51 -0000 Received: from i59F6A940.versanet.de (EHLO localhost) [89.246.169.64] by mail.gmx.net (mp008) with SMTP; 17 Dec 2009 13:11:51 +0100 X-Authenticated: #15668376 X-Provags-ID: V01U2FsdGVkX1+8Vrcx0vC83isKh1AA1qvMhmbpVsy0HaCitQO9JX nGoPjBcrbyAbIc From: Sven Eckelmann To: b.a.t.m.a.n@lists.open-mesh.net Date: Thu, 17 Dec 2009 13:11:55 +0100 Message-Id: <1261051915-13960-1-git-send-email-sven.eckelmann@gmx.de> X-Mailer: git-send-email 1.6.5.4 X-Y-GMX-Trusted: 0 X-FuHaFi: 0.5 Subject: [B.A.T.M.A.N.] [PATCH] batman-adv: Use forw_bcast_list_lock always in disabled interrupt context X-BeenThere: b.a.t.m.a.n@lists.open-mesh.net X-Mailman-Version: 2.1.11 Precedence: list Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Dec 2009 12:57:42 -0000 forw_bcast_list_lock is spin_locked in both process and softirq context. SoftIRQ calls the spinlock with disabled IRQ and normal process context with enabled IRQs. When process context is inside an spin_locked area protected by forw_bcast_list_lock and gets interrupted by an IRQ, it could happen that something tries to lock forw_bcast_list_lock again in SoftIRQ context. It cannot proceed further since the lock is already taken somewhere else, but no reschedule will happen inside the SoftIRQ context. This leads to an complete kernel hang without any chance of resurrection. All functions called in process context must disable IRQs when they try to get get that lock to to prevent any reschedule due to IRQs. Signed-off-by: Sven Eckelmann --- batman-adv-kernelland/send.c | 19 +++++++++++-------- 1 files changed, 11 insertions(+), 8 deletions(-) diff --git a/batman-adv-kernelland/send.c b/batman-adv-kernelland/send.c index fc4953f..49b1534 100644 --- a/batman-adv-kernelland/send.c +++ b/batman-adv-kernelland/send.c @@ -338,12 +338,13 @@ static void forw_packet_free(struct forw_packet *forw_packet) static void _add_bcast_packet_to_list(struct forw_packet *forw_packet, unsigned long send_time) { + unsigned long flags; INIT_HLIST_NODE(&forw_packet->list); /* add new packet to packet list */ - spin_lock(&forw_bcast_list_lock); + spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_add_head(&forw_packet->list, &forw_bcast_list); - spin_unlock(&forw_bcast_list_lock); + spin_unlock_irqrestore(&forw_bcast_list_lock, flags); /* start timer for this packet */ INIT_DELAYED_WORK(&forw_packet->delayed_work, @@ -382,10 +383,11 @@ void send_outstanding_bcast_packet(struct work_struct *work) container_of(work, struct delayed_work, work); struct forw_packet *forw_packet = container_of(delayed_work, struct forw_packet, delayed_work); + unsigned long flags; - spin_lock(&forw_bcast_list_lock); + spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_del(&forw_packet->list); - spin_unlock(&forw_bcast_list_lock); + spin_unlock_irqrestore(&forw_bcast_list_lock, flags); /* rebroadcast packet */ rcu_read_lock(); @@ -436,24 +438,25 @@ void purge_outstanding_packets(void) { struct forw_packet *forw_packet; struct hlist_node *tmp_node, *safe_tmp_node; + unsigned long flags; bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n"); /* free bcast list */ - spin_lock(&forw_bcast_list_lock); + spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, &forw_bcast_list, list) { - spin_unlock(&forw_bcast_list_lock); + spin_unlock_irqrestore(&forw_bcast_list_lock, flags); /** * send_outstanding_bcast_packet() will lock the list to * delete the item from the list */ cancel_delayed_work_sync(&forw_packet->delayed_work); - spin_lock(&forw_bcast_list_lock); + spin_lock_irqsave(&forw_bcast_list_lock, flags); } - spin_unlock(&forw_bcast_list_lock); + spin_unlock_irqrestore(&forw_bcast_list_lock, flags); /* free batman packet list */ spin_lock(&forw_bat_list_lock);