Skip to content

Conversation

@kernel-patches-daemon-bpf
Copy link

Pull request for series with
subject: introduce pagetable_alloc_nolock()
version: 1
url: https://patchwork.kernel.org/project/netdevbpf/list/?series=1032678

@kernel-patches-daemon-bpf
Copy link
Author

Upstream branch: 1d528e7
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1032678
version: 1

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

Cmd('git') failed due to: exit code(128)
  cmdline: git am --3way
  stdout: 'Applying: mm: introduce pagetable_alloc_nolock()
Using index info to reconstruct a base tree...
M	include/linux/mm.h
M	kernel/bpf/stream.c
M	kernel/bpf/syscall.c
M	mm/page_alloc.c
Falling back to patching base and 3-way merge...
Auto-merging mm/page_alloc.c
Auto-merging kernel/bpf/syscall.c
Auto-merging kernel/bpf/stream.c
CONFLICT (content): Merge conflict in kernel/bpf/stream.c
Auto-merging include/linux/mm.h
Patch failed at 0001 mm: introduce pagetable_alloc_nolock()'
  stderr: 'error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config advice.mergeConflict false"'

conflict:

diff --cc kernel/bpf/stream.c
index 0b6bc3f30335,3c80c8007d91..000000000000
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@@ -4,10 -4,111 +4,111 @@@
  #include <linux/bpf.h>
  #include <linux/filter.h>
  #include <linux/bpf_mem_alloc.h>
 -#include <linux/percpu.h>
 -#include <linux/refcount.h>
  #include <linux/gfp.h>
  #include <linux/memory.h>
 -#include <linux/local_lock.h>
  #include <linux/mutex.h>
  
++<<<<<<< HEAD
++=======
+ /*
+  * Simple per-CPU NMI-safe bump allocation mechanism, backed by the NMI-safe
+  * try_alloc_pages()/free_pages_nolock() primitives. We allocate a page and
+  * stash it in a local per-CPU variable, and bump allocate from the page
+  * whenever items need to be printed to a stream. Each page holds a global
+  * atomic refcount in its first 4 bytes, and then records of variable length
+  * that describe the printed messages. Once the global refcount has dropped to
+  * zero, it is a signal to free the page back to the kernel's page allocator,
+  * given all the individual records in it have been consumed.
+  *
+  * It is possible the same page is used to serve allocations across different
+  * programs, which may be consumed at different times individually, hence
+  * maintaining a reference count per-page is critical for correct lifetime
+  * tracking.
+  *
+  * The bpf_stream_page code will be replaced to use kmalloc_nolock() once it
+  * lands.
+  */
+ struct bpf_stream_page {
+ 	refcount_t ref;
+ 	u32 consumed;
+ 	char buf[];
+ };
+ 
+ /* Available room to add data to a refcounted page. */
+ #define BPF_STREAM_PAGE_SZ (PAGE_SIZE - offsetofend(struct bpf_stream_page, consumed))
+ 
+ static DEFINE_PER_CPU(local_trylock_t, stream_local_lock) = INIT_LOCAL_TRYLOCK(stream_local_lock);
+ static DEFINE_PER_CPU(struct bpf_stream_page *, stream_pcpu_page);
+ 
+ static bool bpf_stream_page_local_lock(unsigned long *flags)
+ {
+ 	return local_trylock_irqsave(&stream_local_lock, *flags);
+ }
+ 
+ static void bpf_stream_page_local_unlock(unsigned long *flags)
+ {
+ 	local_unlock_irqrestore(&stream_local_lock, *flags);
+ }
+ 
+ static void bpf_stream_page_free(struct bpf_stream_page *stream_page)
+ {
+ 	struct page *p;
+ 
+ 	if (!stream_page)
+ 		return;
+ 	p = virt_to_page(stream_page);
+ 	free_pages_nolock(p, 0);
+ }
+ 
+ static void bpf_stream_page_get(struct bpf_stream_page *stream_page)
+ {
+ 	refcount_inc(&stream_page->ref);
+ }
+ 
+ static void bpf_stream_page_put(struct bpf_stream_page *stream_page)
+ {
+ 	if (refcount_dec_and_test(&stream_page->ref))
+ 		bpf_stream_page_free(stream_page);
+ }
+ 
+ static void bpf_stream_page_init(struct bpf_stream_page *stream_page)
+ {
+ 	refcount_set(&stream_page->ref, 1);
+ 	stream_page->consumed = 0;
+ }
+ 
+ static struct bpf_stream_page *bpf_stream_page_replace(void)
+ {
+ 	struct bpf_stream_page *stream_page, *old_stream_page;
+ 	struct page *page;
+ 
+ 	page = alloc_pages_nolock(/* Don't account */ __GFP_ZERO, NUMA_NO_NODE, 0);
+ 	if (!page)
+ 		return NULL;
+ 	stream_page = page_address(page);
+ 	bpf_stream_page_init(stream_page);
+ 
+ 	old_stream_page = this_cpu_read(stream_pcpu_page);
+ 	if (old_stream_page)
+ 		bpf_stream_page_put(old_stream_page);
+ 	this_cpu_write(stream_pcpu_page, stream_page);
+ 	return stream_page;
+ }
+ 
+ static int bpf_stream_page_check_room(struct bpf_stream_page *stream_page, int len)
+ {
+ 	int min = offsetof(struct bpf_stream_elem, str[0]);
+ 	int consumed = stream_page->consumed;
+ 	int total = BPF_STREAM_PAGE_SZ;
+ 	int rem = max(0, total - consumed - min);
+ 
+ 	/* Let's give room of at least 8 bytes. */
+ 	WARN_ON_ONCE(rem % 8 != 0);
+ 	rem = rem < 8 ? 0 : rem;
+ 	return min(len, rem);
+ }
+ 
++>>>>>>> mm: introduce pagetable_alloc_nolock()
  static void bpf_stream_elem_init(struct bpf_stream_elem *elem, int len)
  {
  	init_llist_node(&elem->node);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant