forked from mirrors/linux
		
	mm: convert anon_vma->lock to a mutex
Straightforward conversion of anon_vma->lock to a mutex. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Hugh Dickins <hughd@google.com> Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: David Miller <davem@davemloft.net> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Jeff Dike <jdike@addtoit.com> Cc: Richard Weinberger <richard@nod.at> Cc: Tony Luck <tony.luck@intel.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Nick Piggin <npiggin@kernel.dk> Cc: Namhyung Kim <namhyung@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									746b18d421
								
							
						
					
					
						commit
						2b575eb64f
					
				
					 6 changed files with 21 additions and 25 deletions
				
			
		|  | @ -92,12 +92,8 @@ extern void __split_huge_page_pmd(struct mm_struct *mm, pmd_t *pmd); | ||||||
| #define wait_split_huge_page(__anon_vma, __pmd)				\ | #define wait_split_huge_page(__anon_vma, __pmd)				\ | ||||||
| 	do {								\ | 	do {								\ | ||||||
| 		pmd_t *____pmd = (__pmd);				\ | 		pmd_t *____pmd = (__pmd);				\ | ||||||
| 		spin_unlock_wait(&(__anon_vma)->root->lock);		\ | 		anon_vma_lock(__anon_vma);				\ | ||||||
| 		/*							\
 | 		anon_vma_unlock(__anon_vma);				\ | ||||||
| 		 * spin_unlock_wait() is just a loop in C and so the	\ |  | ||||||
| 		 * CPU can reorder anything around it.			\ |  | ||||||
| 		 */							\ |  | ||||||
| 		smp_mb();						\ |  | ||||||
| 		BUG_ON(pmd_trans_splitting(*____pmd) ||			\ | 		BUG_ON(pmd_trans_splitting(*____pmd) ||			\ | ||||||
| 		       pmd_trans_huge(*____pmd));			\ | 		       pmd_trans_huge(*____pmd));			\ | ||||||
| 	} while (0) | 	} while (0) | ||||||
|  |  | ||||||
|  | @ -150,7 +150,7 @@ struct mmu_notifier_ops { | ||||||
|  * Therefore notifier chains can only be traversed when either |  * Therefore notifier chains can only be traversed when either | ||||||
|  * |  * | ||||||
|  * 1. mmap_sem is held. |  * 1. mmap_sem is held. | ||||||
|  * 2. One of the reverse map locks is held (i_mmap_mutex or anon_vma->lock). |  * 2. One of the reverse map locks is held (i_mmap_mutex or anon_vma->mutex). | ||||||
|  * 3. No other concurrent thread can access the list (release) |  * 3. No other concurrent thread can access the list (release) | ||||||
|  */ |  */ | ||||||
| struct mmu_notifier { | struct mmu_notifier { | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include <linux/list.h> | #include <linux/list.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| #include <linux/mm.h> | #include <linux/mm.h> | ||||||
| #include <linux/spinlock.h> | #include <linux/mutex.h> | ||||||
| #include <linux/memcontrol.h> | #include <linux/memcontrol.h> | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -26,7 +26,7 @@ | ||||||
|  */ |  */ | ||||||
| struct anon_vma { | struct anon_vma { | ||||||
| 	struct anon_vma *root;	/* Root of this anon_vma tree */ | 	struct anon_vma *root;	/* Root of this anon_vma tree */ | ||||||
| 	spinlock_t lock;	/* Serialize access to vma list */ | 	struct mutex mutex;	/* Serialize access to vma list */ | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * The refcount is taken on an anon_vma when there is no | 	 * The refcount is taken on an anon_vma when there is no | ||||||
| 	 * guarantee that the vma of page tables will exist for | 	 * guarantee that the vma of page tables will exist for | ||||||
|  | @ -64,7 +64,7 @@ struct anon_vma_chain { | ||||||
| 	struct vm_area_struct *vma; | 	struct vm_area_struct *vma; | ||||||
| 	struct anon_vma *anon_vma; | 	struct anon_vma *anon_vma; | ||||||
| 	struct list_head same_vma;   /* locked by mmap_sem & page_table_lock */ | 	struct list_head same_vma;   /* locked by mmap_sem & page_table_lock */ | ||||||
| 	struct list_head same_anon_vma;	/* locked by anon_vma->lock */ | 	struct list_head same_anon_vma;	/* locked by anon_vma->mutex */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_MMU | #ifdef CONFIG_MMU | ||||||
|  | @ -93,24 +93,24 @@ static inline void vma_lock_anon_vma(struct vm_area_struct *vma) | ||||||
| { | { | ||||||
| 	struct anon_vma *anon_vma = vma->anon_vma; | 	struct anon_vma *anon_vma = vma->anon_vma; | ||||||
| 	if (anon_vma) | 	if (anon_vma) | ||||||
| 		spin_lock(&anon_vma->root->lock); | 		mutex_lock(&anon_vma->root->mutex); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void vma_unlock_anon_vma(struct vm_area_struct *vma) | static inline void vma_unlock_anon_vma(struct vm_area_struct *vma) | ||||||
| { | { | ||||||
| 	struct anon_vma *anon_vma = vma->anon_vma; | 	struct anon_vma *anon_vma = vma->anon_vma; | ||||||
| 	if (anon_vma) | 	if (anon_vma) | ||||||
| 		spin_unlock(&anon_vma->root->lock); | 		mutex_unlock(&anon_vma->root->mutex); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void anon_vma_lock(struct anon_vma *anon_vma) | static inline void anon_vma_lock(struct anon_vma *anon_vma) | ||||||
| { | { | ||||||
| 	spin_lock(&anon_vma->root->lock); | 	mutex_lock(&anon_vma->root->mutex); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void anon_vma_unlock(struct anon_vma *anon_vma) | static inline void anon_vma_unlock(struct anon_vma *anon_vma) | ||||||
| { | { | ||||||
| 	spin_unlock(&anon_vma->root->lock); | 	mutex_unlock(&anon_vma->root->mutex); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
|  | @ -1139,7 +1139,7 @@ static int __split_huge_page_splitting(struct page *page, | ||||||
| 		 * We can't temporarily set the pmd to null in order | 		 * We can't temporarily set the pmd to null in order | ||||||
| 		 * to split it, the pmd must remain marked huge at all | 		 * to split it, the pmd must remain marked huge at all | ||||||
| 		 * times or the VM won't take the pmd_trans_huge paths | 		 * times or the VM won't take the pmd_trans_huge paths | ||||||
| 		 * and it won't wait on the anon_vma->root->lock to | 		 * and it won't wait on the anon_vma->root->mutex to | ||||||
| 		 * serialize against split_huge_page*. | 		 * serialize against split_huge_page*. | ||||||
| 		 */ | 		 */ | ||||||
| 		pmdp_splitting_flush_notify(vma, address, pmd); | 		pmdp_splitting_flush_notify(vma, address, pmd); | ||||||
|  | @ -1333,7 +1333,7 @@ static int __split_huge_page_map(struct page *page, | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* must be called with anon_vma->root->lock hold */ | /* must be called with anon_vma->root->mutex hold */ | ||||||
| static void __split_huge_page(struct page *page, | static void __split_huge_page(struct page *page, | ||||||
| 			      struct anon_vma *anon_vma) | 			      struct anon_vma *anon_vma) | ||||||
| { | { | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								mm/mmap.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								mm/mmap.c
									
									
									
									
									
								
							|  | @ -2502,15 +2502,15 @@ 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 | 		 * The LSB of head.next can't change from under us | ||||||
| 		 * because we hold the mm_all_locks_mutex. | 		 * because we hold the mm_all_locks_mutex. | ||||||
| 		 */ | 		 */ | ||||||
| 		spin_lock_nest_lock(&anon_vma->root->lock, &mm->mmap_sem); | 		mutex_lock_nest_lock(&anon_vma->root->mutex, &mm->mmap_sem); | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * We can safely modify head.next after taking the | 		 * We can safely modify head.next after taking the | ||||||
| 		 * anon_vma->root->lock. If some other vma in this mm shares | 		 * anon_vma->root->mutex. If some other vma in this mm shares | ||||||
| 		 * the same anon_vma we won't take it again. | 		 * the same anon_vma we won't take it again. | ||||||
| 		 * | 		 * | ||||||
| 		 * No need of atomic instructions here, head.next | 		 * No need of atomic instructions here, head.next | ||||||
| 		 * can't change from under us thanks to the | 		 * can't change from under us thanks to the | ||||||
| 		 * anon_vma->root->lock. | 		 * anon_vma->root->mutex. | ||||||
| 		 */ | 		 */ | ||||||
| 		if (__test_and_set_bit(0, (unsigned long *) | 		if (__test_and_set_bit(0, (unsigned long *) | ||||||
| 				       &anon_vma->root->head.next)) | 				       &anon_vma->root->head.next)) | ||||||
|  | @ -2559,7 +2559,7 @@ static void vm_lock_mapping(struct mm_struct *mm, struct address_space *mapping) | ||||||
|  * vma in this mm is backed by the same anon_vma or address_space. |  * vma in this mm is backed by the same anon_vma or address_space. | ||||||
|  * |  * | ||||||
|  * We can take all the locks in random order because the VM code |  * We can take all the locks in random order because the VM code | ||||||
|  * taking i_mmap_mutex or anon_vma->lock outside the mmap_sem never |  * taking i_mmap_mutex or anon_vma->mutex outside the mmap_sem never | ||||||
|  * takes more than one of them in a row. Secondly we're protected |  * takes more than one of them in a row. Secondly we're protected | ||||||
|  * against a concurrent mm_take_all_locks() by the mm_all_locks_mutex. |  * against a concurrent mm_take_all_locks() by the mm_all_locks_mutex. | ||||||
|  * |  * | ||||||
|  | @ -2615,7 +2615,7 @@ static void vm_unlock_anon_vma(struct anon_vma *anon_vma) | ||||||
| 		 * | 		 * | ||||||
| 		 * No need of atomic instructions here, head.next | 		 * No need of atomic instructions here, head.next | ||||||
| 		 * can't change from under us until we release the | 		 * can't change from under us until we release the | ||||||
| 		 * anon_vma->root->lock. | 		 * anon_vma->root->mutex. | ||||||
| 		 */ | 		 */ | ||||||
| 		if (!__test_and_clear_bit(0, (unsigned long *) | 		if (!__test_and_clear_bit(0, (unsigned long *) | ||||||
| 					  &anon_vma->root->head.next)) | 					  &anon_vma->root->head.next)) | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ | ||||||
|  *   mm->mmap_sem |  *   mm->mmap_sem | ||||||
|  *     page->flags PG_locked (lock_page) |  *     page->flags PG_locked (lock_page) | ||||||
|  *       mapping->i_mmap_mutex |  *       mapping->i_mmap_mutex | ||||||
|  *         anon_vma->lock |  *         anon_vma->mutex | ||||||
|  *           mm->page_table_lock or pte_lock |  *           mm->page_table_lock or pte_lock | ||||||
|  *             zone->lru_lock (in mark_page_accessed, isolate_lru_page) |  *             zone->lru_lock (in mark_page_accessed, isolate_lru_page) | ||||||
|  *             swap_lock (in swap_duplicate, swap_info_get) |  *             swap_lock (in swap_duplicate, swap_info_get) | ||||||
|  | @ -40,7 +40,7 @@ | ||||||
|  * |  * | ||||||
|  * (code doesn't rely on that order so it could be switched around) |  * (code doesn't rely on that order so it could be switched around) | ||||||
|  * ->tasklist_lock |  * ->tasklist_lock | ||||||
|  *   anon_vma->lock      (memory_failure, collect_procs_anon) |  *   anon_vma->mutex      (memory_failure, collect_procs_anon) | ||||||
|  *     pte map lock |  *     pte map lock | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | @ -307,7 +307,7 @@ static void anon_vma_ctor(void *data) | ||||||
| { | { | ||||||
| 	struct anon_vma *anon_vma = data; | 	struct anon_vma *anon_vma = data; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_init(&anon_vma->lock); | 	mutex_init(&anon_vma->mutex); | ||||||
| 	atomic_set(&anon_vma->refcount, 0); | 	atomic_set(&anon_vma->refcount, 0); | ||||||
| 	INIT_LIST_HEAD(&anon_vma->head); | 	INIT_LIST_HEAD(&anon_vma->head); | ||||||
| } | } | ||||||
|  | @ -1143,7 +1143,7 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * We need mmap_sem locking, Otherwise VM_LOCKED check makes | 	 * We need mmap_sem locking, Otherwise VM_LOCKED check makes | ||||||
| 	 * unstable result and race. Plus, We can't wait here because | 	 * unstable result and race. Plus, We can't wait here because | ||||||
| 	 * we now hold anon_vma->lock or mapping->i_mmap_mutex. | 	 * we now hold anon_vma->mutex or mapping->i_mmap_mutex. | ||||||
| 	 * if trylock failed, the page remain in evictable lru and later | 	 * if trylock failed, the page remain in evictable lru and later | ||||||
| 	 * vmscan could retry to move the page to unevictable lru if the | 	 * vmscan could retry to move the page to unevictable lru if the | ||||||
| 	 * page is actually mlocked. | 	 * page is actually mlocked. | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Peter Zijlstra
						Peter Zijlstra