linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/24] v1: sysctl header cookies + private children
@ 2011-04-02  2:53 Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed Lucian Adrian Grijincu
                   ` (23 more replies)
  0 siblings, 24 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu


Hi,

The first patches in this series add a 'cookie' to the struct
ctl_table_header.  This cookie is used to store some data and is
passed to proc_handlers. The 'cookie' part series has already been
posted on netdev/lkml, but it was dropped because sysctl has a bigger
problem: an inefficient algorithm to add new tables.


This is where part two comes along: private ctl_table_header nodes.
Not all sysctl headers are the same: while some of them are at a high
level and have lots of other headers attached to them, most other
headers are children of another header and will never have a child
attached to them. With this in mind, we designate some of these
headers to be 'private children' (I don't really like this terminology
- I'm open to suggestions) of another header.

Performance suffers because every header is consulted:
- when we add a new header (to attach the new header somewhere)
- when lookup failed in a table: we consult every other header to see
  whether it was attached to this table.


Neither of these actions are performed for private children. With more
header registered as private, the number of headers consulted in these
steps lowers and performance is better.

Adding nodes for:
- /proc/sys/net/ipv4/conf/DEVNAME
- /proc/sys/net/ipv6/conf/DEVNAME
- /proc/sys/net/ipv4/neigh/DEVNAME
- /proc/sys/net/ipv6/neigh/DEVNAME
as private children has this effect:


$ time modprobe dummy numdummies=$n

Without these patches:
 - n=5000 => 17:31 minutes
 - n=2000 =>  2:23 minutes
 - n=1000 =>  0:25 minutes

With these patches:
 - n=5000 =>  12.50 seconds
 - n=2000 =>   1.59 seconds
 - n=1000 =>   0.44 seconds


I'll follow up with another series adding the cookie in a few more
places and removing some fields in ctl_table, but I'd like some
feedback for these patches.


Patches are against 2.6.39-rc1.

Lucian Adrian Grijincu (24):
  sysctl: net: call unregister_net_sysctl_table where needed
  sysctl: cookie: add ctl_header_cookie
  sysctl: cookie: pass ctl_header_cookie to proc_handler
  sysctl: cookie: add netns_proc_dointvec and other netns_proc_*
    proc_handlers
  sysctl: cookie: share ip4_frags_ns_ctl_table between nets
  sysctl: cookie: share netns_core_table between nets
  sysctl: cookie: share ipv4_route_flush_table between nets
  sysctl: cookie: share ipv4_net_table between nets
  sysctl: cookie: share ip6_frags_ns_ctl_table between nets
  sysctl: cookie: share ip6_ctl_table, ipv6_icmp_table and
    ipv6_route_table between nets
  sysctl: cookie: share acct_sysctl_table table between nets
  sysctl: cookie: share event_sysctl_table between nets
  sysctl: cookie: share nf_ct_sysctl_table between nets
  sysctl: cookie: share unix_table between nets
  sysctl: cookie: share xfrm_table between nets
  sysctl: add support for private_children headers
  sysctl: add register_net_sysctl_table_with_parent
  sysctl: ipv4: register /proc/sys/net/ipv4/conf empty directory
  sysctl: ipv4: register devinet tables as private children
  sysctl: ipv6: register /proc/sys/net/ipv6/conf empty directory
  sysctl: ipv6: register addrconf tables as private children
  sysctl: ipv4: register /proc/sys/net/ipv4/neigh empty directory
  sysctl: ipv6: register /proc/sys/net/ipv6/neigh empty directory
  sysctl: neigh: ipv4 and ipv6 neigh tables as private children

 arch/frv/kernel/pm.c                    |   22 ++--
 arch/frv/kernel/sysctl.c                |    4 +-
 arch/mips/lasat/sysctl.c                |   28 +++---
 arch/s390/appldata/appldata_base.c      |   15 ++--
 arch/s390/kernel/debug.c                |    6 +-
 arch/s390/mm/cmm.c                      |    4 +-
 drivers/cdrom/cdrom.c                   |   12 +-
 drivers/char/random.c                   |    6 +-
 drivers/macintosh/mac_hid.c             |    4 +-
 drivers/parport/procfs.c                |   29 +++---
 drivers/s390/char/sclp_async.c          |    2 +-
 fs/dcache.c                             |    4 +-
 fs/drop_caches.c                        |    5 +-
 fs/file_table.c                         |   10 +-
 fs/fscache/main.c                       |    6 +-
 fs/inode.c                              |    6 +-
 fs/pipe.c                               |    4 +-
 fs/proc/proc_sysctl.c                   |   24 ++++-
 fs/quota/dquot.c                        |    5 +-
 fs/xfs/linux-2.6/xfs_sysctl.c           |   10 +-
 include/linux/compaction.h              |    6 +-
 include/linux/fs.h                      |   12 +-
 include/linux/ftrace.h                  |    4 +-
 include/linux/hugetlb.h                 |   13 ++-
 include/linux/kprobes.h                 |    6 +-
 include/linux/mm.h                      |    4 +-
 include/linux/mmzone.h                  |   23 ++--
 include/linux/nmi.h                     |    4 +-
 include/linux/perf_event.h              |    2 +-
 include/linux/pipe_fs_i.h               |    2 +-
 include/linux/sched.h                   |   16 ++--
 include/linux/security.h                |    3 +-
 include/linux/swap.h                    |    4 +-
 include/linux/sysctl.h                  |   45 ++++++--
 include/linux/writeback.h               |   18 +--
 include/net/ipv6.h                      |    8 +-
 include/net/ndisc.h                     |    7 +-
 include/net/neighbour.h                 |    9 +-
 include/net/net_namespace.h             |   36 +++++++
 include/net/netns/ipv4.h                |   10 +-
 include/net/netns/ipv6.h                |    4 +-
 ipc/ipc_sysctl.c                        |   21 ++--
 ipc/mq_sysctl.c                         |   11 +-
 kernel/hung_task.c                      |    6 +-
 kernel/kprobes.c                        |    4 +-
 kernel/perf_event.c                     |    4 +-
 kernel/sched.c                          |    4 +-
 kernel/sched_fair.c                     |    4 +-
 kernel/sysctl.c                         |  171 +++++++++++++++++++++++--------
 kernel/trace/ftrace.c                   |    4 +-
 kernel/trace/trace_stack.c              |    4 +-
 kernel/utsname_sysctl.c                 |    6 +-
 kernel/watchdog.c                       |   11 +-
 mm/compaction.c                         |    8 +-
 mm/hugetlb.c                            |   24 +++--
 mm/page-writeback.c                     |   24 ++---
 mm/page_alloc.c                         |   25 ++---
 mm/vmscan.c                             |    6 +-
 net/bridge/br_netfilter.c               |    6 +-
 net/core/neighbour.c                    |    6 +-
 net/core/sysctl_net_core.c              |   33 +-----
 net/decnet/dn_dev.c                     |   10 +-
 net/decnet/sysctl_net_decnet.c          |    8 +-
 net/ipv4/arp.c                          |   71 ++++++++++++-
 net/ipv4/devinet.c                      |   52 +++++++---
 net/ipv4/ip_fragment.c                  |   34 +-----
 net/ipv4/route.c                        |   49 +++-------
 net/ipv4/sysctl_net_ipv4.c              |   78 ++++----------
 net/ipv6/addrconf.c                     |   50 +++++++--
 net/ipv6/af_inet6.c                     |   12 --
 net/ipv6/icmp.c                         |   17 +---
 net/ipv6/ndisc.c                        |   91 ++++++++++++----
 net/ipv6/reassembly.c                   |   34 +-----
 net/ipv6/route.c                        |   60 +++--------
 net/ipv6/sysctl_net_ipv6.c              |   88 ++--------------
 net/irda/irsysctl.c                     |   12 +-
 net/netfilter/ipvs/ip_vs_ctl.c          |   12 +-
 net/netfilter/nf_conntrack_acct.c       |   24 +----
 net/netfilter/nf_conntrack_ecache.c     |   30 +-----
 net/netfilter/nf_conntrack_standalone.c |   30 +-----
 net/netfilter/nf_log.c                  |    5 +-
 net/phonet/sysctl.c                     |    6 +-
 net/sunrpc/sysctl.c                     |    9 +-
 net/sunrpc/xprtrdma/svc_rdma.c          |    2 +-
 net/sysctl_net.c                        |   46 ++++++++-
 net/unix/sysctl_net_unix.c              |   22 +----
 net/xfrm/xfrm_sysctl.c                  |   37 ++-----
 security/min_addr.c                     |    5 +-
 88 files changed, 879 insertions(+), 839 deletions(-)

-- 
1.7.5.rc0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-06 19:52   ` David Miller
  2011-04-02  2:53 ` [PATCH 02/24] sysctl: cookie: add ctl_header_cookie Lucian Adrian Grijincu
                   ` (22 subsequent siblings)
  23 siblings, 1 reply; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

ctl_table_headers registered with register_net_sysctl_table should
have been unregistered with the equivalent unregister_net_sysctl_table

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

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 5345b0b..cd9ca08 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1680,7 +1680,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf)
 		return;
 
 	cnf->sysctl = NULL;
-	unregister_sysctl_table(t->sysctl_header);
+	unregister_net_sysctl_table(t->sysctl_header);
 	kfree(t->dev_name);
 	kfree(t);
 }
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3daaf3c..b1654a4 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4537,7 +4537,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
 
 	t = p->sysctl;
 	p->sysctl = NULL;
-	unregister_sysctl_table(t->sysctl_header);
+	unregister_net_sysctl_table(t->sysctl_header);
 	kfree(t->dev_name);
 	kfree(t);
 }
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 02/24] sysctl: cookie: add ctl_header_cookie
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-06 19:53   ` David Miller
  2011-04-02  2:53 ` [PATCH 03/24] sysctl: cookie: pass ctl_header_cookie to proc_handler Lucian Adrian Grijincu
                   ` (21 subsequent siblings)
  23 siblings, 1 reply; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 include/linux/sysctl.h |    5 ++++-
 kernel/sysctl.c        |   12 ++++++++----
 net/sysctl_net.c       |    6 +++---
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 11684d9..f82d456 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -1054,6 +1054,9 @@ struct ctl_table_header
 	struct ctl_table *attached_by;
 	struct ctl_table *attached_to;
 	struct ctl_table_header *parent;
+	/* Pointer to data that outlives this ctl_table_header.
+	 * Caller responsible to free the cookie. */
+	void *ctl_header_cookie;
 };
 
 /* struct ctl_path describes where in the hierarchy a table is added */
@@ -1064,7 +1067,7 @@ 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);
+	const struct ctl_path *path, struct ctl_table *table, void *cookie);
 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 c0bb324..dd3d061 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -205,6 +205,7 @@ static struct ctl_table_header root_table_header = {
 	.ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),}},
 	.root = &sysctl_table_root,
 	.set = &sysctl_table_root.default_set,
+	.ctl_header_cookie = NULL,
 };
 static struct ctl_table_root sysctl_table_root = {
 	.root_list = LIST_HEAD_INIT(sysctl_table_root.root_list),
@@ -1781,6 +1782,9 @@ static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
  * @namespaces: Data to compute which lists of sysctl entries are visible
  * @path: The path to the directory the sysctl table is in.
  * @table: the top-level table structure
+ * @cookie: Pointer to user provided data that must be accessible
+ *  until unregister_sysctl_table. This cookie will be passed to the
+ *  proc_handler.
  *
  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. A completely 0 filled entry terminates the table.
@@ -1829,9 +1833,8 @@ static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
  * to the table header on success.
  */
 struct ctl_table_header *__register_sysctl_paths(
-	struct ctl_table_root *root,
-	struct nsproxy *namespaces,
-	const struct ctl_path *path, struct ctl_table *table)
+	struct ctl_table_root *root, struct nsproxy *namespaces,
+	const struct ctl_path *path, struct ctl_table *table, void *cookie)
 {
 	struct ctl_table_header *header;
 	struct ctl_table *new, **prevp;
@@ -1878,6 +1881,7 @@ struct ctl_table_header *__register_sysctl_paths(
 	header->root = root;
 	sysctl_set_parent(NULL, header->ctl_table);
 	header->count = 1;
+	header->ctl_header_cookie = cookie;
 #ifdef CONFIG_SYSCTL_SYSCALL_CHECK
 	if (sysctl_check_table(namespaces, header->ctl_table)) {
 		kfree(header);
@@ -1918,7 +1922,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);
+				       path, table, NULL);
 }
 
 /**
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index ca84212..9dadd17 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -109,8 +109,8 @@ struct ctl_table_header *register_net_sysctl_table(struct net *net,
 	struct nsproxy namespaces;
 	namespaces = *current->nsproxy;
 	namespaces.net_ns = net;
-	return __register_sysctl_paths(&net_sysctl_root,
-					&namespaces, path, table);
+	return __register_sysctl_paths(&net_sysctl_root, &namespaces, path,
+				       table, 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);
+				       &init_nsproxy, path, table, NULL);
 }
 EXPORT_SYMBOL_GPL(register_net_sysctl_rotable);
 
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 03/24] sysctl: cookie: pass ctl_header_cookie to proc_handler
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 02/24] sysctl: cookie: add ctl_header_cookie Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-06 19:54   ` David Miller
  2011-04-02  2:53 ` [PATCH 04/24] sysctl: cookie: add netns_proc_dointvec and other netns_proc_* proc_handlers Lucian Adrian Grijincu
                   ` (20 subsequent siblings)
  23 siblings, 1 reply; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

The bulk of this patch changes all proc_handlers in the kernel to
receive the cookie.

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 arch/frv/kernel/pm.c               |   22 ++++----
 arch/frv/kernel/sysctl.c           |    4 +-
 arch/mips/lasat/sysctl.c           |   28 ++++++------
 arch/s390/appldata/appldata_base.c |   15 +++---
 arch/s390/kernel/debug.c           |    6 +-
 arch/s390/mm/cmm.c                 |    4 +-
 drivers/cdrom/cdrom.c              |   12 ++--
 drivers/char/random.c              |    6 +-
 drivers/macintosh/mac_hid.c        |    4 +-
 drivers/parport/procfs.c           |   29 +++++------
 drivers/s390/char/sclp_async.c     |    2 +-
 fs/dcache.c                        |    4 +-
 fs/drop_caches.c                   |    5 +-
 fs/file_table.c                    |   10 ++--
 fs/fscache/main.c                  |    6 +-
 fs/inode.c                         |    6 +-
 fs/pipe.c                          |    4 +-
 fs/proc/proc_sysctl.c              |    3 +-
 fs/quota/dquot.c                   |    5 +-
 fs/xfs/linux-2.6/xfs_sysctl.c      |   10 ++--
 include/linux/compaction.h         |    6 ++-
 include/linux/fs.h                 |   12 ++--
 include/linux/ftrace.h             |    4 +-
 include/linux/hugetlb.h            |   13 +++--
 include/linux/kprobes.h            |    6 +-
 include/linux/mm.h                 |    4 +-
 include/linux/mmzone.h             |   23 +++++----
 include/linux/nmi.h                |    4 +-
 include/linux/perf_event.h         |    2 +-
 include/linux/pipe_fs_i.h          |    2 +-
 include/linux/sched.h              |   16 +++---
 include/linux/security.h           |    3 +-
 include/linux/swap.h               |    4 +-
 include/linux/sysctl.h             |   30 ++++++++----
 include/linux/writeback.h          |   18 ++-----
 include/net/ndisc.h                |    7 ++-
 ipc/ipc_sysctl.c                   |   21 +++++----
 ipc/mq_sysctl.c                    |   11 ++--
 kernel/hung_task.c                 |    6 +-
 kernel/kprobes.c                   |    4 +-
 kernel/perf_event.c                |    4 +-
 kernel/sched.c                     |    4 +-
 kernel/sched_fair.c                |    4 +-
 kernel/sysctl.c                    |   91 +++++++++++++++++++++++------------
 kernel/trace/ftrace.c              |    4 +-
 kernel/trace/trace_stack.c         |    4 +-
 kernel/utsname_sysctl.c            |    6 +-
 kernel/watchdog.c                  |   11 ++--
 mm/compaction.c                    |    8 ++-
 mm/hugetlb.c                       |   24 +++++----
 mm/page-writeback.c                |   24 ++++------
 mm/page_alloc.c                    |   25 +++++-----
 mm/vmscan.c                        |    6 +-
 net/bridge/br_netfilter.c          |    6 +-
 net/core/sysctl_net_core.c         |    5 +-
 net/decnet/dn_dev.c                |   10 ++--
 net/decnet/sysctl_net_decnet.c     |    8 ++--
 net/ipv4/devinet.c                 |   18 ++++----
 net/ipv4/route.c                   |    6 +-
 net/ipv4/sysctl_net_ipv4.c         |   25 +++++-----
 net/ipv6/addrconf.c                |   12 ++--
 net/ipv6/ndisc.c                   |   14 +++--
 net/ipv6/route.c                   |    6 +-
 net/irda/irsysctl.c                |   12 ++--
 net/netfilter/ipvs/ip_vs_ctl.c     |   12 ++--
 net/netfilter/nf_log.c             |    5 +-
 net/phonet/sysctl.c                |    6 +-
 net/sunrpc/sysctl.c                |    9 ++--
 net/sunrpc/xprtrdma/svc_rdma.c     |    2 +-
 security/min_addr.c                |    5 +-
 70 files changed, 405 insertions(+), 352 deletions(-)

diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index 5fa3889..a929ffb 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -150,8 +150,8 @@ static int user_atoi(char __user *ubuf, size_t len)
 /*
  * Send us to sleep.
  */
