diff options
-rw-r--r-- | mm/memory-failure.c | 21 | ||||
-rw-r--r-- | mm/rmap.c | 5 |
2 files changed, 8 insertions, 18 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index eac0ba561491..740c4f52059c 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -391,10 +391,11 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill, | |||
391 | struct task_struct *tsk; | 391 | struct task_struct *tsk; |
392 | struct anon_vma *av; | 392 | struct anon_vma *av; |
393 | 393 | ||
394 | read_lock(&tasklist_lock); | ||
395 | av = page_lock_anon_vma(page); | 394 | av = page_lock_anon_vma(page); |
396 | if (av == NULL) /* Not actually mapped anymore */ | 395 | if (av == NULL) /* Not actually mapped anymore */ |
397 | goto out; | 396 | return; |
397 | |||
398 | read_lock(&tasklist_lock); | ||
398 | for_each_process (tsk) { | 399 | for_each_process (tsk) { |
399 | struct anon_vma_chain *vmac; | 400 | struct anon_vma_chain *vmac; |
400 | 401 | ||
@@ -408,9 +409,8 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill, | |||
408 | add_to_kill(tsk, page, vma, to_kill, tkc); | 409 | add_to_kill(tsk, page, vma, to_kill, tkc); |
409 | } | 410 | } |
410 | } | 411 | } |
411 | page_unlock_anon_vma(av); | ||
412 | out: | ||
413 | read_unlock(&tasklist_lock); | 412 | read_unlock(&tasklist_lock); |
413 | page_unlock_anon_vma(av); | ||
414 | } | 414 | } |
415 | 415 | ||
416 | /* | 416 | /* |
@@ -424,17 +424,8 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill, | |||
424 | struct prio_tree_iter iter; | 424 | struct prio_tree_iter iter; |
425 | struct address_space *mapping = page->mapping; | 425 | struct address_space *mapping = page->mapping; |
426 | 426 | ||
427 | /* | ||
428 | * A note on the locking order between the two locks. | ||
429 | * We don't rely on this particular order. | ||
430 | * If you have some other code that needs a different order | ||
431 | * feel free to switch them around. Or add a reverse link | ||
432 | * from mm_struct to task_struct, then this could be all | ||
433 | * done without taking tasklist_lock and looping over all tasks. | ||
434 | */ | ||
435 | |||
436 | read_lock(&tasklist_lock); | ||
437 | mutex_lock(&mapping->i_mmap_mutex); | 427 | mutex_lock(&mapping->i_mmap_mutex); |
428 | read_lock(&tasklist_lock); | ||
438 | for_each_process(tsk) { | 429 | for_each_process(tsk) { |
439 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | 430 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); |
440 | 431 | ||
@@ -454,8 +445,8 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill, | |||
454 | add_to_kill(tsk, page, vma, to_kill, tkc); | 445 | add_to_kill(tsk, page, vma, to_kill, tkc); |
455 | } | 446 | } |
456 | } | 447 | } |
457 | mutex_unlock(&mapping->i_mmap_mutex); | ||
458 | read_unlock(&tasklist_lock); | 448 | read_unlock(&tasklist_lock); |
449 | mutex_unlock(&mapping->i_mmap_mutex); | ||
459 | } | 450 | } |
460 | 451 | ||
461 | /* | 452 | /* |
@@ -38,9 +38,8 @@ | |||
38 | * in arch-dependent flush_dcache_mmap_lock, | 38 | * in arch-dependent flush_dcache_mmap_lock, |
39 | * within inode_wb_list_lock in __sync_single_inode) | 39 | * within inode_wb_list_lock in __sync_single_inode) |
40 | * | 40 | * |
41 | * (code doesn't rely on that order so it could be switched around) | 41 | * anon_vma->mutex,mapping->i_mutex (memory_failure, collect_procs_anon) |
42 | * ->tasklist_lock | 42 | * ->tasklist_lock |
43 | * anon_vma->mutex (memory_failure, collect_procs_anon) | ||
44 | * pte map lock | 43 | * pte map lock |
45 | */ | 44 | */ |
46 | 45 | ||