From: "Darrick J. Wong" <djwong@kernel.org>
To: Joanne Koong <joannelkoong@gmail.com>
Cc: brauner@kernel.org, miklos@szeredi.hu, hch@infradead.org,
hsiangkao@linux.alibaba.com, linux-block@vger.kernel.org,
gfs2@lists.linux.dev, linux-fsdevel@vger.kernel.org,
kernel-team@meta.com, linux-xfs@vger.kernel.org,
linux-doc@vger.kernel.org
Subject: Re: [PATCH v3 10/15] iomap: add bias for async read requests
Date: Thu, 18 Sep 2025 15:30:18 -0700 [thread overview]
Message-ID: <20250918223018.GY1587915@frogsfrogsfrogs> (raw)
In-Reply-To: <20250916234425.1274735-11-joannelkoong@gmail.com>
On Tue, Sep 16, 2025 at 04:44:20PM -0700, Joanne Koong wrote:
> Non-block-based filesystems will be using iomap read/readahead. If they
> handle reading in ranges asynchronously and fulfill those read requests
> on an ongoing basis (instead of all together at the end), then there is
> the possibility that the read on the folio may be prematurely ended if
> earlier async requests complete before the later ones have been issued.
>
> For example if there is a large folio and a readahead request for 16
> pages in that folio, if doing readahead on those 16 pages is split into
> 4 async requests and the first request is sent off and then completed
> before we have sent off the second request, then when the first request
> calls iomap_finish_folio_read(), ifs->read_bytes_pending would be 0,
> which would end the read and unlock the folio prematurely.
>
> To mitigate this, a "bias" is added to ifs->read_bytes_pending before
> the first range is forwarded to the caller and removed after the last
> range has been forwarded.
>
> iomap writeback does this with their async requests as well to prevent
> prematurely ending writeback.
>
> Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
> ---
> fs/iomap/buffered-io.c | 55 ++++++++++++++++++++++++++++++++++++------
> 1 file changed, 47 insertions(+), 8 deletions(-)
>
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index 561378f2b9bb..667a49cb5ae5 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -420,6 +420,38 @@ const struct iomap_read_ops iomap_bio_read_ops = {
> };
> EXPORT_SYMBOL_GPL(iomap_bio_read_ops);
>
> +/*
> + * Add a bias to ifs->read_bytes_pending to prevent the read on the folio from
> + * being ended prematurely.
> + *
> + * Otherwise, if the ranges are read asynchronously and read requests are
> + * fulfilled on an ongoing basis, there is the possibility that the read on the
> + * folio may be prematurely ended if earlier async requests complete before the
> + * later ones have been issued.
> + */
> +static void iomap_read_add_bias(struct folio *folio)
> +{
> + iomap_start_folio_read(folio, 1);
I wonder, could you achieve the same effect by elevating
read_bytes_pending by the number of bytes that we think we have to read,
and subtracting from it as the completions come in or we decide that no
read is necessary?
(That might just be overthinking the plumbing though)
--D
> +}
> +
> +static void iomap_read_remove_bias(struct folio *folio, bool *cur_folio_owned)
> +{
> + struct iomap_folio_state *ifs = folio->private;
> + bool finished, uptodate;
> +
> + if (ifs) {
> + spin_lock_irq(&ifs->state_lock);
> + ifs->read_bytes_pending -= 1;
> + finished = !ifs->read_bytes_pending;
> + if (finished)
> + uptodate = ifs_is_fully_uptodate(folio, ifs);
> + spin_unlock_irq(&ifs->state_lock);
> + if (finished)
> + folio_end_read(folio, uptodate);
> + *cur_folio_owned = true;
> + }
> +}
> +
> static int iomap_read_folio_iter(struct iomap_iter *iter,
> struct iomap_read_folio_ctx *ctx, bool *cur_folio_owned)
> {
> @@ -429,7 +461,7 @@ static int iomap_read_folio_iter(struct iomap_iter *iter,
> struct folio *folio = ctx->cur_folio;
> size_t poff, plen;
> loff_t delta;
> - int ret;
> + int ret = 0;
>
> if (iomap->type == IOMAP_INLINE) {
> ret = iomap_read_inline_data(iter, folio);
> @@ -441,6 +473,8 @@ static int iomap_read_folio_iter(struct iomap_iter *iter,
> /* zero post-eof blocks as the page may be mapped */
> ifs_alloc(iter->inode, folio, iter->flags);
>
> + iomap_read_add_bias(folio);
> +
> length = min_t(loff_t, length,
> folio_size(folio) - offset_in_folio(folio, pos));
> while (length) {
> @@ -448,16 +482,18 @@ static int iomap_read_folio_iter(struct iomap_iter *iter,
> &plen);
>
> delta = pos - iter->pos;
> - if (WARN_ON_ONCE(delta + plen > length))
> - return -EIO;
> + if (WARN_ON_ONCE(delta + plen > length)) {
> + ret = -EIO;
> + break;
> + }
> length -= delta + plen;
>
> ret = iomap_iter_advance(iter, &delta);
> if (ret)
> - return ret;
> + break;
>
> if (plen == 0)
> - return 0;
> + break;
>
> if (iomap_block_needs_zeroing(iter, pos)) {
> folio_zero_range(folio, poff, plen);
> @@ -466,16 +502,19 @@ static int iomap_read_folio_iter(struct iomap_iter *iter,
> *cur_folio_owned = true;
> ret = ctx->ops->read_folio_range(iter, ctx, plen);
> if (ret)
> - return ret;
> + break;
> }
>
> delta = plen;
> ret = iomap_iter_advance(iter, &delta);
> if (ret)
> - return ret;
> + break;
> pos = iter->pos;
> }
> - return 0;
> +
> + iomap_read_remove_bias(folio, cur_folio_owned);
> +
> + return ret;
> }
>
> int iomap_read_folio(const struct iomap_ops *ops,
> --
> 2.47.3
>
>
next prev parent reply other threads:[~2025-09-18 22:30 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-16 23:44 [PATCH v3 00/15] fuse: use iomap for buffered reads + readahead Joanne Koong
2025-09-16 23:44 ` [PATCH v3 01/15] iomap: move bio read logic into helper function Joanne Koong
2025-09-18 21:27 ` Darrick J. Wong
2025-09-16 23:44 ` [PATCH v3 02/15] iomap: move read/readahead bio submission " Joanne Koong
2025-09-18 21:27 ` Darrick J. Wong
2025-09-16 23:44 ` [PATCH v3 03/15] iomap: store read/readahead bio generically Joanne Koong
2025-09-18 21:29 ` Darrick J. Wong
2025-09-16 23:44 ` [PATCH v3 04/15] iomap: iterate over entire folio in iomap_readpage_iter() Joanne Koong
2025-09-18 21:37 ` Darrick J. Wong
2025-09-22 22:33 ` Joanne Koong
2025-09-16 23:44 ` [PATCH v3 05/15] iomap: rename iomap_readpage_iter() to iomap_read_folio_iter() Joanne Koong
2025-09-16 23:44 ` [PATCH v3 06/15] iomap: rename iomap_readpage_ctx struct to iomap_read_folio_ctx Joanne Koong
2025-09-16 23:44 ` [PATCH v3 07/15] iomap: track read/readahead folio ownership internally Joanne Koong
2025-09-18 21:49 ` Darrick J. Wong
2025-09-19 18:14 ` Joanne Koong
2025-09-16 23:44 ` [PATCH v3 08/15] iomap: add public start/finish folio read helpers Joanne Koong
2025-09-16 23:44 ` [PATCH v3 09/15] iomap: add caller-provided callbacks for read and readahead Joanne Koong
2025-09-16 23:44 ` [PATCH v3 10/15] iomap: add bias for async read requests Joanne Koong
2025-09-18 22:30 ` Darrick J. Wong [this message]
2025-09-19 18:34 ` Joanne Koong
2025-09-22 18:33 ` Christoph Hellwig
2025-09-22 20:54 ` Matthew Wilcox
2025-09-24 22:56 ` Joanne Koong
2025-09-22 23:19 ` Joanne Koong
2025-09-16 23:44 ` [PATCH v3 11/15] iomap: move buffered io bio logic into new file Joanne Koong
2025-09-17 21:40 ` kernel test robot
2025-09-18 22:31 ` Darrick J. Wong
2025-09-19 15:33 ` Christoph Hellwig
2025-09-19 15:32 ` Christoph Hellwig
2025-09-16 23:44 ` [PATCH v3 12/15] iomap: make iomap_read_folio() a void return Joanne Koong
2025-09-18 21:55 ` Darrick J. Wong
2025-09-16 23:44 ` [PATCH v3 13/15] fuse: use iomap for read_folio Joanne Koong
2025-09-16 23:44 ` [PATCH v3 14/15] fuse: use iomap for readahead Joanne Koong
2025-09-18 22:35 ` Darrick J. Wong
2025-09-16 23:44 ` [PATCH v3 15/15] fuse: remove fc->blkbits workaround for partial writes Joanne Koong
2025-09-18 22:35 ` Darrick J. Wong
2025-09-17 8:30 ` [syzbot ci] Re: fuse: use iomap for buffered reads + readahead syzbot ci
2025-09-17 19:59 ` Joanne Koong
2025-09-18 15:48 ` Aleksandr Nogikh
2025-09-18 21:15 ` Joanne Koong
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=20250918223018.GY1587915@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=brauner@kernel.org \
--cc=gfs2@lists.linux.dev \
--cc=hch@infradead.org \
--cc=hsiangkao@linux.alibaba.com \
--cc=joannelkoong@gmail.com \
--cc=kernel-team@meta.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
/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