All of lore.kernel.org
 help / color / mirror / Atom feed
From: Johannes Berg <johannes@sipsolutions.net>
To: netdev@vger.kernel.org
Cc: linux-wireless@vger.kernel.org, tgraf@suug.ch,
	"Eric W. Biederman" <ebiederm@xmission.com>
Subject: [PATCH 1/4] netlink: use call_rcu for netlink_change_ngroups
Date: Fri, 10 Jul 2009 21:51:32 +0200	[thread overview]
Message-ID: <20090710195536.193846183@sipsolutions.net> (raw)
In-Reply-To: 20090710195131.504091075@sipsolutions.net

For the network namespace work in generic netlink I need
to be able to call this function under rcu_read_lock(),
otherwise the locking becomes a nightmare and more locks
would be needed. Instead, just embed a struct rcu_head
(actually a struct listeners_rcu_head that also carries
the pointer to the memory block) into the listeners
memory so we can use call_rcu() instead of synchronising
and then freeing. No rcu_barrier() is needed since this
code cannot be modular.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 net/netlink/af_netlink.c |   34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

--- wireless-testing.orig/net/netlink/af_netlink.c	2009-07-10 20:36:53.000000000 +0200
+++ wireless-testing/net/netlink/af_netlink.c	2009-07-10 20:51:40.000000000 +0200
@@ -83,6 +83,11 @@ struct netlink_sock {
 	struct module		*module;
 };
 
+struct listeners_rcu_head {
+	struct rcu_head rcu_head;
+	void *ptr;
+};
+
 #define NETLINK_KERNEL_SOCKET	0x1
 #define NETLINK_RECV_PKTINFO	0x2
 #define NETLINK_BROADCAST_SEND_ERROR	0x4
@@ -1487,7 +1492,8 @@ netlink_kernel_create(struct net *net, i
 	if (groups < 32)
 		groups = 32;
 
-	listeners = kzalloc(NLGRPSZ(groups), GFP_KERNEL);
+	listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head),
+			    GFP_KERNEL);
 	if (!listeners)
 		goto out_sock_release;
 
@@ -1535,6 +1541,14 @@ netlink_kernel_release(struct sock *sk)
 EXPORT_SYMBOL(netlink_kernel_release);
 
 
+static void netlink_free_old_listeners(struct rcu_head *rcu_head)
+{
+	struct listeners_rcu_head *lrh;
+
+	lrh = container_of(rcu_head, struct listeners_rcu_head, rcu_head);
+	kfree(lrh->ptr);
+}
+
 /**
  * netlink_change_ngroups - change number of multicast groups
  *
@@ -1550,6 +1564,7 @@ EXPORT_SYMBOL(netlink_kernel_release);
 int netlink_change_ngroups(struct sock *sk, unsigned int groups)
 {
 	unsigned long *listeners, *old = NULL;
+	struct listeners_rcu_head *old_rcu_head;
 	struct netlink_table *tbl = &nl_table[sk->sk_protocol];
 	int err = 0;
 
@@ -1558,7 +1573,9 @@ int netlink_change_ngroups(struct sock *
 
 	netlink_table_grab();
 	if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) {
-		listeners = kzalloc(NLGRPSZ(groups), GFP_ATOMIC);
+		listeners = kzalloc(NLGRPSZ(groups) +
+				    sizeof(struct listeners_rcu_head),
+				    GFP_ATOMIC);
 		if (!listeners) {
 			err = -ENOMEM;
 			goto out_ungrab;
@@ -1566,13 +1583,22 @@ int netlink_change_ngroups(struct sock *
 		old = tbl->listeners;
 		memcpy(listeners, old, NLGRPSZ(tbl->groups));
 		rcu_assign_pointer(tbl->listeners, listeners);
+		/*
+		 * Free the old memory after an RCU grace period so we
+		 * don't leak it. We use call_rcu() here in order to be
+		 * able to call this function from atomic contexts. The
+		 * allocation of this memory will have reserved enough
+		 * space for struct listeners_rcu_head at the end.
+		 */
+		old_rcu_head = (void *)(tbl->listeners +
+					NLGRPLONGS(tbl->groups));
+		old_rcu_head->ptr = old;
+		call_rcu(&old_rcu_head->rcu_head, netlink_free_old_listeners);
 	}
 	tbl->groups = groups;
 
  out_ungrab:
 	netlink_table_ungrab();
-	synchronize_rcu();
-	kfree(old);
 	return err;
 }
 

-- 


WARNING: multiple messages have this Message-ID (diff)
From: Johannes Berg <johannes@sipsolutions.net>
To: netdev@vger.kernel.org
Cc: linux-wireless@vger.kernel.org, tgraf@suug.ch,
	"Eric W. Biederman" <ebiederm@xmission.com>
Subject: [PATCH 1/4] netlink: use call_rcu for netlink_change_ngroups
Date: Fri, 10 Jul 2009 21:51:32 +0200	[thread overview]
Message-ID: <20090710195536.193846183@sipsolutions.net> (raw)
In-Reply-To: 20090710195131.504091075@sipsolutions.net

