diff options
author | Nishanth Aravamudan <nacc@us.ibm.com> | 2008-02-13 18:03:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-13 19:21:18 -0500 |
commit | 064d9efe947542097be669581f82d6b097e81d1a (patch) | |
tree | ddfc9f1c4d60135a7d7a1c5ebb7d0e85f683cfcb /mm | |
parent | 2695a14d315c014474ccadbaed40b0169b00cb5b (diff) |
hugetlb: fix overcommit locking
proc_doulongvec_minmax() calls copy_to_user()/copy_from_user(), so we can't
hold hugetlb_lock over the call. Use a dummy variable to store the sysctl
result, like in hugetlb_sysctl_handler(), then grab the lock to update
nr_overcommit_huge_pages.
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
Reported-by: Miles Lane <miles.lane@gmail.com>
Cc: Adam Litke <agl@us.ibm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/hugetlb.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index d9a380312467..cb1b3a7ecdfc 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -24,14 +24,15 @@ | |||
24 | const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; | 24 | const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL; |
25 | static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages; | 25 | static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages; |
26 | static unsigned long surplus_huge_pages; | 26 | static unsigned long surplus_huge_pages; |
27 | static unsigned long nr_overcommit_huge_pages; | ||
27 | unsigned long max_huge_pages; | 28 | unsigned long max_huge_pages; |
29 | unsigned long sysctl_overcommit_huge_pages; | ||
28 | static struct list_head hugepage_freelists[MAX_NUMNODES]; | 30 | static struct list_head hugepage_freelists[MAX_NUMNODES]; |
29 | static unsigned int nr_huge_pages_node[MAX_NUMNODES]; | 31 | static unsigned int nr_huge_pages_node[MAX_NUMNODES]; |
30 | static unsigned int free_huge_pages_node[MAX_NUMNODES]; | 32 | static unsigned int free_huge_pages_node[MAX_NUMNODES]; |
31 | static unsigned int surplus_huge_pages_node[MAX_NUMNODES]; | 33 | static unsigned int surplus_huge_pages_node[MAX_NUMNODES]; |
32 | static gfp_t htlb_alloc_mask = GFP_HIGHUSER; | 34 | static gfp_t htlb_alloc_mask = GFP_HIGHUSER; |
33 | unsigned long hugepages_treat_as_movable; | 35 | unsigned long hugepages_treat_as_movable; |
34 | unsigned long nr_overcommit_huge_pages; | ||
35 | static int hugetlb_next_nid; | 36 | static int hugetlb_next_nid; |
36 | 37 | ||
37 | /* | 38 | /* |
@@ -609,8 +610,9 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write, | |||
609 | struct file *file, void __user *buffer, | 610 | struct file *file, void __user *buffer, |
610 | size_t *length, loff_t *ppos) | 611 | size_t *length, loff_t *ppos) |
611 | { | 612 | { |
612 | spin_lock(&hugetlb_lock); | ||
613 | proc_doulongvec_minmax(table, write, file, buffer, length, ppos); | 613 | proc_doulongvec_minmax(table, write, file, buffer, length, ppos); |
614 | spin_lock(&hugetlb_lock); | ||
615 | nr_overcommit_huge_pages = sysctl_overcommit_huge_pages; | ||
614 | spin_unlock(&hugetlb_lock); | 616 | spin_unlock(&hugetlb_lock); |
615 | return 0; | 617 | return 0; |
616 | } | 618 | } |