Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH RESEND] net: convert xen-netfront to hw_features
From: David Miller @ 2011-04-02  3:54 UTC (permalink / raw)
  To: mirq-linux
  Cc: netdev, jeremy.fitzhardinge, konrad.wilk, Ian.Campbell, xen-devel,
	virtualization
In-Reply-To: <20110331110136.03A1A13A6A@rere.qmqm.pl>

From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Thu, 31 Mar 2011 13:01:35 +0200 (CEST)

> Not tested in any way. The original code for offload setting seems broken
> as it resets the features on every netback reconnect.
> 
> This will set GSO_ROBUST at device creation time (earlier than connect time).
> 
> RX checksum offload is forced on - so advertise as it is.
> 
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>

Applied.

^ permalink raw reply

* Re: [PATCH] net: convert SMSC USB net drivers to hw_features
From: David Miller @ 2011-04-02  3:54 UTC (permalink / raw)
  To: mirq-linux; +Cc: netdev, steve.glendinning
In-Reply-To: <20110331110135.E66E413A6B@rere.qmqm.pl>

From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Thu, 31 Mar 2011 13:01:35 +0200 (CEST)

> There's a race (not fixed here) in smsc75xx in setting RFE_CTL that's not
> properly handled via rfe_ctl_lock. Spinlock is not a good tool here, as
> this has to wait for URB completion (or maybe just submission) after issuing
> register write request. Otherwise, the rfe_ctl might be changed just after
> spin_unlock() and device left programmed with other value.
> 
> smsc95xx has increased hard_header_len for the case of TX checksumming.
> 
> smsc75xx is fixed to advertise IP+IPV6_CSUM instead of HW_CSUM as it does
> not use csum_start/csum_offset.
> 
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>

Applied.

^ permalink raw reply

* Re: [PATCH] virtio_net: convert to hw_features
From: David Miller @ 2011-04-02  3:54 UTC (permalink / raw)
  To: mirq-linux; +Cc: netdev, rusty, mst, virtualization
In-Reply-To: <20110331110135.6988113A64@rere.qmqm.pl>

From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Thu, 31 Mar 2011 13:01:35 +0200 (CEST)

> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>

Applied.

^ permalink raw reply

* Re: [PATCH v3] net: Allow no-cache copy from user on transmit
From: David Miller @ 2011-04-02  3:52 UTC (permalink / raw)
  To: therbert; +Cc: netdev
In-Reply-To: <20110401.204922.28812273.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Fri, 01 Apr 2011 20:49:22 -0700 (PDT)

> From: Tom Herbert <therbert@google.com>
> Date: Wed, 30 Mar 2011 22:04:32 -0700 (PDT)
> 
>> This patch uses __copy_from_user_nocache (from skb_copy_to_page)
>> on transmit to bypass data cache for a performance improvement.
>> This functionality is configurable per device using ethtool.
> ...
>> Signed-off-by: Tom Herbert <therbert@google.com>
> 
> It's early in net-next-2.6, so I've applied this now and we can
> add any fixups and tweaks as needed.

Nevermind, you have some work to do in the generic kernel before I
can add this, because nocache copies are not a universally available
feature, for example on sparc64:

In file included from include/linux/tcp.h:210,
                 from include/linux/ipv6.h:221,
                 from include/net/ip_vs.h:26,
                 from kernel/sysctl_binary.c:6:
include/net/sock.h: In function ‘skb_copy_to_page’:
include/net/sock.h:1406: error: implicit declaration of function ‘__copy_from_user_nocache’
make[1]: *** [kernel/sysctl_binary.o] Error 1
make: *** [kernel] Error 2
make: *** Waiting for unfinished jobs....
In file included from include/linux/if_pppox.h:170,
                 from fs/compat_ioctl.c:38:
include/net/sock.h: In function ‘skb_copy_to_page’:
include/net/sock.h:1406: error: implicit declaration of function ‘__copy_from_user_nocache’
In file included from include/linux/highmem.h:7,
                 from include/linux/pagemap.h:10,
                 from include/linux/blkdev.h:12,
                 from fs/compat_ioctl.c:48:
include/linux/uaccess.h: At top level:
include/linux/uaccess.h:49: error: conflicting types for ‘__copy_from_user_nocache’
include/net/sock.h:1406: note: previous implicit declaration of ‘__copy_from_user_nocache’ was here

^ permalink raw reply

* Re: [PATCH v3] net: Allow no-cache copy from user on transmit
From: David Miller @ 2011-04-02  3:49 UTC (permalink / raw)
  To: therbert; +Cc: netdev
In-Reply-To: <alpine.DEB.2.00.1103302156270.17065@pokey.mtv.corp.google.com>

From: Tom Herbert <therbert@google.com>
Date: Wed, 30 Mar 2011 22:04:32 -0700 (PDT)

> This patch uses __copy_from_user_nocache (from skb_copy_to_page)
> on transmit to bypass data cache for a performance improvement.
> This functionality is configurable per device using ethtool.
...
> Signed-off-by: Tom Herbert <therbert@google.com>

It's early in net-next-2.6, so I've applied this now and we can
add any fixups and tweaks as needed.

^ permalink raw reply

* Re: ipv6: Add support for RTA_PREFSRC
From: David Miller @ 2011-04-02  3:46 UTC (permalink / raw)
  To: dwalter; +Cc: netdev


You can't change the layout of "struct in6_rtmsg", as that structure
is explicitly exported to user space and changing it will break every
application out there.

^ permalink raw reply

* Re: [PATCH] net: Fix dev dev_ethtool_get_rx_csum() for forced NETIF_F_RXCSUM
From: David Miller @ 2011-04-02  3:23 UTC (permalink / raw)
  To: mirq-linux; +Cc: netdev
In-Reply-To: <f658c6e20dad946b50fda008c120a0347ad58314.1301565174.git.mirq-linux@rere.qmqm.pl>

From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Date: Thu, 31 Mar 2011 11:58:08 +0200 (CEST)

> dev_ethtool_get_rx_csum() won't report rx checksumming when it's not
> changeable and driver is converted to hw_features and friends. Fix this.
> 
> (dev->hw_features & NETIF_F_RXCSUM) check is dropped - if the
> ethtool_ops->get_rx_csum is set, then driver is not coverted, yet.
> 
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>

Applied, thanks.

^ permalink raw reply

* RE: [PATCH] net: ethtool support to configure number of channels
From: Amit Salecha @ 2011-04-02  3:22 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: davem@davemloft.net, netdev@vger.kernel.org, Ameen Rahman,
	Sucheta Chakraborty, Anirban Chakraborty
In-Reply-To: <99737F4847ED0A48AECC9F4A1974A4B80FD10E8D95@MNEXMB2.qlogic.org>

> > >
> > > > This also omits the 'combined' and 'other' types.  Most
> multiqueue
> > > > drivers pair up RX and TX queues so that most channels combine RX
> > and
> > > > TX
> > > > work.
> > >
> > > 'combined' is ok, what is use of 'other' ?
> >
> > Could be link interrupts, SR-IOV coordination, or something else.
> Not
> > something you'd likely be able to change, but it could be useful to
> > know
> > that some interrupts are allocated to them.  Actually, that does mean
> > it
> > might be helpful for the 'get' operation to return a minimum value
> > along
> > with the maximum value.
> >
> Instead of naming as 'other', corresponding channel type should be
> declared.
> Adapter may have multiple 'other' channel. It's better to name them.
> Naming them will be useful, if one want to configure them.
> So I will rather leave this open and let people to declared channel
> type as they required.
>

I will declare 'other' channel type, which will mean channel other than
declared in ethtool_channel_type (not other than RX/TX).

This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.

^ permalink raw reply

* RE: [PATCH] net: ethtool support to configure number of channels
From: Amit Salecha @ 2011-04-02  3:13 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: davem@davemloft.net, netdev@vger.kernel.org, Ameen Rahman,
	Sucheta Chakraborty, Anirban Chakraborty
In-Reply-To: <1301712946.10056.179.camel@localhost>

