From patchwork Mon Mar 18 05:09:56 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Linus_L=C3=BCssing?= X-Patchwork-Id: 2812 X-Patchwork-Delegate: mareklindner@neomailbox.ch Return-Path: Received: from mout.web.de (mout.web.de [212.227.15.4]) by open-mesh.org (Postfix) with ESMTP id 43B16601E6A for ; Mon, 18 Mar 2013 06:10:12 +0100 (CET) Received: from localhost ([95.211.13.35]) by smtp.web.de (mrweb103) with ESMTPSA (Nemesis) id 0MGzba-1UU5dh2xcY-00E695; Mon, 18 Mar 2013 06:10:11 +0100 From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: b.a.t.m.a.n@lists.open-mesh.org Date: Mon, 18 Mar 2013 06:09:56 +0100 Message-Id: <1363583397-4800-4-git-send-email-linus.luessing@web.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1363583397-4800-1-git-send-email-linus.luessing@web.de> References: <201303071427.27817.lindner_marek@yahoo.de> <1363583397-4800-1-git-send-email-linus.luessing@web.de> MIME-Version: 1.0 X-Provags-ID: V02:K0:Da+VGKfmscbvd1EiRXtsaY52JuC+vNO9Fvnmi94or6i vS06lw29vyUiUSFKARnSZ6dB6z37cBDkk3tMiA44FmN6TTH9H/ Km1ZRX6TLMxz4kY8IPS0LP9Dv4zDrR2awcOPb9lMSyUEyYxHRA 1rEU2GTnQufNLTwifCWw7DILbjjsXu9W+y4NzQfXqVbh9YmVlw /ku7yyexbp0VwX2aAmIZA== Subject: [B.A.T.M.A.N.] [PATCH 4/5] batman-adv: Fix a potential bcast/ogm qeueue purging race condition (2) X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.15 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: Mon, 18 Mar 2013 05:10:12 -0000 - Avoid rearmed bcast packet being missed by cancel_delayed_work_sync(). When a scheduled broadcast packet sending work executes and removes itself from the broadcast queue, it becomes invisible for the purging methods until it re-arms. This means a to be re-armed broadcast work might slip through a cancel_delayed_work_sync() between the removal from and readdition to the broadcast queue. To avoid this we perform the removal and readdition in one atomic step. Signed-off-by: Linus Lüssing --- send.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/send.c b/send.c index 1ddfae7..34c54e9 100644 --- a/send.c +++ b/send.c @@ -217,12 +217,9 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet, unsigned long send_time) { - /* add new packet to packet list and start its timer */ - spin_lock_bh(&bat_priv->forw_bcast_list_lock); hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list); queue_delayed_work(batadv_event_workqueue, &forw_packet->delayed_work, send_time); - spin_unlock_bh(&bat_priv->forw_bcast_list_lock); } /* add a broadcast packet to the queue and setup timers. broadcast packets @@ -272,7 +269,10 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, INIT_DELAYED_WORK(&forw_packet->delayed_work, batadv_send_outstanding_bcast_packet); + spin_lock_bh(&bat_priv->forw_bcast_list_lock); _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, delay); + spin_unlock_bh(&bat_priv->forw_bcast_list_lock); + return NETDEV_TX_OK; packet_free: @@ -296,10 +296,6 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work) soft_iface = forw_packet->if_incoming->soft_iface; bat_priv = netdev_priv(soft_iface); - spin_lock_bh(&bat_priv->forw_bcast_list_lock); - hlist_del(&forw_packet->list); - spin_unlock_bh(&bat_priv->forw_bcast_list_lock); - if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) goto out; @@ -327,12 +323,21 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work) /* if we still have some more bcasts to send */ if (forw_packet->num_packets < BATADV_NUM_BCASTS_MAX) { + spin_lock_bh(&bat_priv->forw_bcast_list_lock); + hlist_del(&forw_packet->list); + _batadv_add_bcast_packet_to_list(bat_priv, forw_packet, msecs_to_jiffies(5)); + spin_unlock_bh(&bat_priv->forw_bcast_list_lock); + return; } out: + spin_lock_bh(&bat_priv->forw_bcast_list_lock); + hlist_del(&forw_packet->list); + spin_unlock_bh(&bat_priv->forw_bcast_list_lock); + batadv_forw_packet_free(forw_packet); }