A netadmin in a user+net namespace can create many IPv4 and IPv6 multicast routing tables with MRT_TABLE and MRT6_TABLE. Each unseen id allocates an mr_table via the shared mr_table_alloc(), links it into the per-net list, and leaves it until netns teardown. Those objects were not charged to memcg, so the host unreclaimable slab grows with the table count. Account mr_table allocations with GFP_KERNEL_ACCOUNT and mark the IPv4/IPv6 MFC caches SLAB_ACCOUNT. This matches the established handling of IP addresses, routes and alternate interface names. Unresolved MFC entries are still allocated from softIRQ with GFP_ATOMIC and are not charged. They expire after 10 seconds and are bounded by the socket receive queue; see commit 0079ad8e8dc3 ("ipmr: remove hard code cache_resolve_queue_len limit").
Unified · Split
| @@ -3376,7 +3376,8 @@ int __init ip_mr_init(void) · 3375 unmodified lines | |||
| 3376 | { | 3376 | { |
| 3377 | int err; | 3377 | int err; |
| 3378 | 3378 | ||
| 3379 | mrt_cachep = KMEM_CACHE(mfc_cache, SLAB_HWCACHE_ALIGN | SLAB_PANIC); | 3379 | mrt_cachep = KMEM_CACHE(mfc_cache, |
| 3380 | SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT); | ||
| 3380 | 3381 | ||
| 3381 | err = register_pernet_subsys(&ipmr_net_ops); | 3382 | err = register_pernet_subsys(&ipmr_net_ops); |
| 3382 | if (err) | 3383 | if (err) |
| @@ -52,7 +52,7 @@ mr_table_alloc(struct net *net, u32 id, · 51 unmodified lines | |||
| 52 | struct mr_table *mrt; | 52 | struct mr_table *mrt; |
| 53 | int err; | 53 | int err; |
| 54 | 54 | ||
| 55 | mrt = kzalloc_obj(*mrt); | 55 | mrt = kzalloc_obj(*mrt, GFP_KERNEL_ACCOUNT); |
| 56 | if (!mrt) | 56 | if (!mrt) |
| 57 | return ERR_PTR(-ENOMEM); | 57 | return ERR_PTR(-ENOMEM); |
| 58 | mrt->id = id; | 58 | mrt->id = id; |
| @@ -1427,7 +1427,7 @@ int __init ip6_mr_init(void) · 1426 unmodified lines | |||
| 1427 | { | 1427 | { |
| 1428 | int err; | 1428 | int err; |
| 1429 | 1429 | ||
| 1430 | mrt_cachep = KMEM_CACHE(mfc6_cache, SLAB_HWCACHE_ALIGN); | 1430 | mrt_cachep = KMEM_CACHE(mfc6_cache, SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT); |
| 1431 | if (!mrt_cachep) | 1431 | if (!mrt_cachep) |
| 1432 | return -ENOMEM; | 1432 | return -ENOMEM; |
| 1433 | 1433 | ||