> >
> > > This also omits the 'combined' and 'other' types.  Most multiqueue
> > > drivers pair up RX and TX queues so that most channels combine RX
> and
> > > TX
> > > work.
> >
> > 'combined' is ok, what is use of 'other' ?
>
> Could be link interrupts, SR-IOV coordination, or something else.  Not
> something you'd likely be able to change, but it could be useful to
> know
> that some interrupts are allocated to them.  Actually, that does mean
> it
> might be helpful for the 'get' operation to return a minimum value
> along
> with the maximum value.
>
Instead of naming as 'other', corresponding channel type should be declared.
Adapter may have multiple 'other' channel. It's better to name them.
Naming them will be useful, if one want to configure them.
So I will rather leave this open and let people to declared channel type as they required.


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.

^ permalink raw reply

* Re: [PATCH v3] usbnet: use eth%d name for known ethernet devices
From: David Miller @ 2011-04-02  3:12 UTC (permalink / raw)
  To: arnd
  Cc: linux-usb, netdev, dbrownell, patches, greg, nicolas.pitre,
	linux-kernel
In-Reply-To: <201104011706.36873.arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Fri, 1 Apr 2011 17:06:36 +0200

> The documentation for the USB ethernet devices suggests that
> only some devices are supposed to use usb0 as the network interface
> name instead of eth0. The logic used there, and documented in
> Kconfig for CDC is that eth0 will be used when the mac address
> is a globally assigned one, but usb0 is used for the locally
> managed range that is typically used on point-to-point links.
> 
> Unfortunately, this has caused a lot of pain on the smsc95xx
> device that is used on the popular pandaboard without an
> EEPROM to store the MAC address, which causes the driver to
> call random_ether_address().
> 
> Obviously, there should be a proper MAC addressed assigned to
> the device, and discussions are ongoing about how to solve
> this, but this patch at least makes sure that the default
> interface naming gets a little saner and matches what the
> user can expect based on the documentation, including for
> new devices.
> 
> The approach taken here is to flag whether a device might be a
> point-to-point link with the new FLAG_POINTTOPOINT setting in
> the usbnet driver_info. A driver can set both FLAG_POINTTOPOINT
> and FLAG_ETHER if it is not sure (e.g. cdc_ether), or just one
> of the two.  The usbnet framework only looks at the MAC address
> for device naming if both flags are set, otherwise it trusts the
> flag.
> 
> Signed-off-by: Arnd Bergmann <arnd.bergmann@linaro.org>
> Tested-by: Andy Green <andy.green@linaro.org>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] starfire: clean up dma_addr_t size test
From: David Miller @ 2011-04-02  3:10 UTC (permalink / raw)
  To: fujita.tomonori; +Cc: netdev
In-Reply-To: <20110402002600P.fujita.tomonori@lab.ntt.co.jp>

From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Date: Sat, 2 Apr 2011 00:27:51 +0900

> Now we have CONFIG_ARCH_DMA_ADDR_T_64BIT. We can fix the hacky
> dma_addr_t size test cleanly.
> 
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>

Applied, thank you for remembering to do this!

^ permalink raw reply

* RE: [PATCH] net: ethtool support to configure number of channels
From: Ben Hutchings @ 2011-04-02  2:55 UTC (permalink / raw)
  To: Amit Salecha
  Cc: davem@davemloft.net, netdev@vger.kernel.org, Ameen Rahman,
	Sucheta Chakraborty, Anirban Chakraborty
In-Reply-To: <99737F4847ED0A48AECC9F4A1974A4B80FD10E8D93@MNEXMB2.qlogic.org>

On Fri, 2011-04-01 at 21:36 -0500, Amit Salecha wrote:
> > I'm not sure why you reduced this to a single count.  If if the driver
> > or hardware doesn't allow certain combinations of counts, it might be
> > necessary to configure several types at the same time
> >
> > > +/* Channel ID is made up of a type */
> > > +enum ethtool_channel_id {
> > > +   ETH_CHAN_TYPE_RX = 0x1,
> > > +   ETH_CHAN_TYPE_TX = 0x2
> > > +};
> > [...]
> >
> > enum ethtool_channel_id was meant to be an identifier of a specific
> > channel.  An enumeration of channel types should be named differently.
> >
> 
> I will name it as ethtool_channel_type. Any other suggestion ?
> 
> > This also omits the 'combined' and 'other' types.  Most multiqueue
> > drivers pair up RX and TX queues so that most channels combine RX and
> > TX
> > work.
> 
> 'combined' is ok, what is use of 'other' ?

Could be link interrupts, SR-IOV coordination, or something else.  Not
something you'd likely be able to change, but it could be useful to know
that some interrupts are allocated to them.  Actually, that does mean it
might be helpful for the 'get' operation to return a minimum value along
with the maximum value.

Ben.

-- 
Ben Hutchings, Senior Software Engineer, Solarflare Communications
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


^ permalink raw reply

* [PATCH 24/24] sysctl: neigh: ipv4 and ipv6 neigh tables as private children
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

$ time modprobe dummy numdummies=$n

Without this patch:
 - n=5000 => real:  9:14m, sys: 8:46m
 - n=2000 => real:  1:19m, sys: 1:17m
 - n=1000 => real:  0:14m, sys: 0:14m

With this patch:
 - n=5000 => real: 12.50s
 - n=2000 => real:  1.59s
 - n=1000 => real:  0.44s

$ time find /proc/sys/net/ > /dev/null

Without this patch:
 - n=5000 => real: 15s
 - n=2000 => real: 12s
 - n=1000 => real:  4s

With this patch:
 - n=5000 => real: 3.77s
 - n=2000 => real: 1.55s
 - n=1000 => real: 1.43s

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 include/net/neighbour.h |    9 ++++-----
 net/core/neighbour.c    |    6 ++++--
 net/ipv4/arp.c          |    3 ++-
 net/ipv4/devinet.c      |    3 ++-
 net/ipv6/addrconf.c     |    3 ++-
 net/ipv6/ndisc.c        |    3 ++-
 6 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 4014b62..3fabfa3 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -259,11 +259,10 @@ extern void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *,
 extern void *neigh_seq_next(struct seq_file *, void *, loff_t *);
 extern void neigh_seq_stop(struct seq_file *, void *);
 
-extern int			neigh_sysctl_register(struct net_device *dev, 
-						      struct neigh_parms *p,
-						      char *p_name,
-						      proc_handler *proc_handler);
-extern void			neigh_sysctl_unregister(struct neigh_parms *p);
+extern int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
+				 char *p_name, proc_handler *proc_handler,
+				 struct ctl_table_header *parent_header);
+extern void neigh_sysctl_unregister(struct neigh_parms *p);
 
 static inline void __neigh_parms_put(struct neigh_parms *parms)
 {
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 799f06e..48141cb 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2804,7 +2804,8 @@ static struct neigh_sysctl_table {
 };
 
 int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
-			  char *p_name, proc_handler *handler)
+			  char *p_name, proc_handler *handler,
+			  struct ctl_table_header *parent_header)
 {
 	struct neigh_sysctl_table *t;
 	const char *dev_name_source = NULL;
@@ -2877,7 +2878,8 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
 	neigh_path[NEIGH_CTL_PATH_PROTO].procname = p_name;
 
 	t->sysctl_header =
-		register_net_sysctl_table(neigh_parms_net(p), neigh_path, t->neigh_vars);
+		register_net_sysctl_table_with_parent(neigh_parms_net(p),
+				      neigh_path, t->neigh_vars, parent_header);
 	if (!t->sysctl_header)
 		goto free_procname;
 
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index d38654f..a5ba277 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1509,7 +1509,8 @@ static int __net_init arp_sysctl_net_init(struct net *net)
 	/* register /proc/sys/net/ipv4/neigh/default */
 	if (net_eq(net, &init_net)) {
 		int err;
-		err = neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL);
+		err = neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4",
+					    NULL, net->ipv4.neigh_hdr);
 		if (err) {
 			unregister_net_sysctl_table(net->ipv4.neigh_hdr);
 			return err;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 2a10365..461466c 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1687,7 +1687,8 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf)
 
 static void devinet_sysctl_register(struct in_device *idev)
 {
-	neigh_sysctl_register(idev->dev, idev->arp_parms, "ipv4", NULL);
+	neigh_sysctl_register(idev->dev, idev->arp_parms, "ipv4",
+			      NULL, dev_net(idev->dev)->ipv4.neigh_hdr);
 	__devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
 					&idev->cnf);
 }
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6ac29d0..30c163c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4545,7 +4545,8 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
 static void addrconf_sysctl_register(struct inet6_dev *idev)
 {
 	neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6",
-			      &ndisc_ifinfo_sysctl_change);
+			      &ndisc_ifinfo_sysctl_change,
+			      dev_net(idev->dev)->ipv6.sysctl.neigh_hdr);
 	__addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
 					idev, &idev->cnf);
 }
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 1cbc3c6..005d163 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1828,7 +1828,8 @@ static int __net_init ndisc_net_init(struct net *net)
 	/* register /proc/sys/net/ipv6/neigh/default */
 	if (net_eq(net, &init_net)) {
 		err = neigh_sysctl_register(NULL, &nd_tbl.parms, "ipv6",
-					    &ndisc_ifinfo_sysctl_change);
+					    &ndisc_ifinfo_sysctl_change,
+					    net->ipv6.sysctl.neigh_hdr);
 		if (err)
 			goto neigh_sysctl_register_fail;
 	}
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 23/24] sysctl: ipv6: register /proc/sys/net/ipv6/neigh empty directory
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

