Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpf: Introduce selectable memcg for bpf map #3512

Closed
wants to merge 13 commits into from

Conversation

kernel-patches-bot
Copy link

Pull request for series with
subject: bpf: Introduce selectable memcg for bpf map
version: 2
url: https://patchwork.kernel.org/project/netdevbpf/list/?series=668781

@kernel-patches-bot
Copy link
Author

Master branch: df78da2
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=668781
version: 2

@kernel-patches-bot
Copy link
Author

Master branch: df78da2
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=668781
version: 2

@kernel-patches-bot
Copy link
Author

Master branch: df78da2
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=668781
version: 2

Kernel Patches Daemon and others added 12 commits August 18, 2022 09:57
After commit f3a2aeb ("cgroup: enable cgroup_get_from_file() on cgroup1")
we can open a cgroup1 dir as well. So let's update the comment.

Cc: Yosry Ahmed <yosryahmed@google.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Replace the open-coded mem_cgroup_put() with a new helper
bpf_map_put_memcg(). That could make it more clear.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
We can use this helper when CONFIG_MEMCG_KMEM or CONFIG_MEMCG is not set.
It also moves bpf_map_{get,put}_memcg into include/linux/bpf.h, so
these two helpers can be used in other source files.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
In order to make all other map related memory allocations been allocated
after memcg is saved in the map, we should save the memcg immediately
after map creation. But the map is created in bpf_map_area_alloc(),
within which we can't get the related bpf_map (except with a pointer
casting which may be error prone), so we can do it in
bpf_map_init_from_attr(), which is used by all bpf maps.

bpf_map_init_from_attr() is executed immediately after
bpf_map_area_alloc() for almost all bpf maps except bpf_struct_ops,
devmap and hashmap, so this patch changes these three maps.

In the future we will change the return type of bpf_map_init_from_attr()
from void to int for error cases, so put it immediately after
bpf_map_area_alloc() will make it eary to handle the error case.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Move bpf_map_save_memcg() into bpf_map_init_from_attr(), then all other
map related memory allocation will be allocated after saving the memcg.
And then we can get memcg from the map in the followup memory allocation.

To pair with this change, bpf_map_release_memcg() is moved into
bpf_map_area_free(). A new parameter struct bpf_map is introduced into
bpf_map_area_free() for this purpose.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Currently bpf_map_area_alloc() is used to allocate a container of struct
bpf_map or members in this container.  To distinguish the map creation
and the other case, a new parameter struct bpf_map is added into
bpf_map_area_alloc(). Then for the non-map-creation case, we could get
the memcg from the map instead of using the current memcg.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Allocate pages related memory into the new helper
bpf_ringbuf_pages_alloc(), then it can be handled as a single unit.

Suggested-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Allocates memory after map creation, then we can use the generic helper
bpf_map_kzalloc() instead of the open-coded kzalloc().

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Introduce new helper bpf_map_kvcalloc() for this memory allocation.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
We want to open a cgroup directory and pass the fd into kernel, and then
in the kernel we can charge the allocated memory into the open cgroup if it
has valid memory subsystem. In the bpf subsystem, the opened cgroup will
be store as a struct obj_cgroup pointer, so a new helper
get_obj_cgroup_from_cgroup() is introduced.

It also add a comment on why the helper  __get_obj_cgroup_from_memcg()
must be protected by rcu read lock.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Add return value for bpf_map_init_from_attr() to indicate whether it
init successfully. This is a preparation of the followup patch.

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
@kernel-patches-bot
Copy link
Author

Master branch: df78da2
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=668781
version: 2

A new bpf attr memcg_fd is introduced for map creation. The map creation
path in libbpf is changed consequently to set this attr.

A new member memcg_fd is introduced into bpf attr of BPF_MAP_CREATE
command, which is the fd of an opened cgroup directory. In this cgroup,
the memory subsystem must be enabled. The valid memcg_fd must be a postive
number, that means it can't be zero(a valid return value of open(2)). Once
the kernel get the memory cgroup from this fd, it will set this memcg into
bpf map, then all the subsequent memory allocation of this map will be
charged to the memcg. The map creation paths in libbpf are also changed
consequently.

The usage of this new member as follows,
	struct bpf_map_create_opts map_opts = {
		.sz = sizeof(map_opts),
	};
	int memcg_fd, map_fd, old_fd;
	int key, value;

	memcg_fd = open("/sys/fs/cgroup/memory/bpf", O_DIRECTORY);
	if (memcg_fd < 0) {
		perror("memcg dir open");
		return -1;
	}

	/* 0 is a invalid fd */
	if (memcg_fd == 0) {
		old_fd = memcg_fd;
		memcg_fd = fcntl(memcg_fd, F_DUPFD_CLOEXEC, 3);
		close(old_fd);
		if (memcg_fd < 0) {
			perror("fcntl");
			return -1;
		}
	}

	map_opts.memcg_fd = memcg_fd;
	map_fd = bpf_map_create(BPF_MAP_TYPE_HASH, "map_for_memcg",
				sizeof(key), sizeof(value),
				1024, &map_opts);
	if (map_fd <= 0) {
		close(memcg_fd);
		perror("map create");
		return -1;
	}

Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
@kernel-patches-bot
Copy link
Author

