[PATCH RFC 1/4] fs/pipe: make the prealloc pool per-pipe infrastructure
From: Breno Leitao
Date: Fri Jun 26 2026 - 06:27:19 EST
Move struct anon_pipe_prealloc and PIPE_PREALLOC_MAX to pipe_fs_i.h and
embed the pool in each pipe via a new prealloc field, next to the existing
tmp_page[2] cache (which will be removed by the end of this patchset).
Add PIPE_PREALLOC_KEEP for the post-write trim target.
The on-stack prealloc pool used by anon_pipe_write() is unchanged; this
only adds the per-pipe storage that later patches switch the read/write
paths over to.
Signed-off-by: Breno Leitao <leitao@xxxxxxxxxx>
---
fs/pipe.c | 7 -------
include/linux/pipe_fs_i.h | 19 +++++++++++++++++++
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/fs/pipe.c b/fs/pipe.c
index 429b0714ec575..325fd9757dbdd 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -111,13 +111,6 @@ void pipe_double_lock(struct pipe_inode_info *pipe1,
pipe_lock(pipe2);
}
-#define PIPE_PREALLOC_MAX 8
-
-struct anon_pipe_prealloc {
- struct page *pages[PIPE_PREALLOC_MAX];
- unsigned int count;
-};
-
/*
* Pre-allocate pages outside pipe->mutex for multi-page writes.
* alloc_page() with GFP_HIGHUSER can sleep in reclaim and runs memcg
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index a1eeed8006694..796860cbddf30 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -13,6 +13,9 @@
#define PIPE_BUF_FLAG_LOSS 0x40 /* Message loss happened after this buffer */
#endif
+#define PIPE_PREALLOC_MAX 8 /* max pages in prealloc pool */
+#define PIPE_PREALLOC_KEEP 2 /* keep at least this many after trim */
+
/**
* struct pipe_buffer - a linux kernel pipe buffer
* @page: the page containing the data for the pipe buffer
@@ -57,6 +60,20 @@ union pipe_index {
};
};
+/**
+ * struct anon_pipe_prealloc - per-pipe page preallocation pool
+ * @pages: array of cached pages (pool)
+ * @count: number of pages currently in the pool
+ *
+ * Each pipe keeps a small bounded pool of preallocated pages to reduce
+ * allocation overhead during writes. The pool is bounded at PIPE_PREALLOC_MAX
+ * and trimmed down to PIPE_PREALLOC_KEEP after a write completes.
+ */
+struct anon_pipe_prealloc {
+ struct page *pages[PIPE_PREALLOC_MAX];
+ unsigned int count;
+};
+
/**
* struct pipe_inode_info - a linux kernel pipe
* @mutex: mutex protecting the whole thing
@@ -68,6 +85,7 @@ union pipe_index {
* @ring_size: total number of buffers (should be a power of 2)
* @nr_accounted: The amount this pipe accounts for in user->pipe_bufs
* @tmp_page: cached released page
+ * @prealloc: per-pipe page preallocation pool
* @readers: number of current readers of this pipe
* @writers: number of current writers of this pipe
* @files: number of struct file referring this pipe (protected by ->i_lock)
@@ -99,6 +117,7 @@ struct pipe_inode_info {
bool note_loss;
#endif
struct page *tmp_page[2];
+ struct anon_pipe_prealloc prealloc;
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
struct pipe_buffer *bufs;
--
2.53.0-Meta