diff options
Diffstat (limited to 'mm/memory-failure.c')
-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 | } |