From: David Howells <dhowells@redhat.com>
To: Christian Brauner <christian@brauner.io>,
Steve French <smfrench@gmail.com>,
Matthew Wilcox <willy@infradead.org>
Cc: David Howells <dhowells@redhat.com>,
Jeff Layton <jlayton@kernel.org>,
Gao Xiang <hsiangkao@linux.alibaba.com>,
Dominique Martinet <asmadeus@codewreck.org>,
Marc Dionne <marc.dionne@auristor.com>,
Paulo Alcantara <pc@manguebit.com>,
Shyam Prasad N <sprasad@microsoft.com>,
Tom Talpey <tom@talpey.com>,
Eric Van Hensbergen <ericvh@kernel.org>,
Ilya Dryomov <idryomov@gmail.com>,
netfs@lists.linux.dev, linux-afs@lists.infradead.org,
linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org,
ceph-devel@vger.kernel.org, v9fs@lists.linux.dev,
linux-erofs@lists.ozlabs.org, linux-fsdevel@vger.kernel.org,
linux-mm@kvack.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 19/27] netfs: Add functions to build/clean a buffer in a folio_queue
Date: Thu, 24 Oct 2024 15:05:17 +0100 [thread overview]
Message-ID: <20241024140539.3828093-20-dhowells@redhat.com> (raw)
In-Reply-To: <20241024140539.3828093-1-dhowells@redhat.com>
Add two netfslib functions to build up or clean up a buffer in a
folio_queue. The first, netfs_alloc_folioq_buffer() will add folios to a
buffer, extending up at least to the given size. If it can, it will add
multipage folios. The folios are optionally have the mapping set and will
have the index set according to the distance from the front of the folio
queue.
The second function will free up a folio queue and put any folios in the
queue that have the first mark set.
The netfs_folio tracepoint is also altered to cope with folios that have a
NULL mapping, and the folios being added/put will have trace lines emitted
and will be accounted in the stats.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Jeff Layton <jlayton@kernel.org>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: netfs@lists.linux.dev
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
---
fs/netfs/misc.c | 95 ++++++++++++++++++++++++++++++++++++
include/linux/netfs.h | 6 +++
include/trace/events/netfs.h | 6 +--
3 files changed, 103 insertions(+), 4 deletions(-)
diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c
index 4249715f4171..01a6ba0e2f82 100644
--- a/fs/netfs/misc.c
+++ b/fs/netfs/misc.c
@@ -8,6 +8,101 @@
#include <linux/swap.h>
#include "internal.h"
+/**
+ * netfs_alloc_folioq_buffer - Allocate buffer space into a folio queue
+ * @mapping: Address space to set on the folio (or NULL).
+ * @_buffer: Pointer to the folio queue to add to (may point to a NULL; updated).
+ * @_cur_size: Current size of the buffer (updated).
+ * @size: Target size of the buffer.
+ * @gfp: The allocation constraints.
+ */
+int netfs_alloc_folioq_buffer(struct address_space *mapping,
+ struct folio_queue **_buffer,
+ size_t *_cur_size, ssize_t size, gfp_t gfp)
+{
+ struct folio_queue *tail = *_buffer, *p;
+
+ size = round_up(size, PAGE_SIZE);
+ if (*_cur_size >= size)
+ return 0;
+
+ if (tail)
+ while (tail->next)
+ tail = tail->next;
+
+ do {
+ struct folio *folio;
+ int order = 0, slot;
+
+ if (!tail || folioq_full(tail)) {
+ p = netfs_folioq_alloc(0, GFP_NOFS, netfs_trace_folioq_alloc_buffer);
+ if (!p)
+ return -ENOMEM;
+ if (tail) {
+ tail->next = p;
+ p->prev = tail;
+ } else {
+ *_buffer = p;
+ }
+ tail = p;
+ }
+
+ if (size - *_cur_size > PAGE_SIZE)
+ order = umin(ilog2(size - *_cur_size) - PAGE_SHIFT,
+ MAX_PAGECACHE_ORDER);
+
+ folio = folio_alloc(gfp, order);
+ if (!folio && order > 0)
+ folio = folio_alloc(gfp, 0);
+ if (!folio)
+ return -ENOMEM;
+
+ folio->mapping = mapping;
+ folio->index = *_cur_size / PAGE_SIZE;
+ trace_netfs_folio(folio, netfs_folio_trace_alloc_buffer);
+ slot = folioq_append_mark(tail, folio);
+ *_cur_size += folioq_folio_size(tail, slot);
+ } while (*_cur_size < size);
+
+ return 0;
+}
+EXPORT_SYMBOL(netfs_alloc_folioq_buffer);
+
+/**
+ * netfs_free_folioq_buffer - Free a folio queue.
+ * @fq: The start of the folio queue to free
+ *
+ * Free up a chain of folio_queues and, if marked, the marked folios they point
+ * to.
+ */
+void netfs_free_folioq_buffer(struct folio_queue *fq)
+{
+ struct folio_queue *next;
+ struct folio_batch fbatch;
+
+ folio_batch_init(&fbatch);
+
+ for (; fq; fq = next) {
+ for (int slot = 0; slot < folioq_count(fq); slot++) {
+ struct folio *folio = folioq_folio(fq, slot);
+ if (!folio ||
+ !folioq_is_marked(fq, slot))
+ continue;
+
+ trace_netfs_folio(folio, netfs_folio_trace_put);
+ if (folio_batch_add(&fbatch, folio))
+ folio_batch_release(&fbatch);
+ }
+
+ netfs_stat_d(&netfs_n_folioq);
+ next = fq->next;
+ kfree(fq);
+ }
+
+ folio_batch_release(&fbatch);
+}
+EXPORT_SYMBOL(netfs_free_folioq_buffer);
+
/*
* Reset the subrequest iterator to refer just to the region remaining to be
* read. The iterator may or may not have been advanced by socket ops or
diff --git a/include/linux/netfs.h b/include/linux/netfs.h
index 738c9c8763f0..921cfcfc62f1 100644
--- a/include/linux/netfs.h
+++ b/include/linux/netfs.h
@@ -458,6 +458,12 @@ struct folio_queue *netfs_folioq_alloc(unsigned int rreq_id, gfp_t gfp,
void netfs_folioq_free(struct folio_queue *folioq,
unsigned int /*enum netfs_trace_folioq*/ trace);
+/* Buffer wrangling helpers API. */
+int netfs_alloc_folioq_buffer(struct address_space *mapping,
+ struct folio_queue **_buffer,
+ size_t *_cur_size, ssize_t size, gfp_t gfp);
+void netfs_free_folioq_buffer(struct folio_queue *fq);
+
/**
* netfs_inode - Get the netfs inode context from the inode
* @inode: The inode to query
diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h
index 7c3c866ae183..167c89bc62e0 100644
--- a/include/trace/events/netfs.h
+++ b/include/trace/events/netfs.h
@@ -155,6 +155,7 @@
EM(netfs_streaming_filled_page, "mod-streamw-f") \
EM(netfs_streaming_cont_filled_page, "mod-streamw-f+") \
EM(netfs_folio_trace_abandon, "abandon") \
+ EM(netfs_folio_trace_alloc_buffer, "alloc-buf") \
EM(netfs_folio_trace_cancel_copy, "cancel-copy") \
EM(netfs_folio_trace_cancel_store, "cancel-store") \
EM(netfs_folio_trace_clear, "clear") \
@@ -195,10 +196,7 @@
E_(netfs_trace_donate_to_deferred_next, "defer-next")
#define netfs_folioq_traces \
- EM(netfs_trace_folioq_alloc_append_folio, "alloc-apf") \
- EM(netfs_trace_folioq_alloc_read_prep, "alloc-r-prep") \
- EM(netfs_trace_folioq_alloc_read_prime, "alloc-r-prime") \
- EM(netfs_trace_folioq_alloc_read_sing, "alloc-r-sing") \
+ EM(netfs_trace_folioq_alloc_buffer, "alloc-buf") \
EM(netfs_trace_folioq_clear, "clear") \
EM(netfs_trace_folioq_delete, "delete") \
EM(netfs_trace_folioq_make_space, "make-space") \
next prev parent reply other threads:[~2024-10-24 14:08 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-24 14:04 [PATCH 00/27] netfs: Read performance improvements and "single-blob" support David Howells
2024-10-24 14:04 ` [PATCH 01/27] netfs: Remove call to folio_index() David Howells
2024-10-24 14:05 ` [PATCH 02/27] netfs: Fix a few minor bugs in netfs_page_mkwrite() David Howells
2024-10-24 14:05 ` [PATCH 03/27] netfs: Remove unnecessary references to pages David Howells
2024-10-24 14:05 ` [PATCH 04/27] netfs: Use a folio_queue allocation and free functions David Howells
2024-10-24 14:05 ` [PATCH 05/27] netfs: Add a tracepoint to log the lifespan of folio_queue structs David Howells
2024-10-24 14:05 ` [PATCH 06/27] netfs: Abstract out a rolling folio buffer implementation David Howells
2024-10-24 14:05 ` [PATCH 07/27] netfs: Make netfs_advance_write() return size_t David Howells
2024-10-24 14:05 ` [PATCH 08/27] netfs: Split retry code out of fs/netfs/write_collect.c David Howells
2024-10-24 14:05 ` [PATCH 09/27] netfs: Drop the error arg from netfs_read_subreq_terminated() David Howells
2024-10-24 14:05 ` [PATCH 10/27] netfs: Drop the was_async " David Howells
2024-10-24 14:05 ` [PATCH 11/27] netfs: Don't use bh spinlock David Howells
2024-10-24 14:05 ` [PATCH 12/27] afs: Don't use mutex for I/O operation lock David Howells
2024-10-24 14:05 ` [PATCH 13/27] afs: Fix EEXIST error returned from afs_rmdir() to be ENOTEMPTY David Howells
2024-10-24 14:05 ` [PATCH 14/27] afs: Fix directory format encoding struct David Howells
2024-10-24 14:05 ` [PATCH 15/27] netfs: Remove some extraneous directory invalidations David Howells
2024-10-24 14:05 ` [PATCH 16/27] cachefiles: Add some subrequest tracepoints David Howells
2024-10-24 14:05 ` [PATCH 17/27] cachefiles: Add auxiliary data trace David Howells
2024-10-24 14:05 ` [PATCH 18/27] afs: Add more tracepoints to do with tracking validity David Howells
2024-10-24 14:05 ` David Howells [this message]
2024-10-24 14:05 ` [PATCH 20/27] netfs: Add support for caching single monolithic objects such as AFS dirs David Howells
2024-10-24 14:05 ` [PATCH 21/27] afs: Make afs_init_request() get a key if not given a file David Howells
2024-10-24 14:05 ` [PATCH 22/27] afs: Use netfslib for directories David Howells
2024-10-24 14:05 ` [PATCH 23/27] afs: Use netfslib for symlinks, allowing them to be cached David Howells
2024-10-24 14:05 ` [PATCH 24/27] afs: Eliminate afs_read David Howells
2024-10-24 14:05 ` [PATCH 25/27] afs: Make {Y,}FS.FetchData an asynchronous operation David Howells
2024-10-24 14:05 ` [PATCH 26/27] netfs: Change the read result collector to only use one work item David Howells
2024-10-24 14:05 ` [PATCH 27/27] afs: Make afs_mkdir() locally initialise a new directory's content David Howells
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=20241024140539.3828093-20-dhowells@redhat.com \
--to=dhowells@redhat.com \
--cc=asmadeus@codewreck.org \
--cc=ceph-devel@vger.kernel.org \
--cc=christian@brauner.io \
--cc=ericvh@kernel.org \
--cc=hsiangkao@linux.alibaba.com \
--cc=idryomov@gmail.com \
--cc=jlayton@kernel.org \
--cc=linux-afs@lists.infradead.org \
--cc=linux-cifs@vger.kernel.org \
--cc=linux-erofs@lists.ozlabs.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-nfs@vger.kernel.org \
--cc=marc.dionne@auristor.com \
--cc=netdev@vger.kernel.org \
--cc=netfs@lists.linux.dev \
--cc=pc@manguebit.com \
--cc=smfrench@gmail.com \
--cc=sprasad@microsoft.com \
--cc=tom@talpey.com \
--cc=v9fs@lists.linux.dev \
--cc=willy@infradead.org \
/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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox