diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2007-08-31 02:56:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-08-31 04:42:22 -0400 |
commit | 989f89c57e6361e7d16fbd9572b5da7d313b073d (patch) | |
tree | cd5f655709e1515568c1e1f309f169723ce3b084 /mm/migrate.c | |
parent | d1254b12c93e1e586137a2ffef71fd33cf273f35 (diff) |
fix rcu_read_lock() in page migraton
In migration fallback path, write_page() or lock_page() will be called.
This causes sleep with holding rcu_read_lock().
For avoding that, just do rcu_lock if the page is Anon.(this is enough.)
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Acked-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index 37c73b902008..e2fdbce1874b 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -611,6 +611,7 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
611 | int rc = 0; | 611 | int rc = 0; |
612 | int *result = NULL; | 612 | int *result = NULL; |
613 | struct page *newpage = get_new_page(page, private, &result); | 613 | struct page *newpage = get_new_page(page, private, &result); |
614 | int rcu_locked = 0; | ||
614 | 615 | ||
615 | if (!newpage) | 616 | if (!newpage) |
616 | return -ENOMEM; | 617 | return -ENOMEM; |
@@ -636,8 +637,13 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
636 | * we cannot notice that anon_vma is freed while we migrates a page. | 637 | * we cannot notice that anon_vma is freed while we migrates a page. |
637 | * This rcu_read_lock() delays freeing anon_vma pointer until the end | 638 | * This rcu_read_lock() delays freeing anon_vma pointer until the end |
638 | * of migration. File cache pages are no problem because of page_lock() | 639 | * of migration. File cache pages are no problem because of page_lock() |
640 | * File Caches may use write_page() or lock_page() in migration, then, | ||
641 | * just care Anon page here. | ||
639 | */ | 642 | */ |
640 | rcu_read_lock(); | 643 | if (PageAnon(page)) { |
644 | rcu_read_lock(); | ||
645 | rcu_locked = 1; | ||
646 | } | ||
641 | /* | 647 | /* |
642 | * This is a corner case handling. | 648 | * This is a corner case handling. |
643 | * When a new swap-cache is read into, it is linked to LRU | 649 | * When a new swap-cache is read into, it is linked to LRU |
@@ -656,7 +662,8 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
656 | if (rc) | 662 | if (rc) |
657 | remove_migration_ptes(page, page); | 663 | remove_migration_ptes(page, page); |
658 | rcu_unlock: | 664 | rcu_unlock: |
659 | rcu_read_unlock(); | 665 | if (rcu_locked) |
666 | rcu_read_unlock(); | ||
660 | 667 | ||
661 | unlock: | 668 | unlock: |
662 | 669 | ||