diff options
| -rw-r--r-- | mm/memory-failure.c | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 729d4b15b645..e17ec3f1c637 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
| @@ -370,9 +370,6 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn) | |||
| 370 | int ret = FAILED; | 370 | int ret = FAILED; |
| 371 | struct address_space *mapping; | 371 | struct address_space *mapping; |
| 372 | 372 | ||
| 373 | if (!isolate_lru_page(p)) | ||
| 374 | page_cache_release(p); | ||
| 375 | |||
| 376 | /* | 373 | /* |
| 377 | * For anonymous pages we're done the only reference left | 374 | * For anonymous pages we're done the only reference left |
| 378 | * should be the one m_f() holds. | 375 | * should be the one m_f() holds. |
| @@ -498,30 +495,18 @@ static int me_pagecache_dirty(struct page *p, unsigned long pfn) | |||
| 498 | */ | 495 | */ |
| 499 | static int me_swapcache_dirty(struct page *p, unsigned long pfn) | 496 | static int me_swapcache_dirty(struct page *p, unsigned long pfn) |
| 500 | { | 497 | { |
| 501 | int ret = FAILED; | ||
| 502 | |||
| 503 | ClearPageDirty(p); | 498 | ClearPageDirty(p); |
| 504 | /* Trigger EIO in shmem: */ | 499 | /* Trigger EIO in shmem: */ |
| 505 | ClearPageUptodate(p); | 500 | ClearPageUptodate(p); |
| 506 | 501 | ||
| 507 | if (!isolate_lru_page(p)) { | 502 | return DELAYED; |
| 508 | page_cache_release(p); | ||
| 509 | ret = DELAYED; | ||
| 510 | } | ||
| 511 | |||
| 512 | return ret; | ||
| 513 | } | 503 | } |
| 514 | 504 | ||
| 515 | static int me_swapcache_clean(struct page *p, unsigned long pfn) | 505 | static int me_swapcache_clean(struct page *p, unsigned long pfn) |
| 516 | { | 506 | { |
| 517 | int ret = FAILED; | ||
| 518 | |||
| 519 | if (!isolate_lru_page(p)) { | ||
| 520 | page_cache_release(p); | ||
| 521 | ret = RECOVERED; | ||
| 522 | } | ||
| 523 | delete_from_swap_cache(p); | 507 | delete_from_swap_cache(p); |
| 524 | return ret; | 508 | |
| 509 | return RECOVERED; | ||
| 525 | } | 510 | } |
| 526 | 511 | ||
| 527 | /* | 512 | /* |
| @@ -611,8 +596,6 @@ static struct page_state { | |||
| 611 | { 0, 0, "unknown page state", me_unknown }, | 596 | { 0, 0, "unknown page state", me_unknown }, |
| 612 | }; | 597 | }; |
| 613 | 598 | ||
| 614 | #undef lru | ||
| 615 | |||
| 616 | static void action_result(unsigned long pfn, char *msg, int result) | 599 | static void action_result(unsigned long pfn, char *msg, int result) |
| 617 | { | 600 | { |
| 618 | struct page *page = NULL; | 601 | struct page *page = NULL; |
| @@ -664,9 +647,6 @@ static void hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 664 | if (PageReserved(p) || PageCompound(p) || PageSlab(p)) | 647 | if (PageReserved(p) || PageCompound(p) || PageSlab(p)) |
| 665 | return; | 648 | return; |
| 666 | 649 | ||
| 667 | if (!PageLRU(p)) | ||
| 668 | lru_add_drain_all(); | ||
| 669 | |||
| 670 | /* | 650 | /* |
| 671 | * This check implies we don't kill processes if their pages | 651 | * This check implies we don't kill processes if their pages |
| 672 | * are in the swap cache early. Those are always late kills. | 652 | * are in the swap cache early. Those are always late kills. |
| @@ -738,6 +718,7 @@ static void hwpoison_user_mappings(struct page *p, unsigned long pfn, | |||
| 738 | 718 | ||
| 739 | int __memory_failure(unsigned long pfn, int trapno, int ref) | 719 | int __memory_failure(unsigned long pfn, int trapno, int ref) |
| 740 | { | 720 | { |
| 721 | unsigned long lru_flag; | ||
| 741 | struct page_state *ps; | 722 | struct page_state *ps; |
| 742 | struct page *p; | 723 | struct page *p; |
| 743 | int res; | 724 | int res; |
| @@ -775,6 +756,24 @@ int __memory_failure(unsigned long pfn, int trapno, int ref) | |||
| 775 | } | 756 | } |
| 776 | 757 | ||
| 777 | /* | 758 | /* |
| 759 | * We ignore non-LRU pages for good reasons. | ||
| 760 | * - PG_locked is only well defined for LRU pages and a few others | ||
| 761 | * - to avoid races with __set_page_locked() | ||
| 762 | * - to avoid races with __SetPageSlab*() (and more non-atomic ops) | ||
| 763 | * The check (unnecessarily) ignores LRU pages being isolated and | ||
| 764 | * walked by the page reclaim code, however that's not a big loss. | ||
| 765 | */ | ||
| 766 | if (!PageLRU(p)) | ||
| 767 | lru_add_drain_all(); | ||
| 768 | lru_flag = p->flags & lru; | ||
| 769 | if (isolate_lru_page(p)) { | ||
| 770 | action_result(pfn, "non LRU", IGNORED); | ||
| 771 | put_page(p); | ||
| 772 | return -EBUSY; | ||
| 773 | } | ||
| 774 | page_cache_release(p); | ||
| 775 | |||
| 776 | /* | ||
| 778 | * Lock the page and wait for writeback to finish. | 777 | * Lock the page and wait for writeback to finish. |
| 779 | * It's very difficult to mess with pages currently under IO | 778 | * It's very difficult to mess with pages currently under IO |
| 780 | * and in many cases impossible, so we just avoid it here. | 779 | * and in many cases impossible, so we just avoid it here. |
| @@ -790,7 +789,7 @@ int __memory_failure(unsigned long pfn, int trapno, int ref) | |||
| 790 | /* | 789 | /* |
| 791 | * Torn down by someone else? | 790 | * Torn down by someone else? |
| 792 | */ | 791 | */ |
| 793 | if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) { | 792 | if ((lru_flag & lru) && !PageSwapCache(p) && p->mapping == NULL) { |
| 794 | action_result(pfn, "already truncated LRU", IGNORED); | 793 | action_result(pfn, "already truncated LRU", IGNORED); |
| 795 | res = 0; | 794 | res = 0; |
| 796 | goto out; | 795 | goto out; |
| @@ -798,7 +797,7 @@ int __memory_failure(unsigned long pfn, int trapno, int ref) | |||
| 798 | 797 | ||
| 799 | res = -EBUSY; | 798 | res = -EBUSY; |
| 800 | for (ps = error_states;; ps++) { | 799 | for (ps = error_states;; ps++) { |
| 801 | if ((p->flags & ps->mask) == ps->res) { | 800 | if (((p->flags | lru_flag)& ps->mask) == ps->res) { |
| 802 | res = page_action(ps, p, pfn, ref); | 801 | res = page_action(ps, p, pfn, ref); |
| 803 | break; | 802 | break; |
| 804 | } | 803 | } |