[-- Attachment #1: 027-netlink-groups-realloc-rcu.patch --]
[-- Type: text/plain, Size: 3189 bytes --]

For the network namespace work in generic netlink I need
to be able to call this function under rcu_read_lock(),
otherwise the locking becomes a nightmare and more locks
would be needed. Instead, just embed a struct rcu_head
(actually a struct listeners_rcu_head that also carries
the pointer to the memory block) into the listeners
memory so we can use call_rcu() instead of synchronising
and then freeing. No rcu_barrier() is needed since this
code cannot be modular.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 net/netlink/af_netlink.c |   34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

--- wireless-testing.orig/net/netlink/af_netlink.c	2009-07-10 20:36:53.000000000 +0200
+++ wireless-testing/net/netlink/af_netlink.c	2009-07-10 20:51:40.000000000 +0200
@@ -83,6 +83,11 @@ struct netlink_sock {
 	struct module		*module;
 };
 
+struct listeners_rcu_head {
+	struct rcu_head rcu_head;
+	void *ptr;
+};
+
 #define NETLINK_KERNEL_SOCKET	0x1
 #define NETLINK_RECV_PKTINFO	0x2
 #define NETLINK_BROADCAST_SEND_ERROR	0x4
@@ -1487,7 +1492,8 @@ netlink_kernel_create(struct net *net, i
 	if (groups < 32)
 		groups = 32;
 
-	listeners = kzalloc(NLGRPSZ(groups), GFP_KERNEL);
+	listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head),
+			    GFP_KERNEL);
 	if (!listeners)
 		goto out_sock_release;
 
@@ -1535,6 +1541,14 @@ netlink_kernel_release(struct sock *sk)
 EXPORT_SYMBOL(netlink_kernel_release);
 
 
+static void netlink_free_old_listeners(struct rcu_head *rcu_head)
+{
+	struct listeners_rcu_head *lrh;
+
+	lrh = container_of(rcu_head, struct listeners_rcu_head, rcu_head);
+	kfree(lrh->ptr);
+}
+
 /**
  * netlink_change_ngroups - change number of multicast groups
  *
@@ -1550,6 +1564,7 @@ EXPORT_SYMBOL(netlink_kernel_release);
 int netlink_change_ngroups(struct sock *sk, unsigned int groups)
 {
 	unsigned long *listeners, *old = NULL;
+	struct listeners_rcu_head *old_rcu_head;
 	struct netlink_table *tbl = &nl_table[sk->sk_protocol];
 	int err = 0;
 
@@ -1558,7 +1573,9 @@ int netlink_change_ngroups(struct sock *
 
 	netlink_table_grab();
 	if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) {
-		listeners = kzalloc(NLGRPSZ(groups), GFP_ATOMIC);
+		listeners = kzalloc(NLGRPSZ(groups) +
+				    sizeof(struct listeners_rcu_head),
+				    GFP_ATOMIC);
 		if (!listeners) {
 			err = -ENOMEM;
 			goto out_ungrab;
@@ -1566,13 +1583,22 @@ int netlink_change_ngroups(struct sock *
 		old = tbl->listeners;
 		memcpy(listeners, old, NLGRPSZ(tbl->groups));
 		rcu_assign_pointer(tbl->listeners, listeners);
+		/*
+		 * Free the old memory after an RCU grace period so we
+		 * don't leak it. We use call_rcu() here in order to be
+		 * able to call this function from atomic contexts. The
+		 * allocation of this memory will have reserved enough
+		 * space for struct listeners_rcu_head at the end.
+		 */
+		old_rcu_head = (void *)(tbl->listeners +
+					NLGRPLONGS(tbl->groups));
+		old_rcu_head->ptr = old;
+		call_rcu(&old_rcu_head->rcu_head, netlink_free_old_listeners);
 	}
 	tbl->groups = groups;
 
  out_ungrab:
 	netlink_table_ungrab();
-	synchronize_rcu();
-	kfree(old);
 	return err;
 }
 

-- 


  reply	other threads:[~2009-07-10 19:57 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-10 19:51 [PATCH 0/4] generic netlink namespace awareness Johannes Berg
2009-07-10 19:51 ` Johannes Berg
2009-07-10 19:51 ` Johannes Berg [this message]
2009-07-10 19:51   ` [PATCH 1/4] netlink: use call_rcu for netlink_change_ngroups Johannes Berg
2009-07-10 19:51 ` [PATCH 2/4] net: make namespace iteration possible under RCU Johannes Berg
2009-07-10 19:51   ` Johannes Berg
2009-07-10 19:51 ` [PATCH 3/4] genetlink: make netns aware Johannes Berg
2009-07-10 19:51   ` Johannes Berg
2009-07-10 19:51 ` [PATCH 4/4] net: move and export get_net_ns_by_pid Johannes Berg
2009-07-10 19:51   ` Johannes Berg
2009-07-12 21:17 ` [PATCH 0/4] generic netlink namespace awareness David Miller
2009-07-12 21:17   ` 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=20090710195536.193846183@sipsolutions.net \
    --to=johannes@sipsolutions.net \
    --cc=ebiederm@xmission.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=tgraf@suug.ch \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.