diff options
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index a6e65d024995..bbd194630c5b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -932,6 +932,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
932 | long mapped_ratio; | 932 | long mapped_ratio; |
933 | long distress; | 933 | long distress; |
934 | long swap_tendency; | 934 | long swap_tendency; |
935 | long imbalance; | ||
935 | 936 | ||
936 | if (zone_is_near_oom(zone)) | 937 | if (zone_is_near_oom(zone)) |
937 | goto force_reclaim_mapped; | 938 | goto force_reclaim_mapped; |
@@ -967,6 +968,46 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
967 | swap_tendency = mapped_ratio / 2 + distress + sc->swappiness; | 968 | swap_tendency = mapped_ratio / 2 + distress + sc->swappiness; |
968 | 969 | ||
969 | /* | 970 | /* |
971 | * If there's huge imbalance between active and inactive | ||
972 | * (think active 100 times larger than inactive) we should | ||
973 | * become more permissive, or the system will take too much | ||
974 | * cpu before it start swapping during memory pressure. | ||
975 | * Distress is about avoiding early-oom, this is about | ||
976 | * making swappiness graceful despite setting it to low | ||
977 | * values. | ||
978 | * | ||
979 | * Avoid div by zero with nr_inactive+1, and max resulting | ||
980 | * value is vm_total_pages. | ||
981 | */ | ||
982 | imbalance = zone_page_state(zone, NR_ACTIVE); | ||
983 | imbalance /= zone_page_state(zone, NR_INACTIVE) + 1; | ||
984 | |||
985 | /* | ||
986 | * Reduce the effect of imbalance if swappiness is low, | ||
987 | * this means for a swappiness very low, the imbalance | ||
988 | * must be much higher than 100 for this logic to make | ||
989 | * the difference. | ||
990 | * | ||
991 | * Max temporary value is vm_total_pages*100. | ||
992 | */ | ||
993 | imbalance *= (vm_swappiness + 1); | ||
994 | imbalance /= 100; | ||
995 | |||
996 | /* | ||
997 | * If not much of the ram is mapped, makes the imbalance | ||
998 | * less relevant, it's high priority we refill the inactive | ||
999 | * list with mapped pages only in presence of high ratio of | ||
1000 | * mapped pages. | ||
1001 | * | ||
1002 | * Max temporary value is vm_total_pages*100. | ||
1003 | */ | ||
1004 | imbalance *= mapped_ratio; | ||
1005 | imbalance /= 100; | ||
1006 | |||
1007 | /* apply imbalance feedback to swap_tendency */ | ||
1008 | swap_tendency += imbalance; | ||
1009 | |||
1010 | /* | ||
970 | * Now use this metric to decide whether to start moving mapped | 1011 | * Now use this metric to decide whether to start moving mapped |
971 | * memory onto the inactive list. | 1012 | * memory onto the inactive list. |
972 | */ | 1013 | */ |
@@ -1371,7 +1412,13 @@ loop_again: | |||
1371 | temp_priority[i] = priority; | 1412 | temp_priority[i] = priority; |
1372 | sc.nr_scanned = 0; | 1413 | sc.nr_scanned = 0; |
1373 | note_zone_scanning_priority(zone, priority); | 1414 | note_zone_scanning_priority(zone, priority); |
1374 | nr_reclaimed += shrink_zone(priority, zone, &sc); | 1415 | /* |
1416 | * We put equal pressure on every zone, unless one | ||
1417 | * zone has way too many pages free already. | ||
1418 | */ | ||
1419 | if (!zone_watermark_ok(zone, order, 8*zone->pages_high, | ||
1420 | end_zone, 0)) | ||
1421 | nr_reclaimed += shrink_zone(priority, zone, &sc); | ||
1375 | reclaim_state->reclaimed_slab = 0; | 1422 | reclaim_state->reclaimed_slab = 0; |
1376 | nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL, | 1423 | nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL, |
1377 | lru_pages); | 1424 | lru_pages); |
@@ -1688,9 +1735,11 @@ static int __devinit cpu_callback(struct notifier_block *nfb, | |||
1688 | { | 1735 | { |
1689 | pg_data_t *pgdat; | 1736 | pg_data_t *pgdat; |
1690 | cpumask_t mask; | 1737 | cpumask_t mask; |
1738 | int nid; | ||
1691 | 1739 | ||
1692 | if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) { | 1740 | if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) { |
1693 | for_each_online_pgdat(pgdat) { | 1741 | for_each_node_state(nid, N_HIGH_MEMORY) { |
1742 | pgdat = NODE_DATA(nid); | ||
1694 | mask = node_to_cpumask(pgdat->node_id); | 1743 | mask = node_to_cpumask(pgdat->node_id); |
1695 | if (any_online_cpu(mask) != NR_CPUS) | 1744 | if (any_online_cpu(mask) != NR_CPUS) |
1696 | /* One of our CPUs online: restore mask */ | 1745 | /* One of our CPUs online: restore mask */ |
@@ -1727,7 +1776,7 @@ static int __init kswapd_init(void) | |||
1727 | int nid; | 1776 | int nid; |
1728 | 1777 | ||
1729 | swap_setup(); | 1778 | swap_setup(); |
1730 | for_each_online_node(nid) | 1779 | for_each_node_state(nid, N_HIGH_MEMORY) |
1731 | kswapd_run(nid); | 1780 | kswapd_run(nid); |
1732 | hotcpu_notifier(cpu_callback, 0); | 1781 | hotcpu_notifier(cpu_callback, 0); |
1733 | return 0; | 1782 | return 0; |
@@ -1847,7 +1896,6 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) | |||
1847 | 1896 | ||
1848 | int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) | 1897 | int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) |
1849 | { | 1898 | { |
1850 | cpumask_t mask; | ||
1851 | int node_id; | 1899 | int node_id; |
1852 | 1900 | ||
1853 | /* | 1901 | /* |
@@ -1884,8 +1932,7 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) | |||
1884 | * as wide as possible. | 1932 | * as wide as possible. |
1885 | */ | 1933 | */ |
1886 | node_id = zone_to_nid(zone); | 1934 | node_id = zone_to_nid(zone); |
1887 | mask = node_to_cpumask(node_id); | 1935 | if (node_state(node_id, N_CPU) && node_id != numa_node_id()) |
1888 | if (!cpus_empty(mask) && node_id != numa_node_id()) | ||
1889 | return 0; | 1936 | return 0; |
1890 | return __zone_reclaim(zone, gfp_mask, order); | 1937 | return __zone_reclaim(zone, gfp_mask, order); |
1891 | } | 1938 | } |