-static int sysctl_pm_do_suspend(ctl_table *ctl, int write,
-				void __user *buffer, size_t *lenp, loff_t *fpos)
+static int sysctl_pm_do_suspend(ctl_table *ctl, int write, void __user *buffer,
+				size_t *lenp, loff_t *fpos, void *cookie)
 {
 	int retval, mode;
 
@@ -198,13 +198,13 @@ static int try_set_cmode(int new_cmode)
 }
 
 
-static int cmode_procctl(ctl_table *ctl, int write,
-			 void __user *buffer, size_t *lenp, loff_t *fpos)
+static int cmode_procctl(ctl_table *ctl, int write, void __user *buffer,
+			 size_t *lenp, loff_t *fpos, void *cookie)
 {
 	int new_cmode;
 
 	if (!write)
-		return proc_dointvec(ctl, write, buffer, lenp, fpos);
+		return proc_dointvec(ctl, write, buffer, lenp, fpos, NULL);
 
 	new_cmode = user_atoi(buffer, *lenp);
 
@@ -270,26 +270,26 @@ static int try_set_cm(int new_cm)
 	return 0;
 }
 
-static int p0_procctl(ctl_table *ctl, int write,
-		      void __user *buffer, size_t *lenp, loff_t *fpos)
+static int p0_procctl(ctl_table *ctl, int write, void __user *buffer,
+		      size_t *lenp, loff_t *fpos, void *cookie)
 {
 	int new_p0;
 
 	if (!write)
-		return proc_dointvec(ctl, write, buffer, lenp, fpos);
+		return proc_dointvec(ctl, write, buffer, lenp, fpos, NULL);
 
 	new_p0 = user_atoi(buffer, *lenp);
 
 	return try_set_p0(new_p0)?:*lenp;
 }
 
-static int cm_procctl(ctl_table *ctl, int write,
-		      void __user *buffer, size_t *lenp, loff_t *fpos)
+static int cm_procctl(ctl_table *ctl, int write, void __user *buffer,
+		      size_t *lenp, loff_t *fpos, void *cookie)
 {
 	int new_cm;
 
 	if (!write)
-		return proc_dointvec(ctl, write, buffer, lenp, fpos);
+		return proc_dointvec(ctl, write, buffer, lenp, fpos, NULL);
 
 	new_cm = user_atoi(buffer, *lenp);
 
diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c
index 6c155d6..e2be463 100644
--- a/arch/frv/kernel/sysctl.c
+++ b/arch/frv/kernel/sysctl.c
@@ -48,7 +48,7 @@ static void frv_change_dcache_mode(unsigned long newmode)
  */
 static int procctl_frv_cachemode(ctl_table *table, int write,
 				 void __user *buffer, size_t *lenp,
-				 loff_t *ppos)
+				 loff_t *ppos, void *cookie)
 {
 	unsigned long hsr0;
 	char buff[8];
@@ -123,7 +123,7 @@ static int procctl_frv_cachemode(ctl_table *table, int write,
 #ifdef CONFIG_MMU
 static int procctl_frv_pin_cxnr(ctl_table *table, int write,
 				void __user *buffer, size_t *lenp,
-				loff_t *ppos)
+				loff_t *ppos, void *cookie)
 {
 	pid_t pid;
 	char buff[16], *p;
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index d87ffd0..33f408c 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -39,12 +39,12 @@
 
 
 /* And the same for proc */
-int proc_dolasatstring(ctl_table *table, int write,
-		       void *buffer, size_t *lenp, loff_t *ppos)
+int proc_dolasatstring(ctl_table *table, int write, void *buffer,
+		       size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int r;
 
-	r = proc_dostring(table, write, buffer, lenp, ppos);
+	r = proc_dostring(table, write, buffer, lenp, ppos, NULL);
 	if ((!write) || r)
 		return r;
 
@@ -54,12 +54,12 @@ int proc_dolasatstring(ctl_table *table, int write,
 }
 
 /* proc function to write EEPROM after changing int entry */
-int proc_dolasatint(ctl_table *table, int write,
-		       void *buffer, size_t *lenp, loff_t *ppos)
+int proc_dolasatint(ctl_table *table, int write, void *buffer,
+		    size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int r;
 
-	r = proc_dointvec(table, write, buffer, lenp, ppos);
+	r = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	if ((!write) || r)
 		return r;
 
@@ -72,8 +72,8 @@ int proc_dolasatint(ctl_table *table, int write,
 static int rtctmp;
 
 /* proc function to read/write RealTime Clock */
-int proc_dolasatrtc(ctl_table *table, int write,
-		       void *buffer, size_t *lenp, loff_t *ppos)
+int proc_dolasatrtc(ctl_table *table, int write, void *buffer,
+		    size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct timespec ts;
 	int r;
@@ -85,7 +85,7 @@ int proc_dolasatrtc(ctl_table *table, int write,
 		if (rtctmp < 0)
 			rtctmp = 0;
 	}
-	r = proc_dointvec(table, write, buffer, lenp, ppos);
+	r = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	if (r)
 		return r;
 
@@ -97,8 +97,8 @@ int proc_dolasatrtc(ctl_table *table, int write,
 #endif
 
 #ifdef CONFIG_INET
-int proc_lasat_ip(ctl_table *table, int write,
-		       void *buffer, size_t *lenp, loff_t *ppos)
+int proc_lasat_ip(ctl_table *table, int write, void *buffer,
+		    size_t *lenp, loff_t *ppos, void *cookie)
 {
 	unsigned int ip;
 	char *p, c;
@@ -157,12 +157,12 @@ int proc_lasat_ip(ctl_table *table, int write,
 }
 #endif
 
-int proc_lasat_prid(ctl_table *table, int write,
-		       void *buffer, size_t *lenp, loff_t *ppos)
+int proc_lasat_prid(ctl_table *table, int write, void *buffer,
+		    size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int r;
 
-	r = proc_dointvec(table, write, buffer, lenp, ppos);
+	r = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	if (r < 0)
 		return r;
 	if (write) {
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 5c91995..866d8c0 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -51,10 +51,11 @@ static struct platform_device *appldata_pdev;
  */
 static const char appldata_proc_name[APPLDATA_PROC_NAME_LENGTH] = "appldata";
 static int appldata_timer_handler(ctl_table *ctl, int write,
-				  void __user *buffer, size_t *lenp, loff_t *ppos);
+				  void __user *buffer, size_t *lenp,
+				  loff_t *ppos, void *cookie);
 static int appldata_interval_handler(ctl_table *ctl, int write,
-					 void __user *buffer,
-					 size_t *lenp, loff_t *ppos);
+				     void __user *buffer, size_t *lenp,
+				     loff_t *ppos, void *cookie);
 
 static struct ctl_table_header *appldata_sysctl_header;
 static struct ctl_table appldata_table[] = {
@@ -246,8 +247,8 @@ __appldata_vtimer_setup(int cmd)
  * Start/Stop timer, show status of timer (0 = not active, 1 = active)
  */
 static int
-appldata_timer_handler(ctl_table *ctl, int write,
-			   void __user *buffer, size_t *lenp, loff_t *ppos)
+appldata_timer_handler(ctl_table *ctl, int write, void __user *buffer,
+		       size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int len;
 	char buf[2];
@@ -334,8 +335,8 @@ out:
  * monitoring (0 = not in process, 1 = in process)
  */
 static int
-appldata_generic_handler(ctl_table *ctl, int write,
-			   void __user *buffer, size_t *lenp, loff_t *ppos)
+appldata_generic_handler(ctl_table *ctl, int write, void __user *buffer,
+			 size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct appldata_ops *ops = NULL, *tmp_ops;
 	int rc, len, found;
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 5ad6bc0..bcd28c3 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -884,11 +884,11 @@ static int debug_active=1;
  * if debug_active is already off
  */
 static int
-s390dbf_procactive(ctl_table *table, int write,
-                     void __user *buffer, size_t *lenp, loff_t *ppos)
+s390dbf_procactive(ctl_table *table, int write, void __user *buffer,
+		   size_t *lenp, loff_t *ppos, void *cookie)
 {
 	if (!write || debug_stoppable || !debug_active)
-		return proc_dointvec(table, write, buffer, lenp, ppos);
+		return proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	else
 		return 0;
 }
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index c66ffd8..1fe48f7 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -254,7 +254,7 @@ static int cmm_skip_blanks(char *cp, char **endp)
 static struct ctl_table cmm_table[];
 
 static int cmm_pages_handler(ctl_table *ctl, int write, void __user *buffer,
-			     size_t *lenp, loff_t *ppos)
+			     size_t *lenp, loff_t *ppos, void *cookie)
 {
 	char buf[16], *p;
 	long nr;
@@ -294,7 +294,7 @@ static int cmm_pages_handler(ctl_table *ctl, int write, void __user *buffer,
 }
 
 static int cmm_timeout_handler(ctl_table *ctl, int write,  void __user *buffer,
-			       size_t *lenp, loff_t *ppos)
+			       size_t *lenp, loff_t *ppos, void *cookie)
 {
 	char buf[64], *p;
 	long nr, seconds;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index e2c48a7..2c3d2d5 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3469,8 +3469,8 @@ static int cdrom_print_info(const char *header, int val, char *info,
 	return 0;
 }
 
-static int cdrom_sysctl_info(ctl_table *ctl, int write,
-                           void __user *buffer, size_t *lenp, loff_t *ppos)
+static int cdrom_sysctl_info(ctl_table *ctl, int write, void __user *buffer,
+			     size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int pos;
 	char *info = cdrom_sysctl_settings.info;
@@ -3546,7 +3546,7 @@ static int cdrom_sysctl_info(ctl_table *ctl, int write,
 		goto done;
 doit:
 	mutex_unlock(&cdrom_mutex);
-	return proc_dostring(ctl, write, buffer, lenp, ppos);
+	return proc_dostring(ctl, write, buffer, lenp, ppos, NULL);
 done:
 	pr_info("info buffer too small\n");
 	goto doit;
@@ -3582,12 +3582,12 @@ static void cdrom_update_settings(void)
 	mutex_unlock(&cdrom_mutex);
 }
 
-static int cdrom_sysctl_handler(ctl_table *ctl, int write,
-				void __user *buffer, size_t *lenp, loff_t *ppos)
+static int cdrom_sysctl_handler(ctl_table *ctl, int write, void __user *buffer,
+				size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int ret;
 	
-	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	ret = proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 
 	if (write) {
 	
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 5e29e80..2e54a13 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1227,8 +1227,8 @@ static char sysctl_bootid[16];
  * as an ASCII string in the standard UUID format.  If accesses via the
  * sysctl system call, it is returned as 16 bytes of binary data.
  */
-static int proc_do_uuid(ctl_table *table, int write,
-			void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_do_uuid(ctl_table *table, int write, void __user *buffer,
+			size_t *lenp, loff_t *ppos, void *cookie)
 {
 	ctl_table fake_table;
 	unsigned char buf[64], tmp_uuid[16], *uuid;
@@ -1246,7 +1246,7 @@ static int proc_do_uuid(ctl_table *table, int write,
 	fake_table.data = buf;
 	fake_table.maxlen = sizeof(buf);
 
-	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+	return proc_dostring(&fake_table, write, buffer, lenp, ppos, NULL);
 }
 
 static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
index 6a82388..76ff0f7 100644
--- a/drivers/macintosh/mac_hid.c
+++ b/drivers/macintosh/mac_hid.c
@@ -183,7 +183,7 @@ static void mac_hid_stop_emulation(void)
 
 static int mac_hid_toggle_emumouse(ctl_table *table, int write,
 				   void __user *buffer, size_t *lenp,
-				   loff_t *ppos)
+				   loff_t *ppos, void *cookie)
 {
 	int *valp = table->data;
 	int old_val = *valp;
@@ -193,7 +193,7 @@ static int mac_hid_toggle_emumouse(ctl_table *table, int write,
 	if (rc)
 		return rc;
 
-	rc = proc_dointvec(table, write, buffer, lenp, ppos);
+	rc = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 
 	if (rc == 0 && write && *valp != old_val) {
 		if (*valp == 1)
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index 3f56bc0..fc4aa33 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -31,8 +31,8 @@
 #define PARPORT_MIN_SPINTIME_VALUE 1
 #define PARPORT_MAX_SPINTIME_VALUE 1000
 
-static int do_active_device(ctl_table *table, int write,
-		      void __user *result, size_t *lenp, loff_t *ppos)
+static int do_active_device(ctl_table *table, int write, void __user *result,
+			    size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct parport *port = (struct parport *)table->extra1;
 	char buffer[256];
@@ -68,8 +68,8 @@ static int do_active_device(ctl_table *table, int write,
 }
 
 #ifdef CONFIG_PARPORT_1284
-static int do_autoprobe(ctl_table *table, int write,
-			void __user *result, size_t *lenp, loff_t *ppos)
+static int do_autoprobe(ctl_table *table, int write, void __user *result,
+			size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct parport_device_info *info = table->extra2;
 	const char *str;
@@ -110,9 +110,9 @@ static int do_autoprobe(ctl_table *table, int write,
 }
 #endif /* IEEE1284.3 support. */
 
-static int do_hardware_base_addr (ctl_table *table, int write,
-				  void __user *result,
-				  size_t *lenp, loff_t *ppos)
+static int do_hardware_base_addr(ctl_table *table, int write,
+				 void __user *result, size_t *lenp,
+				 loff_t *ppos, void *cookie)
 {
 	struct parport *port = (struct parport *)table->extra1;
 	char buffer[20];
@@ -138,9 +138,8 @@ static int do_hardware_base_addr (ctl_table *table, int write,
 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 }
 
-static int do_hardware_irq (ctl_table *table, int write,
-			    void __user *result,
-			    size_t *lenp, loff_t *ppos)
+static int do_hardware_irq(ctl_table *table, int write, void __user *result,
+			   size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct parport *port = (struct parport *)table->extra1;
 	char buffer[20];
@@ -166,9 +165,8 @@ static int do_hardware_irq (ctl_table *table, int write,
 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 }
 
-static int do_hardware_dma (ctl_table *table, int write,
-			    void __user *result,
-			    size_t *lenp, loff_t *ppos)
+static int do_hardware_dma(ctl_table *table, int write, void __user *result,
+			   size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct parport *port = (struct parport *)table->extra1;
 	char buffer[20];
@@ -194,9 +192,8 @@ static int do_hardware_dma (ctl_table *table, int write,
 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 }
 
-static int do_hardware_modes (ctl_table *table, int write,
-			      void __user *result,
-			      size_t *lenp, loff_t *ppos)
+static int do_hardware_modes(ctl_table *table, int write, void __user *result,
+			     size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct parport *port = (struct parport *)table->extra1;
 	char buffer[40];
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c
index 7ad30e7..c4da7ea 100644
--- a/drivers/s390/char/sclp_async.c
+++ b/drivers/s390/char/sclp_async.c
@@ -65,7 +65,7 @@ static struct notifier_block call_home_panic_nb = {
 
 static int proc_handler_callhome(struct ctl_table *ctl, int write,
 				 void __user *buffer, size_t *count,
-				 loff_t *ppos)
+				 loff_t *ppos, void *cookie)
 {
 	unsigned long val;
 	int len, rc;
diff --git a/fs/dcache.c b/fs/dcache.c
index ad25c4c..38b78c4 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -140,10 +140,10 @@ static int get_nr_dentry(void)
 }
 
 int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
-		   size_t *lenp, loff_t *ppos)
+		   size_t *lenp, loff_t *ppos, void *cookie)
 {
 	dentry_stat.nr_dentry = get_nr_dentry();
-	return proc_dointvec(table, write, buffer, lenp, ppos);
+	return proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 }
 #endif
 
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 98b77c8..78f1ce4 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -47,11 +47,12 @@ static void drop_slab(void)
 }
 
 int drop_caches_sysctl_handler(ctl_table *table, int write,
-	void __user *buffer, size_t *length, loff_t *ppos)
+			       void __user *buffer, size_t *length,
+			       loff_t *ppos, void *cookie)
 {
 	int ret;
 
-	ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
+	ret = proc_dointvec_minmax(table, write, buffer, length, ppos, NULL);
 	if (ret)
 		return ret;
 	if (write) {
diff --git a/fs/file_table.c b/fs/file_table.c
index 01e4c1e..d18b9d9 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -78,15 +78,15 @@ EXPORT_SYMBOL_GPL(get_max_files);
  * Handle nr_files sysctl
  */
 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
-int proc_nr_files(ctl_table *table, int write,
-                     void __user *buffer, size_t *lenp, loff_t *ppos)
+int proc_nr_files(ctl_table *table, int write, void __user *buffer,
+		  size_t *lenp, loff_t *ppos, void *cookie)
 {
 	files_stat.nr_files = get_nr_files();
-	return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
+	return proc_doulongvec_minmax(table, write, buffer, lenp, ppos, NULL);
 }
 #else
-int proc_nr_files(ctl_table *table, int write,
-                     void __user *buffer, size_t *lenp, loff_t *ppos)
+int proc_nr_files(ctl_table *table, int write, void __user *buffer,
+		  size_t *lenp, loff_t *ppos, void *cookie)
 {
 	return -ENOSYS;
 }
diff --git a/fs/fscache/main.c b/fs/fscache/main.c
index f9d8567..00415f6 100644
--- a/fs/fscache/main.c
+++ b/fs/fscache/main.c
@@ -54,14 +54,14 @@ static unsigned fscache_op_max_active = 2;
 static struct ctl_table_header *fscache_sysctl_header;
 
 static int fscache_max_active_sysctl(struct ctl_table *table, int write,
-				     void __user *buffer,
-				     size_t *lenp, loff_t *ppos)
+				     void __user *buffer, size_t *lenp,
+				     loff_t *ppos, void *cookie)
 {
 	struct workqueue_struct **wqp = table->extra1;
 	unsigned int *datap = table->data;
 	int ret;
 
-	ret = proc_dointvec(table, write, buffer, lenp, ppos);
+	ret = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	if (ret == 0)
 		workqueue_set_max_active(*wqp, *datap);
 	return ret;
diff --git a/fs/inode.c b/fs/inode.c
index 5f4e11a..ec96079 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -158,11 +158,11 @@ int get_nr_dirty_inodes(void)
  * Handle nr_inode sysctl
  */
 #ifdef CONFIG_SYSCTL
-int proc_nr_inodes(ctl_table *table, int write,
-		   void __user *buffer, size_t *lenp, loff_t *ppos)
+int proc_nr_inodes(ctl_table *table, int write, void __user *buffer,
+		   size_t *lenp, loff_t *ppos, void *cookie)
 {
 	inodes_stat.nr_inodes = get_nr_inodes();
-	return proc_dointvec(table, write, buffer, lenp, ppos);
+	return proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 }
 #endif
 
diff --git a/fs/pipe.c b/fs/pipe.c
index da42f7d..c37413bd 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1186,11 +1186,11 @@ static inline unsigned int round_pipe_size(unsigned int size)
  * will return an error.
  */
 int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
-		 size_t *lenp, loff_t *ppos)
+		 size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int ret;
 
-	ret = proc_dointvec_minmax(table, write, buf, lenp, ppos);
+	ret = proc_dointvec_minmax(table, write, buf, lenp, ppos, NULL);
 	if (ret < 0 || !write)
 		return ret;
 
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index f50133c..f1e91e7 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -155,7 +155,8 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
 
 	/* careful: calling conventions are nasty here */
 	res = count;
-	error = table->proc_handler(table, write, buf, &res, ppos);
+	error = table->proc_handler(table, write, buf, &res,
+				    ppos, head->ctl_header_cookie);
 	if (!error)
 		error = res;
 out:
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index fcc8ae7..894ed7b 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2517,14 +2517,15 @@ const struct quotactl_ops dquot_quotactl_ops = {
 EXPORT_SYMBOL(dquot_quotactl_ops);
 
 static int do_proc_dqstats(struct ctl_table *table, int write,
-		     void __user *buffer, size_t *lenp, loff_t *ppos)
+			   void __user *buffer, size_t *lenp,
+			   loff_t *ppos, void *cookie)
 {
 	unsigned int type = (int *)table->data - dqstats.stat;
 
 	/* Update global table */
 	dqstats.stat[type] =
 			percpu_counter_sum_positive(&dqstats.counter[type]);
-	return proc_dointvec(table, write, buffer, lenp, ppos);
+	return proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 }
 
 static ctl_table fs_dqstats_table[] = {
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index ee2d2ad..1d2a781 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -29,12 +29,13 @@ xfs_stats_clear_proc_handler(
 	int		write,
 	void		__user *buffer,
 	size_t		*lenp,
-	loff_t		*ppos)
+	loff_t		*ppos,
+	void		*cookie)
 {
 	int		c, ret, *valp = ctl->data;
 	__uint32_t	vn_active;
 
-	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
+	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos, NULL);
 
 	if (!ret && write && *valp) {
 		xfs_notice(NULL, "Clearing xfsstats");
@@ -59,11 +60,12 @@ xfs_panic_mask_proc_handler(
 	int		write,
 	void		__user *buffer,
 	size_t		*lenp,
-	loff_t		*ppos)
+	loff_t		*ppos,
+	void		*cookie)
 {
 	int		ret, *valp = ctl->data;
 
-	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
+	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos, NULL);
 	if (!ret && write) {
 		xfs_panic_mask = *valp;
 #ifdef DEBUG
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index cc9f7a4..aa898e5 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -14,10 +14,12 @@
 #ifdef CONFIG_COMPACTION
 extern int sysctl_compact_memory;
 extern int sysctl_compaction_handler(struct ctl_table *table, int write,
-			void __user *buffer, size_t *length, loff_t *ppos);
+				     void __user *buffer, size_t *length,
+				     loff_t *ppos, void *cookie);
 extern int sysctl_extfrag_threshold;
 extern int sysctl_extfrag_handler(struct ctl_table *table, int write,
-			void __user *buffer, size_t *length, loff_t *ppos);
+				  void __user *buffer, size_t *length,
+				  loff_t *ppos, void *cookie);
 
 extern int fragmentation_index(struct zone *zone, unsigned int order);
 extern unsigned long try_to_compact_pages(struct zonelist *zonelist,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 52f283c..1096299 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2562,12 +2562,12 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
 			  size_t len, loff_t *ppos);
 
 struct ctl_table;
-int proc_nr_files(struct ctl_table *table, int write,
-		  void __user *buffer, size_t *lenp, loff_t *ppos);
-int proc_nr_dentry(struct ctl_table *table, int write,
-		  void __user *buffer, size_t *lenp, loff_t *ppos);
-int proc_nr_inodes(struct ctl_table *table, int write,
-		   void __user *buffer, size_t *lenp, loff_t *ppos);
+int proc_nr_files(struct ctl_table *table, int write, void __user *buffer,
+		  size_t *lenp, loff_t *ppos, void *cookie);
+int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer,
+		   size_t *lenp, loff_t *ppos, void *cookie);
+int proc_nr_inodes(struct ctl_table *table, int write, void __user *buffer,
+		   size_t *lenp, loff_t *ppos, void *cookie);
 int __init get_filesystem_list(char *buf);
 
 #define __FMODE_EXEC		((__force int) FMODE_EXEC)
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index ca29e03..6e3a3d9 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -25,7 +25,7 @@ extern int ftrace_enabled;
 extern int
 ftrace_enable_sysctl(struct ctl_table *table, int write,
 		     void __user *buffer, size_t *lenp,
-		     loff_t *ppos);
+		     loff_t *ppos, void *cookie);
 
 typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip);
 
@@ -104,7 +104,7 @@ extern int stack_tracer_enabled;
 int
 stack_trace_sysctl(struct ctl_table *table, int write,
 		   void __user *buffer, size_t *lenp,
-		   loff_t *ppos);
+		   loff_t *ppos, void *cookie);
 #endif
 
 struct ftrace_func_command {
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 943c76b..4bb40ca 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -16,13 +16,16 @@ struct user_struct;
 int PageHuge(struct page *page);
 
 void reset_vma_resv_huge_pages(struct vm_area_struct *vma);
-int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *);
-int hugetlb_overcommit_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *);
-int hugetlb_treat_movable_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *);
+int hugetlb_sysctl_handler(struct ctl_table *, int, void __user *,
+			   size_t *, loff_t *, void *);
+int hugetlb_overcommit_handler(struct ctl_table *, int, void __user *,
+			       size_t *, loff_t *, void *);
+int hugetlb_treat_movable_handler(struct ctl_table *, int, void __user *,
+				  size_t *, loff_t *, void *);
 
 #ifdef CONFIG_NUMA
-int hugetlb_mempolicy_sysctl_handler(struct ctl_table *, int,
-					void __user *, size_t *, loff_t *);
+int hugetlb_mempolicy_sysctl_handler(struct ctl_table *, int, void __user *,
+				     size_t *, loff_t *, void *);
 #endif
 
 int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index dd7c12e..f5c5357 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -288,9 +288,9 @@ extern void opt_pre_handler(struct kprobe *p, struct pt_regs *regs);
 
 #ifdef CONFIG_SYSCTL
 extern int sysctl_kprobes_optimization;
-extern int proc_kprobes_optimization_handler(struct ctl_table *table,
-					     int write, void __user *buffer,
-					     size_t *length, loff_t *ppos);
+extern int proc_kprobes_optimization_handler(struct ctl_table *table, int write,
+					     void __user *buffer, size_t *len,
+					     loff_t *ppos, void *cookie);
 #endif
 
 #endif /* CONFIG_OPTPROBES */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 7606d7d..b0793e5 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1602,8 +1602,8 @@ int in_gate_area_no_mm(unsigned long addr);
 #define in_gate_area(mm, addr) ({(void)mm; in_gate_area_no_mm(addr);})
 #endif	/* __HAVE_ARCH_GATE_AREA */
 
-int drop_caches_sysctl_handler(struct ctl_table *, int,
-					void __user *, size_t *, loff_t *);
+int drop_caches_sysctl_handler(struct ctl_table *, int, void __user *,
+			       size_t *, loff_t *, void *);
 unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
 			unsigned long lru_pages);
 
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index e56f835..7592afd 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -764,20 +764,21 @@ static inline int is_dma(struct zone *zone)
 
 /* These two functions are used to setup the per zone pages min values */
 struct ctl_table;
-int min_free_kbytes_sysctl_handler(struct ctl_table *, int,
-					void __user *, size_t *, loff_t *);
+int min_free_kbytes_sysctl_handler(struct ctl_table *, int, void __user *,
+				   size_t *, loff_t *, void *);
 extern int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1];
-int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int,
-					void __user *, size_t *, loff_t *);
+int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, void __user *,
+					size_t *, loff_t *, void *);
 int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *, int,
-					void __user *, size_t *, loff_t *);
+					    void __user *, size_t *,
+					    loff_t *, void *);
 int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *, int,
-			void __user *, size_t *, loff_t *);
-int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int,
-			void __user *, size_t *, loff_t *);
-
-extern int numa_zonelist_order_handler(struct ctl_table *, int,
-			void __user *, size_t *, loff_t *);
+					     void __user *, size_t *,
+					     loff_t *, void *);
+int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int, void __user *,
+					 size_t *, loff_t *, void *);
+int numa_zonelist_order_handler(struct ctl_table *, int, void __user *,
+				size_t *, loff_t *, void *);
 extern char numa_zonelist_order[];
 #define NUMA_ZONELIST_ORDER_LEN 16	/* string buffer size */
 
diff --git a/include/linux/nmi.h b/include/linux/nmi.h
index c536f85..96eb9c7 100644
--- a/include/linux/nmi.h
+++ b/include/linux/nmi.h
@@ -48,8 +48,8 @@ int hw_nmi_is_cpu_stuck(struct pt_regs *);
 u64 hw_nmi_get_sample_period(void);
 extern int watchdog_enabled;
 struct ctl_table;
-extern int proc_dowatchdog_enabled(struct ctl_table *, int ,
-			void __user *, size_t *, loff_t *);
+extern int proc_dowatchdog_enabled(struct ctl_table *, int, void __user *,
+				   size_t *, loff_t *, void *);
 #endif
 
 #endif
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 311b4dc..840c93b 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1119,7 +1119,7 @@ extern int sysctl_perf_event_sample_rate;
 
 extern int perf_proc_update_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *lenp,
-		loff_t *ppos);
+		loff_t *ppos, void *cookie);
 
 static inline bool perf_paranoid_tracepoint_raw(void)
 {
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 77257c9..b79fc92 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -141,7 +141,7 @@ void pipe_unlock(struct pipe_inode_info *);
 void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
 
 extern unsigned int pipe_max_size, pipe_min_size;
-int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
+int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *, void *);
 
 
 /* Drop the inode semaphore and wait for a pipe event, atomically */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 83bd2e2..0f7ee29 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -312,8 +312,8 @@ extern void touch_softlockup_watchdog(void);
 extern void touch_softlockup_watchdog_sync(void);
 extern void touch_all_softlockup_watchdogs(void);
 extern int proc_dowatchdog_thresh(struct ctl_table *table, int write,
-				  void __user *buffer,
-				  size_t *lenp, loff_t *ppos);
+				  void __user *buffer, size_t *lenp,
+				  loff_t *ppos, void *cookie);
 extern unsigned int  softlockup_panic;
 extern int softlockup_thresh;
 void lockup_detector_init(void);
@@ -338,8 +338,8 @@ extern unsigned long sysctl_hung_task_check_count;
 extern unsigned long sysctl_hung_task_timeout_secs;
 extern unsigned long sysctl_hung_task_warnings;
 extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
-					 void __user *buffer,
-					 size_t *lenp, loff_t *ppos);
+					 void __user *buffer, size_t *lenp,
+					 loff_t *ppos, void *cookie);
 #else
 /* Avoid need for ifdefs elsewhere in the code */
 enum { sysctl_hung_task_timeout_secs = 0 };
