diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/vmscan.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index ca43aa00ea0e..e37e68725090 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -723,23 +723,38 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
723 | /* | 723 | /* |
724 | * memcg doesn't have any dirty pages throttling so we | 724 | * memcg doesn't have any dirty pages throttling so we |
725 | * could easily OOM just because too many pages are in | 725 | * could easily OOM just because too many pages are in |
726 | * writeback from reclaim and there is nothing else to | 726 | * writeback and there is nothing else to reclaim. |
727 | * reclaim. | ||
728 | * | 727 | * |
729 | * Check may_enter_fs, certainly because a loop driver | 728 | * Check __GFP_IO, certainly because a loop driver |
730 | * thread might enter reclaim, and deadlock if it waits | 729 | * thread might enter reclaim, and deadlock if it waits |
731 | * on a page for which it is needed to do the write | 730 | * on a page for which it is needed to do the write |
732 | * (loop masks off __GFP_IO|__GFP_FS for this reason); | 731 | * (loop masks off __GFP_IO|__GFP_FS for this reason); |
733 | * but more thought would probably show more reasons. | 732 | * but more thought would probably show more reasons. |
733 | * | ||
734 | * Don't require __GFP_FS, since we're not going into | ||
735 | * the FS, just waiting on its writeback completion. | ||
736 | * Worryingly, ext4 gfs2 and xfs allocate pages with | ||
737 | * grab_cache_page_write_begin(,,AOP_FLAG_NOFS), so | ||
738 | * testing may_enter_fs here is liable to OOM on them. | ||
734 | */ | 739 | */ |
735 | if (!global_reclaim(sc) && PageReclaim(page) && | 740 | if (global_reclaim(sc) || |
736 | may_enter_fs) | 741 | !PageReclaim(page) || !(sc->gfp_mask & __GFP_IO)) { |
737 | wait_on_page_writeback(page); | 742 | /* |
738 | else { | 743 | * This is slightly racy - end_page_writeback() |
744 | * might have just cleared PageReclaim, then | ||
745 | * setting PageReclaim here end up interpreted | ||
746 | * as PageReadahead - but that does not matter | ||
747 | * enough to care. What we do want is for this | ||
748 | * page to have PageReclaim set next time memcg | ||
749 | * reclaim reaches the tests above, so it will | ||
750 | * then wait_on_page_writeback() to avoid OOM; | ||
751 | * and it's also appropriate in global reclaim. | ||
752 | */ | ||
753 | SetPageReclaim(page); | ||
739 | nr_writeback++; | 754 | nr_writeback++; |
740 | unlock_page(page); | 755 | goto keep_locked; |
741 | goto keep; | ||
742 | } | 756 | } |
757 | wait_on_page_writeback(page); | ||
743 | } | 758 | } |
744 | 759 | ||
745 | references = page_check_references(page, sc); | 760 | references = page_check_references(page, sc); |