diff options
Diffstat (limited to 'mm/vmscan.c')
| -rw-r--r-- | mm/vmscan.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 0ea71e887bb6..64f9570cff56 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -511,10 +511,11 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) | |||
| 511 | * PageDirty _after_ making sure that the page is freeable and | 511 | * PageDirty _after_ making sure that the page is freeable and |
| 512 | * not in use by anybody. (pagecache + us == 2) | 512 | * not in use by anybody. (pagecache + us == 2) |
| 513 | */ | 513 | */ |
| 514 | if (page_count(page) != 2 || PageDirty(page)) { | 514 | if (unlikely(page_count(page) != 2)) |
| 515 | write_unlock_irq(&mapping->tree_lock); | 515 | goto cannot_free; |
| 516 | goto keep_locked; | 516 | smp_rmb(); |
| 517 | } | 517 | if (unlikely(PageDirty(page))) |
| 518 | goto cannot_free; | ||
| 518 | 519 | ||
| 519 | #ifdef CONFIG_SWAP | 520 | #ifdef CONFIG_SWAP |
| 520 | if (PageSwapCache(page)) { | 521 | if (PageSwapCache(page)) { |
| @@ -538,6 +539,10 @@ free_it: | |||
| 538 | __pagevec_release_nonlru(&freed_pvec); | 539 | __pagevec_release_nonlru(&freed_pvec); |
| 539 | continue; | 540 | continue; |
| 540 | 541 | ||
| 542 | cannot_free: | ||
| 543 | write_unlock_irq(&mapping->tree_lock); | ||
| 544 | goto keep_locked; | ||
| 545 | |||
| 541 | activate_locked: | 546 | activate_locked: |
| 542 | SetPageActive(page); | 547 | SetPageActive(page); |
| 543 | pgactivate++; | 548 | pgactivate++; |
