From: David Howells <dhowells@redhat.com>
To: Christian Brauner <christian@brauner.io>,
Matthew Wilcox <willy@infradead.org>,
Christoph Hellwig <hch@infradead.org>
Cc: David Howells <dhowells@redhat.com>,
Paulo Alcantara <pc@manguebit.org>, Jens Axboe <axboe@kernel.dk>,
Leon Romanovsky <leon@kernel.org>,
Steve French <sfrench@samba.org>,
ChenXiaoSong <chenxiaosong@chenxiaosong.com>,
Marc Dionne <marc.dionne@auristor.com>,
Eric Van Hensbergen <ericvh@kernel.org>,
Dominique Martinet <asmadeus@codewreck.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-kernel@vger.kernel.org
Subject: [PATCH v4 30/30] CHANGES
Date: Tue, 16 Jun 2026 11:08:19 +0100 [thread overview]
Message-ID: <20260616100821.2062304-31-dhowells@redhat.com> (raw)
In-Reply-To: <20260616100821.2062304-1-dhowells@redhat.com>
---
fs/netfs/iterator.c | 22 ++++++++++++++--------
fs/netfs/read_retry.c | 12 +++++++++---
fs/netfs/write_issue.c | 24 ++++++++++++++++++++++--
fs/netfs/write_retry.c | 23 ++++++++++++++---------
fs/nfs/fscache.c | 3 ++-
fs/smb/client/file.c | 2 +-
6 files changed, 62 insertions(+), 24 deletions(-)
diff --git a/fs/netfs/iterator.c b/fs/netfs/iterator.c
index d464e1784b8a..5e8e816eeff3 100644
--- a/fs/netfs/iterator.c
+++ b/fs/netfs/iterator.c
@@ -33,8 +33,8 @@
* the original iterator will have been advanced by the amount extracted.
*
* If an error occurs and no pages are extracted, an error will be returned and
- * any allocated bvecq will be freed. The allocated bvecq will also be freed
- * if no pages are extracted, but no error is recorded.
+ * any allocated bvecq will be freed. If there is no data to be extracted (or
+ * @max_len or @max_pages are zero), a single empty bvecq will be returned.
*
* The bvecq segments are marked with indications on how to get clean up the
* extracted fragments.
@@ -43,7 +43,7 @@ ssize_t netfs_extract_iter(struct iov_iter *orig, size_t max_len, size_t max_pag
unsigned long long fpos, struct bvecq **_bvecq_head,
iov_iter_extraction_t extraction_flags)
{
- struct bvecq *bq_tail = NULL;
+ struct bvecq *bq_tail = NULL, *bq;
ssize_t ret = 0;
size_t extracted = 0;
@@ -53,15 +53,13 @@ ssize_t netfs_extract_iter(struct iov_iter *orig, size_t max_len, size_t max_pag
if (max_len > orig->count)
max_len = orig->count;
if (WARN_ON_ONCE(!max_len || !max_pages))
- return 0;
+ goto alloc_empty;
max_pages = iov_iter_npages(orig, max_pages);
if (!max_pages)
- return 0;
+ goto alloc_empty;
do {
- struct bvecq *bq;
-
bq = bvecq_alloc_one(max_pages, GFP_NOFS);
if (!bq) {
ret = -ENOMEM;
@@ -142,10 +140,18 @@ ssize_t netfs_extract_iter(struct iov_iter *orig, size_t max_len, size_t max_pag
} while (max_len > 0 && max_pages > 0);
out:
- if (extracted)
+ if (extracted || ret == 0)
return extracted;
bvecq_put(*_bvecq_head);
*_bvecq_head = NULL;
return ret;
+
+alloc_empty:
+ bq = bvecq_alloc_one(1, GFP_NOFS);
+ if (!bq)
+ return -ENOMEM;
+ *_bvecq_head = bq;
+ return 0;
+
}
EXPORT_SYMBOL_GPL(netfs_extract_iter);
diff --git a/fs/netfs/read_retry.c b/fs/netfs/read_retry.c
index a5cd6e20cae1..0f8ff53fe703 100644
--- a/fs/netfs/read_retry.c
+++ b/fs/netfs/read_retry.c
@@ -79,11 +79,12 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
if (rreq->netfs_ops->retry_request)
rreq->netfs_ops->retry_request(rreq, NULL);
+ /* Read pointer to subreq before reading subreq state. */
+ next = smp_load_acquire(&stream->subrequests.next);
+
/* Renegotiate all the download requests and flip any failed cache
* reads over to being download requests and negotiate those also.
*/
- next = stream->subrequests.next;
-
do {
struct netfs_io_subrequest *from, *to, *tmp;
unsigned long long start;
@@ -110,7 +111,12 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
goto abandon;
}
- list_for_each_continue(next, &stream->subrequests) {
+ for (;;) {
+ /* Read pointer to subreq before reading subreq state. */
+ next = smp_load_acquire(&next->next);
+ if (next == &stream->subrequests)
+ break;
+
subreq = list_entry(next, struct netfs_io_subrequest, rreq_link);
if (subreq->start != start + len ||
subreq->transferred > 0 ||
diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c
index e2e35d619119..37e5b5ee1cea 100644
--- a/fs/netfs/write_issue.c
+++ b/fs/netfs/write_issue.c
@@ -722,6 +722,20 @@ static int netfs_queue_wb_folio(struct netfs_io_request *wreq,
goto out;
}
+static void writeback_iter_cancel(struct address_space *mapping,
+ struct writeback_control *wbc,
+ struct folio *folio, int *error,
+ bool unlocked)
+{
+ do {
+ if (!unlocked) {
+ folio_redirty_for_writepage(wbc, folio);
+ folio_unlock(folio);
+ unlocked = false;
+ }
+ } while ((folio = writeback_iter(mapping, wbc, folio, error)));
+}
+
/*
* Write some of the pending data back to the server
*/
@@ -776,11 +790,15 @@ int netfs_writepages(struct address_space *mapping,
params.notes &= NOTES__KEEP_MASK;
error = netfs_queue_wb_folio(wreq, wbc, folio, ¶ms);
- if (error < 0)
+ if (error < 0) {
+ writeback_iter_cancel(mapping, wbc, folio, &error, false);
break;
+ }
error = netfs_issue_streams(wreq, ¶ms);
- if (error < 0)
+ if (error < 0) {
+ writeback_iter_cancel(mapping, wbc, folio, &error, true);
break;
+ }
bvecq_pos_step(¶ms.dispatch_cursor);
} while ((folio = writeback_iter(mapping, wbc, folio, &error)));
@@ -924,6 +942,7 @@ int netfs_advance_writethrough(struct netfs_writethrough *wthru,
folio_put(wthru->in_progress);
wthru->in_progress = NULL;
wreq->submitted = wreq->len;
+ bvecq_pos_step(&wthru->params.dispatch_cursor);
return ret;
}
@@ -945,6 +964,7 @@ ssize_t netfs_end_writethrough(struct netfs_writethrough *wthru,
ret = netfs_queue_wb_folio(wreq, wbc, folio, &wthru->params);
if (ret == 0)
ret = netfs_issue_streams(wreq, &wthru->params);
+ bvecq_pos_step(&wthru->params.dispatch_cursor);
folio_put(folio);
wthru->in_progress = NULL;
wreq->submitted = wreq->len;
diff --git a/fs/netfs/write_retry.c b/fs/netfs/write_retry.c
index e7955cc707e0..d9cc49f21346 100644
--- a/fs/netfs/write_retry.c
+++ b/fs/netfs/write_retry.c
@@ -23,7 +23,6 @@ int netfs_prepare_write_retry_buffer(struct netfs_io_subrequest *subreq,
unsigned int max_segs)
{
struct netfs_io_request *wreq = subreq->rreq;
- struct netfs_io_stream *stream = &wreq->io_streams[subreq->stream_nr];
size_t len;
bvecq_pos_set(&subreq->dispatch_pos, &wreq->retry_cursor);
@@ -35,9 +34,9 @@ int netfs_prepare_write_retry_buffer(struct netfs_io_subrequest *subreq,
trace_netfs_sreq(subreq, netfs_sreq_trace_limited);
}
- stream->issue_from += len;
- stream->buffered -= len;
- if (stream->buffered == 0)
+ wreq->retry_start += len;
+ wreq->retry_buffered -= len;
+ if (wreq->retry_buffered == 0)
bvecq_pos_unset(&wreq->retry_cursor);
return 0;
}
@@ -63,7 +62,8 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
if (unlikely(stream->failed))
return;
- next = stream->subrequests.next;
+ /* Read pointer to subreq before reading subreq state. */
+ next = smp_load_acquire(&stream->subrequests.next);
do {
struct netfs_io_subrequest *subreq = NULL, *from, *to, *tmp;
@@ -84,7 +84,12 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
!test_bit(NETFS_SREQ_NEED_RETRY, &from->flags))
goto out;
- list_for_each_continue(next, &stream->subrequests) {
+ for (;;) {
+ /* Read pointer to subreq before reading subreq state. */
+ next = smp_load_acquire(&next->next);
+ if (next == &stream->subrequests)
+ break;
+
subreq = list_entry(next, struct netfs_io_subrequest, rreq_link);
if (subreq->start != start + len ||
subreq->transferred > 0 ||
@@ -135,7 +140,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
/* If we managed to use fewer subreqs, we can discard the
* excess; if we used the same number, then we're done.
*/
- if (!len) {
+ if (!wreq->retry_buffered) {
if (subreq == to)
continue;
list_for_each_entry_safe_from(subreq, tmp,
@@ -158,7 +163,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
subreq = netfs_alloc_subrequest(wreq);
subreq->source = to->source;
subreq->start = start;
- subreq->len = len;
+ subreq->len = wreq->retry_buffered;
subreq->stream_nr = to->stream_nr;
subreq->retry_count = 1;
@@ -188,7 +193,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
trace_netfs_sreq(subreq, netfs_sreq_trace_retry);
stream->issue_write(subreq);
- } while (len);
+ } while (wreq->retry_buffered > 0);
} while (!list_is_head(next, &stream->subrequests));
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index cf750faaec6a..f39a351c566d 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -324,7 +324,7 @@ static void nfs_netfs_issue_read(struct netfs_io_subrequest *sreq)
netfs = nfs_netfs_alloc(sreq);
if (!netfs) {
- sreq->error = err;
+ sreq->error = -ENOMEM;
goto term;
}
@@ -343,6 +343,7 @@ static void nfs_netfs_issue_read(struct netfs_io_subrequest *sreq)
out:
nfs_pageio_complete_read(&pgio);
nfs_netfs_put(netfs);
+ return;
term:
return netfs_read_subreq_terminated(sreq);
}
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index d3a9041786ac..b770c349137a 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -222,7 +222,7 @@ static void cifs_issue_read(struct netfs_io_subrequest *subreq)
rc = cifs_reopen_file(req->cfile, true);
} while (rc == -EAGAIN);
if (rc)
- goto failed;
+ goto fail_with_credits;
}
if (subreq->rreq->origin != NETFS_UNBUFFERED_READ &&
next prev parent reply other threads:[~2026-06-16 10:12 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-16 10:07 [PATCH v4 00/30] netfs: Keep track of folios in a segmented bio_vec[] chain David Howells
2026-06-16 10:07 ` [PATCH v4 01/30] netfs: Fix decision whether to disallow write-streaming due to fscache use David Howells
2026-06-16 10:07 ` [PATCH v4 02/30] cachefiles: Fix double fput David Howells
2026-06-16 10:07 ` [PATCH v4 03/30] iov_iter: Fix potential underflow in iov_iter_extract_xarray_pages() David Howells
2026-06-16 10:07 ` [PATCH v4 04/30] iov_iter: Fix missing alloc fail check in iov_iter_extract_bvec_pages() David Howells
2026-06-16 10:07 ` [PATCH v4 05/30] iov_iter: Remove unused variable in kunit_iov_iter.c David Howells
2026-06-16 10:07 ` [PATCH v4 06/30] scatterlist: Fix offset in folio calc in extract_xarray_to_sg() David Howells
2026-06-16 10:07 ` [PATCH v4 07/30] netfs: Replace wb_lock with a bit lock for asynchronicity David Howells
2026-06-16 10:07 ` [PATCH v4 08/30] netfs: Fix kdoc warning David Howells
2026-06-16 10:07 ` [PATCH v4 09/30] cachefiles: Don't rely on backing fs storage map for most use cases David Howells
2026-06-16 10:07 ` [PATCH v4 10/30] netfs: Add the cache object ID to netfs_read/write tracepoints David Howells
2026-06-16 10:08 ` [PATCH v4 11/30] mm: Make readahead store folio count in readahead_control David Howells
2026-06-16 10:08 ` [PATCH v4 12/30] netfs: Bulk load the readahead-provided folios up front David Howells
2026-06-16 10:08 ` [PATCH v4 13/30] Add a function to kmap one page of a multipage bio_vec David Howells
2026-06-16 10:08 ` [PATCH v4 14/30] iov_iter: Make iov_iter_get_pages*() wrap iov_iter_extract_pages() David Howells
2026-06-16 10:08 ` [PATCH v4 15/30] iov_iter: Add a segmented queue of bio_vec[] David Howells
2026-06-16 10:08 ` [PATCH v4 16/30] netfs: Add some tools for managing bvecq chains David Howells
2026-06-16 10:08 ` [PATCH v4 17/30] netfs: Add a function to extract from an iter into a bvecq David Howells
2026-06-16 10:08 ` [PATCH v4 18/30] afs: Use a bvecq to hold dir content rather than folioq David Howells
2026-06-16 10:08 ` [PATCH v4 19/30] cifs: Use a bvecq for buffering instead of a folioq David Howells
2026-06-16 10:08 ` [PATCH v4 20/30] smbdirect: Support ITER_BVECQ in smbdirect_map_sges_from_iter() David Howells
2026-06-16 10:08 ` [PATCH v4 21/30] netfs: Switch to using bvecq rather than folio_queue and rolling_buffer David Howells
2026-06-16 10:08 ` [PATCH v4 22/30] smbdirect: Remove support for ITER_FOLIOQ from smbdirect_map_sges_from_iter() David Howells
2026-06-16 10:08 ` [PATCH v4 23/30] netfs: Remove netfs_alloc/free_folioq_buffer() David Howells
2026-06-16 10:08 ` [PATCH v4 24/30] netfs: Remove netfs_extract_user_iter() David Howells
2026-06-16 10:08 ` [PATCH v4 25/30] iov_iter: Remove ITER_FOLIOQ David Howells
2026-06-16 10:08 ` [PATCH v4 26/30] netfs: Remove folio_queue and rolling_buffer David Howells
2026-06-16 10:08 ` [PATCH v4 27/30] netfs: Check for too much data being read David Howells
2026-06-16 10:08 ` [PATCH v4 28/30] netfs: Limit the minimum trigger for progress reporting David Howells
2026-06-16 10:08 ` [PATCH v4 29/30] netfs: Combine prepare and issue ops and grab the buffers on request David Howells
2026-06-16 10:08 ` David Howells [this message]
2026-06-16 12:47 ` [PATCH v4 30/30] CHANGES ChenXiaoSong
2026-06-16 12:51 ` David Howells
2026-06-16 12:38 ` [PATCH v4 00/30] netfs: Keep track of folios in a segmented bio_vec[] chain Christoph Hellwig
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=20260616100821.2062304-31-dhowells@redhat.com \
--to=dhowells@redhat.com \
--cc=asmadeus@codewreck.org \
--cc=axboe@kernel.dk \
--cc=ceph-devel@vger.kernel.org \
--cc=chenxiaosong@chenxiaosong.com \
--cc=christian@brauner.io \
--cc=ericvh@kernel.org \
--cc=hch@infradead.org \
--cc=idryomov@gmail.com \
--cc=leon@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-nfs@vger.kernel.org \
--cc=marc.dionne@auristor.com \
--cc=netfs@lists.linux.dev \
--cc=pc@manguebit.org \
--cc=sfrench@samba.org \
--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
all inboxes | Powered by JetHome®