diff options
-rw-r--r-- | include/linux/sysctl.h | 8 | ||||
-rw-r--r-- | kernel/sysctl.c | 89 |
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 */ | ||
1063 | struct ctl_path { | ||
1064 | const char *procname; | ||
1065 | int ctl_name; | ||
1066 | }; | ||
1067 | |||
1062 | struct ctl_table_header *register_sysctl_table(struct ctl_table * table); | 1068 | struct ctl_table_header *register_sysctl_table(struct ctl_table * table); |
1069 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, | ||
1070 | struct ctl_table *table); | ||
1063 | 1071 | ||
1064 | void unregister_sysctl_table(struct ctl_table_header * table); | 1072 | void unregister_sysctl_table(struct ctl_table_header * table); |
1065 | int sysctl_check_table(struct ctl_table *table); | 1073 | int 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) | |||
1561 | core_initcall(sysctl_init); | 1561 | core_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 | */ |
1631 | struct ctl_table_header *register_sysctl_table(struct ctl_table * table) | 1632 | struct 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 | */ | ||
1697 | struct 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 | ||
1730 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, | ||
1731 | struct ctl_table *table) | ||
1732 | { | ||
1733 | return NULL; | ||
1734 | } | ||
1735 | |||
1678 | void unregister_sysctl_table(struct ctl_table_header * table) | 1736 | void unregister_sysctl_table(struct ctl_table_header * table) |
1679 | { | 1737 | { |
1680 | } | 1738 | } |
@@ -2733,6 +2791,7 @@ EXPORT_SYMBOL(proc_dostring); | |||
2733 | EXPORT_SYMBOL(proc_doulongvec_minmax); | 2791 | EXPORT_SYMBOL(proc_doulongvec_minmax); |
2734 | EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); | 2792 | EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); |
2735 | EXPORT_SYMBOL(register_sysctl_table); | 2793 | EXPORT_SYMBOL(register_sysctl_table); |
2794 | EXPORT_SYMBOL(register_sysctl_paths); | ||
2736 | EXPORT_SYMBOL(sysctl_intvec); | 2795 | EXPORT_SYMBOL(sysctl_intvec); |
2737 | EXPORT_SYMBOL(sysctl_jiffies); | 2796 | EXPORT_SYMBOL(sysctl_jiffies); |
2738 | EXPORT_SYMBOL(sysctl_ms_jiffies); | 2797 | EXPORT_SYMBOL(sysctl_ms_jiffies); |