@@ -1929,8 +1929,8 @@ extern unsigned int sysctl_timer_migration;
 extern unsigned int sysctl_sched_shares_window;
 
 int sched_proc_update_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *length,
-		loff_t *ppos);
+			      void __user *buffer, size_t *length,
+			      loff_t *ppos, void *cookie);
 #endif
 #ifdef CONFIG_SCHED_DEBUG
 static inline unsigned int get_sysctl_timer_migration(void)
@@ -1947,8 +1947,8 @@ extern unsigned int sysctl_sched_rt_period;
 extern int sysctl_sched_rt_runtime;
 
 int sched_rt_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos);
+		     void __user *buffer, size_t *lenp,
+		     loff_t *ppos, void *cookie);
 
 #ifdef CONFIG_SCHED_AUTOGROUP
 extern unsigned int sysctl_sched_autogroup_enabled;
diff --git a/include/linux/security.h b/include/linux/security.h
index ca02f17..cc2e816 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -144,7 +144,8 @@ static inline unsigned long round_hint_to_min(unsigned long hint)
 	return hint;
 }
 extern int mmap_min_addr_handler(struct ctl_table *table, int write,
-				 void __user *buffer, size_t *lenp, loff_t *ppos);
+				 void __user *buffer, size_t *lenp,
+				 loff_t *ppos, void *cookie);
 #endif
 
 #ifdef CONFIG_SECURITY
diff --git a/include/linux/swap.h b/include/linux/swap.h
index a5c6da5..921b3b4 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -281,8 +281,8 @@ extern int page_evictable(struct page *page, struct vm_area_struct *vma);
 extern void scan_mapping_unevictable_pages(struct address_space *);
 
 extern unsigned long scan_unevictable_pages;
-extern int scan_unevictable_handler(struct ctl_table *, int,
-					void __user *, size_t *, loff_t *);
+extern int scan_unevictable_handler(struct ctl_table *, int, void __user *,
+				    size_t *, loff_t *, void *);
 #ifdef CONFIG_NUMA
 extern int scan_unevictable_register_node(struct node *node);
 extern void scan_unevictable_unregister_node(struct node *node);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index f82d456..f0eb817 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -963,26 +963,36 @@ extern int sysctl_perm(struct ctl_table_root *root,
 typedef struct ctl_table ctl_table;
 
 typedef int proc_handler (struct ctl_table *ctl, int write,
-			  void __user *buffer, size_t *lenp, loff_t *ppos);
+			  void __user *buffer, size_t *lenp,
+			  loff_t *ppos, void *cookie);
 
 extern int proc_dostring(struct ctl_table *, int,
-			 void __user *, size_t *, loff_t *);
+			 void __user *, size_t *,
+			 loff_t *, void *);
 extern int proc_dointvec(struct ctl_table *, int,
-			 void __user *, size_t *, loff_t *);
+			 void __user *, size_t *,
+			 loff_t *, void *);
 extern int proc_dointvec_minmax(struct ctl_table *, int,
-				void __user *, size_t *, loff_t *);
+				void __user *, size_t *,
+				loff_t *, void *);
 extern int proc_dointvec_jiffies(struct ctl_table *, int,
-				 void __user *, size_t *, loff_t *);
+				 void __user *, size_t *,
+				 loff_t *, void *);
 extern int proc_dointvec_userhz_jiffies(struct ctl_table *, int,
-					void __user *, size_t *, loff_t *);
+					void __user *, size_t *,
+					loff_t *, void *);
 extern int proc_dointvec_ms_jiffies(struct ctl_table *, int,
-				    void __user *, size_t *, loff_t *);
+				    void __user *, size_t *,
+				    loff_t *, void *);
 extern int proc_doulongvec_minmax(struct ctl_table *, int,
-				  void __user *, size_t *, loff_t *);
+				  void __user *, size_t *,
+				  loff_t *, void *);
 extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