Master branch: e34cfee
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=668781
version: 2

Pull request is NOT updated. Failed to apply https://patchwork.kernel.org/project/netdevbpf/list/?series=668781
error message:

Cmd('git') failed due to: exit code(128)
  cmdline: git am -3
  stdout: 'Applying: cgroup: Update the comment on cgroup_get_from_fd
Applying: bpf: Introduce new helper bpf_map_put_memcg()
Applying: bpf: Define bpf_map_{get,put}_memcg for !CONFIG_MEMCG_KMEM
Applying: bpf: Call bpf_map_init_from_attr() immediately after map creation
Applying: bpf: Save memcg in bpf_map_init_from_attr()
Applying: bpf: Use scoped-based charge in bpf_map_area_alloc
Applying: bpf: Introduce new helpers bpf_ringbuf_pages_{alloc,free}
Applying: bpf: Use bpf_map_kzalloc in arraymap
Applying: bpf: Use bpf_map_kvcalloc in bpf_local_storage
Applying: mm, memcg: Add new helper get_obj_cgroup_from_cgroup
Using index info to reconstruct a base tree...
M	include/linux/memcontrol.h
M	mm/memcontrol.c
Falling back to patching base and 3-way merge...
Auto-merging mm/memcontrol.c
CONFLICT (content): Merge conflict in mm/memcontrol.c
Auto-merging include/linux/memcontrol.h
Patch failed at 0010 mm, memcg: Add new helper get_obj_cgroup_from_cgroup
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".'
  stderr: 'error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch'

conflict:

diff --cc mm/memcontrol.c
index b69979c9ced5,0409cc456103..000000000000
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@@ -2890,52 -2896,13 +2890,62 @@@ struct mem_cgroup *mem_cgroup_from_obj_
  }
  
  /*
++<<<<<<< HEAD
 + * Returns a pointer to the memory cgroup to which the kernel object is charged.
 + *
 + * A passed kernel object can be a slab object, vmalloc object or a generic
 + * kernel page, so different mechanisms for getting the memory cgroup pointer
 + * should be used.
 + *
 + * In certain cases (e.g. kernel stacks or large kmallocs with SLUB) the caller
 + * can not know for sure how the kernel object is implemented.
 + * mem_cgroup_from_obj() can be safely used in such cases.
 + *
 + * The caller must ensure the memcg lifetime, e.g. by taking rcu_read_lock(),
 + * cgroup_mutex, etc.
 + */
 +struct mem_cgroup *mem_cgroup_from_obj(void *p)
 +{
 +	struct folio *folio;
 +
 +	if (mem_cgroup_disabled())
 +		return NULL;
 +
 +	if (unlikely(is_vmalloc_addr(p)))
 +		folio = page_folio(vmalloc_to_page(p));
 +	else
 +		folio = virt_to_folio(p);
 +
 +	return mem_cgroup_from_obj_folio(folio, p);
 +}
 +
 +/*
 + * Returns a pointer to the memory cgroup to which the kernel object is charged.
 + * Similar to mem_cgroup_from_obj(), but faster and not suitable for objects,
 + * allocated using vmalloc().
 + *
 + * A passed kernel object must be a slab object or a generic kernel page.
 + *
 + * The caller must ensure the memcg lifetime, e.g. by taking rcu_read_lock(),
 + * cgroup_mutex, etc.
 + */
 +struct mem_cgroup *mem_cgroup_from_slab_obj(void *p)
 +{
 +	if (mem_cgroup_disabled())
 +		return NULL;
 +
 +	return mem_cgroup_from_obj_folio(virt_to_folio(p), p);
 +}
 +
++=======
+  * Pls. note that the memg->objcg can be freed after it is deferenced,
+  * that can happen when the memcg is changed from online to offline.
+  * So this helper must be protected by read rcu lock.
+  *
+  * After obj_cgroup_tryget(), it is safe to use the objcg outside of the rcu
+  * read-side critical section.
+  */
++>>>>>>> mm, memcg: Add new helper get_obj_cgroup_from_cgroup
  static struct obj_cgroup *__get_obj_cgroup_from_memcg(struct mem_cgroup *memcg)
  {
  	struct obj_cgroup *objcg = NULL;

@kernel-patches-bot
Copy link
Author

At least one diff in series https://patchwork.kernel.org/project/netdevbpf/list/?series=668781 expired. Closing PR.

@kernel-patches-bot kernel-patches-bot deleted the series/664101=>bpf-next branch August 21, 2022 06:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants