| From stable-bounces@linux.kernel.org Sun Jul 15 23:48:48 2007 |
| From: Joe Jin <joe.jin@oracle.com> |
| Date: Sun, 15 Jul 2007 23:38:12 -0700 |
| Subject: hugetlb: fix race in alloc_fresh_huge_page() |
| To: torvalds@linux-foundation.org |
| Cc: akpm@linux-foundation.org, joe.jin@oracle.com, stable@kernel.org, gurudas.pai@oracle.com |
| Message-ID: <200707160638.l6G6cC01014158@imap1.linux-foundation.org> |
| |
| |
| From: Joe Jin <joe.jin@oracle.com> |
| |
| That static `nid' index needs locking. Without it we can end up calling |
| alloc_pages_node() with an illegal node ID and the kernel crashes. |
| |
| Acked-by: Gurudas Pai <gurudas.pai@oracle.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| mm/hugetlb.c | 15 +++++++++++---- |
| 1 file changed, 11 insertions(+), 4 deletions(-) |
| |
| --- a/mm/hugetlb.c |
| +++ b/mm/hugetlb.c |
| @@ -101,13 +101,20 @@ static void free_huge_page(struct page * |
| |
| static int alloc_fresh_huge_page(void) |
| { |
| - static int nid = 0; |
| + static int prev_nid; |
| struct page *page; |
| - page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN, |
| - HUGETLB_PAGE_ORDER); |
| - nid = next_node(nid, node_online_map); |
| + static DEFINE_SPINLOCK(nid_lock); |
| + int nid; |
| + |
| + spin_lock(&nid_lock); |
| + nid = next_node(prev_nid, node_online_map); |
| if (nid == MAX_NUMNODES) |
| nid = first_node(node_online_map); |
| + prev_nid = nid; |
| + spin_unlock(&nid_lock); |
| + |
| + page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN, |
| + HUGETLB_PAGE_ORDER); |
| if (page) { |
| set_compound_page_dtor(page, free_huge_page); |
| spin_lock(&hugetlb_lock); |