-				      void __user *, size_t *, loff_t *);
+					     void __user *, size_t *,
+					     loff_t *, void *);
 extern int proc_do_large_bitmap(struct ctl_table *, int,
-				void __user *, size_t *, loff_t *);
+				void __user *, size_t *,
+				loff_t *, void *);
 
 /*
  * Register a set of sysctl names by calling register_sysctl_table
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 17e7ccc..6bd24aa 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -108,21 +108,15 @@ extern int laptop_mode;
 extern unsigned long determine_dirtyable_memory(void);
 
 extern int dirty_background_ratio_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos);
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie);
 extern int dirty_background_bytes_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos);
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie);
 extern int dirty_ratio_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos);
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie);
 extern int dirty_bytes_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos);
-
-struct ctl_table;
-int dirty_writeback_centisecs_handler(struct ctl_table *, int,
-				      void __user *, size_t *, loff_t *);
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie);
+extern int dirty_writeback_centisecs_handler(struct ctl_table *table, int write,
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie);
 
 void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty);
 unsigned long bdi_dirty_limit(struct backing_dev_info *bdi,
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index e0e594f..35837cd 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -137,10 +137,13 @@ extern int 			ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
 							   int write,
 							   void __user *buffer,
 							   size_t *lenp,
-							   loff_t *ppos);
+							   loff_t *ppos,
+							   void *cookie);
+
 int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl,
 				 void __user *oldval, size_t __user *oldlenp,
-				 void __user *newval, size_t newlen);
+				 void __user *newval, size_t newlen,
+				 void *cookie);
 #endif
 
 extern void 			inet6_ifinfo_notify(int event,
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 56410fa..f44cb1a 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -27,18 +27,19 @@ static void *get_ipc(ctl_table *table)
 }
 
 #ifdef CONFIG_PROC_SYSCTL
-static int proc_ipc_dointvec(ctl_table *table, int write,
-	void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_ipc_dointvec(ctl_table *table, int write, void __user *buffer,
+			     size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct ctl_table ipc_table;
 	memcpy(&ipc_table, table, sizeof(ipc_table));
 	ipc_table.data = get_ipc(table);
 
-	return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
+	return proc_dointvec(&ipc_table, write, buffer, lenp, ppos, NULL);
 }
 
 static int proc_ipc_callback_dointvec(ctl_table *table, int write,
-	void __user *buffer, size_t *lenp, loff_t *ppos)
+				      void __user *buffer, size_t *lenp,
+				      loff_t *ppos, void *cookie)
 {
 	struct ctl_table ipc_table;
 	size_t lenp_bef = *lenp;
@@ -47,7 +48,7 @@ static int proc_ipc_callback_dointvec(ctl_table *table, int write,
 	memcpy(&ipc_table, table, sizeof(ipc_table));
 	ipc_table.data = get_ipc(table);
 
-	rc = proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
+	rc = proc_dointvec(&ipc_table, write, buffer, lenp, ppos, NULL);
 
 	if (write && !rc && lenp_bef == *lenp)
 		/*
@@ -61,14 +62,15 @@ static int proc_ipc_callback_dointvec(ctl_table *table, int write,
 }
 
 static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
-	void __user *buffer, size_t *lenp, loff_t *ppos)
+				      void __user *buffer, size_t *lenp,
+				      loff_t *ppos, void *cookie)
 {
 	struct ctl_table ipc_table;
 	memcpy(&ipc_table, table, sizeof(ipc_table));
 	ipc_table.data = get_ipc(table);
 
 	return proc_doulongvec_minmax(&ipc_table, write, buffer,
-					lenp, ppos);
+				      lenp, ppos, NULL);
 }
 
 /*
@@ -95,7 +97,8 @@ static void ipc_auto_callback(int val)
 }
 
 static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
-	void __user *buffer, size_t *lenp, loff_t *ppos)
+					void __user *buffer, size_t *lenp,
+					loff_t *ppos, void *cookie)
 {
 	struct ctl_table ipc_table;
 	size_t lenp_bef = *lenp;
@@ -106,7 +109,7 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
 	ipc_table.data = get_ipc(table);
 	oldval = *((int *)(ipc_table.data));
 
-	rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
+	rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos, NULL);
 
 	if (write && !rc && lenp_bef == *lenp) {
 		int newval = *((int *)(ipc_table.data));
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
index 0c09366..384af7d 100644
--- a/ipc/mq_sysctl.c
+++ b/ipc/mq_sysctl.c
@@ -31,25 +31,26 @@ static void *get_mq(ctl_table *table)
 	return which;
 }
 
-static int proc_mq_dointvec(ctl_table *table, int write,
-	void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_mq_dointvec(ctl_table *table, int write, void __user *buffer,
+			    size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct ctl_table mq_table;
 	memcpy(&mq_table, table, sizeof(mq_table));
 	mq_table.data = get_mq(table);
 
-	return proc_dointvec(&mq_table, write, buffer, lenp, ppos);
+	return proc_dointvec(&mq_table, write, buffer, lenp, ppos, NULL);
 }
 
 static int proc_mq_dointvec_minmax(ctl_table *table, int write,
-	void __user *buffer, size_t *lenp, loff_t *ppos)
+				   void __user *buffer, size_t *lenp,
+				   loff_t *ppos, void *cookie)
 {
 	struct ctl_table mq_table;
 	memcpy(&mq_table, table, sizeof(mq_table));
 	mq_table.data = get_mq(table);
 
 	return proc_dointvec_minmax(&mq_table, write, buffer,
-					lenp, ppos);
+				    lenp, ppos, NULL);
 }
 #else
 #define proc_mq_dointvec NULL
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 53ead17..edae933 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -171,12 +171,12 @@ static unsigned long timeout_jiffies(unsigned long timeout)
  * Process updating of timeout sysctl
  */
 int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
-				  void __user *buffer,
-				  size_t *lenp, loff_t *ppos)
+				  void __user *buffer, size_t *lenp,
+				  loff_t *ppos, void *cookie)
 {
 	int ret;
 
-	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
+	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos, NULL);
 
 	if (ret || !write)
 		goto out;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 7798181..8fce3c7 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -826,13 +826,13 @@ static void __kprobes unoptimize_all_kprobes(void)
 int sysctl_kprobes_optimization;
 int proc_kprobes_optimization_handler(struct ctl_table *table, int write,
 				      void __user *buffer, size_t *length,
-				      loff_t *ppos)
+				      loff_t *ppos, void *cookie)
 {
 	int ret;
 
 	mutex_lock(&kprobe_mutex);
 	sysctl_kprobes_optimization = kprobes_allow_optimization ? 1 : 0;
-	ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
+	ret = proc_dointvec_minmax(table, write, buffer, length, ppos, NULL);
 
 	if (sysctl_kprobes_optimization)
 		optimize_all_kprobes();
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index c75925c..fc00e0e 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -158,9 +158,9 @@ static int max_samples_per_tick __read_mostly =
 
 int perf_proc_update_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *lenp,
-		loff_t *ppos)
+		loff_t *ppos, void *cookie)
 {
-	int ret = proc_dointvec(table, write, buffer, lenp, ppos);
+	int ret = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 
 	if (ret || !write)
 		return ret;
diff --git a/kernel/sched.c b/kernel/sched.c
index f592ce6..c787ddf 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -8982,7 +8982,7 @@ static int sched_rt_global_constraints(void)
 
 int sched_rt_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *lenp,
-		loff_t *ppos)
+		loff_t *ppos, void *cookie)
 {
 	int ret;
 	int old_period, old_runtime;
@@ -8992,7 +8992,7 @@ int sched_rt_handler(struct ctl_table *table, int write,
 	old_period = sysctl_sched_rt_period;
 	old_runtime = sysctl_sched_rt_runtime;
 
-	ret = proc_dointvec(table, write, buffer, lenp, ppos);
+	ret = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 
 	if (!ret && write) {
 		ret = sched_rt_global_constraints();
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 3f7ec9e..28ee577 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -448,9 +448,9 @@ static struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
 
 int sched_proc_update_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *lenp,
-		loff_t *ppos)
+		loff_t *ppos, void *cookie)
 {
-	int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos, NULL);
 	int factor = get_update_sysctl_factor();
 
 	if (ret || !write)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index dd3d061..cd7340d 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -165,14 +165,17 @@ extern int unaligned_dump_stack;
 
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(struct ctl_table *table, int write,
-		  void __user *buffer, size_t *lenp, loff_t *ppos);
+			   void __user *buffer, size_t *lenp,
+			   loff_t *ppos, void *cookie);
 static int proc_taint(struct ctl_table *table, int write,
-			       void __user *buffer, size_t *lenp, loff_t *ppos);
+		      void __user *buffer, size_t *lenp,
+		      loff_t *ppos, void *cookie);
 #endif
 
 #ifdef CONFIG_PRINTK
 static int proc_dmesg_restrict(struct ctl_table *table, int write,
-				void __user *buffer, size_t *lenp, loff_t *ppos);
+			       void __user *buffer, size_t *lenp,
+			       loff_t *ppos, void *cookie);
 #endif
 
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -181,11 +184,11 @@ static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
 
 static int sysrq_sysctl_handler(ctl_table *table, int write,
 				void __user *buffer, size_t *lenp,
-				loff_t *ppos)
+				loff_t *ppos, void *cookie)
 {
 	int error;
 
-	error = proc_dointvec(table, write, buffer, lenp, ppos);
+	error = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	if (error)
 		return error;
 
@@ -2089,6 +2092,7 @@ static int _proc_do_string(void* data, int maxlen, int write,
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
  * @ppos: file position
+ * @cookie: ignored by this handler
  *
  * Reads/writes a string from/to the user buffer. If the kernel
  * buffer provided is not large enough to hold the string, the
@@ -2100,7 +2104,8 @@ static int _proc_do_string(void* data, int maxlen, int write,
  * Returns 0 on success.
  */
 int proc_dostring(struct ctl_table *table, int write,
-		  void __user *buffer, size_t *lenp, loff_t *ppos)
+		  void __user *buffer, size_t *lenp,
+		  loff_t *ppos, void *cookie)
 {
 	return _proc_do_string(table->data, table->maxlen, write,
 			       buffer, lenp, ppos);
@@ -2355,6 +2360,7 @@ static int do_proc_dointvec(struct ctl_table *table, int write,
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
  * @ppos: file position
+ * @cookie: ignored by this handler
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string. 
@@ -2362,7 +2368,8 @@ static int do_proc_dointvec(struct ctl_table *table, int write,
  * Returns 0 on success.
  */
 int proc_dointvec(struct ctl_table *table, int write,
-		     void __user *buffer, size_t *lenp, loff_t *ppos)
+		  void __user *buffer, size_t *lenp,
+		  loff_t *ppos, void *cookie)
 {
     return do_proc_dointvec(table,write,buffer,lenp,ppos,
 		    	    NULL,NULL);
@@ -2373,7 +2380,8 @@ int proc_dointvec(struct ctl_table *table, int write,
  * This means we can safely use a temporary.
  */
 static int proc_taint(struct ctl_table *table, int write,
-			       void __user *buffer, size_t *lenp, loff_t *ppos)
+		      void __user *buffer, size_t *lenp,
+		      loff_t *ppos, void *cookie)
 {
 	struct ctl_table t;
 	unsigned long tmptaint = get_taint();
@@ -2384,7 +2392,7 @@ static int proc_taint(struct ctl_table *table, int write,
 
 	t = *table;
 	t.data = &tmptaint;
-	err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
+	err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos, NULL);
 	if (err < 0)
 		return err;
 
@@ -2405,12 +2413,13 @@ static int proc_taint(struct ctl_table *table, int write,
 
 #ifdef CONFIG_PRINTK
 static int proc_dmesg_restrict(struct ctl_table *table, int write,
-				void __user *buffer, size_t *lenp, loff_t *ppos)
+			       void __user *buffer, size_t *lenp,
+			       loff_t *ppos, void *cookie)
 {
 	if (write && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	return proc_dointvec_minmax(table, write, buffer, lenp, ppos, NULL);
 }
 #endif
 
@@ -2450,6 +2459,7 @@ static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
  * @ppos: file position
+ * @cookie: ignored by this handler
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string.
@@ -2460,7 +2470,8 @@ static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
  * Returns 0 on success.
  */
 int proc_dointvec_minmax(struct ctl_table *table, int write,
-		  void __user *buffer, size_t *lenp, loff_t *ppos)
+			 void __user *buffer, size_t *lenp,
+			 loff_t *ppos, void *cookie)
 {
 	struct do_proc_dointvec_minmax_conv_param param = {
 		.min = (int *) table->extra1,
@@ -2567,6 +2578,7 @@ static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
  * @ppos: file position
+ * @cookie: ignored by this handler
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
  * values from/to the user buffer, treated as an ASCII string.
@@ -2577,7 +2589,8 @@ static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
  * Returns 0 on success.
  */
 int proc_doulongvec_minmax(struct ctl_table *table, int write,
-			   void __user *buffer, size_t *lenp, loff_t *ppos)
+			   void __user *buffer, size_t *lenp,
+			   loff_t *ppos, void *cookie)
 {
     return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
 }
@@ -2589,6 +2602,7 @@ int proc_doulongvec_minmax(struct ctl_table *table, int write,
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
  * @ppos: file position
+ * @cookie: ignored by this handler
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
  * values from/to the user buffer, treated as an ASCII string. The values
@@ -2600,8 +2614,8 @@ int proc_doulongvec_minmax(struct ctl_table *table, int write,
  * Returns 0 on success.
  */
 int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
-				      void __user *buffer,
-				      size_t *lenp, loff_t *ppos)
+				      void __user *buffer, size_t *lenp,
+				      loff_t *ppos, void *cookie)
 {
     return do_proc_doulongvec_minmax(table, write, buffer,
 				     lenp, ppos, HZ, 1000l);
@@ -2682,6 +2696,7 @@ static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
  * @ppos: file position
+ * @cookie: ignored by this handler
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string. 
@@ -2691,7 +2706,8 @@ static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
  * Returns 0 on success.
  */
 int proc_dointvec_jiffies(struct ctl_table *table, int write,
-			  void __user *buffer, size_t *lenp, loff_t *ppos)
+			  void __user *buffer, size_t *lenp,
+			  loff_t *ppos, void *cookie)
 {
     return do_proc_dointvec(table,write,buffer,lenp,ppos,
 		    	    do_proc_dointvec_jiffies_conv,NULL);
@@ -2703,7 +2719,8 @@ int proc_dointvec_jiffies(struct ctl_table *table, int write,
  * @write: %TRUE if this is a write to the sysctl file
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
- * @ppos: pointer to the file position
+ * @ppos: file position
+ * @cookie: ignored by this handler
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string. 
@@ -2713,7 +2730,8 @@ int proc_dointvec_jiffies(struct ctl_table *table, int write,
  * Returns 0 on success.
  */
 int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
-				 void __user *buffer, size_t *lenp, loff_t *ppos)
+				 void __user *buffer, size_t *lenp,
+				 loff_t *ppos, void *cookie)
 {
     return do_proc_dointvec(table,write,buffer,lenp,ppos,
 		    	    do_proc_dointvec_userhz_jiffies_conv,NULL);
@@ -2726,7 +2744,7 @@ int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
  * @ppos: file position
- * @ppos: the current position in the file
+ * @cookie: ignored by this handler
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string. 
@@ -2736,14 +2754,16 @@ int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
  * Returns 0 on success.
  */
 int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
-			     void __user *buffer, size_t *lenp, loff_t *ppos)
+			     void __user *buffer, size_t *lenp,
+			     loff_t *ppos, void *cookie)
 {
 	return do_proc_dointvec(table, write, buffer, lenp, ppos,
 				do_proc_dointvec_ms_jiffies_conv, NULL);
 }
 
 static int proc_do_cad_pid(struct ctl_table *table, int write,
-			   void __user *buffer, size_t *lenp, loff_t *ppos)
+			   void __user *buffer, size_t *lenp,
+			   loff_t *ppos, void *cookie)
 {
 	struct pid *new_pid;
 	pid_t tmp;
@@ -2771,6 +2791,7 @@ static int proc_do_cad_pid(struct ctl_table *table, int write,
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
  * @ppos: file position
+ * @cookie: ignored by this handler
  *
  * The bitmap is stored at table->data and the bitmap length (in bits)
  * in table->maxlen.
@@ -2782,7 +2803,8 @@ static int proc_do_cad_pid(struct ctl_table *table, int write,
  * Returns 0 on success.
  */
 int proc_do_large_bitmap(struct ctl_table *table, int write,
-			 void __user *buffer, size_t *lenp, loff_t *ppos)
+			 void __user *buffer, size_t *lenp,
+			 loff_t *ppos, void *cookie)
 {
 	int err = 0;
 	bool first = 1;
@@ -2918,50 +2940,57 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
 #else /* CONFIG_PROC_SYSCTL */
 
 int proc_dostring(struct ctl_table *table, int write,
-		  void __user *buffer, size_t *lenp, loff_t *ppos)
+		  void __user *buffer, size_t *lenp,
+		  loff_t *ppos, void *cookie)
 {
 	return -ENOSYS;
 }
 
 int proc_dointvec(struct ctl_table *table, int write,
-		  void __user *buffer, size_t *lenp, loff_t *ppos)
+		  void __user *buffer, size_t *lenp,
+		  loff_t *ppos, void *cookie)
 {
 	return -ENOSYS;
 }
 
 int proc_dointvec_minmax(struct ctl_table *table, int write,
-		    void __user *buffer, size_t *lenp, loff_t *ppos)
+			 void __user *buffer, size_t *lenp,
+			 loff_t *ppos, void *cookie)
 {
 	return -ENOSYS;
 }
 
 int proc_dointvec_jiffies(struct ctl_table *table, int write,
-		    void __user *buffer, size_t *lenp, loff_t *ppos)
+			  void __user *buffer, size_t *lenp,
+			  loff_t *ppos, void *cookie)
 {
 	return -ENOSYS;
 }
 
 int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
-		    void __user *buffer, size_t *lenp, loff_t *ppos)
+				 void __user *buffer, size_t *lenp,
+				 loff_t *ppos, void *cookie)
 {
 	return -ENOSYS;
 }
 
 int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
-			     void __user *buffer, size_t *lenp, loff_t *ppos)
+			     void __user *buffer, size_t *lenp,
+			     loff_t *ppos, void *cookie)
 {
 	return -ENOSYS;
 }
 
 int proc_doulongvec_minmax(struct ctl_table *table, int write,
-		    void __user *buffer, size_t *lenp, loff_t *ppos)
+			   void __user *buffer, size_t *lenp,
+			   loff_t *ppos, void *cookie)
 {
 	return -ENOSYS;
 }
 
 int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
