diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sysctl.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8ee4a0619fb..60d9357e717 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 | ||
| 1401 | void sysctl_head_get(struct ctl_table_header *head) | ||
| 1402 | { | ||
| 1403 | spin_lock(&sysctl_lock); | ||
| 1404 | head->count++; | ||
| 1405 | spin_unlock(&sysctl_lock); | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | void 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 | |||
| 1416 | struct 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 | |||
| 1398 | void sysctl_head_finish(struct ctl_table_header *head) | 1427 | void 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 | ||
| 1841 | void setup_sysctl_set(struct ctl_table_set *p, | 1872 | void 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 | ||
| 1903 | void sysctl_head_put(struct ctl_table_header *head) | ||
| 1904 | { | ||
| 1905 | } | ||
| 1906 | |||
| 1872 | #endif /* CONFIG_SYSCTL */ | 1907 | #endif /* CONFIG_SYSCTL */ |
| 1873 | 1908 | ||
| 1874 | /* | 1909 | /* |