Similar to the previous patch. This patch also changes the moment
/proc/sys/net/ipv6/neigh/default is registered:

- before this patch: the 'default' was registered directly in ndisc_init()

- with this patch: 'default' is registered after the empty
  /proc/sys/net/ipv6/neigh/ directly which is created for each network
  namespace as a pernet operation. Because of this the neigh_tables
  have to be initialised (neigh_table_init) before registering pernet
  ops and cleaned up after unregistering them.

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 include/net/ipv6.h         |    2 -
 include/net/netns/ipv6.h   |    1 +
 net/ipv6/af_inet6.c        |   12 -------
 net/ipv6/ndisc.c           |   76 ++++++++++++++++++++++++++++++++++----------
 net/ipv6/sysctl_net_ipv6.c |   27 ---------------
 5 files changed, 60 insertions(+), 58 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index bd73439..5e535b3 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -661,8 +661,6 @@ extern ctl_table ipv6_icmp_table[];
 
 extern int ipv6_sysctl_register(void);
 extern void ipv6_sysctl_unregister(void);
-extern int ipv6_static_sysctl_register(void);
-extern void ipv6_static_sysctl_unregister(void);
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index b3c3cd7..58b542f 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -15,6 +15,7 @@ struct netns_sysctl_ipv6 {
 	struct ctl_table_header *table;
 	struct ctl_table_header *frags_hdr;  /* /proc/sys/net/ipv6/ip6frag_*  */
 	struct ctl_table_header *conf_hdr;   /* /proc/sys/net/ipv6/conf/      */
+	struct ctl_table_header *neigh_hdr;  /* /proc/sys/net/ipv6/neigh/     */
 #endif
 	int bindv6only;
 	int flush_delay;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 4b13d5d..5f81711 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -1105,11 +1105,6 @@ static int __init inet6_init(void)
 	if (err)
 		goto out_sock_register_fail;
 
-#ifdef CONFIG_SYSCTL
-	err = ipv6_static_sysctl_register();
-	if (err)
-		goto static_sysctl_fail;
-#endif
 	/*
 	 *	ipngwg API draft makes clear that the correct semantics
 	 *	for TCP and UDP is to consider one TCP and UDP instance
@@ -1234,10 +1229,6 @@ ipmr_fail:
 icmp_fail:
 	unregister_pernet_subsys(&inet6_net_ops);
 register_pernet_fail:
-#ifdef CONFIG_SYSCTL
-	ipv6_static_sysctl_unregister();
-static_sysctl_fail:
-#endif
 	sock_unregister(PF_INET6);
 	rtnl_unregister_all(PF_INET6);
 out_sock_register_fail:
@@ -1294,9 +1285,6 @@ static void __exit inet6_exit(void)
 	rawv6_exit();
 
 	unregister_pernet_subsys(&inet6_net_ops);
-#ifdef CONFIG_SYSCTL
-	ipv6_static_sysctl_unregister();
-#endif
 	proto_unregister(&rawv6_prot);
 	proto_unregister(&udplitev6_prot);
 	proto_unregister(&udpv6_prot);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 61ff29b..1cbc3c6 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1790,19 +1790,58 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write,
 
 #endif
 
+
+#ifdef CONFIG_SYSCTL
+
+/* empty entry for '/proc/sys/net/ipv6/neigh/' */
+static __net_initdata struct ctl_table empty[1];
+static __net_initdata struct ctl_table ipv6_neigh_skel[] = {
+	{
+		.procname       = "neigh",
+		.mode           = 0555,
+		.child          = empty,
+	},
+	{ },
+};
+static __net_initdata const struct ctl_path net_ipv6_path[] = {
+	{ .procname = "net", },
+	{ .procname = "ipv6", },
+	{ },
+};
+
+#endif /* CONFIG_SYSCTL */
+
 static int __net_init ndisc_net_init(struct net *net)
 {
 	struct ipv6_pinfo *np;
 	struct sock *sk;
 	int err;
 
+#ifdef CONFIG_SYSCTL
+	err = -ENOMEM;
+	/* register empty dir for /proc/sys/net/ipv6/neigh/ */
+	net->ipv6.sysctl.neigh_hdr = register_net_sysctl_table(net,
+					net_ipv6_path, ipv6_neigh_skel);
+	if (net->ipv6.sysctl.neigh_hdr == NULL)
+		goto register_net_neigh_skel_fail;
+
+	/* register /proc/sys/net/ipv6/neigh/default */
+	if (net_eq(net, &init_net)) {
+		err = neigh_sysctl_register(NULL, &nd_tbl.parms, "ipv6",
+					    &ndisc_ifinfo_sysctl_change);
+		if (err)
+			goto neigh_sysctl_register_fail;
+	}
+#endif /* CONFIG_SYSCTL */
+
+
 	err = inet_ctl_sock_create(&sk, PF_INET6,
 				   SOCK_RAW, IPPROTO_ICMPV6, net);
 	if (err < 0) {
 		ND_PRINTK0(KERN_ERR
 			   "ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
 			   err);
-		return err;
+		goto inet_ctl_sock_create_fail;
 	}
 
 	net->ipv6.ndisc_sk = sk;
@@ -1813,11 +1852,26 @@ static int __net_init ndisc_net_init(struct net *net)
 	np->mc_loop = 0;
 
 	return 0;
+
+inet_ctl_sock_create_fail:
+
+#ifdef CONFIG_SYSCTL
+	neigh_sysctl_unregister(&nd_tbl.parms);
+neigh_sysctl_register_fail:
+	unregister_net_sysctl_table(net->ipv6.sysctl.neigh_hdr);
+register_net_neigh_skel_fail:
+#endif /* CONFIG_SYSCTL */
+
+	return err;
 }
 
 static void __net_exit ndisc_net_exit(struct net *net)
 {
 	inet_ctl_sock_destroy(net->ipv6.ndisc_sk);
+#ifdef CONFIG_SYSCTL
+	neigh_sysctl_unregister(&nd_tbl.parms);
+	unregister_net_sysctl_table(net->ipv6.sysctl.neigh_hdr);
+#endif /* CONFIG_SYSCTL */
 }
 
 static struct pernet_operations ndisc_net_ops = {
@@ -1829,20 +1883,15 @@ int __init ndisc_init(void)
 {
 	int err;
 
-	err = register_pernet_subsys(&ndisc_net_ops);
-	if (err)
-		return err;
 	/*
 	 * Initialize the neighbour table
 	 */
 	neigh_table_init(&nd_tbl);
 
-#ifdef CONFIG_SYSCTL
-	err = neigh_sysctl_register(NULL, &nd_tbl.parms, "ipv6",
-				    &ndisc_ifinfo_sysctl_change);
+	err = register_pernet_subsys(&ndisc_net_ops);
 	if (err)
-		goto out_unregister_pernet;
-#endif
+		return err;
+
 	err = register_netdevice_notifier(&ndisc_netdev_notifier);
 	if (err)
 		goto out_unregister_sysctl;
@@ -1850,10 +1899,6 @@ out:
 	return err;
 
 out_unregister_sysctl:
-#ifdef CONFIG_SYSCTL
-	neigh_sysctl_unregister(&nd_tbl.parms);
-out_unregister_pernet:
-#endif
 	unregister_pernet_subsys(&ndisc_net_ops);
 	goto out;
 }
@@ -1861,9 +1906,6 @@ out_unregister_pernet:
 void ndisc_cleanup(void)
 {
 	unregister_netdevice_notifier(&ndisc_netdev_notifier);
-#ifdef CONFIG_SYSCTL
-	neigh_sysctl_unregister(&nd_tbl.parms);
-#endif
-	neigh_table_clear(&nd_tbl);
 	unregister_pernet_subsys(&ndisc_net_ops);
+	neigh_table_clear(&nd_tbl);
 }
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 1b6f6fd..b55462f 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -15,18 +15,6 @@
 #include <net/addrconf.h>
 #include <net/inet_frag.h>
 
-static struct ctl_table empty[1];
-
-static ctl_table ipv6_static_skeleton[] = {
-	{
-		.procname	= "neigh",
-		.maxlen		= 0,
-		.mode		= 0555,
-		.child		= empty,
-	},
-	{ }
-};
-
 static ctl_table ipv6_table[] = {
 	{
 		.procname	= "route",
@@ -114,18 +102,3 @@ void ipv6_sysctl_unregister(void)
 	unregister_net_sysctl_table(ip6_header);
 	unregister_pernet_subsys(&ipv6_sysctl_net_ops);
 }
-
-static struct ctl_table_header *ip6_base;
-
-int ipv6_static_sysctl_register(void)
-{
-	ip6_base = register_sysctl_paths(net_ipv6_ctl_path, ipv6_static_skeleton);
-	if (ip6_base == NULL)
-		return -ENOMEM;
-	return 0;
-}
-
-void ipv6_static_sysctl_unregister(void)
-{
-	unregister_net_sysctl_table(ip6_base);
-}
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 22/24] sysctl: ipv4: register /proc/sys/net/ipv4/neigh empty directory
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

As opposed to the patches that added the /proc/sys/net/ipv4/conf and
/proc/sys/net/ipv6/conf empty directories, this patch does include a
change in semantics.

Before this patch /proc/sys/net/ipv4/neigh/default/ was registered
from arp_init() directly.

This patch adds new pernet_operations in which it first registers
/proc/sys/net/ipv4/neigh/ and afterwards /proc/sys/net/ipv4/neigh/default/.

These operations are ran for each network namespace in part, even for
init_net (which is the only net that sees the 'default' entry), thus
/proc/sys/net/ipv4/neigh/default/ gets registered, just that the
registration now happens later that before this patch.

In testing this did not seem to create problems, but I haven't checked
the code thoroughly.

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 include/net/netns/ipv4.h |    1 +
 net/ipv4/arp.c           |   70 ++++++++++++++++++++++++++++++++++++++++++++--
 net/ipv4/route.c         |   13 ++++----
 3 files changed, 74 insertions(+), 10 deletions(-)

diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index cdb8307..182dc69 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -17,6 +17,7 @@ struct netns_ipv4 {
 #ifdef CONFIG_SYSCTL
 	struct ctl_table_header	*forw_hdr;   /* /proc/sys/net/ipv4/ip_forward */
 	struct ctl_table_header	*conf_hdr;   /* /proc/sys/net/ipv4/conf/ */
+	struct ctl_table_header	*neigh_hdr;  /* /proc/sys/net/ipv4/neigh/ */
 	struct ctl_table_header	*frags_hdr;  /* /proc/sys/net/ipv4/ipfrag_* */
 	struct ctl_table_header	*ipv4_hdr;   /* see @ipv4_net_table */
 	struct ctl_table_header *route_hdr;  /* /proc/sys/net/ipv4/route/flush */
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 090d273..d38654f 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1302,6 +1302,7 @@ static struct packet_type arp_packet_type __read_mostly = {
 };
 
 static int arp_proc_init(void);
+static int __init arp_sysctl_init(void);
 
 void __init arp_init(void)
 {
@@ -1309,9 +1310,7 @@ void __init arp_init(void)
 
 	dev_add_pack(&arp_packet_type);
 	arp_proc_init();
-#ifdef CONFIG_SYSCTL
-	neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL);
-#endif
+	arp_sysctl_init();
 	register_netdevice_notifier(&arp_netdev_notifier);
 }
 
@@ -1478,3 +1477,68 @@ static int __init arp_proc_init(void)
 }
 
 #endif /* CONFIG_PROC_FS */
+
+
+
+#ifdef CONFIG_SYSCTL
+
+/* empty entry for '/proc/sys/net/ipv4/neigh/' */
+static struct ctl_table empty[1];
+static struct ctl_table ipv4_neigh_skel[] = {
+	{
+		.procname       = "neigh",
+		.mode           = 0555,
+		.child          = empty,
+	},
+	{ },
+};
+static __net_initdata const struct ctl_path net_ipv4_path[] = {
+	{ .procname = "net", },
+	{ .procname = "ipv4", },
+	{ },
+};
+
+static int __net_init arp_sysctl_net_init(struct net *net)
+{
+	/* register empty dir for /proc/sys/net/ipv4/neigh/ */
+	net->ipv4.neigh_hdr = register_net_sysctl_table(net,
+					net_ipv4_path, ipv4_neigh_skel);
+	if (net->ipv4.neigh_hdr == NULL)
+		return -ENOMEM;
+
+	/* register /proc/sys/net/ipv4/neigh/default */
+	if (net_eq(net, &init_net)) {
+		int err;
+		err = neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL);
+		if (err) {
+			unregister_net_sysctl_table(net->ipv4.neigh_hdr);
+			return err;
+		}
+	}
+	return 0;
+}
+
+static void __net_exit arp_sysctl_net_exit(struct net *net)
+{
+	neigh_sysctl_unregister(&arp_tbl.parms);
+	unregister_sysctl_table(net->ipv4.neigh_hdr);
+}
+
+static struct pernet_operations arp_sysctl_ops = {
+	.init = arp_sysctl_net_init,
+	.exit = arp_sysctl_net_exit,
+};
+
+static int __init arp_sysctl_init(void)
+{
+	return register_pernet_subsys(&arp_sysctl_ops);
+}
+
+#else /* CONFIG_SYSCTL */
+
+static int __init arp_sysctl_init(void)
+{
+	return 0;
+}
+
+#endif /* CONFIG_SYSCTL */
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 1e99f01..180a10d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3139,15 +3139,14 @@ static ctl_table ipv4_route_table[] = {
 	{ }
 };
 