-				      void __user *buffer,
-				      size_t *lenp, loff_t *ppos)
+				      void __user *buffer, size_t *lenp,
+				      loff_t *ppos, void *cookie)
 {
     return -ENOSYS;
 }
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index c075f4e..91a4d03 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3178,7 +3178,7 @@ int unregister_ftrace_function(struct ftrace_ops *ops)
 int
 ftrace_enable_sysctl(struct ctl_table *table, int write,
 		     void __user *buffer, size_t *lenp,
-		     loff_t *ppos)
+		     loff_t *ppos, void *cookie)
 {
 	int ret;
 
@@ -3187,7 +3187,7 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
 
 	mutex_lock(&ftrace_lock);
 
-	ret  = proc_dointvec(table, write, buffer, lenp, ppos);
+	ret  = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 
 	if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
 		goto out;
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 4c5dead..9ac91f2 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -322,13 +322,13 @@ static const struct file_operations stack_trace_fops = {
 int
 stack_trace_sysctl(struct ctl_table *table, int write,
 		   void __user *buffer, size_t *lenp,
-		   loff_t *ppos)
+		   loff_t *ppos, void *cookie)
 {
 	int ret;
 
 	mutex_lock(&stack_sysctl_mutex);
 
-	ret = proc_dointvec(table, write, buffer, lenp, ppos);
+	ret = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 
 	if (ret || !write ||
 	    (last_stack_tracer_enabled == !!stack_tracer_enabled))
diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c
index a2cd77e..a4d0d8c 100644
--- a/kernel/utsname_sysctl.c
+++ b/kernel/utsname_sysctl.c
@@ -42,14 +42,14 @@ static void put_uts(ctl_table *table, int write, void *which)
  *	Special case of dostring for the UTS structure. This has locks
  *	to observe. Should this be in kernel/sys.c ????
  */
-static int proc_do_uts_string(ctl_table *table, int write,
-		  void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_do_uts_string(ctl_table *table, int write, void __user *buffer,
+			      size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct ctl_table uts_table;
 	int r;
 	memcpy(&uts_table, table, sizeof(uts_table));
 	uts_table.data = get_uts(table, write);
-	r = proc_dostring(&uts_table,write,buffer,lenp, ppos);
+	r = proc_dostring(&uts_table,write,buffer,lenp, ppos, NULL);
 	put_uts(table, write, uts_table.data);
 	return r;
 }
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 140dce7..23f78c0 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -502,9 +502,10 @@ static void watchdog_disable_all_cpus(void)
  */
 
 int proc_dowatchdog_enabled(struct ctl_table *table, int write,
-		     void __user *buffer, size_t *length, loff_t *ppos)
+			    void __user *buffer, size_t *length,
+			    loff_t *ppos, void *cookie)
 {
-	proc_dointvec(table, write, buffer, length, ppos);
+	proc_dointvec(table, write, buffer, length, ppos, NULL);
 
 	if (write) {
 		if (watchdog_enabled)
@@ -516,10 +517,10 @@ int proc_dowatchdog_enabled(struct ctl_table *table, int write,
 }
 
 int proc_dowatchdog_thresh(struct ctl_table *table, int write,
-			     void __user *buffer,
-			     size_t *lenp, loff_t *ppos)
+			   void __user *buffer, size_t *lenp,
+			   loff_t *ppos, void *cookie)
 {
-	return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	return proc_dointvec_minmax(table, write, buffer, lenp, ppos, NULL);
 }
 #endif /* CONFIG_SYSCTL */
 
diff --git a/mm/compaction.c b/mm/compaction.c
index 021a296..18dd3e7 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -676,7 +676,8 @@ int sysctl_compact_memory;
 
 /* This is the entry point for compacting all nodes via /proc/sys/vm */
 int sysctl_compaction_handler(struct ctl_table *table, int write,
-			void __user *buffer, size_t *length, loff_t *ppos)
+			      void __user *buffer, size_t *length,
+			      loff_t *ppos, void *cookie)
 {
 	if (write)
 		return compact_nodes();
@@ -685,9 +686,10 @@ int sysctl_compaction_handler(struct ctl_table *table, int write,
 }
 
 int sysctl_extfrag_handler(struct ctl_table *table, int write,
-			void __user *buffer, size_t *length, loff_t *ppos)
+			   void __user *buffer, size_t *length,
+			   loff_t *ppos, void *cookie)
 {
-	proc_dointvec_minmax(table, write, buffer, length, ppos);
+	proc_dointvec_minmax(table, write, buffer, length, ppos, NULL);
 
 	return 0;
 }
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 06de5aa..2f3f60e 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1879,7 +1879,7 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
 
 	table->data = &tmp;
 	table->maxlen = sizeof(unsigned long);
-	ret = proc_doulongvec_minmax(table, write, buffer, length, ppos);
+	ret = proc_doulongvec_minmax(table, write, buffer, length, ppos, NULL);
 	if (ret)
 		goto out;
 
@@ -1901,27 +1901,29 @@ out:
 }
 
 int hugetlb_sysctl_handler(struct ctl_table *table, int write,
-			  void __user *buffer, size_t *length, loff_t *ppos)
+			   void __user *buffer, size_t *length,
+			   loff_t *ppos, void *cookie)
 {
 
 	return hugetlb_sysctl_handler_common(false, table, write,
-							buffer, length, ppos);
+					     buffer, length, ppos);
 }
 
 #ifdef CONFIG_NUMA
 int hugetlb_mempolicy_sysctl_handler(struct ctl_table *table, int write,
-			  void __user *buffer, size_t *length, loff_t *ppos)
+				     void __user *buffer, size_t *length,
+				     loff_t *ppos, void *cookie)
 {
 	return hugetlb_sysctl_handler_common(true, table, write,
-							buffer, length, ppos);
+					     buffer, length, ppos);
 }
 #endif /* CONFIG_NUMA */
 
 int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
-			void __user *buffer,
-			size_t *length, loff_t *ppos)
+				  void __user *buffer, size_t *length,
+				  loff_t *ppos, void *cookie)
 {
-	proc_dointvec(table, write, buffer, length, ppos);
+	proc_dointvec(table, write, buffer, length, ppos, NULL);
 	if (hugepages_treat_as_movable)
 		htlb_alloc_mask = GFP_HIGHUSER_MOVABLE;
 	else
@@ -1930,8 +1932,8 @@ int hugetlb_treat_movable_handler(struct ctl_table *table, int write,
 }
 
 int hugetlb_overcommit_handler(struct ctl_table *table, int write,
-			void __user *buffer,
-			size_t *length, loff_t *ppos)
+			       void __user *buffer, size_t *length,
+			       loff_t *ppos, void *cookie)
 {
 	struct hstate *h = &default_hstate;
 	unsigned long tmp;
@@ -1944,7 +1946,7 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
 
 	table->data = &tmp;
 	table->maxlen = sizeof(unsigned long);
-	ret = proc_doulongvec_minmax(table, write, buffer, length, ppos);
+	ret = proc_doulongvec_minmax(table, write, buffer, length, ppos, NULL);
 	if (ret)
 		goto out;
 
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 31f6988..b8cb0b0 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -159,37 +159,34 @@ static void update_completion_period(void)
 }
 
 int dirty_background_ratio_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos)
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int ret;
 
-	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos, NULL);
 	if (ret == 0 && write)
 		dirty_background_bytes = 0;
 	return ret;
 }
 
 int dirty_background_bytes_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos)
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int ret;
 
-	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
+	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos, NULL);
 	if (ret == 0 && write)
 		dirty_background_ratio = 0;
 	return ret;
 }
 
 int dirty_ratio_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos)
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int old_ratio = vm_dirty_ratio;
 	int ret;
 
