diff options
author | Al Viro <viro@ZenIV.linux.org.uk> | 2008-07-27 01:31:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-27 12:45:34 -0400 |
commit | bfbcf034798b2ca45338cee5049b5694b7ddc865 (patch) | |
tree | 51ca2687c318033b7a41533ecdfd2801a7241327 /kernel/sysctl.c | |
parent | 8be1a6d6c77ab4532e4476fdb8177030ef48b52c (diff) |
lost sysctl fix
try_attach() should walk into the matching subdirectory, not the first one...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Tested-by: Valdis.Kletnieks@vt.edu
Tested-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r-- | kernel/sysctl.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 911d846f0503..fe4713347275 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -1680,43 +1680,45 @@ static __init int sysctl_init(void) | |||
1680 | 1680 | ||
1681 | core_initcall(sysctl_init); | 1681 | core_initcall(sysctl_init); |
1682 | 1682 | ||
1683 | static int is_branch_in(struct ctl_table *branch, struct ctl_table *table) | 1683 | static struct ctl_table *is_branch_in(struct ctl_table *branch, |
1684 | struct ctl_table *table) | ||
1684 | { | 1685 | { |
1685 | struct ctl_table *p; | 1686 | struct ctl_table *p; |
1686 | const char *s = branch->procname; | 1687 | const char *s = branch->procname; |
1687 | 1688 | ||
1688 | /* branch should have named subdirectory as its first element */ | 1689 | /* branch should have named subdirectory as its first element */ |
1689 | if (!s || !branch->child) | 1690 | if (!s || !branch->child) |
1690 | return 0; | 1691 | return NULL; |
1691 | 1692 | ||
1692 | /* ... and nothing else */ | 1693 | /* ... and nothing else */ |
1693 | if (branch[1].procname || branch[1].ctl_name) | 1694 | if (branch[1].procname || branch[1].ctl_name) |
1694 | return 0; | 1695 | return NULL; |
1695 | 1696 | ||
1696 | /* table should contain subdirectory with the same name */ | 1697 | /* table should contain subdirectory with the same name */ |
1697 | for (p = table; p->procname || p->ctl_name; p++) { | 1698 | for (p = table; p->procname || p->ctl_name; p++) { |
1698 | if (!p->child) | 1699 | if (!p->child) |
1699 | continue; | 1700 | continue; |
1700 | if (p->procname && strcmp(p->procname, s) == 0) | 1701 | if (p->procname && strcmp(p->procname, s) == 0) |
1701 | return 1; | 1702 | return p; |
1702 | } | 1703 | } |
1703 | return 0; | 1704 | return NULL; |
1704 | } | 1705 | } |
1705 | 1706 | ||
1706 | /* see if attaching q to p would be an improvement */ | 1707 | /* see if attaching q to p would be an improvement */ |
1707 | static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q) | 1708 | static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q) |
1708 | { | 1709 | { |
1709 | struct ctl_table *to = p->ctl_table, *by = q->ctl_table; | 1710 | struct ctl_table *to = p->ctl_table, *by = q->ctl_table; |
1711 | struct ctl_table *next; | ||
1710 | int is_better = 0; | 1712 | int is_better = 0; |
1711 | int not_in_parent = !p->attached_by; | 1713 | int not_in_parent = !p->attached_by; |
1712 | 1714 | ||
1713 | while (is_branch_in(by, to)) { | 1715 | while ((next = is_branch_in(by, to)) != NULL) { |
1714 | if (by == q->attached_by) | 1716 | if (by == q->attached_by) |
1715 | is_better = 1; | 1717 | is_better = 1; |
1716 | if (to == p->attached_by) | 1718 | if (to == p->attached_by) |
1717 | not_in_parent = 1; | 1719 | not_in_parent = 1; |
1718 | by = by->child; | 1720 | by = by->child; |
1719 | to = to->child; | 1721 | to = next->child; |
1720 | } | 1722 | } |
1721 | 1723 | ||
1722 | if (is_better && not_in_parent) { | 1724 | if (is_better && not_in_parent) { |