aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);