-	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos, NULL);
 	if (ret == 0 && write && vm_dirty_ratio != old_ratio) {
 		update_completion_period();
 		vm_dirty_bytes = 0;
@@ -199,13 +196,12 @@ int dirty_ratio_handler(struct ctl_table *table, int write,
 
 
 int dirty_bytes_handler(struct ctl_table *table, int write,
-		void __user *buffer, size_t *lenp,
-		loff_t *ppos)
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie)
 {
 	unsigned long old_bytes = vm_dirty_bytes;
 	int ret;
 
-	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
+	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos, NULL);
 	if (ret == 0 && write && vm_dirty_bytes != old_bytes) {
 		update_completion_period();
 		vm_dirty_ratio = 0;
@@ -684,9 +680,9 @@ void throttle_vm_writeout(gfp_t gfp_mask)
  * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs
  */
 int dirty_writeback_centisecs_handler(ctl_table *table, int write,
-	void __user *buffer, size_t *length, loff_t *ppos)
+		void __user *buffer, size_t *lenp, loff_t *ppos, void *cookie)
 {
-	proc_dointvec(table, write, buffer, length, ppos);
+	proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	bdi_arm_supers_timer();
 	return 0;
 }
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d6e7ba7..0e46115 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2721,8 +2721,7 @@ early_param("numa_zonelist_order", setup_numa_zonelist_order);
  * sysctl handler for numa_zonelist_order
  */
 int numa_zonelist_order_handler(ctl_table *table, int write,
-		void __user *buffer, size_t *length,
-		loff_t *ppos)
+	void __user *buffer, size_t *length, loff_t *ppos, void *cookie)
 {
 	char saved_string[NUMA_ZONELIST_ORDER_LEN];
 	int ret;
@@ -2731,7 +2730,7 @@ int numa_zonelist_order_handler(ctl_table *table, int write,
 	mutex_lock(&zl_order_mutex);
 	if (write)
 		strcpy(saved_string, (char*)table->data);
-	ret = proc_dostring(table, write, buffer, length, ppos);
+	ret = proc_dostring(table, write, buffer, length, ppos, NULL);
 	if (ret)
 		goto out;
 	if (write) {
@@ -5142,9 +5141,9 @@ module_init(init_per_zone_wmark_min)
  *	changes.
  */
 int min_free_kbytes_sysctl_handler(ctl_table *table, int write, 
-	void __user *buffer, size_t *length, loff_t *ppos)
+	void __user *buffer, size_t *length, loff_t *ppos, void *cookie)
 {
-	proc_dointvec(table, write, buffer, length, ppos);
+	proc_dointvec(table, write, buffer, length, ppos, NULL);
 	if (write)
 		setup_per_zone_wmarks();
 	return 0;
@@ -5152,12 +5151,12 @@ int min_free_kbytes_sysctl_handler(ctl_table *table, int write,
 
 #ifdef CONFIG_NUMA
 int sysctl_min_unmapped_ratio_sysctl_handler(ctl_table *table, int write,
-	void __user *buffer, size_t *length, loff_t *ppos)
+	void __user *buffer, size_t *length, loff_t *ppos, void *cookie)
 {
 	struct zone *zone;
 	int rc;
 
-	rc = proc_dointvec_minmax(table, write, buffer, length, ppos);
+	rc = proc_dointvec_minmax(table, write, buffer, length, ppos, NULL);
 	if (rc)
 		return rc;
 
@@ -5168,12 +5167,12 @@ int sysctl_min_unmapped_ratio_sysctl_handler(ctl_table *table, int write,
 }
 
 int sysctl_min_slab_ratio_sysctl_handler(ctl_table *table, int write,
-	void __user *buffer, size_t *length, loff_t *ppos)
+	void __user *buffer, size_t *length, loff_t *ppos, void *cookie)
 {
 	struct zone *zone;
 	int rc;
 
-	rc = proc_dointvec_minmax(table, write, buffer, length, ppos);
+	rc = proc_dointvec_minmax(table, write, buffer, length, ppos, NULL);
 	if (rc)
 		return rc;
 
@@ -5194,9 +5193,9 @@ int sysctl_min_slab_ratio_sysctl_handler(ctl_table *table, int write,
  * if in function of the boot time zone sizes.
  */
 int lowmem_reserve_ratio_sysctl_handler(ctl_table *table, int write,
-	void __user *buffer, size_t *length, loff_t *ppos)
+	void __user *buffer, size_t *length, loff_t *ppos, void *cookie)
 {
-	proc_dointvec_minmax(table, write, buffer, length, ppos);
+	proc_dointvec_minmax(table, write, buffer, length, ppos, NULL);
 	setup_per_zone_lowmem_reserve();
 	return 0;
 }
@@ -5208,13 +5207,13 @@ int lowmem_reserve_ratio_sysctl_handler(ctl_table *table, int write,
  */
 
 int percpu_pagelist_fraction_sysctl_handler(ctl_table *table, int write,
-	void __user *buffer, size_t *length, loff_t *ppos)
+	void __user *buffer, size_t *length, loff_t *ppos, void *cookie)
 {
 	struct zone *zone;
 	unsigned int cpu;
 	int ret;
 
-	ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
+	ret = proc_dointvec_minmax(table, write, buffer, length, ppos, NULL);
 	if (!write || (ret == -EINVAL))
 		return ret;
 	for_each_populated_zone(zone) {
diff --git a/mm/vmscan.c b/mm/vmscan.c
index f73b865..6a578af 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3273,10 +3273,10 @@ static void scan_all_zones_unevictable_pages(void)
 unsigned long scan_unevictable_pages;
 
 int scan_unevictable_handler(struct ctl_table *table, int write,
-			   void __user *buffer,
-			   size_t *length, loff_t *ppos)
+			     void __user *buffer, size_t *length,
+			     loff_t *ppos, void *cookie)
 {
-	proc_doulongvec_minmax(table, write, buffer, length, ppos);
+	proc_doulongvec_minmax(table, write, buffer, length, ppos, NULL);
 
 	if (write && *(unsigned long *)table->data)
 		scan_all_zones_unevictable_pages();
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 008ff6c..5d5ac11 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -932,12 +932,12 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = {
 
 #ifdef CONFIG_SYSCTL
 static
-int brnf_sysctl_call_tables(ctl_table * ctl, int write,
-			    void __user * buffer, size_t * lenp, loff_t * ppos)
+int brnf_sysctl_call_tables(ctl_table * ctl, int write, void __user * buffer,
+			    size_t * lenp, loff_t * ppos, void * cookie)
 {
 	int ret;
 
-	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	ret = proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 
 	if (write && *(int *)(ctl->data))
 		*(int *)(ctl->data) = 1;
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 385b609..923ae0f 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -20,7 +20,8 @@
 
 #ifdef CONFIG_RPS
 static int rps_sock_flow_sysctl(ctl_table *table, int write,
-				void __user *buffer, size_t *lenp, loff_t *ppos)
+				void __user *buffer, size_t *lenp,
+				loff_t *ppos, void *cookie)
 {
 	unsigned int orig_size, size;
 	int ret, i;
@@ -38,7 +39,7 @@ static int rps_sock_flow_sysctl(ctl_table *table, int write,
 					lockdep_is_held(&sock_flow_mutex));
 	size = orig_size = orig_sock_table ? orig_sock_table->mask + 1 : 0;
 
-	ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);
+	ret = proc_dointvec(&tmp, write, buffer, lenp, ppos, NULL);
 
 	if (write) {
 		if (size) {
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 0dcaa90..6935f42 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -159,8 +159,8 @@ static int max_t3[] = { 8191 }; /* Must fit in 16 bits when multiplied by BCT3MU
 static int min_priority[1];
 static int max_priority[] = { 127 }; /* From DECnet spec */
 
-static int dn_forwarding_proc(ctl_table *, int,
-			void __user *, size_t *, loff_t *);
+static int dn_forwarding_proc(ctl_table *, int, void __user *,
+			      size_t *, loff_t *, void *);
 static struct dn_dev_sysctl_table {
 	struct ctl_table_header *sysctl_header;
 	ctl_table dn_dev_vars[5];
@@ -255,8 +255,8 @@ static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
 }
 
 static int dn_forwarding_proc(ctl_table *table, int write,
-				void __user *buffer,
-				size_t *lenp, loff_t *ppos)
+			      void __user *buffer, size_t *lenp,
+			      loff_t *ppos, void *cookie)
 {
 #ifdef CONFIG_DECNET_ROUTER
 	struct net_device *dev = table->extra1;
@@ -270,7 +270,7 @@ static int dn_forwarding_proc(ctl_table *table, int write,
 	dn_db = rcu_dereference_raw(dev->dn_ptr);
 	old = dn_db->parms.forwarding;
 
-	err = proc_dointvec(table, write, buffer, lenp, ppos);
+	err = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 
 	if ((err >= 0) && write) {
 		if (dn_db->parms.forwarding < 0)
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
index 28f8b5e..90e87a7 100644
--- a/net/decnet/sysctl_net_decnet.c
+++ b/net/decnet/sysctl_net_decnet.c
@@ -132,8 +132,8 @@ static int parse_addr(__le16 *addr, char *str)
 }
 
 static int dn_node_address_handler(ctl_table *table, int write,
-				void __user *buffer,
-				size_t *lenp, loff_t *ppos)
+				   void __user *buffer, size_t *lenp,
+				   loff_t *ppos, void *cookie)
 {
 	char addr[DN_ASCBUF_LEN];
 	size_t len;
@@ -183,8 +183,8 @@ static int dn_node_address_handler(ctl_table *table, int write,
 }
 
 static int dn_def_dev_handler(ctl_table *table, int write,
-				void __user *buffer,
-				size_t *lenp, loff_t *ppos)
+			      void __user *buffer, size_t *lenp,
+			      loff_t *ppos, void *cookie)
 {
 	size_t len;
 	struct net_device *dev;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index cd9ca08..551786f 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1487,10 +1487,10 @@ static void inet_forward_change(struct net *net)
 }
 
 static int devinet_conf_proc(ctl_table *ctl, int write,
-			     void __user *buffer,
-			     size_t *lenp, loff_t *ppos)
+			     void __user *buffer, size_t *lenp,
+			     loff_t *ppos, void *cookie)
 {
-	int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	int ret = proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 
 	if (write) {
 		struct ipv4_devconf *cnf = ctl->extra1;
@@ -1507,13 +1507,13 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
 }
 
 static int devinet_sysctl_forward(ctl_table *ctl, int write,
-				  void __user *buffer,
-				  size_t *lenp, loff_t *ppos)
+				  void __user *buffer, size_t *lenp,
+				  loff_t *ppos, void *cookie)
 {
 	int *valp = ctl->data;
 	int val = *valp;
 	loff_t pos = *ppos;
-	int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	int ret = proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 
 	if (write && *valp != val) {
 		struct net *net = ctl->extra2;
@@ -1542,12 +1542,12 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
 }
 
 static int ipv4_doint_and_flush(ctl_table *ctl, int write,
-				void __user *buffer,
-				size_t *lenp, loff_t *ppos)
+				void __user *buffer, size_t *lenp,
+				loff_t *ppos, void *cookie)
 {
 	int *valp = ctl->data;
 	int val = *valp;
-	int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	int ret = proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 	struct net *net = ctl->extra2;
 
 	if (write && *valp != val)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 4b0c811..0c66ea6 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3009,8 +3009,8 @@ void ip_rt_multicast_event(struct in_device *in_dev)
 
 #ifdef CONFIG_SYSCTL
 static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
-					void __user *buffer,
-					size_t *lenp, loff_t *ppos)
+				     void __user *buffer, size_t *lenp,
+				     loff_t *ppos, void *cookie)
 {
 	if (write) {
 		int flush_delay;
@@ -3019,7 +3019,7 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
 
 		memcpy(&ctl, __ctl, sizeof(ctl));
 		ctl.data = &flush_delay;
-		proc_dointvec(&ctl, write, buffer, lenp, ppos);
+		proc_dointvec(&ctl, write, buffer, lenp, ppos, NULL);
 
 		net = (struct net *)__ctl->extra1;
 		rt_cache_flush(net, flush_delay);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 1a45665..1766d2e 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -42,8 +42,8 @@ static void set_local_port_range(int range[2])
 
 /* Validate changes from /proc interface. */
 static int ipv4_local_port_range(ctl_table *table, int write,
-				 void __user *buffer,
-				 size_t *lenp, loff_t *ppos)
+				 void __user *buffer, size_t *lenp,
+				 loff_t *ppos, void *cookie)
 {
 	int ret;
 	int range[2];
@@ -56,7 +56,7 @@ static int ipv4_local_port_range(ctl_table *table, int write,
 	};
 
 	inet_get_local_port_range(range, range + 1);
-	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos, NULL);
 
 	if (write && ret == 0) {
 		if (range[1] < range[0])
@@ -69,7 +69,8 @@ static int ipv4_local_port_range(ctl_table *table, int write,
 }
 
 static int proc_tcp_congestion_control(ctl_table *ctl, int write,
-				       void __user *buffer, size_t *lenp, loff_t *ppos)
+				       void __user *buffer, size_t *lenp,
+				       loff_t *ppos, void *cookie)
 {
 	char val[TCP_CA_NAME_MAX];
 	ctl_table tbl = {
@@ -80,16 +81,15 @@ static int proc_tcp_congestion_control(ctl_table *ctl, int write,
 
 	tcp_get_default_congestion_control(val);
 
-	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
+	ret = proc_dostring(&tbl, write, buffer, lenp, ppos, NULL);
 	if (write && ret == 0)
 		ret = tcp_set_default_congestion_control(val);
 	return ret;
 }
 
-static int proc_tcp_available_congestion_control(ctl_table *ctl,
-						 int write,
+static int proc_tcp_available_congestion_control(ctl_table *ctl, int write,
 						 void __user *buffer, size_t *lenp,
-						 loff_t *ppos)
+						 loff_t *ppos, void *cookie)
 {
 	ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, };
 	int ret;
@@ -98,15 +98,14 @@ static int proc_tcp_available_congestion_control(ctl_table *ctl,
 	if (!tbl.data)
 		return -ENOMEM;
 	tcp_get_available_congestion_control(tbl.data, TCP_CA_BUF_MAX);
-	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
+	ret = proc_dostring(&tbl, write, buffer, lenp, ppos, NULL);
 	kfree(tbl.data);
 	return ret;
 }
 
-static int proc_allowed_congestion_control(ctl_table *ctl,
-					   int write,
+static int proc_allowed_congestion_control(ctl_table *ctl, int write,
 					   void __user *buffer, size_t *lenp,
-					   loff_t *ppos)
+					   loff_t *ppos, void *cookie)
 {
 	ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
 	int ret;
@@ -116,7 +115,7 @@ static int proc_allowed_congestion_control(ctl_table *ctl,
 		return -ENOMEM;
 
 	tcp_get_allowed_congestion_control(tbl.data, tbl.maxlen);
-	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
+	ret = proc_dostring(&tbl, write, buffer, lenp, ppos, NULL);
 	if (write && ret == 0)
 		ret = tcp_set_allowed_congestion_control(tbl.data);
 	kfree(tbl.data);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b1654a4..4a28442 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4156,15 +4156,15 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 #ifdef CONFIG_SYSCTL
 
 static
-int addrconf_sysctl_forward(ctl_table *ctl, int write,
-			   void __user *buffer, size_t *lenp, loff_t *ppos)
+int addrconf_sysctl_forward(ctl_table *ctl, int write, void __user *buffer,
+			    size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int *valp = ctl->data;
 	int val = *valp;
 	loff_t pos = *ppos;
 	int ret;
 
-	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	ret = proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 
 	if (write)
 		ret = addrconf_fixup_forwarding(ctl, valp, val);
@@ -4229,15 +4229,15 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
 }
 
 static
-int addrconf_sysctl_disable(ctl_table *ctl, int write,
-			    void __user *buffer, size_t *lenp, loff_t *ppos)
+int addrconf_sysctl_disable(ctl_table *ctl, int write, void __user *buffer,
+			    size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int *valp = ctl->data;
 	int val = *valp;
 	loff_t pos = *ppos;
 	int ret;
 
-	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	ret = proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 
 	if (write)
 		ret = addrconf_disable_ipv6(ctl, valp, val);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0e49c9d..61ff29b 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1751,7 +1751,9 @@ static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
 	}
 }
 
-int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
+int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write,
+			       void __user *buffer, size_t *lenp,
+			       loff_t *ppos, void *cookie)
 {
 	struct net_device *dev = ctl->extra1;
 	struct inet6_dev *idev;
@@ -1762,16 +1764,16 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *bu
 		ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
 
 	if (strcmp(ctl->procname, "retrans_time") == 0)
-		ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+		ret = proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 
 	else if (strcmp(ctl->procname, "base_reachable_time") == 0)
-		ret = proc_dointvec_jiffies(ctl, write,
-					    buffer, lenp, ppos);
+		ret = proc_dointvec_jiffies(ctl, write, buffer,
+					    lenp, ppos, NULL);
 
 	else if ((strcmp(ctl->procname, "retrans_time_ms") == 0) ||
 		 (strcmp(ctl->procname, "base_reachable_time_ms") == 0))
-		ret = proc_dointvec_ms_jiffies(ctl, write,
-					       buffer, lenp, ppos);
+		ret = proc_dointvec_ms_jiffies(ctl, write, buffer,
+					       lenp, ppos, NULL);
 	else
 		ret = -1;
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 843406f..48ec0b7 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2593,8 +2593,8 @@ static const struct file_operations rt6_stats_seq_fops = {
 #ifdef CONFIG_SYSCTL
 
 static
-int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write,
-			      void __user *buffer, size_t *lenp, loff_t *ppos)
+int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, void __user *buffer,
+			      size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct net *net;
 	int delay;
@@ -2603,7 +2603,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write,
 
 	net = (struct net *)ctl->extra1;
 	delay = net->ipv6.sysctl.flush_delay;
-	proc_dointvec(ctl, write, buffer, lenp, ppos);
+	proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 	fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
 	return 0;
 }
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c
index d0b70da..1ee0226 100644
--- a/net/irda/irsysctl.c
+++ b/net/irda/irsysctl.c
@@ -73,12 +73,12 @@ static int min_lap_keepalive_time = 100;	/* 100us */
 /* For other sysctl, I've no idea of the range. Maybe Dag could help
  * us on that - Jean II */
 
-static int do_devname(ctl_table *table, int write,
-		      void __user *buffer, size_t *lenp, loff_t *ppos)
+static int do_devname(ctl_table *table, int write, void __user *buffer,
+		      size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int ret;
 
-	ret = proc_dostring(table, write, buffer, lenp, ppos);
+	ret = proc_dostring(table, write, buffer, lenp, ppos, NULL);
 	if (ret == 0 && write) {
 		struct ias_value *val;
 
@@ -90,12 +90,12 @@ static int do_devname(ctl_table *table, int write,
 }
 
 
-static int do_discovery(ctl_table *table, int write,
-                    void __user *buffer, size_t *lenp, loff_t *ppos)
+static int do_discovery(ctl_table *table, int write, void __user *buffer,
+			size_t *lenp, loff_t *ppos, void *cookie)
 {
        int ret;
 
-       ret = proc_dointvec(table, write, buffer, lenp, ppos);
+       ret = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
        if (ret)
 	       return ret;
 
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 33733c8..6269b13 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1514,15 +1514,15 @@ static int ip_vs_zero_all(struct net *net)
 
 #ifdef CONFIG_SYSCTL
 static int
-proc_do_defense_mode(ctl_table *table, int write,
-		     void __user *buffer, size_t *lenp, loff_t *ppos)
+proc_do_defense_mode(ctl_table *table, int write, void __user *buffer,
+		     size_t *lenp, loff_t *ppos, void *cookie)
 {
 	struct net *net = current->nsproxy->net_ns;
 	int *valp = table->data;
 	int val = *valp;
 	int rc;
 
-	rc = proc_dointvec(table, write, buffer, lenp, ppos);
+	rc = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	if (write && (*valp != val)) {
 		if ((*valp < 0) || (*valp > 3)) {
 			/* Restore the correct value */
@@ -1535,8 +1535,8 @@ proc_do_defense_mode(ctl_table *table, int write,
 }
 
 static int
-proc_do_sync_threshold(ctl_table *table, int write,
-		       void __user *buffer, size_t *lenp, loff_t *ppos)
+proc_do_sync_threshold(ctl_table *table, int write, void __user *buffer,
+		       size_t *lenp, loff_t *ppos, void *cookie)
 {
 	int *valp = table->data;
 	int val[2];
@@ -1545,7 +1545,7 @@ proc_do_sync_threshold(ctl_table *table, int write,
 	/* backup the value first */
 	memcpy(val, valp, sizeof(val));
 
-	rc = proc_dointvec(table, write, buffer, lenp, ppos);
+	rc = proc_dointvec(table, write, buffer, lenp, ppos, NULL);
 	if (write && (valp[0] < 0 || valp[1] < 0 || valp[0] >= valp[1])) {
 		/* Restore the correct value */
 		memcpy(valp, val, sizeof(val));
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 20714ed..9bd1f90 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -226,7 +226,8 @@ static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1];
 static struct ctl_table_header *nf_log_dir_header;
 
 static int nf_log_proc_dostring(ctl_table *table, int write,
-			 void __user *buffer, size_t *lenp, loff_t *ppos)
+				void __user *buffer, size_t *lenp,
+				loff_t *ppos, void *cookie)
 {
 	const struct nf_logger *logger;
 	char buf[NFLOGGER_NAME_LEN];
@@ -260,7 +261,7 @@ static int nf_log_proc_dostring(ctl_table *table, int write,
 			table->data = "NONE";
 		else
 			table->data = logger->name;
-		r = proc_dostring(table, write, buffer, lenp, ppos);
+		r = proc_dostring(table, write, buffer, lenp, ppos, NULL);
 		mutex_unlock(&nf_log_mutex);
 	}
 
diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c
index cea1c7d..7bdaf3e 100644
--- a/net/phonet/sysctl.c
+++ b/net/phonet/sysctl.c
@@ -57,8 +57,8 @@ void phonet_get_local_port_range(int *min, int *max)
 }
 
 static int proc_local_port_range(ctl_table *table, int write,
-				void __user *buffer,
-				size_t *lenp, loff_t *ppos)
+				 void __user *buffer, size_t *lenp,
+				 loff_t *ppos, void *cookie)
 {
 	int ret;
 	int range[2] = {local_port_range[0], local_port_range[1]};
@@ -70,7 +70,7 @@ static int proc_local_port_range(ctl_table *table, int write,
 		.extra2 = &local_port_range_max,
 	};
 
-	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos, NULL);
 
 	if (write && ret == 0) {
 		if (range[1] < range[0])
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index e65dcc6..30fc555 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -56,8 +56,8 @@ rpc_unregister_sysctl(void)
 	}
 }
 
-static int proc_do_xprt(ctl_table *table, int write,
-			void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_do_xprt(ctl_table *table, int write, void __user *buffer,
+			size_t *lenp, loff_t *ppos, void *cookie)
 {
 	char tmpbuf[256];
 	size_t len;
@@ -70,9 +70,8 @@ static int proc_do_xprt(ctl_table *table, int write,
 	return simple_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len);
 }
 
-static int
-proc_dodebug(ctl_table *table, int write,
-				void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_dodebug(ctl_table *table, int write, void __user *buffer,
+			size_t *lenp, loff_t *ppos, void *cookie)
 {
 	char		tmpbuf[20], c, *s;
 	char __user *p;
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c
index 09af4fa..fef4bf7 100644
--- a/net/sunrpc/xprtrdma/svc_rdma.c
+++ b/net/sunrpc/xprtrdma/svc_rdma.c
@@ -85,7 +85,7 @@ struct workqueue_struct *svc_rdma_wq;
  */
 static int read_reset_stat(ctl_table *table, int write,
 			   void __user *buffer, size_t *lenp,
-			   loff_t *ppos)
+			   loff_t *ppos, void *cookie)
 {
 	atomic_t *stat = (atomic_t *)table->data;
 
diff --git a/security/min_addr.c b/security/min_addr.c
index f728728..340ae41 100644
--- a/security/min_addr.c
+++ b/security/min_addr.c
@@ -29,14 +29,15 @@ static void update_mmap_min_addr(void)
  * calls update_mmap_min_addr() so non MAP_FIXED hints get rounded properly
  */
 int mmap_min_addr_handler(struct ctl_table *table, int write,
-			  void __user *buffer, size_t *lenp, loff_t *ppos)
+			  void __user *buffer, size_t *lenp,
+			  loff_t *ppos, void *cookie)
 {
 	int ret;
 
 	if (write && !capable(CAP_SYS_RAWIO))
 		return -EPERM;
 
-	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
+	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos, NULL);
 
 	update_mmap_min_addr();
 
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 04/24] sysctl: cookie: add netns_proc_dointvec and other netns_proc_* proc_handlers
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (2 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 03/24] sysctl: cookie: pass ctl_header_cookie to proc_handler Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 05/24] sysctl: cookie: share ip4_frags_ns_ctl_table between nets Lucian Adrian Grijincu
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

Use these handlers when you want to change a netns dependant
variable. The following restrictions apply:

- these handlers must receive as cookie a 'struct net*'

- the data field of ctl_table* must be at a constant offset from
  the init_net structure. e.g.: &init_net.member1.member2..memberN

- these handlers will call their equivalent handler with a
  ctl_table with data of the form: net->member1.member2..memberN

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

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 3ae4919..86c6e57 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -278,4 +278,37 @@ extern struct ctl_table_header *register_net_sysctl_rotable(
 	const struct ctl_path *path, struct ctl_table *table);
 extern void unregister_net_sysctl_table(struct ctl_table_header *header);
 
+
+
+/*
+ * Use these handlers when you want to change a netns dependant
+ * variable. The following restrictions apply:
+ *
+ * - these handlers must receive as cookie a 'struct net*'
+ *
+ * - the data field of ctl_table* must be at a constant offset from
+ *   the init_net structure. e.g.: &init_net.member1.member2..memberN
+ *
+ * - these handlers will call their equivalent handler with a
+ *   ctl_table with data of the form: net->member1.member2..memberN
+ */
+extern int netns_proc_dostring(struct ctl_table *,
+		int, void __user *, size_t *, loff_t *, void *net);
+extern int netns_proc_dointvec(struct ctl_table *, int,
+		void __user *, size_t *, loff_t *, void *net);
+extern int netns_proc_dointvec_minmax(struct ctl_table *, int,
+		void __user *, size_t *, loff_t *, void *net);
+extern int netns_proc_dointvec_jiffies(struct ctl_table *, int,
+		void __user *, size_t *, loff_t *, void *net);
+extern int netns_proc_dointvec_userhz_jiffies(struct ctl_table *, int,
+		void __user *, size_t *, loff_t *, void *net);
+extern int netns_proc_dointvec_ms_jiffies(struct ctl_table *, int,
+		void __user *, size_t *, loff_t *, void *net);
+extern int netns_proc_doulongvec_minmax(struct ctl_table *, int,
+		void __user *, size_t *, loff_t *, void *net);
+extern int netns_proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
+		void __user *, size_t *, loff_t *, void *net);
+extern int netns_proc_do_large_bitmap(struct ctl_table *, int,
+		void __user *, size_t *, loff_t *, void *net);
+
 #endif /* __NET_NET_NAMESPACE_H */
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index 9dadd17..dfff9a3 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -127,3 +127,25 @@ void unregister_net_sysctl_table(struct ctl_table_header *header)
 	unregister_sysctl_table(header);
 }
 EXPORT_SYMBOL_GPL(unregister_net_sysctl_table);
+
+
+
+#define EXPORT_NETNS_PROC_HANDLER(handler)				\
+	int netns_##handler(struct ctl_table *table, int write,		\
+			    void __user *buffer, size_t *lenp,		\
+			    loff_t *ppos, void *net)			\
+	{								\
+		struct ctl_table t = *table;				\
+		t.data += (char *)net - (char *)&init_net;		\
+		return handler(&t, write, buffer, lenp, ppos, NULL);	\
+	}								\
+	EXPORT_SYMBOL_GPL(netns_##handler);
+
+EXPORT_NETNS_PROC_HANDLER(proc_dointvec);
+EXPORT_NETNS_PROC_HANDLER(proc_dointvec_minmax);
+EXPORT_NETNS_PROC_HANDLER(proc_dointvec_jiffies);
+EXPORT_NETNS_PROC_HANDLER(proc_dointvec_userhz_jiffies);
+EXPORT_NETNS_PROC_HANDLER(proc_dointvec_ms_jiffies);
+EXPORT_NETNS_PROC_HANDLER(proc_doulongvec_minmax)
+EXPORT_NETNS_PROC_HANDLER(proc_doulongvec_ms_jiffies_minmax);
+EXPORT_NETNS_PROC_HANDLER(proc_do_large_bitmap);
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 05/24] sysctl: cookie: share ip4_frags_ns_ctl_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (3 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 04/24] sysctl: cookie: add netns_proc_dointvec and other netns_proc_* proc_handlers Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 06/24] sysctl: cookie: share netns_core_table " Lucian Adrian Grijincu
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

We were creating a copy of this table was to set ctl_table->data to
point to data from within the newly created 'struct net*'.

The netns_proc_* handlers do this dynamically.

Also change register_net_sysctl_table() to send the net as a cookie.

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 net/ipv4/ip_fragment.c |   34 ++++++----------------------------
 net/sysctl_net.c       |    2 +-
 2 files changed, 7 insertions(+), 29 deletions(-)

diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index a1151b8..f8fd613 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -677,21 +677,21 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = {
 		.data		= &init_net.ipv4.frags.high_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec
 	},
 	{
 		.procname	= "ipfrag_low_thresh",
 		.data		= &init_net.ipv4.frags.low_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec
 	},
 	{
 		.procname	= "ipfrag_time",
 		.data		= &init_net.ipv4.frags.timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_jiffies,
+		.proc_handler	= netns_proc_dointvec_jiffies,
 	},
 	{ }
 };
@@ -717,41 +717,19 @@ static struct ctl_table ip4_frags_ctl_table[] = {
 
 static int __net_init ip4_frags_ns_ctl_register(struct net *net)
 {
-	struct ctl_table *table;
 	struct ctl_table_header *hdr;
-
-	table = ip4_frags_ns_ctl_table;
-	if (!net_eq(net, &init_net)) {
-		table = kmemdup(table, sizeof(ip4_frags_ns_ctl_table), GFP_KERNEL);
-		if (table == NULL)
-			goto err_alloc;
-
-		table[0].data = &net->ipv4.frags.high_thresh;
-		table[1].data = &net->ipv4.frags.low_thresh;
-		table[2].data = &net->ipv4.frags.timeout;
-	}
-
-	hdr = register_net_sysctl_table(net, net_ipv4_ctl_path, table);
+	hdr = register_net_sysctl_table(net, net_ipv4_ctl_path,
+					ip4_frags_ns_ctl_table);
 	if (hdr == NULL)
-		goto err_reg;
+		return -ENOMEM;
 
 	net->ipv4.frags_hdr = hdr;
 	return 0;
-
-err_reg:
-	if (!net_eq(net, &init_net))
-		kfree(table);
-err_alloc:
-	return -ENOMEM;
 }
 
 static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = net->ipv4.frags_hdr->ctl_table_arg;
 	unregister_net_sysctl_table(net->ipv4.frags_hdr);
-	kfree(table);
 }
 
 static void ip4_frags_ctl_register(void)
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index dfff9a3..7447d6e 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, NULL);
+				       table, net);
 }
 EXPORT_SYMBOL_GPL(register_net_sysctl_table);
 
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 06/24] sysctl: cookie: share netns_core_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (4 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 05/24] sysctl: cookie: share ip4_frags_ns_ctl_table between nets Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 07/24] sysctl: cookie: share ipv4_route_flush_table " Lucian Adrian Grijincu
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 net/core/sysctl_net_core.c |   28 +++-------------------------
 1 files changed, 3 insertions(+), 25 deletions(-)

diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 923ae0f..c4571cc 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -183,7 +183,7 @@ static struct ctl_table netns_core_table[] = {
 		.data		= &init_net.core.sysctl_somaxconn,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{ }
 };
@@ -196,41 +196,19 @@ __net_initdata struct ctl_path net_core_path[] = {
 
 static __net_init int sysctl_core_net_init(struct net *net)
 {
-	struct ctl_table *tbl;
-
 	net->core.sysctl_somaxconn = SOMAXCONN;
 
-	tbl = netns_core_table;
-	if (!net_eq(net, &init_net)) {
-		tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL);
-		if (tbl == NULL)
-			goto err_dup;
-
-		tbl[0].data = &net->core.sysctl_somaxconn;
-	}
-
 	net->core.sysctl_hdr = register_net_sysctl_table(net,
-			net_core_path, tbl);
+			net_core_path, netns_core_table);
 	if (net->core.sysctl_hdr == NULL)
-		goto err_reg;
+		return -ENOMEM;
 
 	return 0;
-
-err_reg:
-	if (tbl != netns_core_table)
-		kfree(tbl);
-err_dup:
-	return -ENOMEM;
 }
 
 static __net_exit void sysctl_core_net_exit(struct net *net)
 {
-	struct ctl_table *tbl;
-
-	tbl = net->core.sysctl_hdr->ctl_table_arg;
 	unregister_net_sysctl_table(net->core.sysctl_hdr);
-	BUG_ON(tbl == netns_core_table);
-	kfree(tbl);
 }
 
 static __net_initdata struct pernet_operations sysctl_core_ops = {
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 07/24] sysctl: cookie: share ipv4_route_flush_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (5 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 06/24] sysctl: cookie: share netns_core_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 08/24] sysctl: cookie: share ipv4_net_table " Lucian Adrian Grijincu
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 0c66ea6..1e99f01 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -3015,13 +3015,12 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
 	if (write) {
 		int flush_delay;
 		ctl_table ctl;
-		struct net *net;
+		struct net *net = (struct net *) cookie;
 
 		memcpy(&ctl, __ctl, sizeof(ctl));
 		ctl.data = &flush_delay;
 		proc_dointvec(&ctl, write, buffer, lenp, ppos, NULL);
 
-		net = (struct net *)__ctl->extra1;
 		rt_cache_flush(net, flush_delay);
 		return 0;
 	}
@@ -3176,37 +3175,16 @@ static __net_initdata struct ctl_path ipv4_route_path[] = {
 
 static __net_init int sysctl_route_net_init(struct net *net)
 {
-	struct ctl_table *tbl;
-
-	tbl = ipv4_route_flush_table;
-	if (!net_eq(net, &init_net)) {
-		tbl = kmemdup(tbl, sizeof(ipv4_route_flush_table), GFP_KERNEL);
-		if (tbl == NULL)
-			goto err_dup;
-	}
-	tbl[0].extra1 = net;
-
-	net->ipv4.route_hdr =
-		register_net_sysctl_table(net, ipv4_route_path, tbl);
+	net->ipv4.route_hdr = register_net_sysctl_table(net,
+				ipv4_route_path, ipv4_route_flush_table);
 	if (net->ipv4.route_hdr == NULL)
-		goto err_reg;
+		return -ENOMEM;
 	return 0;
-
-err_reg:
-	if (tbl != ipv4_route_flush_table)
-		kfree(tbl);
-err_dup:
-	return -ENOMEM;
 }
 
 static __net_exit void sysctl_route_net_exit(struct net *net)
 {
-	struct ctl_table *tbl;
-
-	tbl = net->ipv4.route_hdr->ctl_table_arg;
 	unregister_net_sysctl_table(net->ipv4.route_hdr);
-	BUG_ON(tbl == ipv4_route_flush_table);
-	kfree(tbl);
 }
 
 static __net_initdata struct pernet_operations sysctl_route_ops = {
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 08/24] sysctl: cookie: share ipv4_net_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (6 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 07/24] sysctl: cookie: share ipv4_route_flush_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 09/24] sysctl: cookie: share ip6_frags_ns_ctl_table " Lucian Adrian Grijincu
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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

diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 1766d2e..b7b8dbd 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -635,49 +635,49 @@ static struct ctl_table ipv4_net_table[] = {
 		.data		= &init_net.ipv4.sysctl_icmp_echo_ignore_all,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "icmp_echo_ignore_broadcasts",
 		.data		= &init_net.ipv4.sysctl_icmp_echo_ignore_broadcasts,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "icmp_ignore_bogus_error_responses",
 		.data		= &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "icmp_errors_use_inbound_ifaddr",
 		.data		= &init_net.ipv4.sysctl_icmp_errors_use_inbound_ifaddr,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "icmp_ratelimit",
 		.data		= &init_net.ipv4.sysctl_icmp_ratelimit,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_ms_jiffies,
+		.proc_handler	= netns_proc_dointvec_ms_jiffies,
 	},
 	{
 		.procname	= "icmp_ratemask",
 		.data		= &init_net.ipv4.sysctl_icmp_ratemask,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "rt_cache_rebuild_count",
 		.data		= &init_net.ipv4.sysctl_rt_cache_rebuild_count,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{ }
 };
@@ -691,53 +691,18 @@ EXPORT_SYMBOL_GPL(net_ipv4_ctl_path);
 
 static __net_init int ipv4_sysctl_init_net(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = ipv4_net_table;
-	if (!net_eq(net, &init_net)) {
-		table = kmemdup(table, sizeof(ipv4_net_table), GFP_KERNEL);
-		if (table == NULL)
-			goto err_alloc;
-
-		table[0].data =
-			&net->ipv4.sysctl_icmp_echo_ignore_all;
-		table[1].data =
-			&net->ipv4.sysctl_icmp_echo_ignore_broadcasts;
-		table[2].data =
-			&net->ipv4.sysctl_icmp_ignore_bogus_error_responses;
-		table[3].data =
-			&net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr;
-		table[4].data =
-			&net->ipv4.sysctl_icmp_ratelimit;
-		table[5].data =
-			&net->ipv4.sysctl_icmp_ratemask;
-		table[6].data =
-			&net->ipv4.sysctl_rt_cache_rebuild_count;
-	}
-
 	net->ipv4.sysctl_rt_cache_rebuild_count = 4;
 
 	net->ipv4.ipv4_hdr = register_net_sysctl_table(net,
-			net_ipv4_ctl_path, table);
+			net_ipv4_ctl_path, ipv4_net_table);
 	if (net->ipv4.ipv4_hdr == NULL)
-		goto err_reg;
-
+		return -ENOMEM;
 	return 0;
-
-err_reg:
-	if (!net_eq(net, &init_net))
-		kfree(table);
-err_alloc:
-	return -ENOMEM;
 }
 
 static __net_exit void ipv4_sysctl_exit_net(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = net->ipv4.ipv4_hdr->ctl_table_arg;
 	unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
-	kfree(table);
 }
 
 static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 09/24] sysctl: cookie: share ip6_frags_ns_ctl_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (7 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 08/24] sysctl: cookie: share ipv4_net_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 10/24] sysctl: cookie: share ip6_ctl_table, ipv6_icmp_table and ipv6_route_table " Lucian Adrian Grijincu
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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

diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 07beeb0..405dc11 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -600,21 +600,21 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = {
 		.data		= &init_net.ipv6.frags.high_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "ip6frag_low_thresh",
 		.data		= &init_net.ipv6.frags.low_thresh,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{
 		.procname	= "ip6frag_time",
 		.data		= &init_net.ipv6.frags.timeout,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_jiffies,
+		.proc_handler	= netns_proc_dointvec_jiffies,
 	},
 	{ }
 };
@@ -632,42 +632,20 @@ static struct ctl_table ip6_frags_ctl_table[] = {
 
 static int __net_init ip6_frags_ns_sysctl_register(struct net *net)
 {
-	struct ctl_table *table;
 	struct ctl_table_header *hdr;
 
-	table = ip6_frags_ns_ctl_table;
-	if (!net_eq(net, &init_net)) {
-		table = kmemdup(table, sizeof(ip6_frags_ns_ctl_table), GFP_KERNEL);
-		if (table == NULL)
-			goto err_alloc;
-
-		table[0].data = &net->ipv6.frags.high_thresh;
-		table[1].data = &net->ipv6.frags.low_thresh;
-		table[2].data = &net->ipv6.frags.timeout;
-	}
-
-	hdr = register_net_sysctl_table(net, net_ipv6_ctl_path, table);
+	hdr = register_net_sysctl_table(net, net_ipv6_ctl_path,
+					ip6_frags_ns_ctl_table);
 	if (hdr == NULL)
-		goto err_reg;
+		return -ENOMEM;
 
 	net->ipv6.sysctl.frags_hdr = hdr;
 	return 0;
-
-err_reg:
-	if (!net_eq(net, &init_net))
-		kfree(table);
-err_alloc:
-	return -ENOMEM;
 }
 
 static void __net_exit ip6_frags_ns_sysctl_unregister(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = net->ipv6.sysctl.frags_hdr->ctl_table_arg;
 	unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr);
-	if (!net_eq(net, &init_net))
-		kfree(table);
 }
 
 static struct ctl_table_header *ip6_ctl_header;
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 10/24] sysctl: cookie: share ip6_ctl_table, ipv6_icmp_table and ipv6_route_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (8 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 09/24] sysctl: cookie: share ip6_frags_ns_ctl_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 11/24] sysctl: cookie: share acct_sysctl_table table " Lucian Adrian Grijincu
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
 include/net/ipv6.h         |    6 +---
 net/ipv6/icmp.c            |   17 +-----------
 net/ipv6/route.c           |   58 +++++++++++------------------------------
 net/ipv6/sysctl_net_ipv6.c |   61 ++++++--------------------------------------
 4 files changed, 28 insertions(+), 114 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 34200f9..bd73439 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -656,11 +656,9 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
 #endif
 
 #ifdef CONFIG_SYSCTL
-extern ctl_table ipv6_route_table_template[];
-extern ctl_table ipv6_icmp_table_template[];
+extern ctl_table ipv6_route_table[];
+extern ctl_table ipv6_icmp_table[];
 
-extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
-extern struct ctl_table *ipv6_route_sysctl_init(struct net *net);
 extern int ipv6_sysctl_register(void);
 extern void ipv6_sysctl_unregister(void);
 extern int ipv6_static_sysctl_register(void);
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 83cb4f9..26cdb9b 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -954,29 +954,16 @@ int icmpv6_err_convert(u8 type, u8 code, int *err)
 EXPORT_SYMBOL(icmpv6_err_convert);
 
 #ifdef CONFIG_SYSCTL
-ctl_table ipv6_icmp_table_template[] = {
+ctl_table ipv6_icmp_table[] = {
 	{
 		.procname	= "ratelimit",
 		.data		= &init_net.ipv6.sysctl.icmpv6_time,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_ms_jiffies,
+		.proc_handler	= netns_proc_dointvec_ms_jiffies,
 	},
 	{ },
 };
 
-struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)
-{
-	struct ctl_table *table;
-
-	table = kmemdup(ipv6_icmp_table_template,
-			sizeof(ipv6_icmp_table_template),
-			GFP_KERNEL);
-
-	if (table)
-		table[0].data = &net->ipv6.sysctl.icmpv6_time;
-
-	return table;
-}
 #endif
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 48ec0b7..a110204 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2592,120 +2592,94 @@ static const struct file_operations rt6_stats_seq_fops = {
 
 #ifdef CONFIG_SYSCTL
 
-static
-int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, void __user *buffer,
-			      size_t *lenp, loff_t *ppos, void *cookie)
+static int netns_ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write,
+					   void __user *buffer, size_t *lenp,
+					   loff_t *ppos, void *cookie)
 {
-	struct net *net;
-	int delay;
+	struct net *net = (struct net *) cookie;
+	int delay = net->ipv6.sysctl.flush_delay;
 	if (!write)
 		return -EINVAL;
 
-	net = (struct net *)ctl->extra1;
-	delay = net->ipv6.sysctl.flush_delay;
 	proc_dointvec(ctl, write, buffer, lenp, ppos, NULL);
 	fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net);
 	return 0;
 }
 
