diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/bootmem.c | 14 | ||||
-rw-r--r-- | mm/memcontrol.c | 126 | ||||
-rw-r--r-- | mm/page_alloc.c | 3 | ||||
-rw-r--r-- | mm/page_cgroup.c | 24 | ||||
-rw-r--r-- | mm/rmap.c | 5 | ||||
-rw-r--r-- | mm/slab.c | 15 | ||||
-rw-r--r-- | mm/slub.c | 12 | ||||
-rw-r--r-- | mm/swapfile.c | 16 | ||||
-rw-r--r-- | mm/vmscan.c | 4 |
9 files changed, 155 insertions, 64 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c index 282df0a09e6f..d2a9ce952768 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -536,11 +536,15 @@ static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata, | |||
536 | return kzalloc(size, GFP_NOWAIT); | 536 | return kzalloc(size, GFP_NOWAIT); |
537 | 537 | ||
538 | #ifdef CONFIG_HAVE_ARCH_BOOTMEM | 538 | #ifdef CONFIG_HAVE_ARCH_BOOTMEM |
539 | bootmem_data_t *p_bdata; | 539 | { |
540 | 540 | bootmem_data_t *p_bdata; | |
541 | p_bdata = bootmem_arch_preferred_node(bdata, size, align, goal, limit); | 541 | |
542 | if (p_bdata) | 542 | p_bdata = bootmem_arch_preferred_node(bdata, size, align, |
543 | return alloc_bootmem_core(p_bdata, size, align, goal, limit); | 543 | goal, limit); |
544 | if (p_bdata) | ||
545 | return alloc_bootmem_core(p_bdata, size, align, | ||
546 | goal, limit); | ||
547 | } | ||
544 | #endif | 548 | #endif |
545 | return NULL; | 549 | return NULL; |
546 | } | 550 | } |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 70db6e0a5eec..e2fa20dadf40 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -45,7 +45,7 @@ struct cgroup_subsys mem_cgroup_subsys __read_mostly; | |||
45 | #define MEM_CGROUP_RECLAIM_RETRIES 5 | 45 | #define MEM_CGROUP_RECLAIM_RETRIES 5 |
46 | 46 | ||
47 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP | 47 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP |
48 | /* Turned on only when memory cgroup is enabled && really_do_swap_account = 0 */ | 48 | /* Turned on only when memory cgroup is enabled && really_do_swap_account = 1 */ |
49 | int do_swap_account __read_mostly; | 49 | int do_swap_account __read_mostly; |
50 | static int really_do_swap_account __initdata = 1; /* for remember boot option*/ | 50 | static int really_do_swap_account __initdata = 1; /* for remember boot option*/ |
51 | #else | 51 | #else |
@@ -62,7 +62,8 @@ enum mem_cgroup_stat_index { | |||
62 | * For MEM_CONTAINER_TYPE_ALL, usage = pagecache + rss. | 62 | * For MEM_CONTAINER_TYPE_ALL, usage = pagecache + rss. |
63 | */ | 63 | */ |
64 | MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */ | 64 | MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */ |
65 | MEM_CGROUP_STAT_RSS, /* # of pages charged as rss */ | 65 | MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */ |
66 | MEM_CGROUP_STAT_MAPPED_FILE, /* # of pages charged as file rss */ | ||
66 | MEM_CGROUP_STAT_PGPGIN_COUNT, /* # of pages paged in */ | 67 | MEM_CGROUP_STAT_PGPGIN_COUNT, /* # of pages paged in */ |
67 | MEM_CGROUP_STAT_PGPGOUT_COUNT, /* # of pages paged out */ | 68 | MEM_CGROUP_STAT_PGPGOUT_COUNT, /* # of pages paged out */ |
68 | 69 | ||
@@ -176,6 +177,9 @@ struct mem_cgroup { | |||
176 | 177 | ||
177 | unsigned int swappiness; | 178 | unsigned int swappiness; |
178 | 179 | ||
180 | /* set when res.limit == memsw.limit */ | ||
181 | bool memsw_is_minimum; | ||
182 | |||
179 | /* | 183 | /* |
180 | * statistics. This must be placed at the end of memcg. | 184 | * statistics. This must be placed at the end of memcg. |
181 | */ | 185 | */ |
@@ -188,6 +192,7 @@ enum charge_type { | |||
188 | MEM_CGROUP_CHARGE_TYPE_SHMEM, /* used by page migration of shmem */ | 192 | MEM_CGROUP_CHARGE_TYPE_SHMEM, /* used by page migration of shmem */ |
189 | MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */ | 193 | MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */ |
190 | MEM_CGROUP_CHARGE_TYPE_SWAPOUT, /* for accounting swapcache */ | 194 | MEM_CGROUP_CHARGE_TYPE_SWAPOUT, /* for accounting swapcache */ |
195 | MEM_CGROUP_CHARGE_TYPE_DROP, /* a page was unused swap cache */ | ||
191 | NR_CHARGE_TYPE, | 196 | NR_CHARGE_TYPE, |
192 | }; | 197 | }; |
193 | 198 | ||
@@ -644,6 +649,7 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, | |||
644 | int zid = zone_idx(z); | 649 | int zid = zone_idx(z); |
645 | struct mem_cgroup_per_zone *mz; | 650 | struct mem_cgroup_per_zone *mz; |
646 | int lru = LRU_FILE * !!file + !!active; | 651 | int lru = LRU_FILE * !!file + !!active; |
652 | int ret; | ||
647 | 653 | ||
648 | BUG_ON(!mem_cont); | 654 | BUG_ON(!mem_cont); |
649 | mz = mem_cgroup_zoneinfo(mem_cont, nid, zid); | 655 | mz = mem_cgroup_zoneinfo(mem_cont, nid, zid); |
@@ -661,9 +667,19 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, | |||
661 | continue; | 667 | continue; |
662 | 668 | ||
663 | scan++; | 669 | scan++; |
664 | if (__isolate_lru_page(page, mode, file) == 0) { | 670 | ret = __isolate_lru_page(page, mode, file); |
671 | switch (ret) { | ||
672 | case 0: | ||
665 | list_move(&page->lru, dst); | 673 | list_move(&page->lru, dst); |
674 | mem_cgroup_del_lru(page); | ||
666 | nr_taken++; | 675 | nr_taken++; |
676 | break; | ||
677 | case -EBUSY: | ||
678 | /* we don't affect global LRU but rotate in our LRU */ | ||
679 | mem_cgroup_rotate_lru_list(page, page_lru(page)); | ||
680 | break; | ||
681 | default: | ||
682 | break; | ||
667 | } | 683 | } |
668 | } | 684 | } |
669 | 685 | ||
@@ -845,6 +861,10 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem, | |||
845 | int ret, total = 0; | 861 | int ret, total = 0; |
846 | int loop = 0; | 862 | int loop = 0; |
847 | 863 | ||
864 | /* If memsw_is_minimum==1, swap-out is of-no-use. */ | ||
865 | if (root_mem->memsw_is_minimum) | ||
866 | noswap = true; | ||
867 | |||
848 | while (loop < 2) { | 868 | while (loop < 2) { |
849 | victim = mem_cgroup_select_victim(root_mem); | 869 | victim = mem_cgroup_select_victim(root_mem); |
850 | if (victim == root_mem) | 870 | if (victim == root_mem) |
@@ -900,6 +920,44 @@ static void record_last_oom(struct mem_cgroup *mem) | |||
900 | mem_cgroup_walk_tree(mem, NULL, record_last_oom_cb); | 920 | mem_cgroup_walk_tree(mem, NULL, record_last_oom_cb); |
901 | } | 921 | } |
902 | 922 | ||
923 | /* | ||
924 | * Currently used to update mapped file statistics, but the routine can be | ||
925 | * generalized to update other statistics as well. | ||
926 | */ | ||
927 | void mem_cgroup_update_mapped_file_stat(struct page *page, int val) | ||
928 | { | ||
929 | struct mem_cgroup *mem; | ||
930 | struct mem_cgroup_stat *stat; | ||
931 | struct mem_cgroup_stat_cpu *cpustat; | ||
932 | int cpu; | ||
933 | struct page_cgroup *pc; | ||
934 | |||
935 | if (!page_is_file_cache(page)) | ||
936 | return; | ||
937 | |||
938 | pc = lookup_page_cgroup(page); | ||
939 | if (unlikely(!pc)) | ||
940 | return; | ||
941 | |||
942 | lock_page_cgroup(pc); | ||
943 | mem = pc->mem_cgroup; | ||
944 | if (!mem) | ||
945 | goto done; | ||
946 | |||
947 | if (!PageCgroupUsed(pc)) | ||
948 | goto done; | ||
949 | |||
950 | /* | ||
951 | * Preemption is already disabled, we don't need get_cpu() | ||
952 | */ | ||
953 | cpu = smp_processor_id(); | ||
954 | stat = &mem->stat; | ||
955 | cpustat = &stat->cpustat[cpu]; | ||
956 | |||
957 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_MAPPED_FILE, val); | ||
958 | done: | ||
959 | unlock_page_cgroup(pc); | ||
960 | } | ||
903 | 961 | ||
904 | /* | 962 | /* |
905 | * Unlike exported interface, "oom" parameter is added. if oom==true, | 963 | * Unlike exported interface, "oom" parameter is added. if oom==true, |
@@ -1098,6 +1156,10 @@ static int mem_cgroup_move_account(struct page_cgroup *pc, | |||
1098 | struct mem_cgroup_per_zone *from_mz, *to_mz; | 1156 | struct mem_cgroup_per_zone *from_mz, *to_mz; |
1099 | int nid, zid; | 1157 | int nid, zid; |
1100 | int ret = -EBUSY; | 1158 | int ret = -EBUSY; |
1159 | struct page *page; | ||
1160 | int cpu; | ||
1161 | struct mem_cgroup_stat *stat; | ||
1162 | struct mem_cgroup_stat_cpu *cpustat; | ||
1101 | 1163 | ||
1102 | VM_BUG_ON(from == to); | 1164 | VM_BUG_ON(from == to); |
1103 | VM_BUG_ON(PageLRU(pc->page)); | 1165 | VM_BUG_ON(PageLRU(pc->page)); |
@@ -1118,6 +1180,23 @@ static int mem_cgroup_move_account(struct page_cgroup *pc, | |||
1118 | 1180 | ||
1119 | res_counter_uncharge(&from->res, PAGE_SIZE); | 1181 | res_counter_uncharge(&from->res, PAGE_SIZE); |
1120 | mem_cgroup_charge_statistics(from, pc, false); | 1182 | mem_cgroup_charge_statistics(from, pc, false); |
1183 | |||
1184 | page = pc->page; | ||
1185 | if (page_is_file_cache(page) && page_mapped(page)) { | ||
1186 | cpu = smp_processor_id(); | ||
1187 | /* Update mapped_file data for mem_cgroup "from" */ | ||
1188 | stat = &from->stat; | ||
1189 | cpustat = &stat->cpustat[cpu]; | ||
1190 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_MAPPED_FILE, | ||
1191 | -1); | ||
1192 | |||
1193 | /* Update mapped_file data for mem_cgroup "to" */ | ||
1194 | stat = &to->stat; | ||
1195 | cpustat = &stat->cpustat[cpu]; | ||
1196 | __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_MAPPED_FILE, | ||
1197 | 1); | ||
1198 | } | ||
1199 | |||
1121 | if (do_swap_account) | 1200 | if (do_swap_account) |
1122 | res_counter_uncharge(&from->memsw, PAGE_SIZE); | 1201 | res_counter_uncharge(&from->memsw, PAGE_SIZE); |
1123 | css_put(&from->css); | 1202 | css_put(&from->css); |
@@ -1433,6 +1512,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype) | |||
1433 | 1512 | ||
1434 | switch (ctype) { | 1513 | switch (ctype) { |
1435 | case MEM_CGROUP_CHARGE_TYPE_MAPPED: | 1514 | case MEM_CGROUP_CHARGE_TYPE_MAPPED: |
1515 | case MEM_CGROUP_CHARGE_TYPE_DROP: | ||
1436 | if (page_mapped(page)) | 1516 | if (page_mapped(page)) |
1437 | goto unlock_out; | 1517 | goto unlock_out; |
1438 | break; | 1518 | break; |
@@ -1496,18 +1576,23 @@ void mem_cgroup_uncharge_cache_page(struct page *page) | |||
1496 | * called after __delete_from_swap_cache() and drop "page" account. | 1576 | * called after __delete_from_swap_cache() and drop "page" account. |
1497 | * memcg information is recorded to swap_cgroup of "ent" | 1577 | * memcg information is recorded to swap_cgroup of "ent" |
1498 | */ | 1578 | */ |
1499 | void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent) | 1579 | void |
1580 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) | ||
1500 | { | 1581 | { |
1501 | struct mem_cgroup *memcg; | 1582 | struct mem_cgroup *memcg; |
1583 | int ctype = MEM_CGROUP_CHARGE_TYPE_SWAPOUT; | ||
1584 | |||
1585 | if (!swapout) /* this was a swap cache but the swap is unused ! */ | ||
1586 | ctype = MEM_CGROUP_CHARGE_TYPE_DROP; | ||
1587 | |||
1588 | memcg = __mem_cgroup_uncharge_common(page, ctype); | ||
1502 | 1589 | ||
1503 | memcg = __mem_cgroup_uncharge_common(page, | ||
1504 | MEM_CGROUP_CHARGE_TYPE_SWAPOUT); | ||
1505 | /* record memcg information */ | 1590 | /* record memcg information */ |
1506 | if (do_swap_account && memcg) { | 1591 | if (do_swap_account && swapout && memcg) { |
1507 | swap_cgroup_record(ent, css_id(&memcg->css)); | 1592 | swap_cgroup_record(ent, css_id(&memcg->css)); |
1508 | mem_cgroup_get(memcg); | 1593 | mem_cgroup_get(memcg); |
1509 | } | 1594 | } |
1510 | if (memcg) | 1595 | if (swapout && memcg) |
1511 | css_put(&memcg->css); | 1596 | css_put(&memcg->css); |
1512 | } | 1597 | } |
1513 | #endif | 1598 | #endif |
@@ -1685,6 +1770,12 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, | |||
1685 | break; | 1770 | break; |
1686 | } | 1771 | } |
1687 | ret = res_counter_set_limit(&memcg->res, val); | 1772 | ret = res_counter_set_limit(&memcg->res, val); |
1773 | if (!ret) { | ||
1774 | if (memswlimit == val) | ||
1775 | memcg->memsw_is_minimum = true; | ||
1776 | else | ||
1777 | memcg->memsw_is_minimum = false; | ||
1778 | } | ||
1688 | mutex_unlock(&set_limit_mutex); | 1779 | mutex_unlock(&set_limit_mutex); |
1689 | 1780 | ||
1690 | if (!ret) | 1781 | if (!ret) |
@@ -1703,16 +1794,14 @@ static int mem_cgroup_resize_limit(struct mem_cgroup *memcg, | |||
1703 | return ret; | 1794 | return ret; |
1704 | } | 1795 | } |
1705 | 1796 | ||
1706 | int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, | 1797 | static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, |
1707 | unsigned long long val) | 1798 | unsigned long long val) |
1708 | { | 1799 | { |
1709 | int retry_count; | 1800 | int retry_count; |
1710 | u64 memlimit, oldusage, curusage; | 1801 | u64 memlimit, oldusage, curusage; |
1711 | int children = mem_cgroup_count_children(memcg); | 1802 | int children = mem_cgroup_count_children(memcg); |
1712 | int ret = -EBUSY; | 1803 | int ret = -EBUSY; |
1713 | 1804 | ||
1714 | if (!do_swap_account) | ||
1715 | return -EINVAL; | ||
1716 | /* see mem_cgroup_resize_res_limit */ | 1805 | /* see mem_cgroup_resize_res_limit */ |
1717 | retry_count = children * MEM_CGROUP_RECLAIM_RETRIES; | 1806 | retry_count = children * MEM_CGROUP_RECLAIM_RETRIES; |
1718 | oldusage = res_counter_read_u64(&memcg->memsw, RES_USAGE); | 1807 | oldusage = res_counter_read_u64(&memcg->memsw, RES_USAGE); |
@@ -1734,6 +1823,12 @@ int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, | |||
1734 | break; | 1823 | break; |
1735 | } | 1824 | } |
1736 | ret = res_counter_set_limit(&memcg->memsw, val); | 1825 | ret = res_counter_set_limit(&memcg->memsw, val); |
1826 | if (!ret) { | ||
1827 | if (memlimit == val) | ||
1828 | memcg->memsw_is_minimum = true; | ||
1829 | else | ||
1830 | memcg->memsw_is_minimum = false; | ||
1831 | } | ||
1737 | mutex_unlock(&set_limit_mutex); | 1832 | mutex_unlock(&set_limit_mutex); |
1738 | 1833 | ||
1739 | if (!ret) | 1834 | if (!ret) |
@@ -1947,8 +2042,7 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) | |||
1947 | val = res_counter_read_u64(&mem->res, name); | 2042 | val = res_counter_read_u64(&mem->res, name); |
1948 | break; | 2043 | break; |
1949 | case _MEMSWAP: | 2044 | case _MEMSWAP: |
1950 | if (do_swap_account) | 2045 | val = res_counter_read_u64(&mem->memsw, name); |
1951 | val = res_counter_read_u64(&mem->memsw, name); | ||
1952 | break; | 2046 | break; |
1953 | default: | 2047 | default: |
1954 | BUG(); | 2048 | BUG(); |
@@ -2046,6 +2140,7 @@ static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) | |||
2046 | enum { | 2140 | enum { |
2047 | MCS_CACHE, | 2141 | MCS_CACHE, |
2048 | MCS_RSS, | 2142 | MCS_RSS, |
2143 | MCS_MAPPED_FILE, | ||
2049 | MCS_PGPGIN, | 2144 | MCS_PGPGIN, |
2050 | MCS_PGPGOUT, | 2145 | MCS_PGPGOUT, |
2051 | MCS_INACTIVE_ANON, | 2146 | MCS_INACTIVE_ANON, |
@@ -2066,6 +2161,7 @@ struct { | |||
2066 | } memcg_stat_strings[NR_MCS_STAT] = { | 2161 | } memcg_stat_strings[NR_MCS_STAT] = { |
2067 | {"cache", "total_cache"}, | 2162 | {"cache", "total_cache"}, |
2068 | {"rss", "total_rss"}, | 2163 | {"rss", "total_rss"}, |
2164 | {"mapped_file", "total_mapped_file"}, | ||
2069 | {"pgpgin", "total_pgpgin"}, | 2165 | {"pgpgin", "total_pgpgin"}, |
2070 | {"pgpgout", "total_pgpgout"}, | 2166 | {"pgpgout", "total_pgpgout"}, |
2071 | {"inactive_anon", "total_inactive_anon"}, | 2167 | {"inactive_anon", "total_inactive_anon"}, |
@@ -2086,6 +2182,8 @@ static int mem_cgroup_get_local_stat(struct mem_cgroup *mem, void *data) | |||
2086 | s->stat[MCS_CACHE] += val * PAGE_SIZE; | 2182 | s->stat[MCS_CACHE] += val * PAGE_SIZE; |
2087 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_RSS); | 2183 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_RSS); |
2088 | s->stat[MCS_RSS] += val * PAGE_SIZE; | 2184 | s->stat[MCS_RSS] += val * PAGE_SIZE; |
2185 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_MAPPED_FILE); | ||
2186 | s->stat[MCS_MAPPED_FILE] += val * PAGE_SIZE; | ||
2089 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGIN_COUNT); | 2187 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGIN_COUNT); |
2090 | s->stat[MCS_PGPGIN] += val; | 2188 | s->stat[MCS_PGPGIN] += val; |
2091 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGOUT_COUNT); | 2189 | val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGOUT_COUNT); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a5f3c278c573..6f0753fe694c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -73,6 +73,7 @@ unsigned long totalram_pages __read_mostly; | |||
73 | unsigned long totalreserve_pages __read_mostly; | 73 | unsigned long totalreserve_pages __read_mostly; |
74 | unsigned long highest_memmap_pfn __read_mostly; | 74 | unsigned long highest_memmap_pfn __read_mostly; |
75 | int percpu_pagelist_fraction; | 75 | int percpu_pagelist_fraction; |
76 | gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK; | ||
76 | 77 | ||
77 | #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE | 78 | #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE |
78 | int pageblock_order __read_mostly; | 79 | int pageblock_order __read_mostly; |
@@ -1863,6 +1864,8 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, | |||
1863 | struct page *page; | 1864 | struct page *page; |
1864 | int migratetype = allocflags_to_migratetype(gfp_mask); | 1865 | int migratetype = allocflags_to_migratetype(gfp_mask); |
1865 | 1866 | ||
1867 | gfp_mask &= gfp_allowed_mask; | ||
1868 | |||
1866 | lockdep_trace_alloc(gfp_mask); | 1869 | lockdep_trace_alloc(gfp_mask); |
1867 | 1870 | ||
1868 | might_sleep_if(gfp_mask & __GFP_WAIT); | 1871 | might_sleep_if(gfp_mask & __GFP_WAIT); |
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 11a8a10a3909..f22b4ebbd8dc 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -83,12 +83,12 @@ void __init page_cgroup_init_flatmem(void) | |||
83 | goto fail; | 83 | goto fail; |
84 | } | 84 | } |
85 | printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage); | 85 | printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage); |
86 | printk(KERN_INFO "please try cgroup_disable=memory option if you" | 86 | printk(KERN_INFO "please try 'cgroup_disable=memory' option if you" |
87 | " don't want\n"); | 87 | " don't want memory cgroups\n"); |
88 | return; | 88 | return; |
89 | fail: | 89 | fail: |
90 | printk(KERN_CRIT "allocation of page_cgroup was failed.\n"); | 90 | printk(KERN_CRIT "allocation of page_cgroup failed.\n"); |
91 | printk(KERN_CRIT "please try cgroup_disable=memory boot option\n"); | 91 | printk(KERN_CRIT "please try 'cgroup_disable=memory' boot option\n"); |
92 | panic("Out of memory"); | 92 | panic("Out of memory"); |
93 | } | 93 | } |
94 | 94 | ||
@@ -99,6 +99,8 @@ struct page_cgroup *lookup_page_cgroup(struct page *page) | |||
99 | unsigned long pfn = page_to_pfn(page); | 99 | unsigned long pfn = page_to_pfn(page); |
100 | struct mem_section *section = __pfn_to_section(pfn); | 100 | struct mem_section *section = __pfn_to_section(pfn); |
101 | 101 | ||
102 | if (!section->page_cgroup) | ||
103 | return NULL; | ||
102 | return section->page_cgroup + pfn; | 104 | return section->page_cgroup + pfn; |
103 | } | 105 | } |
104 | 106 | ||
@@ -252,14 +254,14 @@ void __init page_cgroup_init(void) | |||
252 | fail = init_section_page_cgroup(pfn); | 254 | fail = init_section_page_cgroup(pfn); |
253 | } | 255 | } |
254 | if (fail) { | 256 | if (fail) { |
255 | printk(KERN_CRIT "try cgroup_disable=memory boot option\n"); | 257 | printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n"); |
256 | panic("Out of memory"); | 258 | panic("Out of memory"); |
257 | } else { | 259 | } else { |
258 | hotplug_memory_notifier(page_cgroup_callback, 0); | 260 | hotplug_memory_notifier(page_cgroup_callback, 0); |
259 | } | 261 | } |
260 | printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage); | 262 | printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage); |
261 | printk(KERN_INFO "please try cgroup_disable=memory option if you don't" | 263 | printk(KERN_INFO "please try 'cgroup_disable=memory' option if you don't" |
262 | " want\n"); | 264 | " want memory cgroups\n"); |
263 | } | 265 | } |
264 | 266 | ||
265 | void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat) | 267 | void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat) |
@@ -309,8 +311,6 @@ static int swap_cgroup_prepare(int type) | |||
309 | struct swap_cgroup_ctrl *ctrl; | 311 | struct swap_cgroup_ctrl *ctrl; |
310 | unsigned long idx, max; | 312 | unsigned long idx, max; |
311 | 313 | ||
312 | if (!do_swap_account) | ||
313 | return 0; | ||
314 | ctrl = &swap_cgroup_ctrl[type]; | 314 | ctrl = &swap_cgroup_ctrl[type]; |
315 | 315 | ||
316 | for (idx = 0; idx < ctrl->length; idx++) { | 316 | for (idx = 0; idx < ctrl->length; idx++) { |
@@ -347,9 +347,6 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id) | |||
347 | struct swap_cgroup *sc; | 347 | struct swap_cgroup *sc; |
348 | unsigned short old; | 348 | unsigned short old; |
349 | 349 | ||
350 | if (!do_swap_account) | ||
351 | return 0; | ||
352 | |||
353 | ctrl = &swap_cgroup_ctrl[type]; | 350 | ctrl = &swap_cgroup_ctrl[type]; |
354 | 351 | ||
355 | mappage = ctrl->map[idx]; | 352 | mappage = ctrl->map[idx]; |
@@ -378,9 +375,6 @@ unsigned short lookup_swap_cgroup(swp_entry_t ent) | |||
378 | struct swap_cgroup *sc; | 375 | struct swap_cgroup *sc; |
379 | unsigned short ret; | 376 | unsigned short ret; |
380 | 377 | ||
381 | if (!do_swap_account) | ||
382 | return 0; | ||
383 | |||
384 | ctrl = &swap_cgroup_ctrl[type]; | 378 | ctrl = &swap_cgroup_ctrl[type]; |
385 | mappage = ctrl->map[idx]; | 379 | mappage = ctrl->map[idx]; |
386 | sc = page_address(mappage); | 380 | sc = page_address(mappage); |
@@ -703,8 +703,10 @@ void page_add_new_anon_rmap(struct page *page, | |||
703 | */ | 703 | */ |
704 | void page_add_file_rmap(struct page *page) | 704 | void page_add_file_rmap(struct page *page) |
705 | { | 705 | { |
706 | if (atomic_inc_and_test(&page->_mapcount)) | 706 | if (atomic_inc_and_test(&page->_mapcount)) { |
707 | __inc_zone_page_state(page, NR_FILE_MAPPED); | 707 | __inc_zone_page_state(page, NR_FILE_MAPPED); |
708 | mem_cgroup_update_mapped_file_stat(page, 1); | ||
709 | } | ||
708 | } | 710 | } |
709 | 711 | ||
710 | #ifdef CONFIG_DEBUG_VM | 712 | #ifdef CONFIG_DEBUG_VM |
@@ -753,6 +755,7 @@ void page_remove_rmap(struct page *page) | |||
753 | mem_cgroup_uncharge_page(page); | 755 | mem_cgroup_uncharge_page(page); |
754 | __dec_zone_page_state(page, | 756 | __dec_zone_page_state(page, |
755 | PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED); | 757 | PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED); |
758 | mem_cgroup_update_mapped_file_stat(page, -1); | ||
756 | /* | 759 | /* |
757 | * It would be tidy to reset the PageAnon mapping here, | 760 | * It would be tidy to reset the PageAnon mapping here, |
758 | * but that might overwrite a racing page_add_anon_rmap | 761 | * but that might overwrite a racing page_add_anon_rmap |
@@ -305,12 +305,6 @@ struct kmem_list3 { | |||
305 | }; | 305 | }; |
306 | 306 | ||
307 | /* | 307 | /* |
308 | * The slab allocator is initialized with interrupts disabled. Therefore, make | ||
309 | * sure early boot allocations don't accidentally enable interrupts. | ||
310 | */ | ||
311 | static gfp_t slab_gfp_mask __read_mostly = SLAB_GFP_BOOT_MASK; | ||
312 | |||
313 | /* | ||
314 | * Need this for bootstrapping a per node allocator. | 308 | * Need this for bootstrapping a per node allocator. |
315 | */ | 309 | */ |
316 | #define NUM_INIT_LISTS (3 * MAX_NUMNODES) | 310 | #define NUM_INIT_LISTS (3 * MAX_NUMNODES) |
@@ -1559,11 +1553,6 @@ void __init kmem_cache_init_late(void) | |||
1559 | { | 1553 | { |
1560 | struct kmem_cache *cachep; | 1554 | struct kmem_cache *cachep; |
1561 | 1555 | ||
1562 | /* | ||
1563 | * Interrupts are enabled now so all GFP allocations are safe. | ||
1564 | */ | ||
1565 | slab_gfp_mask = __GFP_BITS_MASK; | ||
1566 | |||
1567 | /* 6) resize the head arrays to their final sizes */ | 1556 | /* 6) resize the head arrays to their final sizes */ |
1568 | mutex_lock(&cache_chain_mutex); | 1557 | mutex_lock(&cache_chain_mutex); |
1569 | list_for_each_entry(cachep, &cache_chain, next) | 1558 | list_for_each_entry(cachep, &cache_chain, next) |
@@ -3307,7 +3296,7 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, | |||
3307 | unsigned long save_flags; | 3296 | unsigned long save_flags; |
3308 | void *ptr; | 3297 | void *ptr; |
3309 | 3298 | ||
3310 | flags &= slab_gfp_mask; | 3299 | flags &= gfp_allowed_mask; |
3311 | 3300 | ||
3312 | lockdep_trace_alloc(flags); | 3301 | lockdep_trace_alloc(flags); |
3313 | 3302 | ||
@@ -3392,7 +3381,7 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) | |||
3392 | unsigned long save_flags; | 3381 | unsigned long save_flags; |
3393 | void *objp; | 3382 | void *objp; |
3394 | 3383 | ||
3395 | flags &= slab_gfp_mask; | 3384 | flags &= gfp_allowed_mask; |
3396 | 3385 | ||
3397 | lockdep_trace_alloc(flags); | 3386 | lockdep_trace_alloc(flags); |
3398 | 3387 | ||
@@ -179,12 +179,6 @@ static enum { | |||
179 | SYSFS /* Sysfs up */ | 179 | SYSFS /* Sysfs up */ |
180 | } slab_state = DOWN; | 180 | } slab_state = DOWN; |
181 | 181 | ||
182 | /* | ||
183 | * The slab allocator is initialized with interrupts disabled. Therefore, make | ||
184 | * sure early boot allocations don't accidentally enable interrupts. | ||
185 | */ | ||
186 | static gfp_t slab_gfp_mask __read_mostly = SLAB_GFP_BOOT_MASK; | ||
187 | |||
188 | /* A list of all slab caches on the system */ | 182 | /* A list of all slab caches on the system */ |
189 | static DECLARE_RWSEM(slub_lock); | 183 | static DECLARE_RWSEM(slub_lock); |
190 | static LIST_HEAD(slab_caches); | 184 | static LIST_HEAD(slab_caches); |
@@ -1692,7 +1686,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, | |||
1692 | unsigned long flags; | 1686 | unsigned long flags; |
1693 | unsigned int objsize; | 1687 | unsigned int objsize; |
1694 | 1688 | ||
1695 | gfpflags &= slab_gfp_mask; | 1689 | gfpflags &= gfp_allowed_mask; |
1696 | 1690 | ||
1697 | lockdep_trace_alloc(gfpflags); | 1691 | lockdep_trace_alloc(gfpflags); |
1698 | might_sleep_if(gfpflags & __GFP_WAIT); | 1692 | might_sleep_if(gfpflags & __GFP_WAIT); |
@@ -3220,10 +3214,6 @@ void __init kmem_cache_init(void) | |||
3220 | 3214 | ||
3221 | void __init kmem_cache_init_late(void) | 3215 | void __init kmem_cache_init_late(void) |
3222 | { | 3216 | { |
3223 | /* | ||
3224 | * Interrupts are enabled now so all GFP allocations are safe. | ||
3225 | */ | ||
3226 | slab_gfp_mask = __GFP_BITS_MASK; | ||
3227 | } | 3217 | } |
3228 | 3218 | ||
3229 | /* | 3219 | /* |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 28faa01cf578..d1ade1a48ee7 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -583,8 +583,9 @@ static int swap_entry_free(struct swap_info_struct *p, | |||
583 | swap_list.next = p - swap_info; | 583 | swap_list.next = p - swap_info; |
584 | nr_swap_pages++; | 584 | nr_swap_pages++; |
585 | p->inuse_pages--; | 585 | p->inuse_pages--; |
586 | mem_cgroup_uncharge_swap(ent); | ||
587 | } | 586 | } |
587 | if (!swap_count(count)) | ||
588 | mem_cgroup_uncharge_swap(ent); | ||
588 | return count; | 589 | return count; |
589 | } | 590 | } |
590 | 591 | ||
@@ -609,12 +610,19 @@ void swap_free(swp_entry_t entry) | |||
609 | void swapcache_free(swp_entry_t entry, struct page *page) | 610 | void swapcache_free(swp_entry_t entry, struct page *page) |
610 | { | 611 | { |
611 | struct swap_info_struct *p; | 612 | struct swap_info_struct *p; |
613 | int ret; | ||
612 | 614 | ||
613 | if (page) | ||
614 | mem_cgroup_uncharge_swapcache(page, entry); | ||
615 | p = swap_info_get(entry); | 615 | p = swap_info_get(entry); |
616 | if (p) { | 616 | if (p) { |
617 | swap_entry_free(p, entry, SWAP_CACHE); | 617 | ret = swap_entry_free(p, entry, SWAP_CACHE); |
618 | if (page) { | ||
619 | bool swapout; | ||
620 | if (ret) | ||
621 | swapout = true; /* the end of swap out */ | ||
622 | else | ||
623 | swapout = false; /* no more swap users! */ | ||
624 | mem_cgroup_uncharge_swapcache(page, entry, swapout); | ||
625 | } | ||
618 | spin_unlock(&swap_lock); | 626 | spin_unlock(&swap_lock); |
619 | } | 627 | } |
620 | return; | 628 | return; |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 4139aa52b941..e8fa2d9eb212 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -837,7 +837,6 @@ int __isolate_lru_page(struct page *page, int mode, int file) | |||
837 | */ | 837 | */ |
838 | ClearPageLRU(page); | 838 | ClearPageLRU(page); |
839 | ret = 0; | 839 | ret = 0; |
840 | mem_cgroup_del_lru(page); | ||
841 | } | 840 | } |
842 | 841 | ||
843 | return ret; | 842 | return ret; |
@@ -885,12 +884,14 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, | |||
885 | switch (__isolate_lru_page(page, mode, file)) { | 884 | switch (__isolate_lru_page(page, mode, file)) { |
886 | case 0: | 885 | case 0: |
887 | list_move(&page->lru, dst); | 886 | list_move(&page->lru, dst); |
887 | mem_cgroup_del_lru(page); | ||
888 | nr_taken++; | 888 | nr_taken++; |
889 | break; | 889 | break; |
890 | 890 | ||
891 | case -EBUSY: | 891 | case -EBUSY: |
892 | /* else it is being freed elsewhere */ | 892 | /* else it is being freed elsewhere */ |
893 | list_move(&page->lru, src); | 893 | list_move(&page->lru, src); |
894 | mem_cgroup_rotate_lru_list(page, page_lru(page)); | ||
894 | continue; | 895 | continue; |
895 | 896 | ||
896 | default: | 897 | default: |
@@ -931,6 +932,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan, | |||
931 | continue; | 932 | continue; |
932 | if (__isolate_lru_page(cursor_page, mode, file) == 0) { | 933 | if (__isolate_lru_page(cursor_page, mode, file) == 0) { |
933 | list_move(&cursor_page->lru, dst); | 934 | list_move(&cursor_page->lru, dst); |
935 | mem_cgroup_del_lru(page); | ||
934 | nr_taken++; | 936 | nr_taken++; |
935 | scan++; | 937 | scan++; |
936 | } | 938 | } |