diff options
Diffstat (limited to 'mm/vmscan.c')
| -rw-r--r-- | mm/vmscan.c | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index c391c320dbaf..c5dfabf25f11 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -1804,12 +1804,11 @@ static void shrink_zone(int priority, struct zone *zone, | |||
| 1804 | * If a zone is deemed to be full of pinned pages then just give it a light | 1804 | * If a zone is deemed to be full of pinned pages then just give it a light |
| 1805 | * scan then give up on it. | 1805 | * scan then give up on it. |
| 1806 | */ | 1806 | */ |
| 1807 | static bool shrink_zones(int priority, struct zonelist *zonelist, | 1807 | static void shrink_zones(int priority, struct zonelist *zonelist, |
| 1808 | struct scan_control *sc) | 1808 | struct scan_control *sc) |
| 1809 | { | 1809 | { |
| 1810 | struct zoneref *z; | 1810 | struct zoneref *z; |
| 1811 | struct zone *zone; | 1811 | struct zone *zone; |
| 1812 | bool all_unreclaimable = true; | ||
| 1813 | 1812 | ||
| 1814 | for_each_zone_zonelist_nodemask(zone, z, zonelist, | 1813 | for_each_zone_zonelist_nodemask(zone, z, zonelist, |
| 1815 | gfp_zone(sc->gfp_mask), sc->nodemask) { | 1814 | gfp_zone(sc->gfp_mask), sc->nodemask) { |
| @@ -1827,8 +1826,38 @@ static bool shrink_zones(int priority, struct zonelist *zonelist, | |||
| 1827 | } | 1826 | } |
| 1828 | 1827 | ||
| 1829 | shrink_zone(priority, zone, sc); | 1828 | shrink_zone(priority, zone, sc); |
| 1830 | all_unreclaimable = false; | ||
| 1831 | } | 1829 | } |
| 1830 | } | ||
| 1831 | |||
| 1832 | static bool zone_reclaimable(struct zone *zone) | ||
| 1833 | { | ||
| 1834 | return zone->pages_scanned < zone_reclaimable_pages(zone) * 6; | ||
| 1835 | } | ||
| 1836 | |||
| 1837 | /* | ||
| 1838 | * As hibernation is going on, kswapd is freezed so that it can't mark | ||
| 1839 | * the zone into all_unreclaimable. It can't handle OOM during hibernation. | ||
| 1840 | * So let's check zone's unreclaimable in direct reclaim as well as kswapd. | ||
| 1841 | */ | ||
| 1842 | static bool all_unreclaimable(struct zonelist *zonelist, | ||
| 1843 | struct scan_control *sc) | ||
| 1844 | { | ||
| 1845 | struct zoneref *z; | ||
| 1846 | struct zone *zone; | ||
| 1847 | bool all_unreclaimable = true; | ||
| 1848 | |||
| 1849 | for_each_zone_zonelist_nodemask(zone, z, zonelist, | ||
| 1850 | gfp_zone(sc->gfp_mask), sc->nodemask) { | ||
| 1851 | if (!populated_zone(zone)) | ||
| 1852 | continue; | ||
| 1853 | if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL)) | ||
| 1854 | continue; | ||
| 1855 | if (zone_reclaimable(zone)) { | ||
| 1856 | all_unreclaimable = false; | ||
| 1857 | break; | ||
| 1858 | } | ||
| 1859 | } | ||
| 1860 | |||
| 1832 | return all_unreclaimable; | 1861 | return all_unreclaimable; |
| 1833 | } | 1862 | } |
| 1834 | 1863 | ||
| @@ -1852,7 +1881,6 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
| 1852 | struct scan_control *sc) | 1881 | struct scan_control *sc) |
| 1853 | { | 1882 | { |
| 1854 | int priority; | 1883 | int priority; |
| 1855 | bool all_unreclaimable; | ||
| 1856 | unsigned long total_scanned = 0; | 1884 | unsigned long total_scanned = 0; |
| 1857 | struct reclaim_state *reclaim_state = current->reclaim_state; | 1885 | struct reclaim_state *reclaim_state = current->reclaim_state; |
| 1858 | struct zoneref *z; | 1886 | struct zoneref *z; |
| @@ -1869,7 +1897,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
| 1869 | sc->nr_scanned = 0; | 1897 | sc->nr_scanned = 0; |
| 1870 | if (!priority) | 1898 | if (!priority) |
| 1871 | disable_swap_token(); | 1899 | disable_swap_token(); |
| 1872 | all_unreclaimable = shrink_zones(priority, zonelist, sc); | 1900 | shrink_zones(priority, zonelist, sc); |
| 1873 | /* | 1901 | /* |
| 1874 | * Don't shrink slabs when reclaiming memory from | 1902 | * Don't shrink slabs when reclaiming memory from |
| 1875 | * over limit cgroups | 1903 | * over limit cgroups |
| @@ -1931,7 +1959,7 @@ out: | |||
| 1931 | return sc->nr_reclaimed; | 1959 | return sc->nr_reclaimed; |
| 1932 | 1960 | ||
| 1933 | /* top priority shrink_zones still had more to do? don't OOM, then */ | 1961 | /* top priority shrink_zones still had more to do? don't OOM, then */ |
| 1934 | if (scanning_global_lru(sc) && !all_unreclaimable) | 1962 | if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc)) |
| 1935 | return 1; | 1963 | return 1; |
| 1936 | 1964 | ||
| 1937 | return 0; | 1965 | return 0; |
| @@ -2197,8 +2225,7 @@ loop_again: | |||
| 2197 | total_scanned += sc.nr_scanned; | 2225 | total_scanned += sc.nr_scanned; |
| 2198 | if (zone->all_unreclaimable) | 2226 | if (zone->all_unreclaimable) |
| 2199 | continue; | 2227 | continue; |
| 2200 | if (nr_slab == 0 && | 2228 | if (nr_slab == 0 && !zone_reclaimable(zone)) |
| 2201 | zone->pages_scanned >= (zone_reclaimable_pages(zone) * 6)) | ||
| 2202 | zone->all_unreclaimable = 1; | 2229 | zone->all_unreclaimable = 1; |
| 2203 | /* | 2230 | /* |
| 2204 | * If we've done a decent amount of scanning and | 2231 | * If we've done a decent amount of scanning and |