-static struct ctl_table empty[1];
-
 static struct ctl_table ipv4_skeleton[] =
 {
-	{ .procname = "route", 
-	  .mode = 0555, .child = ipv4_route_table},
-	{ .procname = "neigh", 
-	  .mode = 0555, .child = empty},
-	{ }
+	{
+		.procname = "route",
+		.mode     = 0555,
+		.child    = ipv4_route_table,
+	},
+	{ },
 };
 
 static __net_initdata struct ctl_path ipv4_path[] = {
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 21/24] sysctl: ipv6: register addrconf tables as private children
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

This halves the time it takes to add an interface:

$ time modprobe dummy numdummies=$n

Without this patch:
 - n=5000 => real:  9:14m, sys: 8:46m
 - n=2000 => real:  1:19m, sys: 1:17m
 - n=1000 => real:  0:14m, sys: 0:14m

With this patch:
 - n=5000 => real:  4:43m, sys: 4:32m
 - n=2000 => real:  0:39m, sys: 0:39m
 - n=1000 => real:  0:07m, sys: 0:07m

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 net/ipv6/addrconf.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6833fcb..6ac29d0 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4512,8 +4512,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
 
 	addrconf_ctl_path[ADDRCONF_CTL_PATH_DEV].procname = t->dev_name;
 
-	t->sysctl_header = register_net_sysctl_table(net, addrconf_ctl_path,
-			t->addrconf_vars);
+	t->sysctl_header = register_net_sysctl_table_with_parent(net,
+	        addrconf_ctl_path, t->addrconf_vars, net->ipv6.sysctl.conf_hdr);
 	if (t->sysctl_header == NULL)
 		goto free_procname;
 
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 20/24] sysctl: ipv6: register /proc/sys/net/ipv6/conf empty directory
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

This does not change any semantics: it just adds a new header that
will be used in the next patch as a parent for all headers for
all /proc/sys/net/ipv6/conf/DEVNAME entries.

For now, all interface headers for /proc/sys/net/ipv6/conf/DEVNAME
will be bound to this header as opposed to another one from above, but
this shouldn't affect performance or behaviour.

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 include/net/netns/ipv6.h |    3 ++-
 net/ipv6/addrconf.c      |   29 ++++++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 81abfcb..b3c3cd7 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -13,7 +13,8 @@ struct ctl_table_header;
 struct netns_sysctl_ipv6 {
 #ifdef CONFIG_SYSCTL
 	struct ctl_table_header *table;
-	struct ctl_table_header *frags_hdr;
+	struct ctl_table_header *frags_hdr;  /* /proc/sys/net/ipv6/ip6frag_*  */
+	struct ctl_table_header *conf_hdr;   /* /proc/sys/net/ipv6/conf/      */
 #endif
 	int bindv6only;
 	int flush_delay;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 4a28442..6833fcb 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4556,8 +4556,25 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev)
 	neigh_sysctl_unregister(idev->nd_parms);
 }
 
+/* empty entry for '/proc/sys/net/ipv6/conf/' */
+static __net_initdata struct ctl_table empty[1];
+static __net_initdata struct ctl_table ipv6_conf_skel[] = {
+	{
+		.procname       = "conf",
+		.mode           = 0555,
+		.child          = empty,
+	},
+	{ },
+};
+
+static __net_initdata const struct ctl_path net_ipv6_path[] = {
+	{ .procname = "net", },
+	{ .procname = "ipv6", },
+	{ },
+};
+
+#endif /* CONFIG_SYSCTL */
 
-#endif
 
 static int __net_init addrconf_init_net(struct net *net)
 {
@@ -4586,6 +4603,12 @@ static int __net_init addrconf_init_net(struct net *net)
 	net->ipv6.devconf_dflt = dflt;
 
 #ifdef CONFIG_SYSCTL
+	err = -ENOMEM;
+	net->ipv6.sysctl.conf_hdr = register_net_sysctl_table(net,
+					net_ipv6_path, ipv6_conf_skel);
+	if (net->ipv6.sysctl.conf_hdr == NULL)
+		goto err_reg_conf;
+
 	err = __addrconf_sysctl_register(net, "all", NULL, all);
 	if (err < 0)
 		goto err_reg_all;
@@ -4593,6 +4616,7 @@ static int __net_init addrconf_init_net(struct net *net)
 	err = __addrconf_sysctl_register(net, "default", NULL, dflt);
 	if (err < 0)
 		goto err_reg_dflt;
+
 #endif
 	return 0;
 
@@ -4600,6 +4624,8 @@ static int __net_init addrconf_init_net(struct net *net)
 err_reg_dflt:
 	__addrconf_sysctl_unregister(all);
 err_reg_all:
+	unregister_net_sysctl_table(net->ipv6.sysctl.conf_hdr);
+err_reg_conf:
 	kfree(dflt);
 #endif
 err_alloc_dflt:
@@ -4613,6 +4639,7 @@ static void __net_exit addrconf_exit_net(struct net *net)
 #ifdef CONFIG_SYSCTL
 	__addrconf_sysctl_unregister(net->ipv6.devconf_dflt);
 	__addrconf_sysctl_unregister(net->ipv6.devconf_all);
+	unregister_net_sysctl_table(net->ipv6.sysctl.conf_hdr);
 #endif
 	if (!net_eq(net, &init_net)) {
 		kfree(net->ipv6.devconf_dflt);
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 19/24] sysctl: ipv4: register devinet tables as private children
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

This halves the time it takes to add an interface:

$ time modprobe dummy numdummies=$n

Without this patch:
 - n=5000 => real: 17:31m, sys 15:29m
 - n=2000 => real:  2:23m, sys  2:19m
 - n=1000 => real:  0:25m, sys  0:24m

With this patch:
 - n=5000 => real:  9:14m, sys: 8:46m
 - n=2000 => real:  1:19m, sys: 1:17m
 - n=1000 => real:  0:14m, sys: 0:14m

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 net/ipv4/devinet.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a31cc90..2a10365 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1656,8 +1656,8 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
 
 	devinet_ctl_path[DEVINET_CTL_PATH_DEV].procname = t->dev_name;
 
-	t->sysctl_header = register_net_sysctl_table(net, devinet_ctl_path,
-			t->devinet_vars);
+	t->sysctl_header = register_net_sysctl_table_with_parent(net,
+			 devinet_ctl_path, t->devinet_vars, net->ipv4.conf_hdr);
 	if (!t->sysctl_header)
 		goto free_procname;
 
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 18/24] sysctl: ipv4: register /proc/sys/net/ipv4/conf empty directory
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

This does not change any semantics: it just adds a new header that
will be used in the next patch as a parent for all headers for
all /proc/sys/net/ipv4/conf/DEVNAME entries.

For now, all interface headers for /proc/sys/net/ipv4/conf/DEVNAME
will be bound to this header as opposed to another one from above, but
this shouldn't affect performance or behaviour.

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 include/net/netns/ipv4.h |    9 +++++----
 net/ipv4/devinet.c       |   25 +++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 542195d..cdb8307 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -15,10 +15,11 @@ struct sock;
 
 struct netns_ipv4 {
 #ifdef CONFIG_SYSCTL
-	struct ctl_table_header	*forw_hdr;
-	struct ctl_table_header	*frags_hdr;
-	struct ctl_table_header	*ipv4_hdr;
-	struct ctl_table_header *route_hdr;
+	struct ctl_table_header	*forw_hdr;   /* /proc/sys/net/ipv4/ip_forward */
+	struct ctl_table_header	*conf_hdr;   /* /proc/sys/net/ipv4/conf/ */
+	struct ctl_table_header	*frags_hdr;  /* /proc/sys/net/ipv4/ipfrag_* */
+	struct ctl_table_header	*ipv4_hdr;   /* see @ipv4_net_table */
+	struct ctl_table_header *route_hdr;  /* /proc/sys/net/ipv4/route/flush */
 #endif
 	struct ipv4_devconf	*devconf_all;
 	struct ipv4_devconf	*devconf_dflt;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 551786f..a31cc90 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1698,6 +1698,18 @@ static void devinet_sysctl_unregister(struct in_device *idev)
 	neigh_sysctl_unregister(idev->arp_parms);
 }
 
