diff --git a/include/linux/rmap.h b/include/linux/rmap.h index cb0ba70..6b32ecf 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -25,7 +25,7 @@ * pointing to this anon_vma once its vma list is empty. */ struct anon_vma { - spinlock_t lock; /* Serialize access to vma list */ + rwlock_t lock; /* Serialize access to vma list */ /* * NOTE: the LSB of the head.next is set by * mm_take_all_locks() _after_ taking the above lock. So the @@ -43,14 +43,14 @@ static inline void anon_vma_lock(struct vm_area_struct *vma) { struct anon_vma *anon_vma = vma->anon_vma; if (anon_vma) - spin_lock(&anon_vma->lock); + write_lock(&anon_vma->lock); } static inline void anon_vma_unlock(struct vm_area_struct *vma) { struct anon_vma *anon_vma = vma->anon_vma; if (anon_vma) - spin_unlock(&anon_vma->lock); + write_unlock(&anon_vma->lock); } /* diff --git a/mm/migrate.c b/mm/migrate.c index 7dbcb22..3f0305b 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -183,12 +183,12 @@ static void remove_anon_migration_ptes(struct page *old, struct page *new) * We hold the mmap_sem lock. So no need to call page_lock_anon_vma. */ anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); - spin_lock(&anon_vma->lock); + write_lock(&anon_vma->lock); list_for_each_entry(vma, &anon_vma->head, anon_vma_node) remove_migration_pte(vma, old, new); - spin_unlock(&anon_vma->lock); + write_unlock(&anon_vma->lock); } /* diff --git a/mm/mmap.c b/mm/mmap.c index 814b95f..42324cb 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -592,7 +592,7 @@ again: remove_next = 1 + (end > next->vm_end); if (vma->anon_vma && (insert || importer || start != vma->vm_start)) anon_vma = vma->anon_vma; if (anon_vma) { - spin_lock(&anon_vma->lock); + write_lock(&anon_vma->lock); /* * Easily overlooked: when mprotect shifts the boundary, * make sure the expanding vma has anon_vma set if the @@ -646,7 +646,7 @@ again: remove_next = 1 + (end > next->vm_end); } if (anon_vma) - spin_unlock(&anon_vma->lock); + write_unlock(&anon_vma->lock); if (mapping) spin_unlock(&mapping->i_mmap_lock); @@ -2442,7 +2442,7 @@ static void vm_lock_anon_vma(struct mm_struct *mm, struct anon_vma *anon_vma) * The LSB of head.next can't change from under us * because we hold the mm_all_locks_mutex. */ - spin_lock_nest_lock(&anon_vma->lock, &mm->mmap_sem); + write_lock(&anon_vma->lock); /* * We can safely modify head.next after taking the * anon_vma->lock. If some other vma in this mm shares @@ -2558,7 +2558,7 @@ static void vm_unlock_anon_vma(struct anon_vma *anon_vma) if (!__test_and_clear_bit(0, (unsigned long *) &anon_vma->head.next)) BUG(); - spin_unlock(&anon_vma->lock); + write_unlock(&anon_vma->lock); } } diff --git a/mm/rmap.c b/mm/rmap.c index dd43373..abddf95 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -116,7 +116,7 @@ int anon_vma_prepare(struct vm_area_struct *vma) return -ENOMEM; allocated = anon_vma; } - spin_lock(&anon_vma->lock); + write_lock(&anon_vma->lock); /* page_table_lock to protect against threads */ spin_lock(&mm->page_table_lock); @@ -127,7 +127,7 @@ int anon_vma_prepare(struct vm_area_struct *vma) } spin_unlock(&mm->page_table_lock); - spin_unlock(&anon_vma->lock); + write_unlock(&anon_vma->lock); if (unlikely(allocated)) anon_vma_free(allocated); } @@ -153,9 +153,9 @@ void anon_vma_link(struct vm_area_struct *vma) struct anon_vma *anon_vma = vma->anon_vma; if (anon_vma) { - spin_lock(&anon_vma->lock); + write_lock(&anon_vma->lock); list_add_tail(&vma->anon_vma_node, &anon_vma->head); - spin_unlock(&anon_vma->lock); + write_unlock(&anon_vma->lock); } } @@ -167,12 +167,12 @@ void anon_vma_unlink(struct vm_area_struct *vma) if (!anon_vma) return; - spin_lock(&anon_vma->lock); + write_lock(&anon_vma->lock); list_del(&vma->anon_vma_node); /* We must garbage collect the anon_vma if it's empty */ empty = list_empty(&anon_vma->head); - spin_unlock(&anon_vma->lock); + write_unlock(&anon_vma->lock); if (empty) anon_vma_free(anon_vma); @@ -182,7 +182,7 @@ static void anon_vma_ctor(void *data) { struct anon_vma *anon_vma = data; - spin_lock_init(&anon_vma->lock); + rwlock_init(&anon_vma->lock); INIT_LIST_HEAD(&anon_vma->head); } @@ -209,7 +209,7 @@ struct anon_vma *page_lock_anon_vma(struct page *page) goto out; anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON); - spin_lock(&anon_vma->lock); + read_lock(&anon_vma->lock); return anon_vma; out: rcu_read_unlock(); @@ -218,7 +218,7 @@ out: void page_unlock_anon_vma(struct anon_vma *anon_vma) { - spin_unlock(&anon_vma->lock); + read_unlock(&anon_vma->lock); rcu_read_unlock(); }