diff options
| -rw-r--r-- | include/linux/memcontrol.h | 15 | ||||
| -rw-r--r-- | mm/memcontrol.c | 4 | ||||
| -rw-r--r-- | mm/slab.c | 7 | ||||
| -rw-r--r-- | mm/slab.h | 29 | ||||
| -rw-r--r-- | mm/slab_common.c | 6 | ||||
| -rw-r--r-- | mm/slub.c | 24 |
6 files changed, 59 insertions, 26 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index b569b8be5c5a..96e5d2573eb0 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h | |||
| @@ -506,6 +506,9 @@ void memcg_update_array_size(int num_groups); | |||
| 506 | struct kmem_cache * | 506 | struct kmem_cache * |
| 507 | __memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp); | 507 | __memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp); |
| 508 | 508 | ||
| 509 | int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size); | ||
| 510 | void memcg_uncharge_kmem(struct mem_cgroup *memcg, u64 size); | ||
| 511 | |||
| 509 | void mem_cgroup_destroy_cache(struct kmem_cache *cachep); | 512 | void mem_cgroup_destroy_cache(struct kmem_cache *cachep); |
| 510 | int __kmem_cache_destroy_memcg_children(struct kmem_cache *s); | 513 | int __kmem_cache_destroy_memcg_children(struct kmem_cache *s); |
| 511 | 514 | ||
| @@ -583,17 +586,7 @@ memcg_kmem_commit_charge(struct page *page, struct mem_cgroup *memcg, int order) | |||
| 583 | * @cachep: the original global kmem cache | 586 | * @cachep: the original global kmem cache |
| 584 | * @gfp: allocation flags. | 587 | * @gfp: allocation flags. |
| 585 | * | 588 | * |
| 586 | * This function assumes that the task allocating, which determines the memcg | 589 | * All memory allocated from a per-memcg cache is charged to the owner memcg. |
| 587 | * in the page allocator, belongs to the same cgroup throughout the whole | ||
| 588 | * process. Misacounting can happen if the task calls memcg_kmem_get_cache() | ||
| 589 | * while belonging to a cgroup, and later on changes. This is considered | ||
| 590 | * acceptable, and should only happen upon task migration. | ||
| 591 | * | ||
| 592 | * Before the cache is created by the memcg core, there is also a possible | ||
| 593 | * imbalance: the task belongs to a memcg, but the cache being allocated from | ||
| 594 | * is the global cache, since the child cache is not yet guaranteed to be | ||
| 595 | * ready. This case is also fine, since in this case the GFP_KMEMCG will not be | ||
| 596 | * passed and the page allocator will not attempt any cgroup accounting. | ||
| 597 | */ | 590 | */ |
| 598 | static __always_inline struct kmem_cache * | 591 | static __always_inline struct kmem_cache * |
| 599 | memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp) | 592 | memcg_kmem_get_cache(struct kmem_cache *cachep, gfp_t gfp) |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 5177c6d4a2dd..56a768b3d5a8 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -2953,7 +2953,7 @@ static int mem_cgroup_slabinfo_read(struct seq_file *m, void *v) | |||
| 2953 | } | 2953 | } |
| 2954 | #endif | 2954 | #endif |
| 2955 | 2955 | ||
| 2956 | static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size) | 2956 | int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size) |
| 2957 | { | 2957 | { |
| 2958 | struct res_counter *fail_res; | 2958 | struct res_counter *fail_res; |
| 2959 | int ret = 0; | 2959 | int ret = 0; |
| @@ -2991,7 +2991,7 @@ static int memcg_charge_kmem(struct mem_cgroup *memcg, gfp_t gfp, u64 size) | |||
| 2991 | return ret; | 2991 | return ret; |
| 2992 | } | 2992 | } |
| 2993 | 2993 | ||
| 2994 | static void memcg_uncharge_kmem(struct mem_cgroup *memcg, u64 size) | 2994 | void memcg_uncharge_kmem(struct mem_cgroup *memcg, u64 size) |
| 2995 | { | 2995 | { |
| 2996 | res_counter_uncharge(&memcg->res, size); | 2996 | res_counter_uncharge(&memcg->res, size); |
| 2997 | if (do_swap_account) | 2997 | if (do_swap_account) |
| @@ -1688,8 +1688,12 @@ static struct page *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, | |||
| 1688 | if (cachep->flags & SLAB_RECLAIM_ACCOUNT) | 1688 | if (cachep->flags & SLAB_RECLAIM_ACCOUNT) |
| 1689 | flags |= __GFP_RECLAIMABLE; | 1689 | flags |= __GFP_RECLAIMABLE; |
| 1690 | 1690 | ||
| 1691 | if (memcg_charge_slab(cachep, flags, cachep->gfporder)) | ||
| 1692 | return NULL; | ||
| 1693 | |||
| 1691 | page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder); | 1694 | page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder); |
| 1692 | if (!page) { | 1695 | if (!page) { |
| 1696 | memcg_uncharge_slab(cachep, cachep->gfporder); | ||
| 1693 | slab_out_of_memory(cachep, flags, nodeid); | 1697 | slab_out_of_memory(cachep, flags, nodeid); |
| 1694 | return NULL; | 1698 | return NULL; |
| 1695 | } | 1699 | } |
| @@ -1747,7 +1751,8 @@ static void kmem_freepages(struct kmem_cache *cachep, struct page *page) | |||
| 1747 | memcg_release_pages(cachep, cachep->gfporder); | 1751 | memcg_release_pages(cachep, cachep->gfporder); |
| 1748 | if (current->reclaim_state) | 1752 | if (current->reclaim_state) |
| 1749 | current->reclaim_state->reclaimed_slab += nr_freed; | 1753 | current->reclaim_state->reclaimed_slab += nr_freed; |
| 1750 | __free_memcg_kmem_pages(page, cachep->gfporder); | 1754 | __free_pages(page, cachep->gfporder); |
| 1755 | memcg_uncharge_slab(cachep, cachep->gfporder); | ||
| 1751 | } | 1756 | } |
| 1752 | 1757 | ||
| 1753 | static void kmem_rcu_free(struct rcu_head *head) | 1758 | static void kmem_rcu_free(struct rcu_head *head) |
| @@ -192,6 +192,26 @@ static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s) | |||
| 192 | return s; | 192 | return s; |
| 193 | return s->memcg_params->root_cache; | 193 | return s->memcg_params->root_cache; |
| 194 | } | 194 | } |
| 195 | |||
| 196 | static __always_inline int memcg_charge_slab(struct kmem_cache *s, | ||
| 197 | gfp_t gfp, int order) | ||
| 198 | { | ||
| 199 | if (!memcg_kmem_enabled()) | ||
| 200 | return 0; | ||
| 201 | if (is_root_cache(s)) | ||
| 202 | return 0; | ||
| 203 | return memcg_charge_kmem(s->memcg_params->memcg, gfp, | ||
| 204 | PAGE_SIZE << order); | ||
| 205 | } | ||
| 206 | |||
| 207 | static __always_inline void memcg_uncharge_slab(struct kmem_cache *s, int order) | ||
| 208 | { | ||
| 209 | if (!memcg_kmem_enabled()) | ||
| 210 | return; | ||
| 211 | if (is_root_cache(s)) | ||
| 212 | return; | ||
| 213 | memcg_uncharge_kmem(s->memcg_params->memcg, PAGE_SIZE << order); | ||
| 214 | } | ||
| 195 | #else | 215 | #else |
| 196 | static inline bool is_root_cache(struct kmem_cache *s) | 216 | static inline bool is_root_cache(struct kmem_cache *s) |
| 197 | { | 217 | { |
| @@ -227,6 +247,15 @@ static inline struct kmem_cache *memcg_root_cache(struct kmem_cache *s) | |||
| 227 | { | 247 | { |
| 228 | return s; | 248 | return s; |
| 229 | } | 249 | } |
| 250 | |||
| 251 | static inline int memcg_charge_slab(struct kmem_cache *s, gfp_t gfp, int order) | ||
| 252 | { | ||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static inline void memcg_uncharge_slab(struct kmem_cache *s, int order) | ||
| 257 | { | ||
| 258 | } | ||
| 230 | #endif | 259 | #endif |
| 231 | 260 | ||
| 232 | static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) | 261 | static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) |
diff --git a/mm/slab_common.c b/mm/slab_common.c index 102cc6fca3d3..06f0c6125632 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c | |||
| @@ -290,12 +290,8 @@ void kmem_cache_create_memcg(struct mem_cgroup *memcg, struct kmem_cache *root_c | |||
| 290 | root_cache->size, root_cache->align, | 290 | root_cache->size, root_cache->align, |
| 291 | root_cache->flags, root_cache->ctor, | 291 | root_cache->flags, root_cache->ctor, |
| 292 | memcg, root_cache); | 292 | memcg, root_cache); |
| 293 | if (IS_ERR(s)) { | 293 | if (IS_ERR(s)) |
| 294 | kfree(cache_name); | 294 | kfree(cache_name); |
| 295 | goto out_unlock; | ||
| 296 | } | ||
| 297 | |||
| 298 | s->allocflags |= __GFP_KMEMCG; | ||
| 299 | 295 | ||
| 300 | out_unlock: | 296 | out_unlock: |
| 301 | mutex_unlock(&slab_mutex); | 297 | mutex_unlock(&slab_mutex); |
| @@ -1312,17 +1312,26 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x) | |||
| 1312 | /* | 1312 | /* |
| 1313 | * Slab allocation and freeing | 1313 | * Slab allocation and freeing |
| 1314 | */ | 1314 | */ |
| 1315 | static inline struct page *alloc_slab_page(gfp_t flags, int node, | 1315 | static inline struct page *alloc_slab_page(struct kmem_cache *s, |
| 1316 | struct kmem_cache_order_objects oo) | 1316 | gfp_t flags, int node, struct kmem_cache_order_objects oo) |
| 1317 | { | 1317 | { |
| 1318 | struct page *page; | ||
| 1318 | int order = oo_order(oo); | 1319 | int order = oo_order(oo); |
| 1319 | 1320 | ||
| 1320 | flags |= __GFP_NOTRACK; | 1321 | flags |= __GFP_NOTRACK; |
| 1321 | 1322 | ||
| 1323 | if (memcg_charge_slab(s, flags, order)) | ||
| 1324 | return NULL; | ||
| 1325 | |||
| 1322 | if (node == NUMA_NO_NODE) | 1326 | if (node == NUMA_NO_NODE) |
| 1323 | return alloc_pages(flags, order); | 1327 | page = alloc_pages(flags, order); |
| 1324 | else | 1328 | else |
| 1325 | return alloc_pages_exact_node(node, flags, order); | 1329 | page = alloc_pages_exact_node(node, flags, order); |
| 1330 | |||
| 1331 | if (!page) | ||
| 1332 | memcg_uncharge_slab(s, order); | ||
| 1333 | |||
| 1334 | return page; | ||
| 1326 | } | 1335 | } |
| 1327 | 1336 | ||
| 1328 | static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) | 1337 | static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) |
| @@ -1344,7 +1353,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) | |||
| 1344 | */ | 1353 | */ |
| 1345 | alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL; | 1354 | alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL; |
| 1346 | 1355 | ||
| 1347 | page = alloc_slab_page(alloc_gfp, node, oo); | 1356 | page = alloc_slab_page(s, alloc_gfp, node, oo); |
| 1348 | if (unlikely(!page)) { | 1357 | if (unlikely(!page)) { |
| 1349 | oo = s->min; | 1358 | oo = s->min; |
| 1350 | alloc_gfp = flags; | 1359 | alloc_gfp = flags; |
| @@ -1352,7 +1361,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) | |||
| 1352 | * Allocation may have failed due to fragmentation. | 1361 | * Allocation may have failed due to fragmentation. |
| 1353 | * Try a lower order alloc if possible | 1362 | * Try a lower order alloc if possible |
| 1354 | */ | 1363 | */ |
| 1355 | page = alloc_slab_page(alloc_gfp, node, oo); | 1364 | page = alloc_slab_page(s, alloc_gfp, node, oo); |
| 1356 | 1365 | ||
| 1357 | if (page) | 1366 | if (page) |
| 1358 | stat(s, ORDER_FALLBACK); | 1367 | stat(s, ORDER_FALLBACK); |
| @@ -1468,7 +1477,8 @@ static void __free_slab(struct kmem_cache *s, struct page *page) | |||
| 1468 | page_mapcount_reset(page); | 1477 | page_mapcount_reset(page); |
| 1469 | if (current->reclaim_state) | 1478 | if (current->reclaim_state) |
| 1470 | current->reclaim_state->reclaimed_slab += pages; | 1479 | current->reclaim_state->reclaimed_slab += pages; |
| 1471 | __free_memcg_kmem_pages(page, order); | 1480 | __free_pages(page, order); |
| 1481 | memcg_uncharge_slab(s, order); | ||
| 1472 | } | 1482 | } |
| 1473 | 1483 | ||
| 1474 | #define need_reserve_slab_rcu \ | 1484 | #define need_reserve_slab_rcu \ |