-ctl_table ipv6_route_table_template[] = {
+ctl_table ipv6_route_table[] = {
 	{
 		.procname	=	"flush",
 		.data		=	&init_net.ipv6.sysctl.flush_delay,
 		.maxlen		=	sizeof(int),
 		.mode		=	0200,
-		.proc_handler	=	ipv6_sysctl_rtcache_flush
+		.proc_handler	=	netns_ipv6_sysctl_rtcache_flush,
 	},
 	{
 		.procname	=	"gc_thresh",
 		.data		=	&ip6_dst_ops_template.gc_thresh,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec,
+		.proc_handler	=	netns_proc_dointvec,
 	},
 	{
 		.procname	=	"max_size",
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_max_size,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec,
+		.proc_handler	=	netns_proc_dointvec,
 	},
 	{
 		.procname	=	"gc_min_interval",
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec_jiffies,
+		.proc_handler	=	netns_proc_dointvec_jiffies,
 	},
 	{
 		.procname	=	"gc_timeout",
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_timeout,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec_jiffies,
+		.proc_handler	=	netns_proc_dointvec_jiffies,
 	},
 	{
 		.procname	=	"gc_interval",
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec_jiffies,
+		.proc_handler	=	netns_proc_dointvec_jiffies,
 	},
 	{
 		.procname	=	"gc_elasticity",
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_elasticity,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec,
+		.proc_handler	=	netns_proc_dointvec,
 	},
 	{
 		.procname	=	"mtu_expires",
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_mtu_expires,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec_jiffies,
+		.proc_handler	=	netns_proc_dointvec_jiffies,
 	},
 	{
 		.procname	=	"min_adv_mss",
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_min_advmss,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec,
+		.proc_handler	=	netns_proc_dointvec,
 	},
 	{
 		.procname	=	"gc_min_interval_ms",
 		.data		=	&init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
 		.maxlen		=	sizeof(int),
 		.mode		=	0644,
-		.proc_handler	=	proc_dointvec_ms_jiffies,
+		.proc_handler	=	netns_proc_dointvec_ms_jiffies,
 	},
 	{ }
 };
 
-struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net)
-{
-	struct ctl_table *table;
-
-	table = kmemdup(ipv6_route_table_template,
-			sizeof(ipv6_route_table_template),
-			GFP_KERNEL);
-
-	if (table) {
-		table[0].data = &net->ipv6.sysctl.flush_delay;
-		table[0].extra1 = net;
-		table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh;
-		table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
-		table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
-		table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
-		table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
-		table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
-		table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
-		table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
-		table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
-	}
-
-	return table;
-}
 #endif
 
 static int __net_init ip6_route_net_init(struct net *net)
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 6dcf5e7..1b6f6fd 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -27,25 +27,25 @@ static ctl_table ipv6_static_skeleton[] = {
 	{ }
 };
 
-static ctl_table ipv6_table_template[] = {
+static ctl_table ipv6_table[] = {
 	{
 		.procname	= "route",
 		.maxlen		= 0,
 		.mode		= 0555,
-		.child		= ipv6_route_table_template
+		.child		= ipv6_route_table
 	},
 	{
 		.procname	= "icmp",
 		.maxlen		= 0,
 		.mode		= 0555,
-		.child		= ipv6_icmp_table_template
+		.child		= ipv6_icmp_table
 	},
 	{
 		.procname	= "bindv6only",
 		.data		= &init_net.ipv6.sysctl.bindv6only,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{ }
 };
@@ -70,62 +70,17 @@ EXPORT_SYMBOL_GPL(net_ipv6_ctl_path);
 
 static int __net_init ipv6_sysctl_net_init(struct net *net)
 {
-	struct ctl_table *ipv6_table;
-	struct ctl_table *ipv6_route_table;
-	struct ctl_table *ipv6_icmp_table;
-	int err;
-
-	err = -ENOMEM;
-	ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template),
-			     GFP_KERNEL);
-	if (!ipv6_table)
-		goto out;
-
-	ipv6_route_table = ipv6_route_sysctl_init(net);
-	if (!ipv6_route_table)
-		goto out_ipv6_table;
-	ipv6_table[0].child = ipv6_route_table;
-
-	ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
-	if (!ipv6_icmp_table)
-		goto out_ipv6_route_table;
-	ipv6_table[1].child = ipv6_icmp_table;
-
-	ipv6_table[2].data = &net->ipv6.sysctl.bindv6only;
-
-	net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path,
-							   ipv6_table);
+	net->ipv6.sysctl.table = register_net_sysctl_table(net,
+				   net_ipv6_ctl_path, ipv6_table);
 	if (!net->ipv6.sysctl.table)
-		goto out_ipv6_icmp_table;
-
-	err = 0;
-out:
-	return err;
+		return -ENOMEM;
 
-out_ipv6_icmp_table:
-	kfree(ipv6_icmp_table);
-out_ipv6_route_table:
-	kfree(ipv6_route_table);
-out_ipv6_table:
-	kfree(ipv6_table);
-	goto out;
+	return 0;
 }
 
 static void __net_exit ipv6_sysctl_net_exit(struct net *net)
 {
-	struct ctl_table *ipv6_table;
-	struct ctl_table *ipv6_route_table;
-	struct ctl_table *ipv6_icmp_table;
-
-	ipv6_table = net->ipv6.sysctl.table->ctl_table_arg;
-	ipv6_route_table = ipv6_table[0].child;
-	ipv6_icmp_table = ipv6_table[1].child;
-
 	unregister_net_sysctl_table(net->ipv6.sysctl.table);
-
-	kfree(ipv6_table);
-	kfree(ipv6_route_table);
-	kfree(ipv6_icmp_table);
 }
 
 static struct pernet_operations ipv6_sysctl_net_ops = {
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 11/24] sysctl: cookie: share acct_sysctl_table table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (9 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 10/24] sysctl: cookie: share ip6_ctl_table, ipv6_icmp_table and ipv6_route_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 12/24] sysctl: cookie: share event_sysctl_table " Lucian Adrian Grijincu
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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

diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index 5178c69..8f37d96 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -29,7 +29,7 @@ static struct ctl_table acct_sysctl_table[] = {
 		.data		= &init_net.ct.sysctl_acct,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= netns_proc_dointvec,
 	},
 	{}
 };
@@ -59,36 +59,18 @@ static struct nf_ct_ext_type acct_extend __read_mostly = {
 #ifdef CONFIG_SYSCTL
 static int nf_conntrack_acct_init_sysctl(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = kmemdup(acct_sysctl_table, sizeof(acct_sysctl_table),
-			GFP_KERNEL);
-	if (!table)
-		goto out;
-
-	table[0].data = &net->ct.sysctl_acct;
-
 	net->ct.acct_sysctl_header = register_net_sysctl_table(net,
-			nf_net_netfilter_sysctl_path, table);
+			nf_net_netfilter_sysctl_path, acct_sysctl_table);
 	if (!net->ct.acct_sysctl_header) {
 		printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
-		goto out_register;
+		return -ENOMEM;
 	}
 	return 0;
-
-out_register:
-	kfree(table);
-out:
-	return -ENOMEM;
 }
 
 static void nf_conntrack_acct_fini_sysctl(struct net *net)
 {
-	struct ctl_table *table;
-
-	table = net->ct.acct_sysctl_header->ctl_table_arg;
 	unregister_net_sysctl_table(net->ct.acct_sysctl_header);
-	kfree(table);
 }
 #else
 static int nf_conntrack_acct_init_sysctl(struct net *net)
-- 
1.7.5.rc0


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 12/24] sysctl: cookie: share event_sysctl_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (10 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 11/24] sysctl: cookie: share acct_sysctl_table table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 13/24] sysctl: cookie: share nf_ct_sysctl_table " Lucian Adrian Grijincu
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 13/24] sysctl: cookie: share nf_ct_sysctl_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (11 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 12/24] sysctl: cookie: share event_sysctl_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 14/24] sysctl: cookie: share unix_table " Lucian Adrian Grijincu
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 14/24] sysctl: cookie: share unix_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (12 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 13/24] sysctl: cookie: share nf_ct_sysctl_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 15/24] sysctl: cookie: share xfrm_table " Lucian Adrian Grijincu
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 15/24] sysctl: cookie: share xfrm_table between nets
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (13 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 14/24] sysctl: cookie: share unix_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 16/24] sysctl: add support for private_children headers Lucian Adrian Grijincu
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 16/24] sysctl: add support for private_children headers
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (14 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 15/24] sysctl: cookie: share xfrm_table " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 17/24] sysctl: add register_net_sysctl_table_with_parent Lucian Adrian Grijincu
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 17/24] sysctl: add register_net_sysctl_table_with_parent
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (15 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 16/24] sysctl: add support for private_children headers Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 18/24] sysctl: ipv4: register /proc/sys/net/ipv4/conf empty directory Lucian Adrian Grijincu
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 18/24] sysctl: ipv4: register /proc/sys/net/ipv4/conf empty directory
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (16 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 17/24] sysctl: add register_net_sysctl_table_with_parent Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 19/24] sysctl: ipv4: register devinet tables as private children Lucian Adrian Grijincu
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 19/24] sysctl: ipv4: register devinet tables as private children
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (17 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 18/24] sysctl: ipv4: register /proc/sys/net/ipv4/conf empty directory Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 20/24] sysctl: ipv6: register /proc/sys/net/ipv6/conf empty directory Lucian Adrian Grijincu
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 20/24] sysctl: ipv6: register /proc/sys/net/ipv6/conf empty directory
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (18 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 19/24] sysctl: ipv4: register devinet tables as private children Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 21/24] sysctl: ipv6: register addrconf tables as private children Lucian Adrian Grijincu
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 21/24] sysctl: ipv6: register addrconf tables as private children
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (19 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 20/24] sysctl: ipv6: register /proc/sys/net/ipv6/conf empty directory Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 22/24] sysctl: ipv4: register /proc/sys/net/ipv4/neigh empty directory Lucian Adrian Grijincu
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 22/24] sysctl: ipv4: register /proc/sys/net/ipv4/neigh empty directory
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (20 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 21/24] sysctl: ipv6: register addrconf tables as private children Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 23/24] sysctl: ipv6: register /proc/sys/net/ipv6/neigh " Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 24/24] sysctl: neigh: ipv4 and ipv6 neigh tables as private children Lucian Adrian Grijincu
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 23/24] sysctl: ipv6: register /proc/sys/net/ipv6/neigh empty directory
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (21 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 22/24] sysctl: ipv4: register /proc/sys/net/ipv4/neigh empty directory Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  2011-04-02  2:53 ` [PATCH 24/24] sysctl: neigh: ipv4 and ipv6 neigh tables as private children Lucian Adrian Grijincu
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

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	[flat|nested] 30+ messages in thread

* [PATCH 24/24] sysctl: neigh: ipv4 and ipv6 neigh tables as private children
  2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
                   ` (22 preceding siblings ...)
  2011-04-02  2:53 ` [PATCH 23/24] sysctl: ipv6: register /proc/sys/net/ipv6/neigh " Lucian Adrian Grijincu
@ 2011-04-02  2:53 ` Lucian Adrian Grijincu
  23 siblings, 0 replies; 30+ messages in thread
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, netdev
  Cc: Lucian Adrian Grijincu

$ 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	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed
  2011-04-02  2:53 ` [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed Lucian Adrian Grijincu
@ 2011-04-06 19:52   ` David Miller
  2011-04-06 20:04     ` Lucian Adrian Grijincu
  0 siblings, 1 reply; 30+ messages in thread
From: David Miller @ 2011-04-06 19:52 UTC (permalink / raw)
  To: lucian.grijincu; +Cc: adobriyan, ebiederm, tavi, linux-kernel, netdev

From: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
Date: Sat,  2 Apr 2011 04:53:15 +0200

> ctl_table_headers registered with register_net_sysctl_table should
> have been unregistered with the equivalent unregister_net_sysctl_table
> 
> Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>

Oops, hmmm...  Can this actually cause any real problems currently?

If so I'd like to toss this specific patch into net-2.6

Thanks.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/24] sysctl: cookie: add ctl_header_cookie
  2011-04-02  2:53 ` [PATCH 02/24] sysctl: cookie: add ctl_header_cookie Lucian Adrian Grijincu
@ 2011-04-06 19:53   ` David Miller
  0 siblings, 0 replies; 30+ messages in thread
From: David Miller @ 2011-04-06 19:53 UTC (permalink / raw)
  To: lucian.grijincu; +Cc: adobriyan, ebiederm, tavi, linux-kernel, netdev

From: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
Date: Sat,  2 Apr 2011 04:53:16 +0200

> @@ -205,6 +205,7 @@ static struct ctl_table_header root_table_header = {
>  	.ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),}},
>  	.root = &sysctl_table_root,
>  	.set = &sysctl_table_root.default_set,
> +	.ctl_header_cookie = NULL,
>  };

Such explicit setting of structure members to NULL in an assignment is
never necessary.  Please remove these, there were a few cases in this
patch.

Thanks.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 03/24] sysctl: cookie: pass ctl_header_cookie to proc_handler
  2011-04-02  2:53 ` [PATCH 03/24] sysctl: cookie: pass ctl_header_cookie to proc_handler Lucian Adrian Grijincu
@ 2011-04-06 19:54   ` David Miller
  0 siblings, 0 replies; 30+ messages in thread
From: David Miller @ 2011-04-06 19:54 UTC (permalink / raw)
  To: lucian.grijincu; +Cc: adobriyan, ebiederm, tavi, linux-kernel, netdev

From: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
Date: Sat,  2 Apr 2011 04:53:17 +0200

> The bulk of this patch changes all proc_handlers in the kernel to
> receive the cookie.
> 
> Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>

Since this stuff is pretty invasive outside of the networking I really
need to see two things:

1) Feedback from sysctl folks.

2) Some coordination with whoever maintains sysctl stuff so we can
   decide how to stage these changes in various maintainer trees,
   including mine.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed
  2011-04-06 19:52   ` David Miller
@ 2011-04-06 20:04     ` Lucian Adrian Grijincu
  2011-04-06 20:06       ` David Miller
  0 siblings, 1 reply; 30+ messages in thread
From: Lucian Adrian Grijincu @ 2011-04-06 20:04 UTC (permalink / raw)
  To: David Miller; +Cc: adobriyan, ebiederm, tavi, linux-kernel, netdev

On Wed, Apr 6, 2011 at 9:52 PM, David Miller <davem@davemloft.net> wrote:
> Oops, hmmm...  Can this actually cause any real problems currently?
>
> If so I'd like to toss this specific patch into net-2.6


Nope:

void unregister_net_sysctl_table(struct ctl_table_header *header)
{
        unregister_sysctl_table(header);
}
EXPORT_SYMBOL_GPL(unregister_net_sysctl_table);

But I thought that in the future, if something special needs to be
done for unregister_net_sysctl_table, it would be better to have these
consistent. I'll do a check on all the tree to see if there are other
cases.

Another approach would be to remove unregister_net_sysctl_table, as it
does nothing different of unregister_sysctl_table and let our future
selves deal with the problem.

Can you tell me what you'd like?

-- 
 .
..: Lucian

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed
  2011-04-06 20:04     ` Lucian Adrian Grijincu
@ 2011-04-06 20:06       ` David Miller
  0 siblings, 0 replies; 30+ messages in thread
From: David Miller @ 2011-04-06 20:06 UTC (permalink / raw)
  To: lucian.grijincu; +Cc: adobriyan, ebiederm, tavi, linux-kernel, netdev

From: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
Date: Wed, 6 Apr 2011 22:04:53 +0200

> On Wed, Apr 6, 2011 at 9:52 PM, David Miller <davem@davemloft.net> wrote:
>> Oops, hmmm...  Can this actually cause any real problems currently?
>>
>> If so I'd like to toss this specific patch into net-2.6
> 
> 
> Nope:
> 
> void unregister_net_sysctl_table(struct ctl_table_header *header)
> {
>         unregister_sysctl_table(header);
> }
> EXPORT_SYMBOL_GPL(unregister_net_sysctl_table);

Ok, that's good.

> But I thought that in the future, if something special needs to be
> done for unregister_net_sysctl_table, it would be better to have these
> consistent. I'll do a check on all the tree to see if there are other
> cases.
> 
> Another approach would be to remove unregister_net_sysctl_table, as it
> does nothing different of unregister_sysctl_table and let our future
> selves deal with the problem.
> 
> Can you tell me what you'd like?

I think the thing to do is to keep this patch as it is, and only apply
it along with this cookie patch series, for -next.

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2011-04-06 20:07 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-02  2:53 [PATCH 00/24] v1: sysctl header cookies + private children Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 01/24] sysctl: net: call unregister_net_sysctl_table where needed Lucian Adrian Grijincu
2011-04-06 19:52   ` David Miller
2011-04-06 20:04     ` Lucian Adrian Grijincu
2011-04-06 20:06       ` David Miller
2011-04-02  2:53 ` [PATCH 02/24] sysctl: cookie: add ctl_header_cookie Lucian Adrian Grijincu
2011-04-06 19:53   ` David Miller
2011-04-02  2:53 ` [PATCH 03/24] sysctl: cookie: pass ctl_header_cookie to proc_handler Lucian Adrian Grijincu
2011-04-06 19:54   ` David Miller
2011-04-02  2:53 ` [PATCH 04/24] sysctl: cookie: add netns_proc_dointvec and other netns_proc_* proc_handlers Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 05/24] sysctl: cookie: share ip4_frags_ns_ctl_table between nets Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 06/24] sysctl: cookie: share netns_core_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 07/24] sysctl: cookie: share ipv4_route_flush_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 08/24] sysctl: cookie: share ipv4_net_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 09/24] sysctl: cookie: share ip6_frags_ns_ctl_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 10/24] sysctl: cookie: share ip6_ctl_table, ipv6_icmp_table and ipv6_route_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 11/24] sysctl: cookie: share acct_sysctl_table table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 12/24] sysctl: cookie: share event_sysctl_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 13/24] sysctl: cookie: share nf_ct_sysctl_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 14/24] sysctl: cookie: share unix_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 15/24] sysctl: cookie: share xfrm_table " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 16/24] sysctl: add support for private_children headers Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 17/24] sysctl: add register_net_sysctl_table_with_parent Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 18/24] sysctl: ipv4: register /proc/sys/net/ipv4/conf empty directory Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 19/24] sysctl: ipv4: register devinet tables as private children Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 20/24] sysctl: ipv6: register /proc/sys/net/ipv6/conf empty directory Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 21/24] sysctl: ipv6: register addrconf tables as private children Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 22/24] sysctl: ipv4: register /proc/sys/net/ipv4/neigh empty directory Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 23/24] sysctl: ipv6: register /proc/sys/net/ipv6/neigh " Lucian Adrian Grijincu
2011-04-02  2:53 ` [PATCH 24/24] sysctl: neigh: ipv4 and ipv6 neigh tables as private children Lucian Adrian Grijincu

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).