diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-04-19 13:34:18 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-20 21:22:28 -0400 |
commit | 0ca7a4c87d27dd2fde0783dec94a821d6d035696 (patch) | |
tree | 3f9d1cd9a8146ce751e43f8f103a255fc7ec199d /net/ax25/sysctl_net_ax25.c | |
parent | 4e5ca78541c549ec8886ad2fc19306f35ee672e1 (diff) | |
download | blackbird-op-linux-0ca7a4c87d27dd2fde0783dec94a821d6d035696.tar.gz blackbird-op-linux-0ca7a4c87d27dd2fde0783dec94a821d6d035696.zip |
net ax25: Simplify and cleanup the ax25 sysctl handling.
Don't register/unregister every ax25 table in a batch. Instead register
and unregister per device ax25 sysctls as ax25 devices come and go.
This moves ax25 to be a completely modern sysctl user. Registering the
sysctls in just the initial network namespace, removing the use of
.child entries that are no longer natively supported by the sysctl core
and taking advantage of the fact that there are no longer any ordering
constraints between registering and unregistering different sysctl
tables.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ax25/sysctl_net_ax25.c')
-rw-r--r-- | net/ax25/sysctl_net_ax25.c | 82 |
1 files changed, 28 insertions, 54 deletions
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c index 7ba381b6f074..d5744b752511 100644 --- a/net/ax25/sysctl_net_ax25.c +++ b/net/ax25/sysctl_net_ax25.c @@ -29,17 +29,6 @@ static int min_proto[1], max_proto[] = { AX25_PROTO_MAX }; static int min_ds_timeout[1], max_ds_timeout[] = {65535000}; #endif -static struct ctl_table_header *ax25_table_header; - -static ctl_table *ax25_table; -static int ax25_table_size; - -static struct ctl_path ax25_path[] = { - { .procname = "net", }, - { .procname = "ax25", }, - { } -}; - static const ctl_table ax25_param_table[] = { { .procname = "ip_default_mode", @@ -159,52 +148,37 @@ static const ctl_table ax25_param_table[] = { { } /* that's all, folks! */ }; -void ax25_register_sysctl(void) +int ax25_register_dev_sysctl(ax25_dev *ax25_dev) { - ax25_dev *ax25_dev; - int n, k; - - spin_lock_bh(&ax25_dev_lock); - for (ax25_table_size = sizeof(ctl_table), ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) - ax25_table_size += sizeof(ctl_table); - - if ((ax25_table = kzalloc(ax25_table_size, GFP_ATOMIC)) == NULL) { - spin_unlock_bh(&ax25_dev_lock); - return; - } - - for (n = 0, ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) { - struct ctl_table *child = kmemdup(ax25_param_table, - sizeof(ax25_param_table), - GFP_ATOMIC); - if (!child) { - while (n--) - kfree(ax25_table[n].child); - kfree(ax25_table); - spin_unlock_bh(&ax25_dev_lock); - return; - } - ax25_table[n].child = ax25_dev->systable = child; - ax25_table[n].procname = ax25_dev->dev->name; - ax25_table[n].mode = 0555; - - - for (k = 0; k < AX25_MAX_VALUES; k++) - child[k].data = &ax25_dev->values[k]; - - n++; + char path[sizeof("net/ax25/") + IFNAMSIZ]; + int k; + struct ctl_table *table; + + table = kmemdup(ax25_param_table, sizeof(ax25_param_table), GFP_KERNEL); + if (!table) + return -ENOMEM; + + for (k = 0; k < AX25_MAX_VALUES; k++) + table[k].data = &ax25_dev->values[k]; + + snprintf(path, sizeof(path), "net/ax25/%s", ax25_dev->dev->name); + ax25_dev->sysheader = register_net_sysctl(&init_net, path, table); + if (!ax25_dev->sysheader) { + kfree(table); + return -ENOMEM; } - spin_unlock_bh(&ax25_dev_lock); - - ax25_table_header = register_net_sysctl_table(&init_net, ax25_path, ax25_table); + return 0; } -void ax25_unregister_sysctl(void) +void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) { - ctl_table *p; - unregister_net_sysctl_table(ax25_table_header); - - for (p = ax25_table; p->procname; p++) - kfree(p->child); - kfree(ax25_table); + struct ctl_table_header *header = ax25_dev->sysheader; + struct ctl_table *table; + + if (header) { + ax25_dev->sysheader = NULL; + table = header->ctl_table_arg; + unregister_net_sysctl_table(header); + kfree(table); + } } |