+
+/* empty entry for '/proc/sys/net/ipv4/conf/' */
+static __net_initdata struct ctl_table empty[1];
+static __net_initdata struct ctl_table ipv4_conf_skel[] = {
+	{
+		.procname	= "conf",
+		.mode		= 0555,
+		.child		= empty,
+	},
+	{ },
+};
+
 static struct ctl_table ctl_forward_entry[] = {
 	{
 		.procname	= "ip_forward",
@@ -1712,7 +1724,7 @@ static struct ctl_table ctl_forward_entry[] = {
 	{ },
 };
 
-static __net_initdata struct ctl_path net_ipv4_path[] = {
+static __net_initdata const struct ctl_path net_ipv4_path[] = {
 	{ .procname = "net", },
 	{ .procname = "ipv4", },
 	{ },
@@ -1725,7 +1737,7 @@ static __net_init int devinet_init_net(struct net *net)
 	struct ipv4_devconf *all, *dflt;
 #ifdef CONFIG_SYSCTL
 	struct ctl_table *tbl = ctl_forward_entry;
-	struct ctl_table_header *forw_hdr;
+	struct ctl_table_header *forw_hdr, *conf_hdr;
 #endif
 
 	err = -ENOMEM;
@@ -1753,6 +1765,12 @@ static __net_init int devinet_init_net(struct net *net)
 	}
 
 #ifdef CONFIG_SYSCTL
+	err = -ENOMEM;
+	conf_hdr = register_net_sysctl_table(net, net_ipv4_path, ipv4_conf_skel);
+	if (conf_hdr == NULL)
+		goto err_reg_conf;
+	net->ipv4.conf_hdr = conf_hdr;
+
 	err = __devinet_sysctl_register(net, "all", all);
 	if (err < 0)
 		goto err_reg_all;
@@ -1778,6 +1796,8 @@ err_reg_ctl:
 err_reg_dflt:
 	__devinet_sysctl_unregister(all);
 err_reg_all:
+	unregister_net_sysctl_table(conf_hdr);
+err_reg_conf:
 	if (tbl != ctl_forward_entry)
 		kfree(tbl);
 err_alloc_ctl:
@@ -1800,6 +1820,7 @@ static __net_exit void devinet_exit_net(struct net *net)
 	unregister_net_sysctl_table(net->ipv4.forw_hdr);
 	__devinet_sysctl_unregister(net->ipv4.devconf_dflt);
 	__devinet_sysctl_unregister(net->ipv4.devconf_all);
+	unregister_net_sysctl_table(net->ipv4.conf_hdr);
 	kfree(tbl);
 #endif
 	kfree(net->ipv4.devconf_dflt);
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 17/24] sysctl: add register_net_sysctl_table_with_parent
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 include/net/net_namespace.h |    3 +++
 net/sysctl_net.c            |   20 +++++++++++++++++---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 86c6e57..dd4d3cf 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -272,6 +272,9 @@ struct ctl_path;
 struct ctl_table;
 struct ctl_table_header;
 
+extern struct ctl_table_header *register_net_sysctl_table_with_parent(
+	struct net *net, const struct ctl_path *path,
+	struct ctl_table *table, struct ctl_table_header *parent);
 extern struct ctl_table_header *register_net_sysctl_table(struct net *net,
 	const struct ctl_path *path, struct ctl_table *table);
 extern struct ctl_table_header *register_net_sysctl_rotable(
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index aa6c6f4..a4f853a 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -103,14 +103,28 @@ out:
 }
 subsys_initcall(sysctl_init);
 
-struct ctl_table_header *register_net_sysctl_table(struct net *net,
-	const struct ctl_path *path, struct ctl_table *table)
+/* The newly created ctl_table_header will be a member of the parent's
+ * private_children list. The following restrictions apply:
+ * - the children must be freed before the parent
+ * - the children are assumed to be unique (no duplicate checks)
+ * - the children are not listed under attached_to/attached_by
+ * - you cannot attach another node under a private child. */
+struct ctl_table_header *register_net_sysctl_table_with_parent(struct net *net,
+	const struct ctl_path *path, struct ctl_table *table,
+	struct ctl_table_header *parent)
 {
 	struct nsproxy namespaces;
 	namespaces = *current->nsproxy;
 	namespaces.net_ns = net;
 	return __register_sysctl_paths(&net_sysctl_root, &namespaces, path,
-				       table, net, NULL);
+				       table, net, parent);
+}
+EXPORT_SYMBOL_GPL(register_net_sysctl_table_with_parent);
+
+struct ctl_table_header *register_net_sysctl_table(struct net *net,
+	const struct ctl_path *path, struct ctl_table *table)
+{
+	return register_net_sysctl_table_with_parent(net, path, table, NULL);
 }
 EXPORT_SYMBOL_GPL(register_net_sysctl_table);
 
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 16/24] sysctl: add support for private_children headers
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

Problem:

- some subsystems register a lot of sysctl tables in a well known
  place.  e.g. all the '/proc/sys/net/ipv4/conf/$DEVNAME' headers
  under '/proc/sys/net/ipv4/conf/'.

- each time we look for a header we search the list of all headers in
  it's set (each network namespace specific headers gets it's own set)

When to use private_children:

- when you have registered the parent node of the table you're
  registering, and you know no other node with a path closer to the
  one you're registering will be registered.

- when you don't want to register another table underneath the header
  you're registering

- when you don't need to check for duplicate table names (you have
  external logic that prevents duplicates).

Advantages of private_children usage:

- the private children are not checked for duplicates

- the private children will be attached to the specified parent. We
  don't compute the parent by checking with all headers in the set.

- the private children list will only be accessed if the specified
  parent was accessed. All non-private headers in the set are iterated
  over when looking for headers attached to another header.

Private headers bring these benefits:

- fast insertion time: O(1) [no duplicate check, fixed parent]

- fast lookup time: only search the parent and it's private_children
  Not looking over the list of all headers.

- fewer headers in the per-set list of headers => overall reduced
  insertion/lookup times

Notes for reviewers: there is also room for improvement:

- The cost of checking the list of private children can be very low by
  limiting the cases where private children may be used:

For example:
	p = find_in_table(table, name);
	if (!p)
		for (h = sysctl_private_child_next(NULL, head); h;
		     h = sysctl_private_child_next(h, head)) { ... }

can be converted into:
	if (table->procname)
	   p = find_in_table(table, name);
	else
		for (h = sysctl_private_child_next(NULL, head); h;
		     h = sysctl_private_child_next(h, head)) { ... }

If only headers that point to empty directories are allowed to hold
private children, and all private children are located in the deepest
element of the path, we can use the second variant.

I didn't limit the usability of private children in this patch,
because someone else may find use for them in contexts that I have not
foreseen, but all of the patches that follow in this series respect
this restriction: e.g.:
- the parent header is an empty dir /proc/sys/net/ipv4/conf/
- all children are of the for /proc/sys/net/ipv4/conf/DEVNAME. No
  private child is registered at a level higher that 'conf'.

Another optimisation would be to replace the linked list of private
children with a hashtable: this would lower the lookup times, but
would cost more memory and complicate the disposal logic.

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 fs/proc/proc_sysctl.c  |   21 ++++++++++++++
 include/linux/sysctl.h |   12 +++++++-
 kernel/sysctl.c        |   72 +++++++++++++++++++++++++++++++++++++++++------
 net/sysctl_net.c       |    4 +-
 4 files changed, 96 insertions(+), 13 deletions(-)

diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index f1e91e7..5e79c0b 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -99,6 +99,16 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
 
 	p = find_in_table(table, name);
 	if (!p) {
+		for (h = sysctl_private_child_next(NULL, head); h;
+		     h = sysctl_private_child_next(h, head)) {
+			if (h->attached_to != table)
+				continue;
+			p = find_in_table(h->attached_by, name);
+			if (p)
+				break;
+		}
+	}
+	if (!p) {
 		for (h = sysctl_head_next(NULL); h; h = sysctl_head_next(h)) {
 			if (h->attached_to != table)
 				continue;
@@ -280,6 +290,17 @@ static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	if (ret)
 		goto out;
 
+	for (h = sysctl_private_child_next(NULL, head); h;
+	     h = sysctl_private_child_next(h, head)) {
+		if (h->attached_to != table)
+			continue;
+		ret = scan(h, h->attached_by, &pos, filp, dirent, filldir);
+		if (ret) {
+			sysctl_head_finish(h);
+			break;
+		}
+	}
+
 	for (h = sysctl_head_next(NULL); h; h = sysctl_head_next(h)) {
 		if (h->attached_to != table)
 			continue;
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index f0eb817..f7addab 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -956,6 +956,8 @@ extern struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *);
 extern struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev);
 extern struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
 						struct ctl_table_header *prev);
+extern struct ctl_table_header *sysctl_private_child_next(
+	struct ctl_table_header *prev, struct ctl_table_header *parent);
 extern void sysctl_head_finish(struct ctl_table_header *prev);
 extern int sysctl_perm(struct ctl_table_root *root,
 		struct ctl_table *table, int op);
@@ -1067,6 +1069,13 @@ struct ctl_table_header
 	/* Pointer to data that outlives this ctl_table_header.
 	 * Caller responsible to free the cookie. */
 	void *ctl_header_cookie;
+
+	/* List of other headers that are 'children' of this header:
+	 * - the children must be freed before this header
+	 * - the children are assumed to be unique (no duplicate checks)
+	 * - the children are not listed under attached_to/attached_by
+	 * - you cannot attach another node under a private child. */
+	struct list_head private_children;
 };
 
 /* struct ctl_path describes where in the hierarchy a table is added */
@@ -1077,7 +1086,8 @@ struct ctl_path {
 void register_sysctl_root(struct ctl_table_root *root);
 struct ctl_table_header *__register_sysctl_paths(
 	struct ctl_table_root *root, struct nsproxy *namespaces,
-	const struct ctl_path *path, struct ctl_table *table, void *cookie);
+	const struct ctl_path *path, struct ctl_table *table,
+	void *cookie, struct ctl_table_header *private_parent);
 struct ctl_table_header *register_sysctl_table(struct ctl_table * table);
 struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
 						struct ctl_table *table);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index cd7340d..2639029 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -209,6 +209,7 @@ static struct ctl_table_header root_table_header = {
 	.root = &sysctl_table_root,
 	.set = &sysctl_table_root.default_set,
 	.ctl_header_cookie = NULL,
+	.private_children = LIST_HEAD_INIT(root_table_header.private_children),
 };
 static struct ctl_table_root sysctl_table_root = {
 	.root_list = LIST_HEAD_INIT(sysctl_table_root.root_list),
@@ -1676,6 +1677,38 @@ struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
 	return __sysctl_head_next(current->nsproxy, prev);
 }
 
