aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-08-11 07:27:47 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-11 07:27:47 -0400
commitc4c0c56a7a85ed5725786219e4fbca7e840b1531 (patch)
treec9d6b35a571fd5e80ddf5bf4a60142480eaa18d8 /kernel/sysctl.c
parent5127bed588a2f8f3a1f732de2a8a190b7df5dce3 (diff)
parent796aadeb1b2db9b5d463946766c5bbfd7717158c (diff)
Merge branch 'linus' into core/rcu
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c206
1 files changed, 178 insertions, 28 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 6b16e16428d8..fe4713347275 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -43,6 +43,7 @@
43#include <linux/limits.h> 43#include <linux/limits.h>
44#include <linux/dcache.h> 44#include <linux/dcache.h>
45#include <linux/syscalls.h> 45#include <linux/syscalls.h>
46#include <linux/vmstat.h>
46#include <linux/nfs_fs.h> 47#include <linux/nfs_fs.h>
47#include <linux/acpi.h> 48#include <linux/acpi.h>
48#include <linux/reboot.h> 49#include <linux/reboot.h>
@@ -80,7 +81,6 @@ extern int sysctl_drop_caches;
80extern int percpu_pagelist_fraction; 81extern int percpu_pagelist_fraction;
81extern int compat_log; 82extern int compat_log;
82extern int maps_protect; 83extern int maps_protect;
83extern int sysctl_stat_interval;
84extern int latencytop_enabled; 84extern int latencytop_enabled;
85extern int sysctl_nr_open_min, sysctl_nr_open_max; 85extern int sysctl_nr_open_min, sysctl_nr_open_max;
86#ifdef CONFIG_RCU_TORTURE_TEST 86#ifdef CONFIG_RCU_TORTURE_TEST
@@ -88,12 +88,13 @@ extern int rcutorture_runnable;
88#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ 88#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
89 89
90/* Constants used for minimum and maximum */ 90/* Constants used for minimum and maximum */
91#if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM) 91#if defined(CONFIG_HIGHMEM) || defined(CONFIG_DETECT_SOFTLOCKUP)
92static int one = 1; 92static int one = 1;
93#endif 93#endif
94 94
95#ifdef CONFIG_DETECT_SOFTLOCKUP 95#ifdef CONFIG_DETECT_SOFTLOCKUP
96static int sixty = 60; 96static int sixty = 60;
97static int neg_one = -1;
97#endif 98#endif
98 99
99#ifdef CONFIG_MMU 100#ifdef CONFIG_MMU
@@ -110,7 +111,7 @@ static int min_percpu_pagelist_fract = 8;
110 111
111static int ngroups_max = NGROUPS_MAX; 112static int ngroups_max = NGROUPS_MAX;
112 113
113#ifdef CONFIG_KMOD 114#ifdef CONFIG_MODULES
114extern char modprobe_path[]; 115extern char modprobe_path[];
115#endif 116#endif
116#ifdef CONFIG_CHR_DEV_SG 117#ifdef CONFIG_CHR_DEV_SG
@@ -159,12 +160,13 @@ static struct ctl_table root_table[];
159static struct ctl_table_root sysctl_table_root; 160static struct ctl_table_root sysctl_table_root;
160static struct ctl_table_header root_table_header = { 161static struct ctl_table_header root_table_header = {
161 .ctl_table = root_table, 162 .ctl_table = root_table,
162 .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.header_list), 163 .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),
163 .root = &sysctl_table_root, 164 .root = &sysctl_table_root,
165 .set = &sysctl_table_root.default_set,
164}; 166};
165static struct ctl_table_root sysctl_table_root = { 167static struct ctl_table_root sysctl_table_root = {
166 .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list), 168 .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list),
167 .header_list = LIST_HEAD_INIT(root_table_header.ctl_entry), 169 .default_set.list = LIST_HEAD_INIT(root_table_header.ctl_entry),
168}; 170};
169 171
170static struct ctl_table kern_table[]; 172static struct ctl_table kern_table[];
@@ -475,7 +477,7 @@ static struct ctl_table kern_table[] = {
475 .proc_handler = &ftrace_enable_sysctl, 477 .proc_handler = &ftrace_enable_sysctl,
476 }, 478 },
477#endif 479#endif
478#ifdef CONFIG_KMOD 480#ifdef CONFIG_MODULES
479 { 481 {
480 .ctl_name = KERN_MODPROBE, 482 .ctl_name = KERN_MODPROBE,
481 .procname = "modprobe", 483 .procname = "modprobe",
@@ -623,7 +625,7 @@ static struct ctl_table kern_table[] = {
623 { 625 {
624 .ctl_name = KERN_PRINTK_RATELIMIT, 626 .ctl_name = KERN_PRINTK_RATELIMIT,
625 .procname = "printk_ratelimit", 627 .procname = "printk_ratelimit",
626 .data = &printk_ratelimit_jiffies, 628 .data = &printk_ratelimit_state.interval,
627 .maxlen = sizeof(int), 629 .maxlen = sizeof(int),
628 .mode = 0644, 630 .mode = 0644,
629 .proc_handler = &proc_dointvec_jiffies, 631 .proc_handler = &proc_dointvec_jiffies,
@@ -632,7 +634,7 @@ static struct ctl_table kern_table[] = {
632 { 634 {
633 .ctl_name = KERN_PRINTK_RATELIMIT_BURST, 635 .ctl_name = KERN_PRINTK_RATELIMIT_BURST,
634 .procname = "printk_ratelimit_burst", 636 .procname = "printk_ratelimit_burst",
635 .data = &printk_ratelimit_burst, 637 .data = &printk_ratelimit_state.burst,
636 .maxlen = sizeof(int), 638 .maxlen = sizeof(int),
637 .mode = 0644, 639 .mode = 0644,
638 .proc_handler = &proc_dointvec, 640 .proc_handler = &proc_dointvec,
@@ -739,13 +741,24 @@ static struct ctl_table kern_table[] = {
739#ifdef CONFIG_DETECT_SOFTLOCKUP 741#ifdef CONFIG_DETECT_SOFTLOCKUP
740 { 742 {
741 .ctl_name = CTL_UNNUMBERED, 743 .ctl_name = CTL_UNNUMBERED,
744 .procname = "softlockup_panic",
745 .data = &softlockup_panic,
746 .maxlen = sizeof(int),
747 .mode = 0644,
748 .proc_handler = &proc_dointvec_minmax,
749 .strategy = &sysctl_intvec,
750 .extra1 = &zero,
751 .extra2 = &one,
752 },
753 {
754 .ctl_name = CTL_UNNUMBERED,
742 .procname = "softlockup_thresh", 755 .procname = "softlockup_thresh",
743 .data = &softlockup_thresh, 756 .data = &softlockup_thresh,
744 .maxlen = sizeof(unsigned long), 757 .maxlen = sizeof(int),
745 .mode = 0644, 758 .mode = 0644,
746 .proc_handler = &proc_doulongvec_minmax, 759 .proc_handler = &proc_dointvec_minmax,
747 .strategy = &sysctl_intvec, 760 .strategy = &sysctl_intvec,
748 .extra1 = &one, 761 .extra1 = &neg_one,
749 .extra2 = &sixty, 762 .extra2 = &sixty,
750 }, 763 },
751 { 764 {
@@ -947,7 +960,7 @@ static struct ctl_table vm_table[] = {
947#ifdef CONFIG_HUGETLB_PAGE 960#ifdef CONFIG_HUGETLB_PAGE
948 { 961 {
949 .procname = "nr_hugepages", 962 .procname = "nr_hugepages",
950 .data = &max_huge_pages, 963 .data = NULL,
951 .maxlen = sizeof(unsigned long), 964 .maxlen = sizeof(unsigned long),
952 .mode = 0644, 965 .mode = 0644,
953 .proc_handler = &hugetlb_sysctl_handler, 966 .proc_handler = &hugetlb_sysctl_handler,
@@ -973,10 +986,12 @@ static struct ctl_table vm_table[] = {
973 { 986 {
974 .ctl_name = CTL_UNNUMBERED, 987 .ctl_name = CTL_UNNUMBERED,
975 .procname = "nr_overcommit_hugepages", 988 .procname = "nr_overcommit_hugepages",
976 .data = &sysctl_overcommit_huge_pages, 989 .data = NULL,
977 .maxlen = sizeof(sysctl_overcommit_huge_pages), 990 .maxlen = sizeof(unsigned long),
978 .mode = 0644, 991 .mode = 0644,
979 .proc_handler = &hugetlb_overcommit_handler, 992 .proc_handler = &hugetlb_overcommit_handler,
993 .extra1 = (void *)&hugetlb_zero,
994 .extra2 = (void *)&hugetlb_infinity,
980 }, 995 },
981#endif 996#endif
982 { 997 {
@@ -1372,6 +1387,9 @@ static void start_unregistering(struct ctl_table_header *p)
1372 spin_unlock(&sysctl_lock); 1387 spin_unlock(&sysctl_lock);
1373 wait_for_completion(&wait); 1388 wait_for_completion(&wait);
1374 spin_lock(&sysctl_lock); 1389 spin_lock(&sysctl_lock);
1390 } else {
1391 /* anything non-NULL; we'll never dereference it */
1392 p->unregistering = ERR_PTR(-EINVAL);
1375 } 1393 }
1376 /* 1394 /*
1377 * do not remove from the list until nobody holds it; walking the 1395 * do not remove from the list until nobody holds it; walking the
@@ -1380,6 +1398,32 @@ static void start_unregistering(struct ctl_table_header *p)
1380 list_del_init(&p->ctl_entry); 1398 list_del_init(&p->ctl_entry);
1381} 1399}
1382 1400
1401void sysctl_head_get(struct ctl_table_header *head)
1402{
1403 spin_lock(&sysctl_lock);
1404 head->count++;
1405 spin_unlock(&sysctl_lock);
1406}
1407
1408void sysctl_head_put(struct ctl_table_header *head)
1409{
1410 spin_lock(&sysctl_lock);
1411 if (!--head->count)
1412 kfree(head);
1413 spin_unlock(&sysctl_lock);
1414}
1415
1416struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
1417{
1418 if (!head)
1419 BUG();
1420 spin_lock(&sysctl_lock);
1421 if (!use_table(head))
1422 head = ERR_PTR(-ENOENT);
1423 spin_unlock(&sysctl_lock);
1424 return head;
1425}
1426
1383void sysctl_head_finish(struct ctl_table_header *head) 1427void sysctl_head_finish(struct ctl_table_header *head)
1384{ 1428{
1385 if (!head) 1429 if (!head)
@@ -1389,14 +1433,20 @@ void sysctl_head_finish(struct ctl_table_header *head)
1389 spin_unlock(&sysctl_lock); 1433 spin_unlock(&sysctl_lock);
1390} 1434}
1391 1435
1436static struct ctl_table_set *
1437lookup_header_set(struct ctl_table_root *root, struct nsproxy *namespaces)
1438{
1439 struct ctl_table_set *set = &root->default_set;
1440 if (root->lookup)
1441 set = root->lookup(root, namespaces);
1442 return set;
1443}
1444
1392static struct list_head * 1445static struct list_head *
1393lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces) 1446lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces)
1394{ 1447{
1395 struct list_head *header_list; 1448 struct ctl_table_set *set = lookup_header_set(root, namespaces);
1396 header_list = &root->header_list; 1449 return &set->list;
1397 if (root->lookup)
1398 header_list = root->lookup(root, namespaces);
1399 return header_list;
1400} 1450}
1401 1451
1402struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces, 1452struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
@@ -1466,9 +1516,9 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
1466 int op = 0, rc; 1516 int op = 0, rc;
1467 1517
1468 if (oldval) 1518 if (oldval)
1469 op |= 004; 1519 op |= MAY_READ;
1470 if (newval) 1520 if (newval)
1471 op |= 002; 1521 op |= MAY_WRITE;
1472 if (sysctl_perm(root, table, op)) 1522 if (sysctl_perm(root, table, op))
1473 return -EPERM; 1523 return -EPERM;
1474 1524
@@ -1510,7 +1560,7 @@ repeat:
1510 if (n == table->ctl_name) { 1560 if (n == table->ctl_name) {
1511 int error; 1561 int error;
1512 if (table->child) { 1562 if (table->child) {
1513 if (sysctl_perm(root, table, 001)) 1563 if (sysctl_perm(root, table, MAY_EXEC))
1514 return -EPERM; 1564 return -EPERM;
1515 name++; 1565 name++;
1516 nlen--; 1566 nlen--;
@@ -1585,7 +1635,7 @@ static int test_perm(int mode, int op)
1585 mode >>= 6; 1635 mode >>= 6;
1586 else if (in_egroup_p(0)) 1636 else if (in_egroup_p(0))
1587 mode >>= 3; 1637 mode >>= 3;
1588 if ((mode & op & 0007) == op) 1638 if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0)
1589 return 0; 1639 return 0;
1590 return -EACCES; 1640 return -EACCES;
1591} 1641}
@@ -1595,7 +1645,7 @@ int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
1595 int error; 1645 int error;
1596 int mode; 1646 int mode;
1597 1647
1598 error = security_sysctl(table, op); 1648 error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC));
1599 if (error) 1649 if (error)
1600 return error; 1650 return error;
1601 1651
@@ -1630,6 +1680,54 @@ static __init int sysctl_init(void)
1630 1680
1631core_initcall(sysctl_init); 1681core_initcall(sysctl_init);
1632 1682
1683static struct ctl_table *is_branch_in(struct ctl_table *branch,
1684 struct ctl_table *table)
1685{
1686 struct ctl_table *p;
1687 const char *s = branch->procname;
1688
1689 /* branch should have named subdirectory as its first element */
1690 if (!s || !branch->child)
1691 return NULL;
1692
1693 /* ... and nothing else */
1694 if (branch[1].procname || branch[1].ctl_name)
1695 return NULL;
1696
1697 /* table should contain subdirectory with the same name */
1698 for (p = table; p->procname || p->ctl_name; p++) {
1699 if (!p->child)
1700 continue;
1701 if (p->procname && strcmp(p->procname, s) == 0)
1702 return p;
1703 }
1704 return NULL;
1705}
1706
1707/* see if attaching q to p would be an improvement */
1708static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
1709{
1710 struct ctl_table *to = p->ctl_table, *by = q->ctl_table;
1711 struct ctl_table *next;
1712 int is_better = 0;
1713 int not_in_parent = !p->attached_by;
1714
1715 while ((next = is_branch_in(by, to)) != NULL) {
1716 if (by == q->attached_by)
1717 is_better = 1;
1718 if (to == p->attached_by)
1719 not_in_parent = 1;
1720 by = by->child;
1721 to = next->child;
1722 }
1723
1724 if (is_better && not_in_parent) {
1725 q->attached_by = by;
1726 q->attached_to = to;
1727 q->parent = p;
1728 }
1729}
1730
1633/** 1731/**
1634 * __register_sysctl_paths - register a sysctl hierarchy 1732 * __register_sysctl_paths - register a sysctl hierarchy
1635 * @root: List of sysctl headers to register on 1733 * @root: List of sysctl headers to register on
@@ -1706,10 +1804,10 @@ struct ctl_table_header *__register_sysctl_paths(
1706 struct nsproxy *namespaces, 1804 struct nsproxy *namespaces,
1707 const struct ctl_path *path, struct ctl_table *table) 1805 const struct ctl_path *path, struct ctl_table *table)
1708{ 1806{
1709 struct list_head *header_list;
1710 struct ctl_table_header *header; 1807 struct ctl_table_header *header;
1711 struct ctl_table *new, **prevp; 1808 struct ctl_table *new, **prevp;
1712 unsigned int n, npath; 1809 unsigned int n, npath;
1810 struct ctl_table_set *set;
1713 1811
1714 /* Count the path components */ 1812 /* Count the path components */
1715 for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath) 1813 for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath)
@@ -1751,6 +1849,7 @@ struct ctl_table_header *__register_sysctl_paths(
1751 header->unregistering = NULL; 1849 header->unregistering = NULL;
1752 header->root = root; 1850 header->root = root;
1753 sysctl_set_parent(NULL, header->ctl_table); 1851 sysctl_set_parent(NULL, header->ctl_table);
1852 header->count = 1;
1754#ifdef CONFIG_SYSCTL_SYSCALL_CHECK 1853#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
1755 if (sysctl_check_table(namespaces, header->ctl_table)) { 1854 if (sysctl_check_table(namespaces, header->ctl_table)) {
1756 kfree(header); 1855 kfree(header);
@@ -1758,8 +1857,20 @@ struct ctl_table_header *__register_sysctl_paths(
1758 } 1857 }
1759#endif 1858#endif
1760 spin_lock(&sysctl_lock); 1859 spin_lock(&sysctl_lock);
1761 header_list = lookup_header_list(root, namespaces); 1860 header->set = lookup_header_set(root, namespaces);
1762 list_add_tail(&header->ctl_entry, header_list); 1861 header->attached_by = header->ctl_table;
1862 header->attached_to = root_table;
1863 header->parent = &root_table_header;
1864 for (set = header->set; set; set = set->parent) {
1865 struct ctl_table_header *p;
1866 list_for_each_entry(p, &set->list, ctl_entry) {
1867 if (p->unregistering)
1868 continue;
1869 try_attach(p, header);
1870 }
1871 }
1872 header->parent->count++;
1873 list_add_tail(&header->ctl_entry, &header->set->list);
1763 spin_unlock(&sysctl_lock); 1874 spin_unlock(&sysctl_lock);
1764 1875
1765 return header; 1876 return header;
@@ -1814,8 +1925,37 @@ void unregister_sysctl_table(struct ctl_table_header * header)
1814 1925
1815 spin_lock(&sysctl_lock); 1926 spin_lock(&sysctl_lock);
1816 start_unregistering(header); 1927 start_unregistering(header);
1928 if (!--header->parent->count) {
1929 WARN_ON(1);
1930 kfree(header->parent);
1931 }
1932 if (!--header->count)
1933 kfree(header);
1934 spin_unlock(&sysctl_lock);
1935}
1936
1937int sysctl_is_seen(struct ctl_table_header *p)
1938{
1939 struct ctl_table_set *set = p->set;
1940 int res;
1941 spin_lock(&sysctl_lock);
1942 if (p->unregistering)
1943 res = 0;
1944 else if (!set->is_seen)
1945 res = 1;
1946 else
1947 res = set->is_seen(set);
1817 spin_unlock(&sysctl_lock); 1948 spin_unlock(&sysctl_lock);
1818 kfree(header); 1949 return res;
1950}
1951
1952void setup_sysctl_set(struct ctl_table_set *p,
1953 struct ctl_table_set *parent,
1954 int (*is_seen)(struct ctl_table_set *))
1955{
1956 INIT_LIST_HEAD(&p->list);
1957 p->parent = parent ? parent : &sysctl_table_root.default_set;
1958 p->is_seen = is_seen;
1819} 1959}
1820 1960
1821#else /* !CONFIG_SYSCTL */ 1961#else /* !CONFIG_SYSCTL */
@@ -1834,6 +1974,16 @@ void unregister_sysctl_table(struct ctl_table_header * table)
1834{ 1974{
1835} 1975}
1836 1976
1977void setup_sysctl_set(struct ctl_table_set *p,
1978 struct ctl_table_set *parent,
1979 int (*is_seen)(struct ctl_table_set *))
1980{
1981}
1982
1983void sysctl_head_put(struct ctl_table_header *head)
1984{
1985}
1986
1837#endif /* CONFIG_SYSCTL */ 1987#endif /* CONFIG_SYSCTL */
1838 1988
1839/* 1989/*