diff options
-rw-r--r-- | include/linux/mmzone.h | 9 | ||||
-rw-r--r-- | mm/vmscan.c | 31 |
2 files changed, 34 insertions, 6 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 5c76737d836b..2aaf72f7e345 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -495,6 +495,10 @@ typedef enum { | |||
495 | ZONE_CONGESTED, /* zone has many dirty pages backed by | 495 | ZONE_CONGESTED, /* zone has many dirty pages backed by |
496 | * a congested BDI | 496 | * a congested BDI |
497 | */ | 497 | */ |
498 | ZONE_TAIL_LRU_DIRTY, /* reclaim scanning has recently found | ||
499 | * many dirty file pages at the tail | ||
500 | * of the LRU. | ||
501 | */ | ||
498 | } zone_flags_t; | 502 | } zone_flags_t; |
499 | 503 | ||
500 | static inline void zone_set_flag(struct zone *zone, zone_flags_t flag) | 504 | static inline void zone_set_flag(struct zone *zone, zone_flags_t flag) |
@@ -517,6 +521,11 @@ static inline int zone_is_reclaim_congested(const struct zone *zone) | |||
517 | return test_bit(ZONE_CONGESTED, &zone->flags); | 521 | return test_bit(ZONE_CONGESTED, &zone->flags); |
518 | } | 522 | } |
519 | 523 | ||
524 | static inline int zone_is_reclaim_dirty(const struct zone *zone) | ||
525 | { | ||
526 | return test_bit(ZONE_TAIL_LRU_DIRTY, &zone->flags); | ||
527 | } | ||
528 | |||
520 | static inline int zone_is_reclaim_locked(const struct zone *zone) | 529 | static inline int zone_is_reclaim_locked(const struct zone *zone) |
521 | { | 530 | { |
522 | return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags); | 531 | return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags); |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 1505c573719d..d6c916d808ba 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -676,13 +676,14 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
676 | struct zone *zone, | 676 | struct zone *zone, |
677 | struct scan_control *sc, | 677 | struct scan_control *sc, |
678 | enum ttu_flags ttu_flags, | 678 | enum ttu_flags ttu_flags, |
679 | unsigned long *ret_nr_dirty, | 679 | unsigned long *ret_nr_unqueued_dirty, |
680 | unsigned long *ret_nr_writeback, | 680 | unsigned long *ret_nr_writeback, |
681 | bool force_reclaim) | 681 | bool force_reclaim) |
682 | { | 682 | { |
683 | LIST_HEAD(ret_pages); | 683 | LIST_HEAD(ret_pages); |
684 | LIST_HEAD(free_pages); | 684 | LIST_HEAD(free_pages); |
685 | int pgactivate = 0; | 685 | int pgactivate = 0; |
686 | unsigned long nr_unqueued_dirty = 0; | ||
686 | unsigned long nr_dirty = 0; | 687 | unsigned long nr_dirty = 0; |
687 | unsigned long nr_congested = 0; | 688 | unsigned long nr_congested = 0; |
688 | unsigned long nr_reclaimed = 0; | 689 | unsigned long nr_reclaimed = 0; |
@@ -808,14 +809,17 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
808 | if (PageDirty(page)) { | 809 | if (PageDirty(page)) { |
809 | nr_dirty++; | 810 | nr_dirty++; |
810 | 811 | ||
812 | if (!PageWriteback(page)) | ||
813 | nr_unqueued_dirty++; | ||
814 | |||
811 | /* | 815 | /* |
812 | * Only kswapd can writeback filesystem pages to | 816 | * Only kswapd can writeback filesystem pages to |
813 | * avoid risk of stack overflow but do not writeback | 817 | * avoid risk of stack overflow but only writeback |
814 | * unless under significant pressure. | 818 | * if many dirty pages have been encountered. |
815 | */ | 819 | */ |
816 | if (page_is_file_cache(page) && | 820 | if (page_is_file_cache(page) && |
817 | (!current_is_kswapd() || | 821 | (!current_is_kswapd() || |
818 | sc->priority >= DEF_PRIORITY - 2)) { | 822 | !zone_is_reclaim_dirty(zone))) { |
819 | /* | 823 | /* |
820 | * Immediately reclaim when written back. | 824 | * Immediately reclaim when written back. |
821 | * Similar in principal to deactivate_page() | 825 | * Similar in principal to deactivate_page() |
@@ -960,7 +964,7 @@ keep: | |||
960 | list_splice(&ret_pages, page_list); | 964 | list_splice(&ret_pages, page_list); |
961 | count_vm_events(PGACTIVATE, pgactivate); | 965 | count_vm_events(PGACTIVATE, pgactivate); |
962 | mem_cgroup_uncharge_end(); | 966 | mem_cgroup_uncharge_end(); |
963 | *ret_nr_dirty += nr_dirty; | 967 | *ret_nr_unqueued_dirty += nr_unqueued_dirty; |
964 | *ret_nr_writeback += nr_writeback; | 968 | *ret_nr_writeback += nr_writeback; |
965 | return nr_reclaimed; | 969 | return nr_reclaimed; |
966 | } | 970 | } |
@@ -1373,6 +1377,15 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, | |||
1373 | (nr_taken >> (DEF_PRIORITY - sc->priority))) | 1377 | (nr_taken >> (DEF_PRIORITY - sc->priority))) |
1374 | wait_iff_congested(zone, BLK_RW_ASYNC, HZ/10); | 1378 | wait_iff_congested(zone, BLK_RW_ASYNC, HZ/10); |
1375 | 1379 | ||
1380 | /* | ||
1381 | * Similarly, if many dirty pages are encountered that are not | ||
1382 | * currently being written then flag that kswapd should start | ||
1383 | * writing back pages. | ||
1384 | */ | ||
1385 | if (global_reclaim(sc) && nr_dirty && | ||
1386 | nr_dirty >= (nr_taken >> (DEF_PRIORITY - sc->priority))) | ||
1387 | zone_set_flag(zone, ZONE_TAIL_LRU_DIRTY); | ||
1388 | |||
1376 | trace_mm_vmscan_lru_shrink_inactive(zone->zone_pgdat->node_id, | 1389 | trace_mm_vmscan_lru_shrink_inactive(zone->zone_pgdat->node_id, |
1377 | zone_idx(zone), | 1390 | zone_idx(zone), |
1378 | nr_scanned, nr_reclaimed, | 1391 | nr_scanned, nr_reclaimed, |
@@ -2769,8 +2782,12 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, | |||
2769 | end_zone = i; | 2782 | end_zone = i; |
2770 | break; | 2783 | break; |
2771 | } else { | 2784 | } else { |
2772 | /* If balanced, clear the congested flag */ | 2785 | /* |
2786 | * If balanced, clear the dirty and congested | ||
2787 | * flags | ||
2788 | */ | ||
2773 | zone_clear_flag(zone, ZONE_CONGESTED); | 2789 | zone_clear_flag(zone, ZONE_CONGESTED); |
2790 | zone_clear_flag(zone, ZONE_TAIL_LRU_DIRTY); | ||
2774 | } | 2791 | } |
2775 | } | 2792 | } |
2776 | 2793 | ||
@@ -2888,8 +2905,10 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, | |||
2888 | * possible there are dirty pages backed by | 2905 | * possible there are dirty pages backed by |
2889 | * congested BDIs but as pressure is relieved, | 2906 | * congested BDIs but as pressure is relieved, |
2890 | * speculatively avoid congestion waits | 2907 | * speculatively avoid congestion waits |
2908 | * or writing pages from kswapd context. | ||
2891 | */ | 2909 | */ |
2892 | zone_clear_flag(zone, ZONE_CONGESTED); | 2910 | zone_clear_flag(zone, ZONE_CONGESTED); |
2911 | zone_clear_flag(zone, ZONE_TAIL_LRU_DIRTY); | ||
2893 | } | 2912 | } |
2894 | 2913 | ||
2895 | /* | 2914 | /* |