aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/hugetlb.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 41b1038f76da..d5987a87bbe5 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -13,6 +13,7 @@
13#include <linux/pagemap.h> 13#include <linux/pagemap.h>
14#include <linux/mempolicy.h> 14#include <linux/mempolicy.h>
15#include <linux/cpuset.h> 15#include <linux/cpuset.h>
16#include <linux/mutex.h>
16 17
17#include <asm/page.h> 18#include <asm/page.h>
18#include <asm/pgtable.h> 19#include <asm/pgtable.h>
@@ -26,6 +27,10 @@ unsigned long max_huge_pages;
26static struct list_head hugepage_freelists[MAX_NUMNODES]; 27static struct list_head hugepage_freelists[MAX_NUMNODES];
27static unsigned int nr_huge_pages_node[MAX_NUMNODES]; 28static unsigned int nr_huge_pages_node[MAX_NUMNODES];
28static unsigned int free_huge_pages_node[MAX_NUMNODES]; 29static unsigned int free_huge_pages_node[MAX_NUMNODES];
30/*
31 * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
32 */
33static DEFINE_SPINLOCK(hugetlb_lock);
29 34
30static void clear_huge_page(struct page *page, unsigned long addr) 35static void clear_huge_page(struct page *page, unsigned long addr)
31{ 36{
@@ -50,11 +55,6 @@ static void copy_huge_page(struct page *dst, struct page *src,
50 } 55 }
51} 56}
52 57
53/*
54 * Protects updates to hugepage_freelists, nr_huge_pages, and free_huge_pages
55 */
56static DEFINE_SPINLOCK(hugetlb_lock);
57
58static void enqueue_huge_page(struct page *page) 58static void enqueue_huge_page(struct page *page)
59{ 59{
60 int nid = page_to_nid(page); 60 int nid = page_to_nid(page);
@@ -508,14 +508,24 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
508 pte_t *ptep; 508 pte_t *ptep;
509 pte_t entry; 509 pte_t entry;
510 int ret; 510 int ret;
511 static DEFINE_MUTEX(hugetlb_instantiation_mutex);
511 512
512 ptep = huge_pte_alloc(mm, address); 513 ptep = huge_pte_alloc(mm, address);
513 if (!ptep) 514 if (!ptep)
514 return VM_FAULT_OOM; 515 return VM_FAULT_OOM;
515 516
517 /*
518 * Serialize hugepage allocation and instantiation, so that we don't
519 * get spurious allocation failures if two CPUs race to instantiate
520 * the same page in the page cache.
521 */
522 mutex_lock(&hugetlb_instantiation_mutex);
516 entry = *ptep; 523 entry = *ptep;
517 if (pte_none(entry)) 524 if (pte_none(entry)) {
518 return hugetlb_no_page(mm, vma, address, ptep, write_access); 525 ret = hugetlb_no_page(mm, vma, address, ptep, write_access);
526 mutex_unlock(&hugetlb_instantiation_mutex);
527 return ret;
528 }
519 529
520 ret = VM_FAULT_MINOR; 530 ret = VM_FAULT_MINOR;
521 531
@@ -525,6 +535,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
525 if (write_access && !pte_write(entry)) 535 if (write_access && !pte_write(entry))
526 ret = hugetlb_cow(mm, vma, address, ptep, entry); 536 ret = hugetlb_cow(mm, vma, address, ptep, entry);
527 spin_unlock(&mm->page_table_lock); 537 spin_unlock(&mm->page_table_lock);
538 mutex_unlock(&hugetlb_instantiation_mutex);
528 539
529 return ret; 540 return ret;
530} 541}