netfs.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
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 v4 20/33] netfs: Add functions to build/clean a buffer in a folio_queue
Date: Fri,  8 Nov 2024 17:32:21 +0000	[thread overview]
Message-ID: <20241108173236.1382366-21-dhowells@redhat.com> (raw)
In-Reply-To: <20241108173236.1382366-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")	\


  parent reply	other threads:[~2024-11-08 17:35 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-08 17:32 [PATCH v4 00/33] netfs: Read performance improvements and "single-blob" support David Howells
2024-11-08 17:32 ` [PATCH v4 01/33] kheaders: Ignore silly-rename files David Howells
2024-11-08 17:32 ` [PATCH v4 02/33] netfs: Remove call to folio_index() David Howells
2024-11-08 17:32 ` [PATCH v4 03/33] netfs: Fix a few minor bugs in netfs_page_mkwrite() David Howells
2024-11-08 17:32 ` [PATCH v4 04/33] netfs: Remove unnecessary references to pages David Howells
2024-11-08 17:32 ` [PATCH v4 05/33] netfs: Use a folio_queue allocation and free functions David Howells
2024-11-08 17:32 ` [PATCH v4 06/33] netfs: Add a tracepoint to log the lifespan of folio_queue structs David Howells
2024-11-08 17:32 ` [PATCH v4 07/33] netfs: Abstract out a rolling folio buffer implementation David Howells
2024-11-15 20:01   ` Kees Bakker
2024-11-18 16:39   ` David Howells
2024-11-08 17:32 ` [PATCH v4 08/33] netfs: Make netfs_advance_write() return size_t David Howells
2024-11-08 17:32 ` [PATCH v4 09/33] netfs: Split retry code out of fs/netfs/write_collect.c David Howells
2024-11-08 17:32 ` [PATCH v4 10/33] netfs: Drop the error arg from netfs_read_subreq_terminated() David Howells
2024-11-08 17:32 ` [PATCH v4 11/33] netfs: Drop the was_async " David Howells
2024-11-08 17:32 ` [PATCH v4 12/33] netfs: Don't use bh spinlock David Howells
2024-11-08 17:32 ` [PATCH v4 13/33] afs: Don't use mutex for I/O operation lock David Howells
2024-11-08 17:32 ` [PATCH v4 14/33] afs: Fix EEXIST error returned from afs_rmdir() to be ENOTEMPTY David Howells
2024-11-08 17:32 ` [PATCH v4 15/33] afs: Fix directory format encoding struct David Howells
2024-11-08 17:32 ` [PATCH v4 16/33] netfs: Remove some extraneous directory invalidations David Howells
2024-11-08 17:32 ` [PATCH v4 17/33] cachefiles: Add some subrequest tracepoints David Howells
2024-11-08 17:32 ` [PATCH v4 18/33] cachefiles: Add auxiliary data trace David Howells
2024-11-08 17:32 ` [PATCH v4 19/33] afs: Add more tracepoints to do with tracking validity David Howells
2024-11-08 17:32 ` David Howells [this message]
2024-11-08 17:32 ` [PATCH v4 21/33] netfs: Add support for caching single monolithic objects such as AFS dirs David Howells
2024-11-08 17:32 ` [PATCH v4 22/33] afs: Make afs_init_request() get a key if not given a file David Howells
2024-11-08 17:32 ` [PATCH v4 23/33] afs: Use netfslib for directories David Howells
2024-11-15 20:32   ` Kees Bakker
2024-11-18 16:35   ` David Howells
2024-11-08 17:32 ` [PATCH v4 24/33] afs: Use netfslib for symlinks, allowing them to be cached David Howells
2024-11-08 17:32 ` [PATCH v4 25/33] afs: Eliminate afs_read David Howells
2024-11-08 17:32 ` [PATCH v4 26/33] afs: Fix cleanup of immediately failed async calls David Howells
2024-11-08 17:32 ` [PATCH v4 27/33] afs: Make {Y,}FS.FetchData an asynchronous operation David Howells
2024-11-08 17:32 ` [PATCH v4 28/33] netfs: Change the read result collector to only use one work item David Howells
2024-11-14 16:39   ` Nathan Chancellor
2024-11-18 17:20   ` David Howells
2024-11-08 17:32 ` [PATCH v4 29/33] afs: Make afs_mkdir() locally initialise a new directory's content David Howells
2024-11-08 17:32 ` [PATCH v4 30/33] afs: Use the contained hashtable to search a directory David Howells
2024-11-08 17:32 ` [PATCH v4 31/33] afs: Locally initialise the contents of a new symlink on creation David Howells
2024-11-08 17:32 ` [PATCH v4 32/33] afs: Add a tracepoint for afs_read_receive() David Howells
2024-11-08 17:32 ` [PATCH v4 33/33] netfs: Report on NULL folioq in netfs_writeback_unlock_folios() David Howells
2024-11-11  9:12 ` [PATCH v4 00/33] netfs: Read performance improvements and "single-blob" support Christian Brauner

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=20241108173236.1382366-21-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;
as well as URLs for NNTP newsgroup(s).