aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-11-30 07:50:18 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:55:16 -0500
commit29e796fd4de54b8f5bc30d897611210ece4fd0f2 (patch)
treea05b5e87e7b6c4d1820d892c4aabc438ccee58e5
parentbe0ea7d5da3d99140bde7e5cea328eb111731700 (diff)
sysctl: Add register_sysctl_paths function
There are a number of modules that register a sysctl table somewhere deeply nested in the sysctl hierarchy, such as fs/nfs, fs/xfs, dev/cdrom, etc. They all specify several dummy ctl_tables for the path name. This patch implements register_sysctl_path that takes an additional path name, and makes up dummy sysctl nodes for each component. This patch was originally written by Olaf Kirch and brought to my attention and reworked some by Olaf Hering. I have changed a few additional things so the bugs are mine. After converting all of the easy callers Olaf Hering observed allyesconfig ARCH=i386, the patch reduces the final binary size by 9369 bytes. .text +897 .data -7008 text data bss dec hex filename 26959310 4045899 4718592 35723801 2211a19 ../vmlinux-vanilla 26960207 4038891 4718592 35717690 221023a ../O-allyesconfig/vmlinux So this change is both a space savings and a code simplification. CC: Olaf Kirch <okir@suse.de> CC: Olaf Hering <olaf@aepfle.de> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Serge Hallyn <serue@us.ibm.com> Cc: Daniel Lezcano <dlezcano@fr.ibm.com> Cc: Cedric Le Goater <clg@fr.ibm.com> Cc: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/sysctl.h8
-rw-r--r--kernel/sysctl.c89
2 files changed, 82 insertions, 15 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 4f5047df8a9e..3b6e2c9fbb2e 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -1059,7 +1059,15 @@ struct ctl_table_header
1059 struct completion *unregistering; 1059 struct completion *unregistering;
1060}; 1060};
1061 1061
1062/* struct ctl_path describes where in the hierarchy a table is added */
1063struct ctl_path {
1064 const char *procname;
1065 int ctl_name;
1066};
1067
1062struct ctl_table_header *register_sysctl_table(struct ctl_table * table); 1068struct ctl_table_header *register_sysctl_table(struct ctl_table * table);
1069struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
1070 struct ctl_table *table);
1063 1071
1064void unregister_sysctl_table(struct ctl_table_header * table); 1072void unregister_sysctl_table(struct ctl_table_header * table);
1065int sysctl_check_table(struct ctl_table *table); 1073int sysctl_check_table(struct ctl_table *table);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8e96558cb8f3..f580542333eb 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1561,11 +1561,12 @@ static __init int sysctl_init(void)
1561core_initcall(sysctl_init); 1561core_initcall(sysctl_init);
1562 1562
1563/** 1563/**
1564 * register_sysctl_table - register a sysctl hierarchy 1564 * register_sysctl_paths - register a sysctl hierarchy
1565 * @path: The path to the directory the sysctl table is in.
1565 * @table: the top-level table structure 1566 * @table: the top-level table structure
1566 * 1567 *
1567 * Register a sysctl table hierarchy. @table should be a filled in ctl_table 1568 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
1568 * array. An entry with a ctl_name of 0 terminates the table. 1569 * array. A completely 0 filled entry terminates the table.
1569 * 1570 *
1570 * The members of the &struct ctl_table structure are used as follows: 1571 * The members of the &struct ctl_table structure are used as follows:
1571 * 1572 *
@@ -1628,25 +1629,76 @@ core_initcall(sysctl_init);
1628 * This routine returns %NULL on a failure to register, and a pointer 1629 * This routine returns %NULL on a failure to register, and a pointer
1629 * to the table header on success. 1630 * to the table header on success.
1630 */ 1631 */
1631struct ctl_table_header *register_sysctl_table(struct ctl_table * table) 1632struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
1633 struct ctl_table *table)
1632{ 1634{
1633 struct ctl_table_header *tmp; 1635 struct ctl_table_header *header;
1634 tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL); 1636 struct ctl_table *new, **prevp;
1635 if (!tmp) 1637 unsigned int n, npath;
1638
1639 /* Count the path components */
1640 for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath)
1641 ;
1642
1643 /*
1644 * For each path component, allocate a 2-element ctl_table array.
1645 * The first array element will be filled with the sysctl entry
1646 * for this, the second will be the sentinel (ctl_name == 0).
1647 *
1648 * We allocate everything in one go so that we don't have to
1649 * worry about freeing additional memory in unregister_sysctl_table.
1650 */
1651 header = kzalloc(sizeof(struct ctl_table_header) +
1652 (2 * npath * sizeof(struct ctl_table)), GFP_KERNEL);
1653 if (!header)
1636 return NULL; 1654 return NULL;
1637 tmp->ctl_table = table; 1655
1638 INIT_LIST_HEAD(&tmp->ctl_entry); 1656 new = (struct ctl_table *) (header + 1);
1639 tmp->used = 0; 1657
1640 tmp->unregistering = NULL; 1658 /* Now connect the dots */
1641 sysctl_set_parent(NULL, table); 1659 prevp = &header->ctl_table;
1642 if (sysctl_check_table(tmp->ctl_table)) { 1660 for (n = 0; n < npath; ++n, ++path) {
1643 kfree(tmp); 1661 /* Copy the procname */
1662 new->procname = path->procname;
1663 new->ctl_name = path->ctl_name;
1664 new->mode = 0555;
1665
1666 *prevp = new;
1667 prevp = &new->child;
1668
1669 new += 2;
1670 }
1671 *prevp = table;
1672
1673 INIT_LIST_HEAD(&header->ctl_entry);
1674 header->used = 0;
1675 header->unregistering = NULL;
1676 sysctl_set_parent(NULL, header->ctl_table);
1677 if (sysctl_check_table(header->ctl_table)) {
1678 kfree(header);
1644 return NULL; 1679 return NULL;
1645 } 1680 }
1646 spin_lock(&sysctl_lock); 1681 spin_lock(&sysctl_lock);
1647 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); 1682 list_add_tail(&header->ctl_entry, &root_table_header.ctl_entry);
1648 spin_unlock(&sysctl_lock); 1683 spin_unlock(&sysctl_lock);
1649 return tmp; 1684
1685 return header;
1686}
1687
1688/**
1689 * register_sysctl_table - register a sysctl table hierarchy
1690 * @table: the top-level table structure
1691 *
1692 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
1693 * array. A completely 0 filled entry terminates the table.
1694 *
1695 * See register_sysctl_paths for more details.
1696 */
1697struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
1698{
1699 static const struct ctl_path null_path[] = { {} };
1700
1701 return register_sysctl_paths(null_path, table);
1650} 1702}
1651 1703
1652/** 1704/**
@@ -1675,6 +1727,12 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
1675 return NULL; 1727 return NULL;
1676} 1728}
1677 1729
1730struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
1731 struct ctl_table *table)
1732{
1733 return NULL;
1734}
1735
1678void unregister_sysctl_table(struct ctl_table_header * table) 1736void unregister_sysctl_table(struct ctl_table_header * table)
1679{ 1737{
1680} 1738}
@@ -2733,6 +2791,7 @@ EXPORT_SYMBOL(proc_dostring);
2733EXPORT_SYMBOL(proc_doulongvec_minmax); 2791EXPORT_SYMBOL(proc_doulongvec_minmax);
2734EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); 2792EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
2735EXPORT_SYMBOL(register_sysctl_table); 2793EXPORT_SYMBOL(register_sysctl_table);
2794EXPORT_SYMBOL(register_sysctl_paths);
2736EXPORT_SYMBOL(sysctl_intvec); 2795EXPORT_SYMBOL(sysctl_intvec);
2737EXPORT_SYMBOL(sysctl_jiffies); 2796EXPORT_SYMBOL(sysctl_jiffies);
2738EXPORT_SYMBOL(sysctl_ms_jiffies); 2797EXPORT_SYMBOL(sysctl_ms_jiffies);