From: Sven Eckelmann <sven@narfation.org>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, b.a.t.m.a.n@lists.open-mesh.org,
Marek Lindner <lindner_marek@yahoo.de>
Subject: [PATCH 12/28] batman-adv: Correct rcu refcounting for gw_node
Date: Sat, 5 Mar 2011 13:28:26 +0100 [thread overview]
Message-ID: <1299328122-21468-13-git-send-email-sven@narfation.org> (raw)
In-Reply-To: <1299328122-21468-1-git-send-email-sven@narfation.org>
From: Marek Lindner <lindner_marek@yahoo.de>
It might be possible that 2 threads access the same data in the same
rcu grace period. The first thread calls call_rcu() to decrement the
refcount and free the data while the second thread increases the
refcount to use the data. To avoid this race condition all refcount
operations have to be atomic.
Reported-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/gateway_client.c | 37 ++++++++++++++++---------------------
net/batman-adv/types.h | 2 +-
2 files changed, 17 insertions(+), 22 deletions(-)
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 429a013..517e001 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -28,20 +28,18 @@
#include <linux/udp.h>
#include <linux/if_vlan.h>
-static void gw_node_free_ref(struct kref *refcount)
+static void gw_node_free_rcu(struct rcu_head *rcu)
{
struct gw_node *gw_node;
- gw_node = container_of(refcount, struct gw_node, refcount);
+ gw_node = container_of(rcu, struct gw_node, rcu);
kfree(gw_node);
}
-static void gw_node_free_rcu(struct rcu_head *rcu)
+static void gw_node_free_ref(struct gw_node *gw_node)
{
- struct gw_node *gw_node;
-
- gw_node = container_of(rcu, struct gw_node, rcu);
- kref_put(&gw_node->refcount, gw_node_free_ref);
+ if (atomic_dec_and_test(&gw_node->refcount))
+ call_rcu(&gw_node->rcu, gw_node_free_rcu);
}
void *gw_get_selected(struct bat_priv *bat_priv)
@@ -61,25 +59,26 @@ void gw_deselect(struct bat_priv *bat_priv)
bat_priv->curr_gw = NULL;
if (gw_node)
- kref_put(&gw_node->refcount, gw_node_free_ref);
+ gw_node_free_ref(gw_node);
}
-static struct gw_node *gw_select(struct bat_priv *bat_priv,
- struct gw_node *new_gw_node)
+static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
{
struct gw_node *curr_gw_node = bat_priv->curr_gw;
- if (new_gw_node)
- kref_get(&new_gw_node->refcount);
+ if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
+ new_gw_node = NULL;
bat_priv->curr_gw = new_gw_node;
- return curr_gw_node;
+
+ if (curr_gw_node)
+ gw_node_free_ref(curr_gw_node);
}
void gw_election(struct bat_priv *bat_priv)
{
struct hlist_node *node;
- struct gw_node *gw_node, *curr_gw_tmp = NULL, *old_gw_node = NULL;
+ struct gw_node *gw_node, *curr_gw_tmp = NULL;
uint8_t max_tq = 0;
uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
int down, up;
@@ -174,14 +173,10 @@ void gw_election(struct bat_priv *bat_priv)
curr_gw_tmp->orig_node->gw_flags,
curr_gw_tmp->orig_node->router->tq_avg);
- old_gw_node = gw_select(bat_priv, curr_gw_tmp);
+ gw_select(bat_priv, curr_gw_tmp);
}
rcu_read_unlock();
-
- /* the kfree() has to be outside of the rcu lock */
- if (old_gw_node)
- kref_put(&old_gw_node->refcount, gw_node_free_ref);
}
void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
@@ -242,7 +237,7 @@ static void gw_node_add(struct bat_priv *bat_priv,
memset(gw_node, 0, sizeof(struct gw_node));
INIT_HLIST_NODE(&gw_node->list);
gw_node->orig_node = orig_node;
- kref_init(&gw_node->refcount);
+ atomic_set(&gw_node->refcount, 1);
spin_lock_bh(&bat_priv->gw_list_lock);
hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list);
@@ -325,7 +320,7 @@ void gw_node_purge(struct bat_priv *bat_priv)
gw_deselect(bat_priv);
hlist_del_rcu(&gw_node->list);
- call_rcu(&gw_node->rcu, gw_node_free_rcu);
+ gw_node_free_ref(gw_node);
}
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 084604a..cfbeb45 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -98,7 +98,7 @@ struct gw_node {
struct hlist_node list;
struct orig_node *orig_node;
unsigned long deleted;
- struct kref refcount;
+ atomic_t refcount;
struct rcu_head rcu;
};
--
1.7.2.3
next prev parent reply other threads:[~2011-03-05 12:29 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-05 12:28 pull request: batman-adv 2011-03-05 Sven Eckelmann
2011-03-05 12:28 ` [PATCH 07/28] batman-adv: protect each hash row with rcu locks Sven Eckelmann
2011-03-05 12:28 ` [PATCH 08/28] batman-adv: protect originator nodes with reference counters Sven Eckelmann
2011-03-05 12:28 ` [PATCH 09/28] batman-adv: protect ogm counter arrays with spinlock Sven Eckelmann
2011-03-05 12:28 ` [PATCH 10/28] batman-adv: protect bonding with rcu locks Sven Eckelmann
[not found] ` <1299328122-21468-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
2011-03-05 12:28 ` [PATCH 01/28] batman-adv: Remove two duplicate includes Sven Eckelmann
2011-03-05 12:28 ` [PATCH 02/28] batman-adv: protect neighbor nodes with reference counters Sven Eckelmann
2011-03-05 12:28 ` [PATCH 03/28] batman-adv: convert neighbor list to hlist Sven Eckelmann
2011-03-05 12:28 ` [PATCH 04/28] batman-adv: protect neighbor list with rcu locks Sven Eckelmann
2011-03-05 12:28 ` [PATCH 05/28] batman-adv: free neighbors when an interface is deactivated Sven Eckelmann
2011-03-05 12:28 ` [PATCH 06/28] batman-adv: protect neigh_nodes used outside of rcu_locks with refcounting Sven Eckelmann
2011-03-05 12:28 ` [PATCH 11/28] batman-adv: Correct rcu refcounting for neigh_node Sven Eckelmann
2011-03-05 12:28 ` [PATCH 19/28] batman-adv: Fix possible buffer overflow in softif neigh list output Sven Eckelmann
2011-03-05 12:28 ` Sven Eckelmann [this message]
2011-03-05 12:28 ` [PATCH 13/28] batman-adv: Correct rcu refcounting for softif_neigh Sven Eckelmann
2011-03-05 12:28 ` [PATCH 14/28] batman-adv: Correct rcu refcounting for batman_if Sven Eckelmann
2011-03-05 12:28 ` [PATCH 15/28] batman-adv: protect bit operations to count OGMs with spinlock Sven Eckelmann
2011-03-05 12:28 ` [PATCH 16/28] batman-adv: make broadcast seqno operations atomic Sven Eckelmann
2011-03-05 12:28 ` [PATCH 17/28] batman-adv: Make bat_priv->curr_gw an rcu protected pointer Sven Eckelmann
2011-03-05 12:28 ` [PATCH 18/28] batman-adv: Increase orig_node refcount before releasing rcu read lock Sven Eckelmann
2011-03-05 12:28 ` [PATCH 20/28] batman-adv: separate ethernet comparing calls from hash functions Sven Eckelmann
2011-03-05 12:28 ` [PATCH 21/28] batman-adv: remove extra layer between hash and hash element - hash bucket Sven Eckelmann
2011-03-05 12:28 ` [PATCH 22/28] batman-adv: Correct rcu refcounting for orig_node Sven Eckelmann
2011-03-05 12:28 ` [PATCH 23/28] batman-adv: increase refcount in create_neighbor to be consistent Sven Eckelmann
2011-03-05 12:28 ` [PATCH 24/28] batman-adv: remove orig_hash spinlock Sven Eckelmann
2011-03-05 12:28 ` [PATCH 25/28] batman-adv: rename global if_list to hardif_list Sven Eckelmann
2011-03-05 12:28 ` [PATCH 26/28] batman-adv: rename batman_if struct to hard_iface Sven Eckelmann
2011-03-05 12:28 ` [PATCH 27/28] batman-adv: Remove unused hdr_size variable in route_unicast_packet() Sven Eckelmann
2011-03-05 12:28 ` [PATCH 28/28] batman-adv: Disallow regular interface as mesh device Sven Eckelmann
2011-03-05 14:13 ` [B.A.T.M.A.N.] pull request: batman-adv 2011-03-05 Sven Eckelmann
2011-03-07 2:14 ` David Miller
2011-03-07 9:01 ` Sven Eckelmann
2011-03-07 9:19 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1299328122-21468-13-git-send-email-sven@narfation.org \
--to=sven@narfation.org \
--cc=b.a.t.m.a.n@lists.open-mesh.org \
--cc=davem@davemloft.net \
--cc=lindner_marek@yahoo.de \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).