Netdev Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Shakeel Butt <shakeelb@google.com>
To: Roman Gushchin <guro@fb.com>
Cc: bpf@vger.kernel.org, netdev <netdev@vger.kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Kernel Team <kernel-team@fb.com>,
LKML <linux-kernel@vger.kernel.org>,
Johannes Weiner <hannes@cmpxchg.org>,
Linux MM <linux-mm@kvack.org>
Subject: Re: [PATCH bpf-next v4 03/30] bpf: memcg-based memory accounting for bpf maps
Date: Tue, 25 Aug 2020 16:27:09 -0700 [thread overview]
Message-ID: <CALvZod70cywN0-HCXUPfyLN1vQdOBb46uCRk5E3NkOTDeWcEtg@mail.gmail.com> (raw)
In-Reply-To: <20200821150134.2581465-4-guro@fb.com>
On Fri, Aug 21, 2020 at 8:01 AM Roman Gushchin <guro@fb.com> wrote:
>
> This patch enables memcg-based memory accounting for memory allocated
> by __bpf_map_area_alloc(), which is used by most map types for
> large allocations.
>
> If a map is updated from an interrupt context, and the update
> results in memory allocation, the memory cgroup can't be determined
> from the context of the current process. To address this case,
> bpf map preserves a pointer to the memory cgroup of the process,
> which created the map. This memory cgroup is charged for allocations
> from interrupt context.
>
> Following patches in the series will refine the accounting for
> some map types.
>
> Signed-off-by: Roman Gushchin <guro@fb.com>
> ---
> include/linux/bpf.h | 4 ++++
> kernel/bpf/helpers.c | 37 ++++++++++++++++++++++++++++++++++++-
> kernel/bpf/syscall.c | 27 ++++++++++++++++++++++++++-
> 3 files changed, 66 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index a9b7185a6b37..b5f178afde94 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -34,6 +34,7 @@ struct btf_type;
> struct exception_table_entry;
> struct seq_operations;
> struct bpf_iter_aux_info;
> +struct mem_cgroup;
>
> extern struct idr btf_idr;
> extern spinlock_t btf_idr_lock;
> @@ -138,6 +139,9 @@ struct bpf_map {
> u32 btf_value_type_id;
> struct btf *btf;
> struct bpf_map_memory memory;
> +#ifdef CONFIG_MEMCG_KMEM
> + struct mem_cgroup *memcg;
> +#endif
> char name[BPF_OBJ_NAME_LEN];
> u32 btf_vmlinux_value_type_id;
> bool bypass_spec_v1;
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index be43ab3e619f..f8ce7bc7003f 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -14,6 +14,7 @@
> #include <linux/jiffies.h>
> #include <linux/pid_namespace.h>
> #include <linux/proc_ns.h>
> +#include <linux/sched/mm.h>
>
> #include "../../lib/kstrtox.h"
>
> @@ -41,11 +42,45 @@ const struct bpf_func_proto bpf_map_lookup_elem_proto = {
> .arg2_type = ARG_PTR_TO_MAP_KEY,
> };
>
> +#ifdef CONFIG_MEMCG_KMEM
> +static __always_inline int __bpf_map_update_elem(struct bpf_map *map, void *key,
> + void *value, u64 flags)
> +{
> + struct mem_cgroup *old_memcg;
> + bool in_interrupt;
> + int ret;
> +
> + /*
> + * If update from an interrupt context results in a memory allocation,
> + * the memory cgroup to charge can't be determined from the context
> + * of the current task. Instead, we charge the memory cgroup, which
> + * contained a process created the map.
> + */
> + in_interrupt = in_interrupt();
> + if (in_interrupt)
> + old_memcg = memalloc_use_memcg(map->memcg);
> +
The memcg_kmem_bypass() will bypass all __GFP_ACCOUNT allocations even
before looking at current->active_memcg, so, this patch will be a
noop.
> + ret = map->ops->map_update_elem(map, key, value, flags);
> +
> + if (in_interrupt)
> + memalloc_use_memcg(old_memcg);
> +
> + return ret;
> +}
> +#else
> +static __always_inline int __bpf_map_update_elem(struct bpf_map *map, void *key,
> + void *value, u64 flags)
> +{
> + return map->ops->map_update_elem(map, key, value, flags);
> +}
> +#endif
> +
> BPF_CALL_4(bpf_map_update_elem, struct bpf_map *, map, void *, key,
> void *, value, u64, flags)
> {
> WARN_ON_ONCE(!rcu_read_lock_held());
> - return map->ops->map_update_elem(map, key, value, flags);
> +
> + return __bpf_map_update_elem(map, key, value, flags);
> }
>
> const struct bpf_func_proto bpf_map_update_elem_proto = {
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 689d736b6904..683614c17a95 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -29,6 +29,7 @@
> #include <linux/bpf_lsm.h>
> #include <linux/poll.h>
> #include <linux/bpf-netns.h>
> +#include <linux/memcontrol.h>
>
> #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
> (map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
> @@ -275,7 +276,7 @@ static void *__bpf_map_area_alloc(u64 size, int numa_node, bool mmapable)
> * __GFP_RETRY_MAYFAIL to avoid such situations.
> */
>
> - const gfp_t gfp = __GFP_NOWARN | __GFP_ZERO;
> + const gfp_t gfp = __GFP_NOWARN | __GFP_ZERO | __GFP_ACCOUNT;
> unsigned int flags = 0;
> unsigned long align = 1;
> void *area;
> @@ -452,6 +453,27 @@ void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock)
> __release(&map_idr_lock);
> }
>
> +#ifdef CONFIG_MEMCG_KMEM
> +static void bpf_map_save_memcg(struct bpf_map *map)
> +{
> + map->memcg = get_mem_cgroup_from_mm(current->mm);
> +}
> +
> +static void bpf_map_release_memcg(struct bpf_map *map)
> +{
> + mem_cgroup_put(map->memcg);
> +}
> +
> +#else
> +static void bpf_map_save_memcg(struct bpf_map *map)
> +{
> +}
> +
> +static void bpf_map_release_memcg(struct bpf_map *map)
> +{
> +}
> +#endif
> +
> /* called from workqueue */
> static void bpf_map_free_deferred(struct work_struct *work)
> {
> @@ -463,6 +485,7 @@ static void bpf_map_free_deferred(struct work_struct *work)
> /* implementation dependent freeing */
> map->ops->map_free(map);
> bpf_map_charge_finish(&mem);
> + bpf_map_release_memcg(map);
> }
>
> static void bpf_map_put_uref(struct bpf_map *map)
> @@ -869,6 +892,8 @@ static int map_create(union bpf_attr *attr)
> if (err)
> goto free_map_sec;
>
> + bpf_map_save_memcg(map);
> +
> err = bpf_map_new_fd(map, f_flags);
> if (err < 0) {
> /* failed to allocate fd.
> --
> 2.26.2
>
next prev parent reply other threads:[~2020-08-25 23:27 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-21 15:01 [PATCH bpf-next v4 00/30] bpf: switch to memcg-based memory accounting Roman Gushchin
2020-08-21 15:01 ` [PATCH bpf-next v4 01/30] mm: support nesting memalloc_use_memcg() Roman Gushchin
2020-08-21 16:29 ` Shakeel Butt
2020-08-21 15:01 ` [PATCH bpf-next v4 02/30] bpf: memcg-based memory accounting for bpf progs Roman Gushchin
2020-08-25 19:00 ` Shakeel Butt
2020-08-25 22:26 ` Roman Gushchin
2020-08-21 15:01 ` [PATCH bpf-next v4 03/30] bpf: memcg-based memory accounting for bpf maps Roman Gushchin
2020-08-25 23:27 ` Shakeel Butt [this message]
2020-08-26 2:38 ` Roman Gushchin
2020-08-26 8:57 ` [bpf] 3ebc0a7f46: BUG:KASAN:use-after-free_in_b kernel test robot
2020-08-21 15:01 ` [PATCH bpf-next v4 28/30] bpf: eliminate rlimit-based memory accounting infra for bpf maps Roman Gushchin
2020-08-21 18:23 ` Alexei Starovoitov
2020-08-21 23:15 ` Roman Gushchin
2020-08-21 22:20 ` [PATCH bpf-next v4 00/30] bpf: switch to memcg-based memory accounting Roman Gushchin
[not found] ` <20200821150134.2581465-5-guro@fb.com>
2020-08-27 1:19 ` [PATCH bpf-next v4 04/30] bpf: refine memcg-based memory accounting for arraymap maps Shakeel Butt
[not found] ` <20200821150134.2581465-6-guro@fb.com>
2020-08-27 1:24 ` [PATCH bpf-next v4 05/30] bpf: refine memcg-based memory accounting for cpumap maps Shakeel Butt
[not found] ` <20200821150134.2581465-7-guro@fb.com>
2020-08-27 1:25 ` [PATCH bpf-next v4 06/30] bpf: memcg-based memory accounting for cgroup storage maps Shakeel Butt
[not found] ` <20200821150134.2581465-8-guro@fb.com>
2020-08-27 1:38 ` [PATCH bpf-next v4 07/30] bpf: refine memcg-based memory accounting for devmap maps Shakeel Butt
[not found] ` <20200821150134.2581465-9-guro@fb.com>
2020-08-28 16:44 ` [PATCH bpf-next v4 08/30] bpf: refine memcg-based memory accounting for hashtab maps Shakeel Butt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CALvZod70cywN0-HCXUPfyLN1vQdOBb46uCRk5E3NkOTDeWcEtg@mail.gmail.com \
--to=shakeelb@google.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=guro@fb.com \
--cc=hannes@cmpxchg.org \
--cc=kernel-team@fb.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=netdev@vger.kernel.org \
--subject='Re: [PATCH bpf-next v4 03/30] bpf: memcg-based memory accounting for bpf maps' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).