]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
hugetlb: fix race in alloc_fresh_huge_page()
authorJoe Jin <joe.jin@oracle.com>
Mon, 16 Jul 2007 06:38:12 +0000 (23:38 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 9 Aug 2007 21:27:40 +0000 (14:27 -0700)
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

index a45d1f0691cecb63e088d02fb3ff287f025e4d78..5fb38f1c1c37967162901fbea203d5ae1d286f80 100644 (file)
@@ -101,13 +101,20 @@ static void free_huge_page(struct page *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);