+struct ctl_table_header *
+sysctl_private_child_next(struct ctl_table_header *prev,
+			  struct ctl_table_header *parent)
+{
+	struct list_head *tmp;
+
+	if (!parent)
+		return NULL;
+
+	spin_lock(&sysctl_lock);
+	if (prev) {
+		tmp = prev->ctl_entry.next;
+		unuse_table(prev);
+	} else {
+		tmp = parent->private_children.next;
+	}
+	for (;;) {
+		struct ctl_table_header *head;
+		if (tmp == &parent->private_children)
+			break; /* reached end-of-list sentinel */
+
+		head = list_entry(tmp, struct ctl_table_header, ctl_entry);
+		if (use_table(head)) {
+			spin_unlock(&sysctl_lock);
+			return head;
+		}
+		tmp = tmp->next;
+	}
+	spin_unlock(&sysctl_lock);
+	return NULL;
+}
+
 void register_sysctl_root(struct ctl_table_root *root)
 {
 	spin_lock(&sysctl_lock);
@@ -1788,6 +1821,16 @@ static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
  * @cookie: Pointer to user provided data that must be accessible
  *  until unregister_sysctl_table. This cookie will be passed to the
  *  proc_handler.
+ * @private_parent: if NULL then the the created header will have as a
+ *  parent the first header registered with the closest matching path.
+ *  If not-NULL, the created header will be ca private child of
+ *  @private_parent. There will be no attempt to check whether there
+ *  is a better match for a parent (another header with a closer
+ *  matching path). To be used when you dynamically create a lot of
+ *  headers under the same path. E.g. when creating an entry for eth0
+ *  under '/proc/sys/net/ipv4/conf/eth0', set @private_parent to the
+ *  header corresponding to '/proc/sys/net/ipv4/conf/'
+ *
  *
  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. A completely 0 filled entry terminates the table.
@@ -1837,7 +1880,8 @@ static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
  */
 struct ctl_table_header *__register_sysctl_paths(
 	struct ctl_table_root *root, struct nsproxy *namespaces,
-	const struct ctl_path *path, struct ctl_table *table, void *cookie)
+	const struct ctl_path *path, struct ctl_table *table,
+	void *cookie, struct ctl_table_header *private_parent)
 {
 	struct ctl_table_header *header;
 	struct ctl_table *new, **prevp;
@@ -1879,6 +1923,7 @@ struct ctl_table_header *__register_sysctl_paths(
 	header->ctl_table_arg = table;
 
 	INIT_LIST_HEAD(&header->ctl_entry);
+	INIT_LIST_HEAD(&header->private_children);
 	header->used = 0;
 	header->unregistering = NULL;
 	header->root = root;
@@ -1886,26 +1931,33 @@ struct ctl_table_header *__register_sysctl_paths(
 	header->count = 1;
 	header->ctl_header_cookie = cookie;
 #ifdef CONFIG_SYSCTL_SYSCALL_CHECK
-	if (sysctl_check_table(namespaces, header->ctl_table)) {
+	if (!private_parent && sysctl_check_table(namespaces, header->ctl_table)) {
 		kfree(header);
 		return NULL;
 	}
 #endif
 	spin_lock(&sysctl_lock);
+
 	header->set = lookup_header_set(root, namespaces);
 	header->attached_by = header->ctl_table;
 	header->attached_to = root_table;
 	header->parent = &root_table_header;
-	for (set = header->set; set; set = set->parent) {
-		struct ctl_table_header *p;
-		list_for_each_entry(p, &set->list, ctl_entry) {
-			if (p->unregistering)
-				continue;
-			try_attach(p, header);
+
+	if (private_parent) {
+		try_attach(private_parent, header);
+		list_add_tail(&header->ctl_entry, &private_parent->private_children);
+	} else {
+		for (set = header->set; set; set = set->parent) {
+			struct ctl_table_header *p;
+			list_for_each_entry(p, &set->list, ctl_entry) {
+				if (p->unregistering)
+					continue;
+				try_attach(p, header);
+			}
 		}
+		list_add_tail(&header->ctl_entry, &header->set->list);
 	}
 	header->parent->count++;
-	list_add_tail(&header->ctl_entry, &header->set->list);
 	spin_unlock(&sysctl_lock);
 
 	return header;
@@ -1925,7 +1977,7 @@ struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
 						struct ctl_table *table)
 {
 	return __register_sysctl_paths(&sysctl_table_root, current->nsproxy,
-				       path, table, NULL);
+				       path, table, NULL, NULL);
 }
 
 /**
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index 7447d6e..aa6c6f4 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -110,7 +110,7 @@ struct ctl_table_header *register_net_sysctl_table(struct net *net,
 	namespaces = *current->nsproxy;
 	namespaces.net_ns = net;
 	return __register_sysctl_paths(&net_sysctl_root, &namespaces, path,
-				       table, net);
+				       table, net, NULL);
 }
 EXPORT_SYMBOL_GPL(register_net_sysctl_table);
 
@@ -118,7 +118,7 @@ struct ctl_table_header *register_net_sysctl_rotable(const
 		struct ctl_path *path, struct ctl_table *table)
 {
 	return __register_sysctl_paths(&net_sysctl_ro_root,
-				       &init_nsproxy, path, table, NULL);
+				       &init_nsproxy, path, table, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(register_net_sysctl_rotable);
 
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 15/24] sysctl: cookie: share xfrm_table between nets
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 net/xfrm/xfrm_sysctl.c |   37 +++++++++++--------------------------
 1 files changed, 11 insertions(+), 26 deletions(-)

diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
index 05640bc..9ca4e05 100644
--- a/net/xfrm/xfrm_sysctl.c
+++ b/net/xfrm/xfrm_sysctl.c
@@ -15,63 +15,48 @@ static void __net_init __xfrm_sysctl_init(struct net *net)
 static struct ctl_table xfrm_table[] = {
 	{
 		.procname	= "xfrm_aevent_etime",
+		.data		= &init_net.xfrm.sysctl_aevent_etime,
 		.maxlen		= sizeof(u32),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "xfrm_aevent_rseqth",
+		.data		= &init_net.xfrm.sysctl_aevent_rseqth,
 		.maxlen		= sizeof(u32),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "xfrm_larval_drop",
+		.data		= &init_net.xfrm.sysctl_larval_drop,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "xfrm_acq_expires",
+		.data		= &init_net.xfrm.sysctl_acq_expires,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{}
 };
 
 int __net_init xfrm_sysctl_init(struct net *net)
 {
-	struct ctl_table *table;
-
 	__xfrm_sysctl_init(net);
-
-	table = kmemdup(xfrm_table, sizeof(xfrm_table), GFP_KERNEL);
-	if (!table)
-		goto out_kmemdup;
-	table[0].data = &net->xfrm.sysctl_aevent_etime;
-	table[1].data = &net->xfrm.sysctl_aevent_rseqth;
-	table[2].data = &net->xfrm.sysctl_larval_drop;
-	table[3].data = &net->xfrm.sysctl_acq_expires;
-
-	net->xfrm.sysctl_hdr = register_net_sysctl_table(net, net_core_path, table);
+	net->xfrm.sysctl_hdr = register_net_sysctl_table(net,
+				 net_core_path, xfrm_table);
 	if (!net->xfrm.sysctl_hdr)
-		goto out_register;
+		return -ENOMEM;
 	return 0;
-
-out_register:
-	kfree(table);
-out_kmemdup:
-	return -ENOMEM;
 }
 
 void __net_exit xfrm_sysctl_fini(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = net->xfrm.sysctl_hdr->ctl_table_arg;
 	unregister_net_sysctl_table(net->xfrm.sysctl_hdr);
-	kfree(table);
 }
 #else
 int __net_init xfrm_sysctl_init(struct net *net)
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 14/24] sysctl: cookie: share unix_table between nets
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 net/unix/sysctl_net_unix.c |   22 +++-------------------
 1 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 397cffe..d514f62 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -21,7 +21,7 @@ static ctl_table unix_table[] = {
 		.data		= &init_net.unx.sysctl_max_dgram_qlen,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{ }
 };
@@ -34,30 +34,14 @@ static struct ctl_path unix_path[] = {
 
 int __net_init unix_sysctl_register(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = kmemdup(unix_table, sizeof(unix_table), GFP_KERNEL);
-	if (table == NULL)
-		goto err_alloc;
-
-	table[0].data = &net->unx.sysctl_max_dgram_qlen;
-	net->unx.ctl = register_net_sysctl_table(net, unix_path, table);
+	net->unx.ctl = register_net_sysctl_table(net, unix_path, unix_table);
 	if (net->unx.ctl == NULL)
-		goto err_reg;
+		return -ENOMEM;
 
 	return 0;
-
-err_reg:
-	kfree(table);
-err_alloc:
-	return -ENOMEM;
 }
 
 void unix_sysctl_unregister(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = net->unx.ctl->ctl_table_arg;
 	unregister_sysctl_table(net->unx.ctl);
-	kfree(table);
 }
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 13/24] sysctl: cookie: share nf_ct_sysctl_table between nets
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

Also, minor reordering at unregister: unregister sysctls in reverse order of registering.

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 net/netfilter/nf_conntrack_standalone.c |   30 ++++++------------------------
 1 files changed, 6 insertions(+), 24 deletions(-)

diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 0ae1428..42b8c3b 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -420,28 +420,28 @@ static ctl_table nf_ct_sysctl_table[] = {
 		.data		= &init_net.ct.count,
 		.maxlen		= sizeof(int),
 		.mode		= 0444,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname       = "nf_conntrack_buckets",
 		.data           = &init_net.ct.htable_size,
 		.maxlen         = sizeof(unsigned int),
 		.mode           = 0444,
-		.proc_handler   = proc_dointvec,
+		.proc_handler   = netns_proc_dointvec,
 	},
 	{
 		.procname	= "nf_conntrack_checksum",
 		.data		= &init_net.ct.sysctl_checksum,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "nf_conntrack_log_invalid",
 		.data		= &init_net.ct.sysctl_log_invalid,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
+		.proc_handler	= netns_proc_dointvec_minmax,
 		.extra1		= &log_invalid_proto_min,
 		.extra2		= &log_invalid_proto_max,
 	},
@@ -475,8 +475,6 @@ static struct ctl_path nf_ct_path[] = {
 
 static int nf_conntrack_standalone_init_sysctl(struct net *net)
 {
-	struct ctl_table *table;
-
 	if (net_eq(net, &init_net)) {
 		nf_ct_netfilter_header =
 		       register_sysctl_paths(nf_ct_path, nf_ct_netfilter_table);
@@ -484,26 +482,14 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
 			goto out;
 	}
 
-	table = kmemdup(nf_ct_sysctl_table, sizeof(nf_ct_sysctl_table),
-			GFP_KERNEL);
-	if (!table)
-		goto out_kmemdup;
-
-	table[1].data = &net->ct.count;
-	table[2].data = &net->ct.htable_size;
-	table[3].data = &net->ct.sysctl_checksum;
-	table[4].data = &net->ct.sysctl_log_invalid;
-
 	net->ct.sysctl_header = register_net_sysctl_table(net,
-					nf_net_netfilter_sysctl_path, table);
+			nf_net_netfilter_sysctl_path, nf_ct_sysctl_table);
 	if (!net->ct.sysctl_header)
 		goto out_unregister_netfilter;
 
 	return 0;
 
 out_unregister_netfilter:
-	kfree(table);
-out_kmemdup:
 	if (net_eq(net, &init_net))
 		unregister_sysctl_table(nf_ct_netfilter_header);
 out:
@@ -513,13 +499,9 @@ out:
 
 static void nf_conntrack_standalone_fini_sysctl(struct net *net)
 {
-	struct ctl_table *table;
-
+	unregister_net_sysctl_table(net->ct.sysctl_header);
 	if (net_eq(net, &init_net))
 		unregister_sysctl_table(nf_ct_netfilter_header);
-	table = net->ct.sysctl_header->ctl_table_arg;
-	unregister_net_sysctl_table(net->ct.sysctl_header);
-	kfree(table);
 }
 #else
 static int nf_conntrack_standalone_init_sysctl(struct net *net)
-- 
1.7.5.rc0


^ permalink raw reply related

* [PATCH 12/24] sysctl: cookie: share event_sysctl_table between nets
From: Lucian Adrian Grijincu @ 2011-04-02  2:53 UTC (permalink / raw)
  To: 'David S . Miller', Alexey Dobriyan, Eric W . Biederman,
	Octavian Purdila, linux-kernel
  Cc: Lucian Adrian Grijincu
In-Reply-To: <cover.1301711868.git.lucian.grijincu@gmail.com>

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 net/netfilter/nf_conntrack_ecache.c |   30 +++++-------------------------
 1 files changed, 5 insertions(+), 25 deletions(-)

diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 63a1b91..b799e9e 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -163,14 +163,14 @@ static struct ctl_table event_sysctl_table[] = {
 		.data		= &init_net.ct.sysctl_events,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "nf_conntrack_events_retry_timeout",
 		.data		= &init_net.ct.sysctl_events_retry_timeout,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_jiffies,
+		.proc_handler	= netns_proc_dointvec_jiffies,
 	},
 	{}
 };
@@ -185,38 +185,18 @@ static struct nf_ct_ext_type event_extend __read_mostly = {
 #ifdef CONFIG_SYSCTL
 static int nf_conntrack_event_init_sysctl(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = kmemdup(event_sysctl_table, sizeof(event_sysctl_table),
-			GFP_KERNEL);
-	if (!table)
-		goto out;
-
-	table[0].data = &net->ct.sysctl_events;
-	table[1].data = &net->ct.sysctl_events_retry_timeout;
-
-	net->ct.event_sysctl_header =
-		register_net_sysctl_table(net,
-					  nf_net_netfilter_sysctl_path, table);
+	net->ct.event_sysctl_header = register_net_sysctl_table(net,
+			  nf_net_netfilter_sysctl_path, event_sysctl_table);
 	if (!net->ct.event_sysctl_header) {
 		printk(KERN_ERR "nf_ct_event: can't register to sysctl.\n");
-		goto out_register;
+		return -ENOMEM;
 	}
 	return 0;
-
-out_register:
-	kfree(table);
-out:
-	return -ENOMEM;
 }
 
 static void nf_conntrack_event_fini_sysctl(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = net->ct.event_sysctl_header->ctl_table_arg;
 	unregister_net_sysctl_table(net->ct.event_sysctl_header);
-	kfree(table);
 }
 #else
 static int nf_conntrack_event_init_sysctl(struct net *net)
-- 
1.7.5.rc0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox