aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sysctl.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8ee4a0619fbb..60d9357e7172 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1387,6 +1387,9 @@ static void start_unregistering(struct ctl_table_header *p)
1387 spin_unlock(&sysctl_lock); 1387 spin_unlock(&sysctl_lock);
1388 wait_for_completion(&wait); 1388 wait_for_completion(&wait);
1389 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);
1390 } 1393 }
1391 /* 1394 /*
1392 * 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
@@ -1395,6 +1398,32 @@ static void start_unregistering(struct ctl_table_header *p)
1395 list_del_init(&p->ctl_entry); 1398 list_del_init(&p->ctl_entry);
1396} 1399}
1397 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
1398void sysctl_head_finish(struct ctl_table_header *head) 1427void sysctl_head_finish(struct ctl_table_header *head)
1399{ 1428{
1400 if (!head) 1429 if (!head)
@@ -1771,6 +1800,7 @@ struct ctl_table_header *__register_sysctl_paths(
1771 header->unregistering = NULL; 1800 header->unregistering = NULL;
1772 header->root = root; 1801 header->root = root;
1773 sysctl_set_parent(NULL, header->ctl_table); 1802 sysctl_set_parent(NULL, header->ctl_table);
1803 header->count = 1;
1774#ifdef CONFIG_SYSCTL_SYSCALL_CHECK 1804#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
1775 if (sysctl_check_table(namespaces, header->ctl_table)) { 1805 if (sysctl_check_table(namespaces, header->ctl_table)) {
1776 kfree(header); 1806 kfree(header);
@@ -1834,8 +1864,9 @@ void unregister_sysctl_table(struct ctl_table_header * header)
1834 1864
1835 spin_lock(&sysctl_lock); 1865 spin_lock(&sysctl_lock);
1836 start_unregistering(header); 1866 start_unregistering(header);
1867 if (!--header->count)
1868 kfree(header);
1837 spin_unlock(&sysctl_lock); 1869 spin_unlock(&sysctl_lock);
1838 kfree(header);
1839} 1870}
1840 1871
1841void setup_sysctl_set(struct ctl_table_set *p, 1872void setup_sysctl_set(struct ctl_table_set *p,
@@ -1869,6 +1900,10 @@ void setup_sysctl_set(struct ctl_table_set *p,
1869{ 1900{
1870} 1901}
1871 1902
1903void sysctl_head_put(struct ctl_table_header *head)
1904{
1905}
1906
1872#endif /* CONFIG_SYSCTL */ 1907#endif /* CONFIG_SYSCTL */
1873 1908
1874/* 1909/*