hugetlb: fix lack of radix tree locking
This adds a spinlock to each individual key, initializes it and the atomic counter, and uses it when manipulating the radix tree. As pointed out by akpm.
hugetlbpage.c | 8 ++++++++ 1 files changed, 8 insertions(+)
arch/i386/mm/hugetlbpage.c +8 -0
@@ -32,6 +32,7 @@ static spinlock_t htlbpage_lock = SPIN_Lstruct hugetlb_key {struct radix_tree_root tree;atomic_t count; +spinlock_t lock;int key;int busy;uid_t uid;
@@ -392,6 +393,7 @@ static int prefault_key(struct hugetlb_kBUG_ON (vma->vm_end & ~HPAGE_MASK );spin_lock (&mm->page_table_lock); +spin_lock (&key->lock);for (addr = vma->vm_start; addr < vma->vm_end; addr +=HPAGE_SIZE ) {unsigned long idx;pte_t *pte =huge_pte_alloc (mm, addr);
@@ -410,6 +412,7 @@ static int prefault_key(struct hugetlb_kif (!page) { page =alloc_hugetlb_page ();if (!page) { +spin_unlock (&key->lock); ret = -ENOMEM ; goto out; }
@@ -418,6 +421,7 @@ static int prefault_key(struct hugetlb_k }set_huge_pte (mm, vma, page, pte, vma->vm_flags &VM_WRITE ); } +spin_unlock (&key->lock); out:spin_unlock (&mm->page_table_lock);return ret;
@@ -625,6 +629,10 @@ static int __init hugetlb_init(void) } htlbpage_max = htlbpagemem = htlbzone_pages = i;printk ("Total HugeTLB memory allocated, %ld\n" , htlbpagemem); +for (i =0 ; i <MAX_ID ; ++i) { +atomic_init (&htlbpagek[i].count); +spinlock_init (&htlbpagek[i].lock); + }return 0 ; }module_init (hugetlb_init);
Review
Quoted 4 lines · William Lee Irwin III
(quoted diff) +4
-0+ for (i = 0; i < MAX_ID; ++i) { + atomic_init(&htlbpagek[i].count); + spinlock_init(&htlbpagek[i].lock); + }
erm, wtf?
This adds a spinlock to each individual key, initializes it and the atomic counter, and uses it when manipulating the radix tree.
hugetlbpage.c | 8 ++++++++ 1 files changed, 8 insertions(+)
arch/i386/mm/hugetlbpage.c +8 -0
@@ -32,6 +32,7 @@ static spinlock_t htlbpage_lock = SPIN_Lstruct hugetlb_key {struct radix_tree_root tree;atomic_t count; +spinlock_t lock;int key;int busy;uid_t uid;
@@ -392,6 +393,7 @@ static int prefault_key(struct hugetlb_kBUG_ON (vma->vm_end & ~HPAGE_MASK );spin_lock (&mm->page_table_lock); +spin_lock (&key->lock);for (addr = vma->vm_start; addr < vma->vm_end; addr +=HPAGE_SIZE ) {unsigned long idx;pte_t *pte =huge_pte_alloc (mm, addr);
@@ -410,6 +412,7 @@ static int prefault_key(struct hugetlb_kif (!page) { page =alloc_hugetlb_page ();if (!page) { +spin_unlock (&key->lock); ret = -ENOMEM ; goto out; }
@@ -418,6 +421,7 @@ static int prefault_key(struct hugetlb_k }set_huge_pte (mm, vma, page, pte, vma->vm_flags &VM_WRITE ); } +spin_unlock (&key->lock); out:spin_unlock (&mm->page_table_lock);return ret;
@@ -625,6 +629,10 @@ static int __init hugetlb_init(void) } htlbpage_max = htlbpagemem = htlbzone_pages = i;printk ("Total HugeTLB memory allocated, %ld\n" , htlbpagemem); +for (i =0 ; i <MAX_ID ; ++i) { +atomic_set (&htlbpagek[i].count,0 ); +spin_lock_init (&htlbpagek[i].lock); + }return 0 ; }module_init (hugetlb_init);