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;
}
--
next prev parent reply other threads:[~2009-07-10 19:57 UTC|newest]
Thread overview: 6+ 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 [this message]
2009-07-10 19:51 ` [PATCH 2/4] net: make namespace iteration possible under RCU Johannes Berg
2009-07-10 19:51 ` [PATCH 3/4] genetlink: make netns aware Johannes Berg
2009-07-10 19:51 ` [PATCH 4/4] net: move and export get_net_ns_by_pid Johannes Berg
2009-07-12 21:17 ` [PATCH 0/4] generic netlink namespace awareness 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 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).