aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c276
1 files changed, 219 insertions, 57 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 29116652dca8..cfc5295f1e82 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -43,9 +43,11 @@
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>
50#include <linux/ftrace.h>
49 51
50#include <asm/uaccess.h> 52#include <asm/uaccess.h>
51#include <asm/processor.h> 53#include <asm/processor.h>
@@ -78,21 +80,23 @@ extern int pid_max_min, pid_max_max;
78extern int sysctl_drop_caches; 80extern int sysctl_drop_caches;
79extern int percpu_pagelist_fraction; 81extern int percpu_pagelist_fraction;
80extern int compat_log; 82extern int compat_log;
81extern int maps_protect;
82extern int sysctl_stat_interval;
83extern int latencytop_enabled; 83extern int latencytop_enabled;
84extern int sysctl_nr_open_min, sysctl_nr_open_max; 84extern int sysctl_nr_open_min, sysctl_nr_open_max;
85#ifdef CONFIG_RCU_TORTURE_TEST
86extern int rcutorture_runnable;
87#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
85 88
86/* Constants used for minimum and maximum */ 89/* Constants used for minimum and maximum */
87#if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM) 90#if defined(CONFIG_HIGHMEM) || defined(CONFIG_DETECT_SOFTLOCKUP)
88static int one = 1; 91static int one = 1;
89#endif 92#endif
90 93
91#ifdef CONFIG_DETECT_SOFTLOCKUP 94#ifdef CONFIG_DETECT_SOFTLOCKUP
92static int sixty = 60; 95static int sixty = 60;
96static int neg_one = -1;
93#endif 97#endif
94 98
95#ifdef CONFIG_MMU 99#if defined(CONFIG_MMU) && defined(CONFIG_FILE_LOCKING)
96static int two = 2; 100static int two = 2;
97#endif 101#endif
98 102
@@ -106,17 +110,15 @@ static int min_percpu_pagelist_fract = 8;
106 110
107static int ngroups_max = NGROUPS_MAX; 111static int ngroups_max = NGROUPS_MAX;
108 112
109#ifdef CONFIG_KMOD 113#ifdef CONFIG_MODULES
110extern char modprobe_path[]; 114extern char modprobe_path[];
111#endif 115#endif
112#ifdef CONFIG_CHR_DEV_SG 116#ifdef CONFIG_CHR_DEV_SG
113extern int sg_big_buff; 117extern int sg_big_buff;
114#endif 118#endif
115 119
116#ifdef __sparc__ 120#ifdef CONFIG_SPARC
117extern char reboot_command []; 121#include <asm/system.h>
118extern int stop_a_enabled;
119extern int scons_pwroff;
120#endif 122#endif
121 123
122#ifdef __hppa__ 124#ifdef __hppa__
@@ -132,8 +134,6 @@ extern int sysctl_userprocess_debug;
132extern int spin_retry; 134extern int spin_retry;
133#endif 135#endif
134 136
135extern int sysctl_hz_timer;
136
137#ifdef CONFIG_BSD_PROCESS_ACCT 137#ifdef CONFIG_BSD_PROCESS_ACCT
138extern int acct_parm[]; 138extern int acct_parm[];
139#endif 139#endif
@@ -156,13 +156,15 @@ static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *
156static struct ctl_table root_table[]; 156static struct ctl_table root_table[];
157static struct ctl_table_root sysctl_table_root; 157static struct ctl_table_root sysctl_table_root;
158static struct ctl_table_header root_table_header = { 158static struct ctl_table_header root_table_header = {
159 .count = 1,
159 .ctl_table = root_table, 160 .ctl_table = root_table,
160 .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.header_list), 161 .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),
161 .root = &sysctl_table_root, 162 .root = &sysctl_table_root,
163 .set = &sysctl_table_root.default_set,
162}; 164};
163static struct ctl_table_root sysctl_table_root = { 165static struct ctl_table_root sysctl_table_root = {
164 .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list), 166 .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list),
165 .header_list = LIST_HEAD_INIT(root_table_header.ctl_entry), 167 .default_set.list = LIST_HEAD_INIT(root_table_header.ctl_entry),
166}; 168};
167 169
168static struct ctl_table kern_table[]; 170static struct ctl_table kern_table[];
@@ -266,6 +268,14 @@ static struct ctl_table kern_table[] = {
266 }, 268 },
267 { 269 {
268 .ctl_name = CTL_UNNUMBERED, 270 .ctl_name = CTL_UNNUMBERED,
271 .procname = "sched_shares_ratelimit",
272 .data = &sysctl_sched_shares_ratelimit,
273 .maxlen = sizeof(unsigned int),
274 .mode = 0644,
275 .proc_handler = &proc_dointvec,
276 },
277 {
278 .ctl_name = CTL_UNNUMBERED,
269 .procname = "sched_child_runs_first", 279 .procname = "sched_child_runs_first",
270 .data = &sysctl_sched_child_runs_first, 280 .data = &sysctl_sched_child_runs_first,
271 .maxlen = sizeof(unsigned int), 281 .maxlen = sizeof(unsigned int),
@@ -402,7 +412,7 @@ static struct ctl_table kern_table[] = {
402 .mode = 0644, 412 .mode = 0644,
403 .proc_handler = &proc_dointvec, 413 .proc_handler = &proc_dointvec,
404 }, 414 },
405#ifdef __sparc__ 415#ifdef CONFIG_SPARC
406 { 416 {
407 .ctl_name = KERN_SPARC_REBOOT, 417 .ctl_name = KERN_SPARC_REBOOT,
408 .procname = "reboot-cmd", 418 .procname = "reboot-cmd",
@@ -455,7 +465,17 @@ static struct ctl_table kern_table[] = {
455 .mode = 0644, 465 .mode = 0644,
456 .proc_handler = &proc_dointvec, 466 .proc_handler = &proc_dointvec,
457 }, 467 },
458#ifdef CONFIG_KMOD 468#ifdef CONFIG_FTRACE
469 {
470 .ctl_name = CTL_UNNUMBERED,
471 .procname = "ftrace_enabled",
472 .data = &ftrace_enabled,
473 .maxlen = sizeof(int),
474 .mode = 0644,
475 .proc_handler = &ftrace_enable_sysctl,
476 },
477#endif
478#ifdef CONFIG_MODULES
459 { 479 {
460 .ctl_name = KERN_MODPROBE, 480 .ctl_name = KERN_MODPROBE,
461 .procname = "modprobe", 481 .procname = "modprobe",
@@ -563,16 +583,6 @@ static struct ctl_table kern_table[] = {
563 .proc_handler = &proc_dointvec, 583 .proc_handler = &proc_dointvec,
564 }, 584 },
565#endif 585#endif
566#ifdef CONFIG_NO_IDLE_HZ
567 {
568 .ctl_name = KERN_HZ_TIMER,
569 .procname = "hz_timer",
570 .data = &sysctl_hz_timer,
571 .maxlen = sizeof(int),
572 .mode = 0644,
573 .proc_handler = &proc_dointvec,
574 },
575#endif
576 { 586 {
577 .ctl_name = KERN_S390_USER_DEBUG_LOGGING, 587 .ctl_name = KERN_S390_USER_DEBUG_LOGGING,
578 .procname = "userprocess_debug", 588 .procname = "userprocess_debug",
@@ -613,7 +623,7 @@ static struct ctl_table kern_table[] = {
613 { 623 {
614 .ctl_name = KERN_PRINTK_RATELIMIT, 624 .ctl_name = KERN_PRINTK_RATELIMIT,
615 .procname = "printk_ratelimit", 625 .procname = "printk_ratelimit",
616 .data = &printk_ratelimit_jiffies, 626 .data = &printk_ratelimit_state.interval,
617 .maxlen = sizeof(int), 627 .maxlen = sizeof(int),
618 .mode = 0644, 628 .mode = 0644,
619 .proc_handler = &proc_dointvec_jiffies, 629 .proc_handler = &proc_dointvec_jiffies,
@@ -622,7 +632,7 @@ static struct ctl_table kern_table[] = {
622 { 632 {
623 .ctl_name = KERN_PRINTK_RATELIMIT_BURST, 633 .ctl_name = KERN_PRINTK_RATELIMIT_BURST,
624 .procname = "printk_ratelimit_burst", 634 .procname = "printk_ratelimit_burst",
625 .data = &printk_ratelimit_burst, 635 .data = &printk_ratelimit_state.burst,
626 .maxlen = sizeof(int), 636 .maxlen = sizeof(int),
627 .mode = 0644, 637 .mode = 0644,
628 .proc_handler = &proc_dointvec, 638 .proc_handler = &proc_dointvec,
@@ -729,13 +739,24 @@ static struct ctl_table kern_table[] = {
729#ifdef CONFIG_DETECT_SOFTLOCKUP 739#ifdef CONFIG_DETECT_SOFTLOCKUP
730 { 740 {
731 .ctl_name = CTL_UNNUMBERED, 741 .ctl_name = CTL_UNNUMBERED,
742 .procname = "softlockup_panic",
743 .data = &softlockup_panic,
744 .maxlen = sizeof(int),
745 .mode = 0644,
746 .proc_handler = &proc_dointvec_minmax,
747 .strategy = &sysctl_intvec,
748 .extra1 = &zero,
749 .extra2 = &one,
750 },
751 {
752 .ctl_name = CTL_UNNUMBERED,
732 .procname = "softlockup_thresh", 753 .procname = "softlockup_thresh",
733 .data = &softlockup_thresh, 754 .data = &softlockup_thresh,
734 .maxlen = sizeof(unsigned long), 755 .maxlen = sizeof(int),
735 .mode = 0644, 756 .mode = 0644,
736 .proc_handler = &proc_doulongvec_minmax, 757 .proc_handler = &proc_dointvec_minmax,
737 .strategy = &sysctl_intvec, 758 .strategy = &sysctl_intvec,
738 .extra1 = &one, 759 .extra1 = &neg_one,
739 .extra2 = &sixty, 760 .extra2 = &sixty,
740 }, 761 },
741 { 762 {
@@ -786,16 +807,6 @@ static struct ctl_table kern_table[] = {
786 .proc_handler = &proc_dointvec, 807 .proc_handler = &proc_dointvec,
787 }, 808 },
788#endif 809#endif
789#ifdef CONFIG_PROC_FS
790 {
791 .ctl_name = CTL_UNNUMBERED,
792 .procname = "maps_protect",
793 .data = &maps_protect,
794 .maxlen = sizeof(int),
795 .mode = 0644,
796 .proc_handler = &proc_dointvec,
797 },
798#endif
799 { 810 {
800 .ctl_name = CTL_UNNUMBERED, 811 .ctl_name = CTL_UNNUMBERED,
801 .procname = "poweroff_cmd", 812 .procname = "poweroff_cmd",
@@ -813,6 +824,16 @@ static struct ctl_table kern_table[] = {
813 .child = key_sysctls, 824 .child = key_sysctls,
814 }, 825 },
815#endif 826#endif
827#ifdef CONFIG_RCU_TORTURE_TEST
828 {
829 .ctl_name = CTL_UNNUMBERED,
830 .procname = "rcutorture_runnable",
831 .data = &rcutorture_runnable,
832 .maxlen = sizeof(int),
833 .mode = 0644,
834 .proc_handler = &proc_dointvec,
835 },
836#endif
816/* 837/*
817 * NOTE: do not add new entries to this table unless you have read 838 * NOTE: do not add new entries to this table unless you have read
818 * Documentation/sysctl/ctl_unnumbered.txt 839 * Documentation/sysctl/ctl_unnumbered.txt
@@ -927,7 +948,7 @@ static struct ctl_table vm_table[] = {
927#ifdef CONFIG_HUGETLB_PAGE 948#ifdef CONFIG_HUGETLB_PAGE
928 { 949 {
929 .procname = "nr_hugepages", 950 .procname = "nr_hugepages",
930 .data = &max_huge_pages, 951 .data = NULL,
931 .maxlen = sizeof(unsigned long), 952 .maxlen = sizeof(unsigned long),
932 .mode = 0644, 953 .mode = 0644,
933 .proc_handler = &hugetlb_sysctl_handler, 954 .proc_handler = &hugetlb_sysctl_handler,
@@ -953,10 +974,12 @@ static struct ctl_table vm_table[] = {
953 { 974 {
954 .ctl_name = CTL_UNNUMBERED, 975 .ctl_name = CTL_UNNUMBERED,
955 .procname = "nr_overcommit_hugepages", 976 .procname = "nr_overcommit_hugepages",
956 .data = &sysctl_overcommit_huge_pages, 977 .data = NULL,
957 .maxlen = sizeof(sysctl_overcommit_huge_pages), 978 .maxlen = sizeof(unsigned long),
958 .mode = 0644, 979 .mode = 0644,
959 .proc_handler = &hugetlb_overcommit_handler, 980 .proc_handler = &hugetlb_overcommit_handler,
981 .extra1 = (void *)&hugetlb_zero,
982 .extra2 = (void *)&hugetlb_infinity,
960 }, 983 },
961#endif 984#endif
962 { 985 {
@@ -1225,6 +1248,7 @@ static struct ctl_table fs_table[] = {
1225 .extra1 = &minolduid, 1248 .extra1 = &minolduid,
1226 .extra2 = &maxolduid, 1249 .extra2 = &maxolduid,
1227 }, 1250 },
1251#ifdef CONFIG_FILE_LOCKING
1228 { 1252 {
1229 .ctl_name = FS_LEASES, 1253 .ctl_name = FS_LEASES,
1230 .procname = "leases-enable", 1254 .procname = "leases-enable",
@@ -1233,6 +1257,7 @@ static struct ctl_table fs_table[] = {
1233 .mode = 0644, 1257 .mode = 0644,
1234 .proc_handler = &proc_dointvec, 1258 .proc_handler = &proc_dointvec,
1235 }, 1259 },
1260#endif
1236#ifdef CONFIG_DNOTIFY 1261#ifdef CONFIG_DNOTIFY
1237 { 1262 {
1238 .ctl_name = FS_DIR_NOTIFY, 1263 .ctl_name = FS_DIR_NOTIFY,
@@ -1244,6 +1269,7 @@ static struct ctl_table fs_table[] = {
1244 }, 1269 },
1245#endif 1270#endif
1246#ifdef CONFIG_MMU 1271#ifdef CONFIG_MMU
1272#ifdef CONFIG_FILE_LOCKING
1247 { 1273 {
1248 .ctl_name = FS_LEASE_TIME, 1274 .ctl_name = FS_LEASE_TIME,
1249 .procname = "lease-break-time", 1275 .procname = "lease-break-time",
@@ -1255,6 +1281,7 @@ static struct ctl_table fs_table[] = {
1255 .extra1 = &zero, 1281 .extra1 = &zero,
1256 .extra2 = &two, 1282 .extra2 = &two,
1257 }, 1283 },
1284#endif
1258 { 1285 {
1259 .procname = "aio-nr", 1286 .procname = "aio-nr",
1260 .data = &aio_nr, 1287 .data = &aio_nr,
@@ -1352,6 +1379,9 @@ static void start_unregistering(struct ctl_table_header *p)
1352 spin_unlock(&sysctl_lock); 1379 spin_unlock(&sysctl_lock);
1353 wait_for_completion(&wait); 1380 wait_for_completion(&wait);
1354 spin_lock(&sysctl_lock); 1381 spin_lock(&sysctl_lock);
1382 } else {
1383 /* anything non-NULL; we'll never dereference it */
1384 p->unregistering = ERR_PTR(-EINVAL);
1355 } 1385 }
1356 /* 1386 /*
1357 * do not remove from the list until nobody holds it; walking the 1387 * do not remove from the list until nobody holds it; walking the
@@ -1360,6 +1390,32 @@ static void start_unregistering(struct ctl_table_header *p)
1360 list_del_init(&p->ctl_entry); 1390 list_del_init(&p->ctl_entry);
1361} 1391}
1362 1392
1393void sysctl_head_get(struct ctl_table_header *head)
1394{
1395 spin_lock(&sysctl_lock);
1396 head->count++;
1397 spin_unlock(&sysctl_lock);
1398}
1399
1400void sysctl_head_put(struct ctl_table_header *head)
1401{
1402 spin_lock(&sysctl_lock);
1403 if (!--head->count)
1404 kfree(head);
1405 spin_unlock(&sysctl_lock);
1406}
1407
1408struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head)
1409{
1410 if (!head)
1411 BUG();
1412 spin_lock(&sysctl_lock);
1413 if (!use_table(head))
1414 head = ERR_PTR(-ENOENT);
1415 spin_unlock(&sysctl_lock);
1416 return head;
1417}
1418
1363void sysctl_head_finish(struct ctl_table_header *head) 1419void sysctl_head_finish(struct ctl_table_header *head)
1364{ 1420{
1365 if (!head) 1421 if (!head)
@@ -1369,14 +1425,20 @@ void sysctl_head_finish(struct ctl_table_header *head)
1369 spin_unlock(&sysctl_lock); 1425 spin_unlock(&sysctl_lock);
1370} 1426}
1371 1427
1428static struct ctl_table_set *
1429lookup_header_set(struct ctl_table_root *root, struct nsproxy *namespaces)
1430{
1431 struct ctl_table_set *set = &root->default_set;
1432 if (root->lookup)
1433 set = root->lookup(root, namespaces);
1434 return set;
1435}
1436
1372static struct list_head * 1437static struct list_head *
1373lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces) 1438lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces)
1374{ 1439{
1375 struct list_head *header_list; 1440 struct ctl_table_set *set = lookup_header_set(root, namespaces);
1376 header_list = &root->header_list; 1441 return &set->list;
1377 if (root->lookup)
1378 header_list = root->lookup(root, namespaces);
1379 return header_list;
1380} 1442}
1381 1443
1382struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces, 1444struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
@@ -1446,9 +1508,9 @@ static int do_sysctl_strategy(struct ctl_table_root *root,
1446 int op = 0, rc; 1508 int op = 0, rc;
1447 1509
1448 if (oldval) 1510 if (oldval)
1449 op |= 004; 1511 op |= MAY_READ;
1450 if (newval) 1512 if (newval)
1451 op |= 002; 1513 op |= MAY_WRITE;
1452 if (sysctl_perm(root, table, op)) 1514 if (sysctl_perm(root, table, op))
1453 return -EPERM; 1515 return -EPERM;
1454 1516
@@ -1490,7 +1552,7 @@ repeat:
1490 if (n == table->ctl_name) { 1552 if (n == table->ctl_name) {
1491 int error; 1553 int error;
1492 if (table->child) { 1554 if (table->child) {
1493 if (sysctl_perm(root, table, 001)) 1555 if (sysctl_perm(root, table, MAY_EXEC))
1494 return -EPERM; 1556 return -EPERM;
1495 name++; 1557 name++;
1496 nlen--; 1558 nlen--;
@@ -1565,7 +1627,7 @@ static int test_perm(int mode, int op)
1565 mode >>= 6; 1627 mode >>= 6;
1566 else if (in_egroup_p(0)) 1628 else if (in_egroup_p(0))
1567 mode >>= 3; 1629 mode >>= 3;
1568 if ((mode & op & 0007) == op) 1630 if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0)
1569 return 0; 1631 return 0;
1570 return -EACCES; 1632 return -EACCES;
1571} 1633}
@@ -1575,7 +1637,7 @@ int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
1575 int error; 1637 int error;
1576 int mode; 1638 int mode;
1577 1639
1578 error = security_sysctl(table, op); 1640 error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC));
1579 if (error) 1641 if (error)
1580 return error; 1642 return error;
1581 1643
@@ -1610,6 +1672,54 @@ static __init int sysctl_init(void)
1610 1672
1611core_initcall(sysctl_init); 1673core_initcall(sysctl_init);
1612 1674
1675static struct ctl_table *is_branch_in(struct ctl_table *branch,
1676 struct ctl_table *table)
1677{
1678 struct ctl_table *p;
1679 const char *s = branch->procname;
1680
1681 /* branch should have named subdirectory as its first element */
1682 if (!s || !branch->child)
1683 return NULL;
1684
1685 /* ... and nothing else */
1686 if (branch[1].procname || branch[1].ctl_name)
1687 return NULL;
1688
1689 /* table should contain subdirectory with the same name */
1690 for (p = table; p->procname || p->ctl_name; p++) {
1691 if (!p->child)
1692 continue;
1693 if (p->procname && strcmp(p->procname, s) == 0)
1694 return p;
1695 }
1696 return NULL;
1697}
1698
1699/* see if attaching q to p would be an improvement */
1700static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q)
1701{
1702 struct ctl_table *to = p->ctl_table, *by = q->ctl_table;
1703 struct ctl_table *next;
1704 int is_better = 0;
1705 int not_in_parent = !p->attached_by;
1706
1707 while ((next = is_branch_in(by, to)) != NULL) {
1708 if (by == q->attached_by)
1709 is_better = 1;
1710 if (to == p->attached_by)
1711 not_in_parent = 1;
1712 by = by->child;
1713 to = next->child;
1714 }
1715
1716 if (is_better && not_in_parent) {
1717 q->attached_by = by;
1718 q->attached_to = to;
1719 q->parent = p;
1720 }
1721}
1722
1613/** 1723/**
1614 * __register_sysctl_paths - register a sysctl hierarchy 1724 * __register_sysctl_paths - register a sysctl hierarchy
1615 * @root: List of sysctl headers to register on 1725 * @root: List of sysctl headers to register on
@@ -1686,10 +1796,10 @@ struct ctl_table_header *__register_sysctl_paths(
1686 struct nsproxy *namespaces, 1796 struct nsproxy *namespaces,
1687 const struct ctl_path *path, struct ctl_table *table) 1797 const struct ctl_path *path, struct ctl_table *table)
1688{ 1798{
1689 struct list_head *header_list;
1690 struct ctl_table_header *header; 1799 struct ctl_table_header *header;
1691 struct ctl_table *new, **prevp; 1800 struct ctl_table *new, **prevp;
1692 unsigned int n, npath; 1801 unsigned int n, npath;
1802 struct ctl_table_set *set;
1693 1803
1694 /* Count the path components */ 1804 /* Count the path components */
1695 for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath) 1805 for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath)
@@ -1731,6 +1841,7 @@ struct ctl_table_header *__register_sysctl_paths(
1731 header->unregistering = NULL; 1841 header->unregistering = NULL;
1732 header->root = root; 1842 header->root = root;
1733 sysctl_set_parent(NULL, header->ctl_table); 1843 sysctl_set_parent(NULL, header->ctl_table);
1844 header->count = 1;
1734#ifdef CONFIG_SYSCTL_SYSCALL_CHECK 1845#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
1735 if (sysctl_check_table(namespaces, header->ctl_table)) { 1846 if (sysctl_check_table(namespaces, header->ctl_table)) {
1736 kfree(header); 1847 kfree(header);
@@ -1738,8 +1849,20 @@ struct ctl_table_header *__register_sysctl_paths(
1738 } 1849 }
1739#endif 1850#endif
1740 spin_lock(&sysctl_lock); 1851 spin_lock(&sysctl_lock);
1741 header_list = lookup_header_list(root, namespaces); 1852 header->set = lookup_header_set(root, namespaces);
1742 list_add_tail(&header->ctl_entry, header_list); 1853 header->attached_by = header->ctl_table;
1854 header->attached_to = root_table;
1855 header->parent = &root_table_header;
1856 for (set = header->set; set; set = set->parent) {
1857 struct ctl_table_header *p;
1858 list_for_each_entry(p, &set->list, ctl_entry) {
1859 if (p->unregistering)
1860 continue;
1861 try_attach(p, header);
1862 }
1863 }
1864 header->parent->count++;
1865 list_add_tail(&header->ctl_entry, &header->set->list);
1743 spin_unlock(&sysctl_lock); 1866 spin_unlock(&sysctl_lock);
1744 1867
1745 return header; 1868 return header;
@@ -1794,8 +1917,37 @@ void unregister_sysctl_table(struct ctl_table_header * header)
1794 1917
1795 spin_lock(&sysctl_lock); 1918 spin_lock(&sysctl_lock);
1796 start_unregistering(header); 1919 start_unregistering(header);
1920 if (!--header->parent->count) {
1921 WARN_ON(1);
1922 kfree(header->parent);
1923 }
1924 if (!--header->count)
1925 kfree(header);
1797 spin_unlock(&sysctl_lock); 1926 spin_unlock(&sysctl_lock);
1798 kfree(header); 1927}
1928
1929int sysctl_is_seen(struct ctl_table_header *p)
1930{
1931 struct ctl_table_set *set = p->set;
1932 int res;
1933 spin_lock(&sysctl_lock);
1934 if (p->unregistering)
1935 res = 0;
1936 else if (!set->is_seen)
1937 res = 1;
1938 else
1939 res = set->is_seen(set);
1940 spin_unlock(&sysctl_lock);
1941 return res;
1942}
1943
1944void setup_sysctl_set(struct ctl_table_set *p,
1945 struct ctl_table_set *parent,
1946 int (*is_seen)(struct ctl_table_set *))
1947{
1948 INIT_LIST_HEAD(&p->list);
1949 p->parent = parent ? parent : &sysctl_table_root.default_set;
1950 p->is_seen = is_seen;
1799} 1951}
1800 1952
1801#else /* !CONFIG_SYSCTL */ 1953#else /* !CONFIG_SYSCTL */
@@ -1814,6 +1966,16 @@ void unregister_sysctl_table(struct ctl_table_header * table)
1814{ 1966{
1815} 1967}
1816 1968
1969void setup_sysctl_set(struct ctl_table_set *p,
1970 struct ctl_table_set *parent,
1971 int (*is_seen)(struct ctl_table_set *))
1972{
1973}
1974
1975void sysctl_head_put(struct ctl_table_header *head)
1976{
1977}
1978
1817#endif /* CONFIG_SYSCTL */ 1979#endif /* CONFIG_SYSCTL */
1818 1980
1819/* 1981/*