diff options
-rw-r--r-- | include/linux/gfp.h | 3 | ||||
-rw-r--r-- | mm/page_alloc.c | 35 |
2 files changed, 38 insertions, 0 deletions
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 643c9a6f7f34..0f615eb23d05 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
@@ -367,6 +367,9 @@ extern void free_pages(unsigned long addr, unsigned int order); | |||
367 | extern void free_hot_cold_page(struct page *page, int cold); | 367 | extern void free_hot_cold_page(struct page *page, int cold); |
368 | extern void free_hot_cold_page_list(struct list_head *list, int cold); | 368 | extern void free_hot_cold_page_list(struct list_head *list, int cold); |
369 | 369 | ||
370 | extern void __free_memcg_kmem_pages(struct page *page, unsigned int order); | ||
371 | extern void free_memcg_kmem_pages(unsigned long addr, unsigned int order); | ||
372 | |||
370 | #define __free_page(page) __free_pages((page), 0) | 373 | #define __free_page(page) __free_pages((page), 0) |
371 | #define free_page(addr) free_pages((addr), 0) | 374 | #define free_page(addr) free_pages((addr), 0) |
372 | 375 | ||
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 62496edbd8dd..2ad2ad168efe 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -2612,6 +2612,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, | |||
2612 | int migratetype = allocflags_to_migratetype(gfp_mask); | 2612 | int migratetype = allocflags_to_migratetype(gfp_mask); |
2613 | unsigned int cpuset_mems_cookie; | 2613 | unsigned int cpuset_mems_cookie; |
2614 | int alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET; | 2614 | int alloc_flags = ALLOC_WMARK_LOW|ALLOC_CPUSET; |
2615 | struct mem_cgroup *memcg = NULL; | ||
2615 | 2616 | ||
2616 | gfp_mask &= gfp_allowed_mask; | 2617 | gfp_mask &= gfp_allowed_mask; |
2617 | 2618 | ||
@@ -2630,6 +2631,13 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, | |||
2630 | if (unlikely(!zonelist->_zonerefs->zone)) | 2631 | if (unlikely(!zonelist->_zonerefs->zone)) |
2631 | return NULL; | 2632 | return NULL; |
2632 | 2633 | ||
2634 | /* | ||
2635 | * Will only have any effect when __GFP_KMEMCG is set. This is | ||
2636 | * verified in the (always inline) callee | ||
2637 | */ | ||
2638 | if (!memcg_kmem_newpage_charge(gfp_mask, &memcg, order)) | ||
2639 | return NULL; | ||
2640 | |||
2633 | retry_cpuset: | 2641 | retry_cpuset: |
2634 | cpuset_mems_cookie = get_mems_allowed(); | 2642 | cpuset_mems_cookie = get_mems_allowed(); |
2635 | 2643 | ||
@@ -2665,6 +2673,8 @@ out: | |||
2665 | if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) | 2673 | if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) |
2666 | goto retry_cpuset; | 2674 | goto retry_cpuset; |
2667 | 2675 | ||
2676 | memcg_kmem_commit_charge(page, memcg, order); | ||
2677 | |||
2668 | return page; | 2678 | return page; |
2669 | } | 2679 | } |
2670 | EXPORT_SYMBOL(__alloc_pages_nodemask); | 2680 | EXPORT_SYMBOL(__alloc_pages_nodemask); |
@@ -2717,6 +2727,31 @@ void free_pages(unsigned long addr, unsigned int order) | |||
2717 | 2727 | ||
2718 | EXPORT_SYMBOL(free_pages); | 2728 | EXPORT_SYMBOL(free_pages); |
2719 | 2729 | ||
2730 | /* | ||
2731 | * __free_memcg_kmem_pages and free_memcg_kmem_pages will free | ||
2732 | * pages allocated with __GFP_KMEMCG. | ||
2733 | * | ||
2734 | * Those pages are accounted to a particular memcg, embedded in the | ||
2735 | * corresponding page_cgroup. To avoid adding a hit in the allocator to search | ||
2736 | * for that information only to find out that it is NULL for users who have no | ||
2737 | * interest in that whatsoever, we provide these functions. | ||
2738 | * | ||
2739 | * The caller knows better which flags it relies on. | ||
2740 | */ | ||
2741 | void __free_memcg_kmem_pages(struct page *page, unsigned int order) | ||
2742 | { | ||
2743 | memcg_kmem_uncharge_pages(page, order); | ||
2744 | __free_pages(page, order); | ||
2745 | } | ||
2746 | |||
2747 | void free_memcg_kmem_pages(unsigned long addr, unsigned int order) | ||
2748 | { | ||
2749 | if (addr != 0) { | ||
2750 | VM_BUG_ON(!virt_addr_valid((void *)addr)); | ||
2751 | __free_memcg_kmem_pages(virt_to_page((void *)addr), order); | ||
2752 | } | ||
2753 | } | ||
2754 | |||
2720 | static void *make_alloc_exact(unsigned long addr, unsigned order, size_t size) | 2755 | static void *make_alloc_exact(unsigned long addr, unsigned order, size_t size) |
2721 | { | 2756 | { |
2722 | if (addr) { | 2757 | if (addr) { |