* [v2 077/115] sysctl: add duplicate entry and sanity ctl_table checks
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
include/linux/sysctl.h | 7 ++
kernel/sysctl.c | 19 ++++++-
kernel/sysctl_check.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 177 insertions(+), 2 deletions(-)
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index b626271..22b6eb8 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -1092,6 +1092,13 @@ extern struct ctl_table_header *register_sysctl_paths(const struct ctl_path *pat
struct ctl_table *table);
extern void unregister_sysctl_table(struct ctl_table_header *table);
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+extern int sysctl_check_table(const struct ctl_path *path,
+ int nr_dirs,
+ struct ctl_table *table);
+extern int sysctl_check_duplicates(struct ctl_table_header *header);
+#endif /* CONFIG_SYSCTL_SYSCALL_CHECK */
+
#endif /* __KERNEL__ */
#endif /* _LINUX_SYSCTL_H */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index cbf33b1..d777e89 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1977,8 +1977,14 @@ struct ctl_table_header *__register_sysctl_paths(struct ctl_table_group *group,
const struct ctl_path *path, struct ctl_table *table)
{
struct ctl_table_header *header;
+ int failed_duplicate_check = 0;
int nr_dirs = ctl_path_items(path);
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+ if (sysctl_check_table(path, nr_dirs, table))
+ return NULL;
+#endif
+
header = alloc_sysctl_header(group);
if (!header)
return NULL;
@@ -1993,9 +1999,20 @@ struct ctl_table_header *__register_sysctl_paths(struct ctl_table_group *group,
header->ctl_header_refs = 1;
sysctl_write_lock_head(header->parent);
- list_add_tail(&header->ctl_entry, &header->parent->ctl_tables);
+
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+ failed_duplicate_check = sysctl_check_duplicates(header);
+#endif
+ if (!failed_duplicate_check)
+ list_add_tail(&header->ctl_entry, &header->parent->ctl_tables);
+
sysctl_write_unlock_head(header->parent);
+ if (failed_duplicate_check) {
+ unregister_sysctl_table(header);
+ return NULL;
+ }
+
return header;
}
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index e9a7a58..4e0bce5 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -1 +1,152 @@
-/* will be rewritten */
+#include <linux/sysctl.h>
+#include <linux/string.h>
+
+/*
+ * @path: the path to the offender
+ * @offender is the name of a file or directory that violated some sysctl rules.
+ * @str: a message accompanying the error
+ */
+static void fail(const struct ctl_path *path,
+ const char *offender,
+ const char *str)
+{
+ printk(KERN_ERR "sysctl sanity check failed: ");
+
+ for (; path->procname; path++)
+ printk("/%s", path->procname);
+
+ if (offender)
+ printk("/%s", offender);
+
+ printk(": %s\n", str);
+}
+
+#define FAIL(str) do { fail(path, t->procname, str); error = -EINVAL;} while (0)
+
+int sysctl_check_table(const struct ctl_path *path,
+ int nr_dirs,
+ struct ctl_table *table)
+{
+ struct ctl_table *t;
+ int error = 0;
+
+ if (nr_dirs > CTL_MAXNAME - 1) {
+ fail(path, NULL, "tree too deep");
+ error = -EINVAL;
+ }
+
+ for(t = table; t->procname; t++) {
+ if ((t->proc_handler == proc_dostring) ||
+ (t->proc_handler == proc_dointvec) ||
+ (t->proc_handler == proc_dointvec_minmax) ||
+ (t->proc_handler == proc_dointvec_jiffies) ||
+ (t->proc_handler == proc_dointvec_userhz_jiffies) ||
+ (t->proc_handler == proc_dointvec_ms_jiffies) ||
+ (t->proc_handler == proc_doulongvec_minmax) ||
+ (t->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
+ if (!t->data)
+ FAIL("No data");
+ if (!t->maxlen)
+ FAIL("No maxlen");
+ }
+#ifdef CONFIG_PROC_SYSCTL
+ if (!t->proc_handler)
+ FAIL("No proc_handler");
+#endif
+ if (t->mode > 0777)
+ FAIL("bogus .mode");
+ }
+
+ if (error)
+ dump_stack();
+
+ return error;
+}
+
+
+/*
+ * @dir: the directory imediately above the offender
+ * @offender is the name of a file or directory that violated some sysctl rules.
+ */
+static void duplicate_error(struct ctl_table_header *dir,
+ const char *offender)
+{
+ const char *names[CTL_MAXNAME];
+ int i = 0;
+
+ printk(KERN_ERR "sysctl duplicate check failed: ");
+
+ for (; dir->parent; dir = dir->parent)
+ /* ctl_dirname can be NULL: netns-correspondent
+ * directories do not have a ctl_dirname. Their only
+ * pourpose is to hold the list of
+ * subdirs/subtables. They hold netns-specific
+ * information for the parent directory. */
+ if (dir->ctl_dirname) {
+ names[i] = dir->ctl_dirname;
+ i++;
+ }
+
+ /* Print the names in the normal path order, not reversed */
+ for(i--; i >= 0; i--)
+ printk("/%s", names[i]);
+
+ printk("/%s \n", offender);
+}
+
+/* is there an entry in the table with the same procname? */
+static int match(struct ctl_table *table, const char *name)
+{
+ for ( ; table->procname; table++) {
+
+ if (strcmp(table->procname, name) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+
+/* Called under header->parent write lock.
+ *
+ * checks whether this header's table introduces items that have the
+ * same names as other items at the same level (other files or
+ * subdirectories of the current dir). */
+int sysctl_check_duplicates(struct ctl_table_header *header)
+{
+ int has_duplicates = 0;
+ struct ctl_table *table = header->ctl_table_arg;
+ struct ctl_table_header *dir = header->parent;
+ struct ctl_table_header *h;
+
+ list_for_each_entry(h, &dir->ctl_subdirs, ctl_entry) {
+ if (IS_ERR(sysctl_use_header(h)))
+ continue;
+
+ if (match(table, h->ctl_dirname)) {
+ has_duplicates = 1;
+ duplicate_error(dir, h->ctl_dirname);
+ }
+
+ sysctl_unuse_header(h);
+ }
+
+ list_for_each_entry(h, &dir->ctl_tables, ctl_entry) {
+ ctl_table *t;
+
+ if (IS_ERR(sysctl_use_header(h)))
+ continue;
+
+ for (t = h->ctl_table_arg; t->procname; t++) {
+ if (match(table, t->procname)) {
+ has_duplicates = 1;
+ duplicate_error(dir, t->procname);
+ }
+ }
+ sysctl_unuse_header(h);
+ }
+
+ if (has_duplicates)
+ dump_stack();
+
+ return has_duplicates;
+}
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 078/115] sysctl: alloc ctl_table_header with kmem_cache
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Because now ctl_table_header objects are allocated with a fixed size
buffer (sizeof(struct ctl_table_header)) we can do the allocations
with kmem_cache.
Also, by making sure that the objects that are returned to the cache
are in a sane state we don't waste time reinitializing every field
after kmem_cache_alloc. We only initialize fields that were not left
with a sane value before returning an object to the cache.
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
kernel/sysctl.c | 48 +++++++++++++++++++++++++++++++++++++++---------
1 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index d777e89..c207c19 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -198,6 +198,9 @@ static int sysrq_sysctl_handler(ctl_table *table, int write,
#endif
+/* cache for ctl_table_header objects */
+static struct kmem_cache *sysctl_header_cachep;
+
/* uses default ops */
static const struct ctl_table_group_ops root_table_group_ops = { };
@@ -1553,7 +1556,9 @@ void sysctl_proc_inode_get(struct ctl_table_header *head)
static void free_head(struct rcu_head *rcu)
{
- kfree(container_of(rcu, struct ctl_table_header, rcu));
+ struct ctl_table_header *header;
+ header = container_of(rcu, struct ctl_table_header, rcu);
+ kmem_cache_free(sysctl_header_cachep, header);
}
void sysctl_proc_inode_put(struct ctl_table_header *head)
@@ -1664,6 +1669,8 @@ int sysctl_perm(struct ctl_table_group *group, struct ctl_table *table, int op)
return test_perm(mode, op);
}
+static void sysctl_header_ctor(void *data);
+
__init int sysctl_init(void)
{
struct ctl_table_header *kern_header, *vm_header, *fs_header,
@@ -1672,6 +1679,12 @@ __init int sysctl_init(void)
struct ctl_table_header *binfmt_misc_header;
#endif
+ sysctl_header_cachep = kmem_cache_create("sysctl_header_cachep",
+ sizeof(struct ctl_table_header),
+ 0, 0, &sysctl_header_ctor);
+ if (!sysctl_header_cachep)
+ goto fail_alloc_cachep;
+
kern_header = register_sysctl_paths(kern_path, kern_table);
if (kern_header == NULL)
goto fail_register_kern;
@@ -1715,6 +1728,8 @@ fail_register_fs:
fail_register_vm:
unregister_sysctl_table(kern_header);
fail_register_kern:
+ kmem_cache_destroy(sysctl_header_cachep);
+fail_alloc_cachep:
return -ENOMEM;
}
@@ -1735,19 +1750,34 @@ static int ctl_path_items(const struct ctl_path *path)
return n;
}
+static void sysctl_header_ctor(void *data)
+{
+ struct ctl_table_header *h = data;
+
+ h->ctl_use_refs = 0;
+ h->ctl_procfs_refs = 0;
+ h->ctl_header_refs = 0;
+
+ INIT_LIST_HEAD(&h->ctl_entry);
+ INIT_LIST_HEAD(&h->ctl_subdirs);
+ INIT_LIST_HEAD(&h->ctl_tables);
+}
static struct ctl_table_header *alloc_sysctl_header(struct ctl_table_group *group)
{
struct ctl_table_header *h;
- h = kzalloc(sizeof(*h), GFP_KERNEL);
+ h = kmem_cache_alloc(sysctl_header_cachep, GFP_KERNEL);
if (!h)
return NULL;
+ /* - all _refs members are zero before freeing
+ * - all list_head members point to themselves (empty lists) */
+
+ h->ctl_table_arg = NULL;
+ h->unregistering = NULL;
h->ctl_group = group;
- INIT_LIST_HEAD(&h->ctl_entry);
- INIT_LIST_HEAD(&h->ctl_subdirs);
- INIT_LIST_HEAD(&h->ctl_tables);
+
return h;
}
@@ -1905,12 +1935,12 @@ static struct ctl_table_header *sysctl_mkdirs(struct ctl_table_header *parent,
parent = mkdir_netns_corresp(parent, group, &__netns_corresp);
if (__netns_corresp)
- kfree(__netns_corresp);
+ kmem_cache_free(sysctl_header_cachep, __netns_corresp);
/* free unused pre-allocated entries */
for (i = 0; i < nr_dirs; i++)
if (dirs[i])
- kfree(dirs[i]);
+ kmem_cache_free(sysctl_header_cachep, dirs[i]);
return parent;
@@ -1918,7 +1948,7 @@ err_alloc_coresp:
i = nr_dirs;
err_alloc_dir:
for (i--; i >= 0; i--)
- kfree(dirs[i]);
+ kmem_cache_free(sysctl_header_cachep, dirs[i]);
return NULL;
}
@@ -1991,7 +2021,7 @@ struct ctl_table_header *__register_sysctl_paths(struct ctl_table_group *group,
header->parent = sysctl_mkdirs(&root_table_header, group, path, nr_dirs);
if (!header->parent) {
- kfree(header);
+ kmem_cache_free(sysctl_header_cachep, header);
return NULL;
}
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 079/115] sysctl: single subheader path: optimisation for paths used only once
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
This is an optimisation for registering paths that you know will be
used to register a single table. Because such directories will be used
only once, sysctl will always create an entry for it when it sees it.
When sysctl registers a table, for each directory that may be used
while registering other tables we do a linear search to see if it's
already added, and, if not, add it ourselves.
For example: each netdevice will register a single table under
/proc/sys/net/ipv4/conf/DEVNAME/.
The 'DEVNAME' component of the path is not used to register other
headers, and we can optimise adding that directory: we don't have to
check if it's already registered.
This will have a positive performance impact when registering many
such directories because we're doing a O(nr of sibling directories)
search. With @has_just_one_subheader=1 set we skip that search and add
the directory directly because we know no other sibling directory with
the same name was registered.
NOTE: in this example setting @has_just_one_subheader=1 for the 'conf'
ctl_path would be wrong because it's used when registering other
subheaders too (e.g. subheaders for other netdevices).
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
include/linux/sysctl.h | 31 +++++++++++++++++++++++++++++++
kernel/sysctl.c | 12 +++++++-----
2 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 22b6eb8..bdc8c97 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -1083,6 +1083,37 @@ struct ctl_table_header {
/* struct ctl_path describes where in the hierarchy a table is added */
struct ctl_path {
const char *procname;
+
+
+ /* This is an optimisation for registering paths that you know
+ * will be used to register a single table. Because such
+ * directories will be used only once, sysctl will always
+ * create an entry for it when it sees it.
+ *
+ * When sysctl registers a table, for each directory that may
+ * be used while registering other tables we do a linear
+ * search to see if it's already added, and, if not, add it
+ * ourselves.
+ *
+ * For example: each netdevice will register a single table
+ * under /proc/sys/net/ipv4/conf/DEVNAME/.
+ *
+ * The 'DEVNAME' component of the path is not used to register
+ * other headers, and we can optimise adding that directory:
+ * we don't have to check if it's already registered.
+ *
+ * This will have a positive performance impact when
+ * registering many such directories because we're doing a
+ * O(nr of sibling directories) search. With
+ * @has_just_one_subheader=1 set we skip that search and add
+ * the directory directly because we know no other sibling
+ * directory with the same name was registered.
+ *
+ * NOTE: in this example setting @has_just_one_subheader=1 for
+ * the 'conf' ctl_path would be wrong because it's used when
+ * registering other subheaders too (e.g. subheaders for other
+ * netdevices). */
+ int has_just_one_subheader;
};
extern struct ctl_table_header *__register_sysctl_paths(struct ctl_table_group *g,
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c207c19..9b2c05a 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1906,11 +1906,13 @@ static struct ctl_table_header *sysctl_mkdirs(struct ctl_table_header *parent,
retry:
sysctl_write_lock_head(parent);
- h = mkdir_existing_dir(parent, dirs[i]->ctl_dirname);
- if (h != NULL) {
- sysctl_write_unlock_head(parent);
- parent = h;
- continue;
+ if (!path[i].has_just_one_subheader) {
+ h = mkdir_existing_dir(parent, dirs[i]->ctl_dirname);
+ if (h != NULL) {
+ sysctl_write_unlock_head(parent);
+ parent = h;
+ continue;
+ }
}
if (likely(!create_first_netns_corresp)) {
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 081/115] sysctl: single subheader path: net/{ipv4|ipv6}/neigh/DEV/
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
net/core/neighbour.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 799f06e..63677be 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2818,7 +2818,13 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
{ .procname = "net", },
{ .procname = "proto", },
{ .procname = "neigh", },
- { .procname = "default", },
+ {
+ /* will be set to device name (NEIGH_CTL_PATH_DEV) */
+ .procname = "default",
+ /* skip duplicate name check; we're registering
+ * just one subheader for this directory */
+ .has_just_one_subheader = 1,
+ },
{ },
};
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 082/115] sysctl: single subheader path: net/ipv6/conf/DEVICE-NAME/
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
net/ipv6/addrconf.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a7bda07..3a9f958 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4486,7 +4486,13 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
{ .procname = "net", },
{ .procname = "ipv6", },
{ .procname = "conf", },
- { /* to be set */ },
+ {
+ /* to be set bellow (ADDRCONF_CTL_PATH_DEV) */
+ .procname = NULL,
+ /* skip duplicate name check; we're registering
+ * just one subheader for this directory */
+ .has_just_one_subheader = 1,
+ },
{ },
};
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 085/115] sysctl: single subheader path: kernel/sched_domain/CPU/DOMAIN/
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
kernel/sched.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/kernel/sched.c b/kernel/sched.c
index 6e39b7c..8320365 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6250,7 +6250,13 @@ static void register_sched_domain_sysctl(void)
{ .procname = "kernel" },
{ .procname = "sched_domain" },
{ /* 'cpu0' */ },
- { /* 'domain0' */ },
+ {
+ /* 'domain0' */
+ .procname = NULL,
+ /* skip duplicate name check; we're registering
+ * just one subheader for this directory */
+ .has_just_one_subheader = 1,
+ },
{ },
};
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 087/115] sysctl: check netns-specific registration order respected
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
include/linux/sysctl.h | 2 +
kernel/sysctl.c | 15 ++++++++-
kernel/sysctl_check.c | 78 ++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 85 insertions(+), 10 deletions(-)
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index bdc8c97..036d1aa 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -1128,6 +1128,8 @@ extern int sysctl_check_table(const struct ctl_path *path,
int nr_dirs,
struct ctl_table *table);
extern int sysctl_check_duplicates(struct ctl_table_header *header);
+extern int sysctl_check_netns_correspondents(struct ctl_table_header *header,
+ struct ctl_table_group *group);
#endif /* CONFIG_SYSCTL_SYSCALL_CHECK */
#endif /* __KERNEL__ */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 9b2c05a..9e50334 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1920,6 +1920,12 @@ static struct ctl_table_header *sysctl_mkdirs(struct ctl_table_header *parent,
sysctl_write_unlock_head(parent);
parent = h;
dirs[i] = NULL; /* I'm used, don't free me */
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+ if (sysctl_check_netns_correspondents(parent, group)) {
+ unregister_sysctl_table(h);
+ goto err_check_netns_correspondents;
+ }
+#endif
continue;
}
@@ -1946,11 +1952,18 @@ static struct ctl_table_header *sysctl_mkdirs(struct ctl_table_header *parent,
return parent;
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+err_check_netns_correspondents:
+ if (__netns_corresp)
+ kmem_cache_free(sysctl_header_cachep, __netns_corresp);
+#endif
+
err_alloc_coresp:
i = nr_dirs;
err_alloc_dir:
for (i--; i >= 0; i--)
- kmem_cache_free(sysctl_header_cachep, dirs[i]);
+ if (dirs[i])
+ kmem_cache_free(sysctl_header_cachep, dirs[i]);
return NULL;
}
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index 4e0bce5..55e797a 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -63,19 +63,14 @@ int sysctl_check_table(const struct ctl_path *path,
return error;
}
-
-/*
- * @dir: the directory imediately above the offender
- * @offender is the name of a file or directory that violated some sysctl rules.
- */
-static void duplicate_error(struct ctl_table_header *dir,
- const char *offender)
+/* Print the path from to a sysctl directory. The header must *not*
+ * point to a ctl_table_header that wraps a ctl_table array, it must
+ * be a directory. */
+static void printk_sysctl_dir(struct ctl_table_header *dir)
{
const char *names[CTL_MAXNAME];
int i = 0;
- printk(KERN_ERR "sysctl duplicate check failed: ");
-
for (; dir->parent; dir = dir->parent)
/* ctl_dirname can be NULL: netns-correspondent
* directories do not have a ctl_dirname. Their only
@@ -90,7 +85,18 @@ static void duplicate_error(struct ctl_table_header *dir,
/* Print the names in the normal path order, not reversed */
for(i--; i >= 0; i--)
printk("/%s", names[i]);
+}
+
+/*
+ * @dir: the directory imediately above the offender
+ * @offender is the name of a file or directory that violated some sysctl rules.
+ */
+static void duplicate_error(struct ctl_table_header *dir,
+ const char *offender)
+{
+ printk(KERN_ERR "sysctl duplicate check failed: ");
+ printk_sysctl_dir(dir);
printk("/%s \n", offender);
}
@@ -150,3 +156,57 @@ int sysctl_check_duplicates(struct ctl_table_header *header)
return has_duplicates;
}
+
+/* Check whether adding this header respects the rule that no
+ * non-netns-specific directory will be registered after one with the
+ * same name, but netns-specific was registered before (and still is registered)
+ *
+ * E.g. This sequence of registrations is not valid:
+ * - non-netns-specific: /net/ipv4/
+ * - netns-specific: /net/ipv4/conf/lo
+ * - non-netns-specific: /net/ipv4/conf/
+
+ * because after first adding 'conf' as a netns specific directory,
+ * we're adding one non-netns specific.
+ *
+ * NOTE: in this example, the directory that has a netns-correspondent is 'ipv4'
+ */
+int sysctl_check_netns_correspondents(struct ctl_table_header *header,
+ struct ctl_table_group *group)
+{
+ struct ctl_table_header *netns_corresp, *h;
+ int found = 0;
+ /* we're only checking registration of non-netns paths added,
+ * because only those paths can violate the above rule. */
+ if (group->has_netns_corresp)
+ return 0;
+
+ netns_corresp = sysctl_use_netns_corresp(header->parent);
+ if (!netns_corresp)
+ return 0;
+
+ /* see if the netns_correspondent has a subdir
+ * with the same as this non-netns specific header */
+ sysctl_read_lock_head(netns_corresp);
+ list_for_each_entry(h, &netns_corresp->ctl_subdirs, ctl_entry) {
+ if (IS_ERR(sysctl_use_header(h)))
+ continue;
+ if (strcmp(header->ctl_dirname, h->ctl_dirname) == 0) {
+ sysctl_unuse_header(h);
+ found = 1;
+ break;
+ }
+ sysctl_unuse_header(h);
+ }
+ sysctl_read_unlock_head(netns_corresp);
+
+ if (!found)
+ return 0;
+
+ printk(KERN_ERR "illegal sysctl registration of non-netns-specific "
+ "directory after a netns-specific with the same name\n");
+ printk_sysctl_dir(header);
+ dump_stack();
+
+ return 1;
+}
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 091/115] sysctl: add register_sysctl_dir: register an empty sysctl directory
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
include/linux/sysctl.h | 5 +++--
kernel/sysctl.c | 37 +++++++++++++++++++++++++++++++++++++
kernel/sysctl_check.c | 15 +++++++++++----
3 files changed, 51 insertions(+), 6 deletions(-)
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 322246d..03842cc 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -1133,11 +1133,12 @@ extern struct ctl_table_header *__register_sysctl_paths(struct ctl_table_group *
struct ctl_table *table);
extern struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
struct ctl_table *table);
+struct ctl_table_header *register_sysctl_dir(const struct ctl_path *path);
extern void unregister_sysctl_table(struct ctl_table_header *table);
#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
-extern int sysctl_check_table(const struct ctl_path *path,
- int nr_dirs,
+extern int sysctl_check_path(const struct ctl_path *path, int nr_dirs);
+extern int sysctl_check_table(const struct ctl_path *path, int nr_dirs,
struct ctl_table *table);
extern int sysctl_check_duplicates(struct ctl_table_header *header);
extern int sysctl_check_netns_correspondents(struct ctl_table_header *header,
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 94fff4e..7cf0242 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2045,6 +2045,9 @@ struct ctl_table_header *__register_sysctl_paths(struct ctl_table_group *group,
int dirs_created = 0;
#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+ if (sysctl_check_path(path, nr_dirs))
+ return NULL;
+
if (sysctl_check_table(path, nr_dirs, table))
return NULL;
#endif
@@ -2098,6 +2101,39 @@ struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
return __register_sysctl_paths(&root_table_group, path, table);
}
+/* Register an empty sysctl directory. */
+static struct ctl_table_header *__register_sysctl_dir(
+ struct ctl_table_group *group, const struct ctl_path *path)
+{
+ struct ctl_table_header *dir;
+ int nr_dirs = ctl_path_items(path);
+ int dirs_created = 0;
+
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+ if (sysctl_check_path(path, nr_dirs))
+ return NULL;
+#endif
+
+ dir = sysctl_mkdirs(&root_table_header, group, path,
+ nr_dirs, &dirs_created);
+ if (!dir)
+ return NULL;
+
+ /* -1 because we don't want to count ourselves in the list of
+ * directory headers owned by @dir. NOTE: if all of the dirs
+ * in the path are already registered dirs_created will be 0. */
+ if (dirs_created > 0)
+ dir->ctl_owned_dirs_refs = dirs_created - 1;
+ else
+ dir->ctl_owned_dirs_refs = 0;
+ return dir;
+}
+
+struct ctl_table_header *register_sysctl_dir(const struct ctl_path *path)
+{
+ return __register_sysctl_dir(&root_table_group, path);
+}
+
/**
* unregister_sysctl_table - unregister a sysctl table hierarchy
* @header: the header returned from __register_sysctl_paths
@@ -3193,4 +3229,5 @@ EXPORT_SYMBOL(proc_dostring);
EXPORT_SYMBOL(proc_doulongvec_minmax);
EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
EXPORT_SYMBOL(register_sysctl_paths);
+EXPORT_SYMBOL(register_sysctl_dir);
EXPORT_SYMBOL(unregister_sysctl_table);
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index 205f721..20c1948 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -24,6 +24,17 @@ static void fail(const struct ctl_path *path,
#define FAIL(str) do { fail(path, t->procname, str); error = -EINVAL;} while (0)
+
+int sysctl_check_path(const struct ctl_path *path,
+ int nr_dirs)
+{
+ if (nr_dirs <= CTL_MAXNAME - 1)
+ return 0;
+ fail(path, NULL, "tree too deep");
+ return -EINVAL;
+}
+
+
int sysctl_check_table(const struct ctl_path *path,
int nr_dirs,
struct ctl_table *table)
@@ -33,10 +44,6 @@ int sysctl_check_table(const struct ctl_path *path,
unsigned int nr_files = 0;
int error = 0;
- if (nr_dirs > CTL_MAXNAME - 1) {
- fail(path, NULL, "tree too deep");
- error = -EINVAL;
- }
for(t = table; t->procname; t++) {
nr_files ++;
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 092/115] sysctl: sched: create empty dir with register_sysctl_dir
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
kernel/sched.c | 19 ++++---------------
1 files changed, 4 insertions(+), 15 deletions(-)
diff --git a/kernel/sched.c b/kernel/sched.c
index 8320365..5cda526 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6302,16 +6302,11 @@ static void register_sched_domain_sysctl(void)
i = 0;
for_each_possible_cpu(cpu) {
- struct ctl_table *empty = kzalloc(sizeof(*empty), GFP_KERNEL);
- if (empty == NULL)
- goto unregister_sd_cpudir_headers;
sd_path[SD_PATH_CPU].procname = sd_cpu_names[cpu];
sd_path[SD_PATH_DOM].procname = NULL; /* end of array sentinel */
- sd_cpudir_headers[i] = register_sysctl_paths(sd_path, empty);
- if (sd_cpudir_headers[i] == NULL) {
- kfree(empty);
+ sd_cpudir_headers[i] = register_sysctl_dir(sd_path);
+ if (sd_cpudir_headers[i] == NULL)
goto unregister_sd_cpudir_headers;
- }
i++;
}
@@ -6347,11 +6342,8 @@ unregister_sd_domain_headers:
i = sd_cpudir_headers_num;
unregister_sd_cpudir_headers:
i--;
- for(; i >= 0; i--) {
- struct ctl_table *table = sd_cpudir_headers[i]->ctl_table_arg;
+ for(; i >= 0; i--)
unregister_sysctl_table(sd_cpudir_headers[i]);
- kfree(table);
- }
kfree(sd_domain_headers);
fail_alloc_sd_domain_headers:
@@ -6391,11 +6383,8 @@ static void unregister_sched_domain_sysctl(void)
kfree(table);
}
- for(i = sd_cpudir_headers_num - 1; i >= 0; i--) {
- struct ctl_table *table = sd_cpudir_headers[i]->ctl_table_arg;
+ for(i = sd_cpudir_headers_num - 1; i >= 0; i--)
unregister_sysctl_table(sd_cpudir_headers[i]);
- kfree(table);
- }
kfree(sd_domain_headers);
kfree(sd_cpudir_headers);
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 096/115] sysctl: net/ipv6/neigh: create empty dir with register_sysctl_dir
From: Lucian Adrian Grijincu @ 2011-05-08 22:39 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
net/ipv6/sysctl_net_ipv6.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 1d2d8c7..bb57ab4 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -15,8 +15,6 @@
#include <net/addrconf.h>
#include <net/inet_frag.h>
-static struct ctl_table empty[1];
-
static ctl_table ipv6_bindv6only_template[] = {
{
.procname = "bindv6only",
@@ -173,7 +171,7 @@ static struct ctl_table_header *ip6_base;
int ipv6_static_sysctl_register(void)
{
- ip6_base = register_sysctl_paths(net_ipv6_neigh_path, empty);
+ ip6_base = register_sysctl_dir(net_ipv6_neigh_path);
if (ip6_base == NULL)
return -ENOMEM;
return 0;
--
1.7.5.134.g1c08b
^ permalink raw reply related
* Re: pull request: batman-adv 2011-05-08
From: David Miller @ 2011-05-08 22:40 UTC (permalink / raw)
To: sven-KaDOiPu9UxWEi8DpZVb4nw
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r
In-Reply-To: <1304868284-9364-1-git-send-email-sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
From: Sven Eckelmann <sven-KaDOiPu9UxWEi8DpZVb4nw@public.gmane.org>
Date: Sun, 8 May 2011 17:24:36 +0200
> Hi,
>
> I would like to propose following patches for net-next-2.6/2.6.40. They
> include minor cleanups of comments, a big rename patch s/hna/tt/, but
> also a remove some duplicated code. The spinlock which protected the
> list of possible interfaces for batman-adv was completely replaced by
> rtnl_lock because we want to be in sync with the rest of the network
> stack and the extra spinlock made everything more complex without giving
> any additional feature (and rtnl_lock was already used everywhere).
> Related to this patch is also a fix which should prevent a deadlock
> between the sysfs code and the event listener. Also the reference
> counting in find_router was fixed when an error was detected after the
> refcounter was already increased. The only feature is the support for
> multiple vlans in the bridge loop detection code.
>
> I will submit a patch to remove the atomic_dec_not_zero from main.h
> after Linus accepted the patch you already saw.
Pulled, thanks Sven.
^ permalink raw reply
* [v2 001/115] sysctl: remove .child from dev/parport/default
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
First patch in a series that will end with a rewrite of sysctl. The
new implementation needs to get rid of the .child field of ctl_table.
Same functionality, but a little more clarity.
MAINTAINERS says parport is "Orphan" and I don't have a parallel
port. I minimally tested this patch, but I don't know who to resort to
for an ACK.
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
drivers/parport/procfs.c | 96 +++++++++++++++++++---------------------------
1 files changed, 40 insertions(+), 56 deletions(-)
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index 3f56bc0..89b8b71 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -419,56 +419,6 @@ parport_device_sysctl_template = {
}
};
-struct parport_default_sysctl_table
-{
- struct ctl_table_header *sysctl_header;
- ctl_table vars[3];
- ctl_table default_dir[2];
- ctl_table parport_dir[2];
- ctl_table dev_dir[2];
-};
-
-static struct parport_default_sysctl_table
-parport_default_sysctl_table = {
- .sysctl_header = NULL,
- {
- {
- .procname = "timeslice",
- .data = &parport_default_timeslice,
- .maxlen = sizeof(parport_default_timeslice),
- .mode = 0644,
- .proc_handler = proc_doulongvec_ms_jiffies_minmax,
- .extra1 = (void*) &parport_min_timeslice_value,
- .extra2 = (void*) &parport_max_timeslice_value
- },
- {
- .procname = "spintime",
- .data = &parport_default_spintime,
- .maxlen = sizeof(parport_default_spintime),
- .mode = 0644,
- .proc_handler = proc_dointvec_minmax,
- .extra1 = (void*) &parport_min_spintime_value,
- .extra2 = (void*) &parport_max_spintime_value
- },
- {}
- },
- {
- {
- .procname = "default",
- .mode = 0555,
- .child = parport_default_sysctl_table.vars
- },
- {}
- },
- {
- PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir),
- {}
- },
- {
- PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir),
- {}
- }
-};
int parport_proc_register(struct parport *port)
@@ -558,19 +508,53 @@ int parport_device_proc_unregister(struct pardevice *device)
return 0;
}
+
+static struct ctl_table_header *parport_default_sysctl_header;
+
+static struct ctl_table parport_default_sysctl_table[] = {
+ {
+ .procname = "timeslice",
+ .data = &parport_default_timeslice,
+ .maxlen = sizeof(parport_default_timeslice),
+ .mode = 0644,
+ .proc_handler = proc_doulongvec_ms_jiffies_minmax,
+ .extra1 = (void*) &parport_min_timeslice_value,
+ .extra2 = (void*) &parport_max_timeslice_value
+ },
+ {
+ .procname = "spintime",
+ .data = &parport_default_spintime,
+ .maxlen = sizeof(parport_default_spintime),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = (void*) &parport_min_spintime_value,
+ .extra2 = (void*) &parport_max_spintime_value
+ },
+ { },
+};
+
+static const __initdata struct ctl_path parport_default_path[] = {
+ { .procname = "dev" },
+ { .procname = "parport" },
+ { .procname = "default" },
+ { },
+};
+
static int __init parport_default_proc_register(void)
{
- parport_default_sysctl_table.sysctl_header =
- register_sysctl_table(parport_default_sysctl_table.dev_dir);
+ parport_default_sysctl_header =
+ register_sysctl_paths(parport_default_path,
+ parport_default_sysctl_table);
+ /* XXX: if this fails then we can't access the sysctl tables for
+ * /proc/sys/dev/parport/default/. Should the module fail to load? */
return 0;
}
static void __exit parport_default_proc_unregister(void)
{
- if (parport_default_sysctl_table.sysctl_header) {
- unregister_sysctl_table(parport_default_sysctl_table.
- sysctl_header);
- parport_default_sysctl_table.sysctl_header = NULL;
+ if (parport_default_sysctl_header) {
+ unregister_sysctl_table(parport_default_sysctl_header);
+ parport_default_sysctl_header = NULL;
}
}
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 007/115] sysctl: remove .child from abi/vsyscall32 (x86)
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
arch/x86/vdso/vdso32-setup.c | 14 +++++---------
1 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/arch/x86/vdso/vdso32-setup.c b/arch/x86/vdso/vdso32-setup.c
index 468d591..e6ef3b4 100644
--- a/arch/x86/vdso/vdso32-setup.c
+++ b/arch/x86/vdso/vdso32-setup.c
@@ -380,7 +380,7 @@ subsys_initcall(sysenter_setup);
/* Register vsyscall32 into the ABI table */
#include <linux/sysctl.h>
-static ctl_table abi_table2[] = {
+static ctl_table abi_table[] = {
{
.procname = "vsyscall32",
.data = &sysctl_vsyscall32,
@@ -391,18 +391,14 @@ static ctl_table abi_table2[] = {
{}
};
-static ctl_table abi_root_table2[] = {
- {
- .procname = "abi",
- .mode = 0555,
- .child = abi_table2
- },
- {}
+static const struct ctl_path abi_root_path[] = {
+ { .procname = "abi" },
+ { }
};
static __init int ia32_binfmt_init(void)
{
- register_sysctl_table(abi_root_table2);
+ register_sysctl_paths(abi_root_path, abi_table);
return 0;
}
__initcall(ia32_binfmt_init);
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 011/115] sysctl: remove .child from dev/ipmi/
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
drivers/char/ipmi/ipmi_poweroff.c | 16 ++++------------
1 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index 2efa176..ac71d69 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -668,17 +668,9 @@ static ctl_table ipmi_table[] = {
{ }
};
-static ctl_table ipmi_dir_table[] = {
- { .procname = "ipmi",
- .mode = 0555,
- .child = ipmi_table },
- { }
-};
-
-static ctl_table ipmi_root_table[] = {
- { .procname = "dev",
- .mode = 0555,
- .child = ipmi_dir_table },
+static const struct ctl_path ipmi_path[] = {
+ { .procname = "dev" },
+ { .procname = "ipmi" },
{ }
};
@@ -699,7 +691,7 @@ static int __init ipmi_poweroff_init(void)
printk(KERN_INFO PFX "Power cycle is enabled.\n");
#ifdef CONFIG_PROC_FS
- ipmi_table_header = register_sysctl_table(ipmi_root_table);
+ ipmi_table_header = register_sysctl_paths(ipmi_path, ipmi_table);
if (!ipmi_table_header) {
printk(KERN_ERR PFX "Unable to register powercycle sysctl\n");
rv = -ENOMEM;
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 017/115] sysctl: remove .child from kernel/sclp (s390)
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
drivers/s390/char/sclp_async.c | 13 ++++---------
1 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c
index 7ad30e7..43f8b1e 100644
--- a/drivers/s390/char/sclp_async.c
+++ b/drivers/s390/char/sclp_async.c
@@ -106,14 +106,9 @@ static struct ctl_table callhome_table[] = {
{}
};
-static struct ctl_table kern_dir_table[] = {
- {
- .procname = "kernel",
- .maxlen = 0,
- .mode = 0555,
- .child = callhome_table,
- },
- {}
+static const __initdata struct ctl_path kern_path[] = {
+ { .procname = "kernel" },
+ { }
};
/*
@@ -175,7 +170,7 @@ static int __init sclp_async_init(void)
if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK))
goto out_sclp;
rc = -ENOMEM;
- callhome_sysctl_header = register_sysctl_table(kern_dir_table);
+ callhome_sysctl_header = register_sysctl_paths(kern_path, callhome_table);
if (!callhome_sysctl_header)
goto out_sclp;
request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL);
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 021/115] sysctl: remove .child from fscache/
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
fs/fscache/main.c | 15 ++++++---------
1 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/fs/fscache/main.c b/fs/fscache/main.c
index f9d8567..7f9c055 100644
--- a/fs/fscache/main.c
+++ b/fs/fscache/main.c
@@ -67,7 +67,7 @@ static int fscache_max_active_sysctl(struct ctl_table *table, int write,
return ret;
}
-ctl_table fscache_sysctls[] = {
+static ctl_table fscache_table[] = {
{
.procname = "object_max_active",
.data = &fscache_object_max_active,
@@ -87,14 +87,11 @@ ctl_table fscache_sysctls[] = {
{}
};
-ctl_table fscache_sysctls_root[] = {
- {
- .procname = "fscache",
- .mode = 0555,
- .child = fscache_sysctls,
- },
- {}
+static const __initdata struct ctl_path fscache_path[] = {
+ { .procname = "fscache" },
+ { }
};
+
#endif
/*
@@ -135,7 +132,7 @@ static int __init fscache_init(void)
#ifdef CONFIG_SYSCTL
ret = -ENOMEM;
- fscache_sysctl_header = register_sysctl_table(fscache_sysctls_root);
+ fscache_sysctl_header = register_sysctl_paths(fscache_path, fscache_table);
if (!fscache_sysctl_header)
goto error_sysctl;
#endif
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 025/115] sysctl: remove .child from fs/ocfs2/nm/
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
fs/ocfs2/stackglue.c | 36 +++++-------------------------------
1 files changed, 5 insertions(+), 31 deletions(-)
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index 39abf89..3cb738a 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -654,36 +654,10 @@ static ctl_table ocfs2_nm_table[] = {
{ }
};
-static ctl_table ocfs2_mod_table[] = {
- {
- .procname = "nm",
- .data = NULL,
- .maxlen = 0,
- .mode = 0555,
- .child = ocfs2_nm_table
- },
- { }
-};
-
-static ctl_table ocfs2_kern_table[] = {
- {
- .procname = "ocfs2",
- .data = NULL,
- .maxlen = 0,
- .mode = 0555,
- .child = ocfs2_mod_table
- },
- { }
-};
-
-static ctl_table ocfs2_root_table[] = {
- {
- .procname = "fs",
- .data = NULL,
- .maxlen = 0,
- .mode = 0555,
- .child = ocfs2_kern_table
- },
+static const __initdata struct ctl_path ocfs2_nm_path[] = {
+ { .procname = "fs" },
+ { .procname = "ocfs2" },
+ { .procname = "nm" },
{ }
};
@@ -698,7 +672,7 @@ static int __init ocfs2_stack_glue_init(void)
{
strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB);
- ocfs2_table_header = register_sysctl_table(ocfs2_root_table);
+ ocfs2_table_header = register_sysctl_paths(ocfs2_nm_path, ocfs2_nm_table);
if (!ocfs2_table_header) {
printk(KERN_ERR
"ocfs2 stack glue: unable to register sysctl\n");
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 027/115] sysctl: remove .child from fs/xfs/
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
fs/xfs/linux-2.6/xfs_sysctl.c | 22 +++++-----------------
1 files changed, 5 insertions(+), 17 deletions(-)
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index ee2d2ad..95f803c 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -218,28 +218,16 @@ static ctl_table xfs_table[] = {
{}
};
-static ctl_table xfs_dir_table[] = {
- {
- .procname = "xfs",
- .mode = 0555,
- .child = xfs_table
- },
- {}
-};
-
-static ctl_table xfs_root_table[] = {
- {
- .procname = "fs",
- .mode = 0555,
- .child = xfs_dir_table
- },
- {}
+static const __initdata struct ctl_path xfs_path[] = {
+ { .procname = "fs" },
+ { .procname = "xfs" },
+ { }
};
int
xfs_sysctl_register(void)
{
- xfs_table_header = register_sysctl_table(xfs_root_table);
+ xfs_table_header = register_sysctl_paths(xfs_path, xfs_table);
if (!xfs_table_header)
return -ENOMEM;
return 0;
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 029/115] sysctl: remove .child from fs/mqueue
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
ipc/mq_sysctl.c | 24 ++++++------------------
1 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
index 0c09366..007164b 100644
--- a/ipc/mq_sysctl.c
+++ b/ipc/mq_sysctl.c
@@ -62,7 +62,7 @@ static int msg_max_limit_max = MAX_MSGMAX;
static int msg_maxsize_limit_min = MIN_MSGSIZEMAX;
static int msg_maxsize_limit_max = MAX_MSGSIZEMAX;
-static ctl_table mq_sysctls[] = {
+static ctl_table mq_table[] = {
{
.procname = "queues_max",
.data = &init_ipc_ns.mq_queues_max,
@@ -91,25 +91,13 @@ static ctl_table mq_sysctls[] = {
{}
};
-static ctl_table mq_sysctl_dir[] = {
- {
- .procname = "mqueue",
- .mode = 0555,
- .child = mq_sysctls,
- },
- {}
-};
-
-static ctl_table mq_sysctl_root[] = {
- {
- .procname = "fs",
- .mode = 0555,
- .child = mq_sysctl_dir,
- },
- {}
+static const struct ctl_path mq_path[] = {
+ { .procname = "fs" },
+ { .procname = "mqueue" },
+ { }
};
struct ctl_table_header *mq_register_sysctl_table(void)
{
- return register_sysctl_table(mq_sysctl_root);
+ return register_sysctl_paths(mq_path, mq_table);
}
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 031/115] sysctl: remove .child from kernel/sched_domain/cpuX/domainY/
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Note: this patch makes sure to add empty kernel/sched_domain/cpuX/
directories when there are no domains in them.
This was the behaviour before this patch, and I thought it may need to
remain so in the new implementation. If they are not necessary this
can be removed to simplify the code.
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
kernel/sched.c | 266 ++++++++++++++++++++++++++++++++++++++------------------
1 files changed, 180 insertions(+), 86 deletions(-)
diff --git a/kernel/sched.c b/kernel/sched.c
index 23a980c..6e39b7c 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6181,52 +6181,6 @@ static struct ctl_table sd_table_template[] = {
{ }
};
-static struct ctl_table sd_ctl_dir[] = {
- {
- .procname = "sched_domain",
- .mode = 0555,
- },
- {}
-};
-
-static struct ctl_table sd_ctl_root[] = {
- {
- .procname = "kernel",
- .mode = 0555,
- .child = sd_ctl_dir,
- },
- {}
-};
-
-static struct ctl_table *sd_alloc_ctl_entry(int n)
-{
- struct ctl_table *entry =
- kcalloc(n, sizeof(struct ctl_table), GFP_KERNEL);
-
- return entry;
-}
-
-static void sd_free_ctl_entry(struct ctl_table **tablep)
-{
- struct ctl_table *entry;
-
- /*
- * In the intermediate directories, both the child directory and
- * procname are dynamically allocated and could fail but the mode
- * will always be set. In the lowest directory the names are
- * static strings and all have proc handlers.
- */
- for (entry = *tablep; entry->mode; entry++) {
- if (entry->child)
- sd_free_ctl_entry(&entry->child);
- if (entry->proc_handler == NULL)
- kfree(entry->procname);
- }
-
- kfree(*tablep);
- *tablep = NULL;
-}
-
static struct ctl_table *
sd_alloc_ctl_domain_table(struct sched_domain *sd)
{
@@ -6250,64 +6204,204 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd)
return table;
}
-static ctl_table *sd_alloc_ctl_cpu_table(int cpu)
+/*
+ * Find out what is the maximum number of domains in a cpu, and the
+ * total number of domains across all cpus.
+ */
+static void count_sd_domains(int *p_max, int *p_total)
{
- struct ctl_table *entry, *table;
- struct sched_domain *sd;
- int domain_num = 0, i;
- char buf[32];
+ int cpu;
+ int max = 0;
+ int total = 0;
- for_each_domain(cpu, sd)
- domain_num++;
- entry = table = sd_alloc_ctl_entry(domain_num + 1);
- if (table == NULL)
- return NULL;
+ for_each_possible_cpu(cpu) {
+ struct sched_domain *sd;
+ int domain_num = 0;
- i = 0;
- for_each_domain(cpu, sd) {
- snprintf(buf, 32, "domain%d", i);
- entry->procname = kstrdup(buf, GFP_KERNEL);
- entry->mode = 0555;
- entry->child = sd_alloc_ctl_domain_table(sd);
- entry++;
- i++;
+ for_each_domain(cpu, sd)
+ domain_num++;
+
+ if (domain_num > max)
+ max = domain_num;
+ total += domain_num;
}
- return table;
+ *p_max = max;
+ *p_total = total;
}
-static struct ctl_table_header *sd_sysctl_header;
+
+/* enough space to hold a string "cpu%d" or "domain%d" */
+#define SD_NAME_LEN 32
+typedef char sd_name_buf[SD_NAME_LEN];
+
+static sd_name_buf *sd_cpu_names, *sd_domain_names;
+static int sd_domain_headers_num, sd_cpudir_headers_num;
+static struct ctl_table_header **sd_domain_headers, **sd_cpudir_headers;
+
static void register_sched_domain_sysctl(void)
{
- int i, cpu_num = num_possible_cpus();
- struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1);
- char buf[32];
+ int cpu, i;
+ int cpu_num, max_domain_num;
+
+ /* possitions 2 and 3 in the array bellow */
+#define SD_PATH_CPU 2
+#define SD_PATH_DOM 3
+ struct ctl_path sd_path[] = {
+ { .procname = "kernel" },
+ { .procname = "sched_domain" },
+ { /* 'cpu0' */ },
+ { /* 'domain0' */ },
+ { },
+ };
- WARN_ON(sd_ctl_dir[0].child);
- sd_ctl_dir[0].child = entry;
+ sd_cpudir_headers_num = cpu_num = num_possible_cpus();
+ count_sd_domains(&max_domain_num, &sd_domain_headers_num);
- if (entry == NULL)
- return;
+ /*
+ * Allocate space for:
+ * - all cpu names (cpu0, cpu1,...) and all domain names (domain0,...)
+ * - the array of headers for cpu dirs kernel/sched_domain/cpuX/
+ * - the array of headers for domain dirs kernel/sched_domain/cpuX/domainY
+ *
+ * We only register the empty kernel/sched_domain/cpuX/ dirs
+ * to not break the ABI: if there were no domains defined, we
+ * would still have empty cpuX dir entries in
+ * kernel/sched_domain/.
+ *
+ * If this is not considered useful or part of the ABI, then
+ * we can drop the empty cpu dir entries.
+ */
+ sd_cpu_names = kmalloc(sizeof(sd_name_buf) * cpu_num, GFP_KERNEL);
+ if (sd_cpu_names == NULL)
+ goto fail_alloc_sd_cpu_names;
- for_each_possible_cpu(i) {
- snprintf(buf, 32, "cpu%d", i);
- entry->procname = kstrdup(buf, GFP_KERNEL);
- entry->mode = 0555;
- entry->child = sd_alloc_ctl_cpu_table(i);
- entry++;
+ sd_domain_names = kmalloc(sizeof(sd_name_buf) * max_domain_num, GFP_KERNEL);
+ if (sd_domain_names == NULL)
+ goto fail_alloc_sd_domain_names;
+
+ sd_cpudir_headers = kmalloc(sizeof(*sd_cpudir_headers) *
+ sd_cpudir_headers_num, GFP_KERNEL);
+ if (sd_cpudir_headers == NULL)
+ goto fail_alloc_sd_cpudir_headers;
+
+ sd_domain_headers = kmalloc(sizeof(*sd_domain_headers) *
+ sd_domain_headers_num, GFP_KERNEL);
+ if (sd_domain_headers == NULL)
+ goto fail_alloc_sd_domain_headers;
+
+ for_each_possible_cpu(cpu)
+ snprintf((char*)&sd_cpu_names[cpu], SD_NAME_LEN, "cpu%d", cpu);
+ for (i = 0; i < max_domain_num; i++)
+ snprintf((char*)&sd_domain_names[i], SD_NAME_LEN, "domain%d", i);
+
+ i = 0;
+ for_each_possible_cpu(cpu) {
+ struct ctl_table *empty = kzalloc(sizeof(*empty), GFP_KERNEL);
+ if (empty == NULL)
+ goto unregister_sd_cpudir_headers;
+ sd_path[SD_PATH_CPU].procname = sd_cpu_names[cpu];
+ sd_path[SD_PATH_DOM].procname = NULL; /* end of array sentinel */
+ sd_cpudir_headers[i] = register_sysctl_paths(sd_path, empty);
+ if (sd_cpudir_headers[i] == NULL) {
+ kfree(empty);
+ goto unregister_sd_cpudir_headers;
+ }
+ i++;
+ }
+
+ i = 0;
+ for_each_possible_cpu(cpu) {
+ struct sched_domain *sd;
+ int domain = 0;
+ for_each_domain(cpu, sd) {
+ struct ctl_table *table = sd_alloc_ctl_domain_table(sd);
+ if (table == NULL)
+ goto unregister_sd_domain_headers;
+ sd_path[SD_PATH_CPU].procname = sd_cpu_names[cpu];
+ sd_path[SD_PATH_DOM].procname = sd_domain_names[domain];
+ sd_domain_headers[i] = register_sysctl_paths(sd_path, table);
+ if (sd_domain_headers[i] == NULL) {
+ kfree(table);
+ goto unregister_sd_domain_headers;
+ }
+ i++;
+ domain++;
+ }
}
- WARN_ON(sd_sysctl_header);
- sd_sysctl_header = register_sysctl_table(sd_ctl_root);
+ return;
+
+unregister_sd_domain_headers:
+ i--; /* the current 'i' was being filled in, but fail_alloced */
+ for(; i >= 0; i--) {
+ struct ctl_table *table = sd_domain_headers[i]->ctl_table_arg;
+ unregister_sysctl_table(sd_domain_headers[i]);
+ kfree(table);
+ }
+ i = sd_cpudir_headers_num;
+unregister_sd_cpudir_headers:
+ i--;
+ for(; i >= 0; i--) {
+ struct ctl_table *table = sd_cpudir_headers[i]->ctl_table_arg;
+ unregister_sysctl_table(sd_cpudir_headers[i]);
+ kfree(table);
+ }
+
+ kfree(sd_domain_headers);
+fail_alloc_sd_domain_headers:
+ kfree(sd_cpudir_headers);
+fail_alloc_sd_cpudir_headers:
+ kfree(sd_domain_names);
+fail_alloc_sd_domain_names:
+ kfree(sd_cpu_names);
+fail_alloc_sd_cpu_names:
+ sd_domain_headers = NULL;
+ sd_cpudir_headers = NULL;
+ sd_domain_names = NULL;
+ sd_cpu_names = NULL;
+ sd_domain_headers_num = 0;
+ sd_cpudir_headers_num = 0;
}
/* may be called multiple times per register */
static void unregister_sched_domain_sysctl(void)
{
- if (sd_sysctl_header)
- unregister_sysctl_table(sd_sysctl_header);
- sd_sysctl_header = NULL;
- if (sd_ctl_dir[0].child)
- sd_free_ctl_entry(&sd_ctl_dir[0].child);
+ int i;
+
+ /* because this function may be called multiple times (not
+ * concurrently) for a single register_sched_domain_sysctl call,
+ * we skip unregistering if it was already done by a previous
+ * call. This is also why we make sure to NULLify all
+ * pointers: make sure nothing is double-freed. */
+ if (sd_domain_headers == NULL)
+ return;
+
+ /* unregister in the reverse order of registering, or we'll
+ * get a harmless warning saying that the parent of a header
+ * was registered before all it's children. */
+ for(i = sd_domain_headers_num - 1; i >= 0; i--) {
+ struct ctl_table *table = sd_domain_headers[i]->ctl_table_arg;
+ unregister_sysctl_table(sd_domain_headers[i]);
+ kfree(table);
+ }
+
+ for(i = sd_cpudir_headers_num - 1; i >= 0; i--) {
+ struct ctl_table *table = sd_cpudir_headers[i]->ctl_table_arg;
+ unregister_sysctl_table(sd_cpudir_headers[i]);
+ kfree(table);
+ }
+
+ kfree(sd_domain_headers);
+ kfree(sd_cpudir_headers);
+ kfree(sd_domain_names);
+ kfree(sd_cpu_names);
+
+ sd_domain_headers = NULL;
+ sd_cpudir_headers = NULL;
+ sd_domain_names = NULL;
+ sd_cpu_names = NULL;
+ sd_cpudir_headers_num = 0;
+ sd_domain_headers_num = 0;
}
#else
static void register_sched_domain_sysctl(void)
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 033/115] sysctl: remove .child from sunrpc/
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
net/sunrpc/sysctl.c | 19 +++++++------------
1 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index e65dcc6..7450ab2 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -38,13 +38,17 @@ EXPORT_SYMBOL_GPL(nlm_debug);
#ifdef RPC_DEBUG
static struct ctl_table_header *sunrpc_table_header;
-static ctl_table sunrpc_table[];
+static ctl_table sunrpc_table[];
+static const struct ctl_path sunrpc_path[] = {
+ { .procname = "sunrpc" },
+ { }
+};
void
rpc_register_sysctl(void)
{
if (!sunrpc_table_header)
- sunrpc_table_header = register_sysctl_table(sunrpc_table);
+ sunrpc_table_header = register_sysctl_paths(sunrpc_path, sunrpc_table);
}
void
@@ -133,7 +137,7 @@ done:
}
-static ctl_table debug_table[] = {
+static ctl_table sunrpc_table[] = {
{
.procname = "rpc_debug",
.data = &rpc_debug,
@@ -171,13 +175,4 @@ static ctl_table debug_table[] = {
{ }
};
-static ctl_table sunrpc_table[] = {
- {
- .procname = "sunrpc",
- .mode = 0555,
- .child = debug_table
- },
- { }
-};
-
#endif
--
1.7.5.134.g1c08b
^ permalink raw reply related
* Re: [v2 000/115] faster tree-based sysctl implementation
From: David Miller @ 2011-05-08 22:40 UTC (permalink / raw)
To: lucian.grijincu; +Cc: linux-kernel, netdev, ebiederm, adobriyan, tavi
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
From: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
Date: Mon, 9 May 2011 00:38:12 +0200
> This patch series introduces a faster/leaner sysctl internal implementation:
NO WAY.
Do not send so many patches all at once, never do anything like
that, it's too much.
^ permalink raw reply
* [v2 042/115] sysctl: remove .child from vm/ (s390)
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
arch/s390/mm/cmm.c | 11 +++--------
1 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index c66ffd8..0ef5bbf 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -348,13 +348,8 @@ static struct ctl_table cmm_table[] = {
{ }
};
-static struct ctl_table cmm_dir_table[] = {
- {
- .procname = "vm",
- .maxlen = 0,
- .mode = 0555,
- .child = cmm_table,
- },
+static const __initdata struct ctl_path cmm_path[] = {
+ { .procname = "vm" },
{ }
};
@@ -434,7 +429,7 @@ static int __init cmm_init(void)
{
int rc = -ENOMEM;
- cmm_sysctl_header = register_sysctl_table(cmm_dir_table);
+ cmm_sysctl_header = register_sysctl_paths(cmm_path, cmm_table);
if (!cmm_sysctl_header)
goto out_sysctl;
#ifdef CONFIG_CMM_IUCV
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 045/115] sysctl: remove .child from kernel/powersave-nap (powerpc)
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
arch/powerpc/kernel/idle.c | 13 +++++--------
1 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c
index 39a2baa..88d03c5 100644
--- a/arch/powerpc/kernel/idle.c
+++ b/arch/powerpc/kernel/idle.c
@@ -118,19 +118,16 @@ static ctl_table powersave_nap_ctl_table[]={
},
{}
};
-static ctl_table powersave_nap_sysctl_root[] = {
- {
- .procname = "kernel",
- .mode = 0555,
- .child = powersave_nap_ctl_table,
- },
- {}
+
+static const __initdata struct ctl_path powersave_nap_path[] = {
+ { .procname = "kernel" },
+ { }
};
static int __init
register_powersave_nap_sysctl(void)
{
- register_sysctl_table(powersave_nap_sysctl_root);
+ register_sysctl_paths(powersave_nap_path, powersave_nap_ctl_table);
return 0;
}
--
1.7.5.134.g1c08b
^ permalink raw reply related
* [v2 046/115] sysctl: remove .child from pm/ (frv)
From: Lucian Adrian Grijincu @ 2011-05-08 22:38 UTC (permalink / raw)
To: linux-kernel; +Cc: netdev, Lucian Adrian Grijincu
In-Reply-To: <1304894407-32201-1-git-send-email-lucian.grijincu@gmail.com>
Signed-off-by: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
---
arch/frv/kernel/pm.c | 10 +++-------
1 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index 5fa3889..bcef945 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -329,13 +329,9 @@ static struct ctl_table pm_table[] =
{ }
};
-static struct ctl_table pm_dir_table[] =
+static const __initdata struct ctl_path pm_path[] =
{
- {
- .procname = "pm",
- .mode = 0555,
- .child = pm_table,
- },
+ { .procname = "pm" },
{ }
};
@@ -344,7 +340,7 @@ static struct ctl_table pm_dir_table[] =
*/
static int __init pm_init(void)
{
- register_sysctl_table(pm_dir_table);
+ register_sysctl_paths(pm_path, pm_table);
return 0;
}
--
1.7.5.134.g1c08b
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox