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 | |
| 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>
| -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 | ||
