stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [5.15 REGRESSION] iomap: Fix inline extent handling in iomap_readpage
@ 2021-11-10 11:38 Andreas Gruenbacher
  2021-11-10 12:55 ` Christoph Hellwig
  0 siblings, 1 reply; 5+ messages in thread
From: Andreas Gruenbacher @ 2021-11-10 11:38 UTC (permalink / raw)
  To: Christoph Hellwig, Darrick J . Wong
  Cc: linux-xfs, linux-fsdevel, cluster-devel, Andreas Gruenbacher, stable

When reporting IOMAP_INLINE extents, filesystems set iomap->length to
the length of iomap->inline_data.  For reading that into the page cache,
function iomap_read_inline_data copies the inline data, zeroes out the
rest of the page, and marks the entire page up-to-date.

Before commit 740499c78408 ("iomap: fix the iomap_readpage_actor return
value for inline data"), when hitting an IOMAP_INLINE extent,
iomap_readpage_actor would report having read the entire page.  Since
then, it only reports having read the inline data (iomap->length).

This will force iomap_readpage into another iteration, and the
filesystem will report an unaligned hole after the IOMAP_INLINE extent.
But iomap_readpage_actor (now iomap_readpage_iter) isn't prepared to
deal with unaligned extents, it will get things wrong on filesystems
with a block size smaller than the page size, and we'll eventually run
into the following warning in iomap_iter_advance:

  WARN_ON_ONCE(iter->processed > iomap_length(iter));

Fix that by changing iomap_readpage_iter back to report that we've read
the entire page, which avoids having to deal with unaligned extents.  To
prevent iomap from complaining about running past the end of the extent,
fix up the extent size as well.

Fixes: 740499c78408 ("iomap: fix the iomap_readpage_actor return value for inline data")
Cc: stable@vger.kernel.org # v5.15+
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/iomap/buffered-io.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 1753c26c8e76..de3fcd2522a2 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -244,10 +244,10 @@ static inline bool iomap_block_needs_zeroing(const struct iomap_iter *iter,
 		pos >= i_size_read(iter->inode);
 }
 
-static loff_t iomap_readpage_iter(const struct iomap_iter *iter,
+static loff_t iomap_readpage_iter(struct iomap_iter *iter,
 		struct iomap_readpage_ctx *ctx, loff_t offset)
 {
-	const struct iomap *iomap = &iter->iomap;
+	struct iomap *iomap = &iter->iomap;
 	loff_t pos = iter->pos + offset;
 	loff_t length = iomap_length(iter) - offset;
 	struct page *page = ctx->cur_page;
@@ -256,8 +256,15 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter,
 	unsigned poff, plen;
 	sector_t sector;
 
-	if (iomap->type == IOMAP_INLINE)
-		return min(iomap_read_inline_data(iter, page), length);
+	if (iomap->type == IOMAP_INLINE) {
+		/*
+		 * The filesystem sets iomap->length to the size of the inline
+		 * data.  We're at the end of the file, so we know that the
+		 * rest of the page needs to be zeroed out.
+		 */
+		iomap->length = iomap_read_inline_data(iter, page);
+		return iomap->length;
+	}
 
 	/* zero post-eof blocks as the page may be mapped */
 	iop = iomap_page_create(iter->inode, page);
@@ -352,7 +359,7 @@ iomap_readpage(struct page *page, const struct iomap_ops *ops)
 }
 EXPORT_SYMBOL_GPL(iomap_readpage);
 
-static loff_t iomap_readahead_iter(const struct iomap_iter *iter,
+static loff_t iomap_readahead_iter(struct iomap_iter *iter,
 		struct iomap_readpage_ctx *ctx)
 {
 	loff_t length = iomap_length(iter);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [5.15 REGRESSION] iomap: Fix inline extent handling in iomap_readpage
  2021-11-10 11:38 [5.15 REGRESSION] iomap: Fix inline extent handling in iomap_readpage Andreas Gruenbacher
@ 2021-11-10 12:55 ` Christoph Hellwig
  2021-11-10 14:52   ` Andreas Gruenbacher
  0 siblings, 1 reply; 5+ messages in thread
From: Christoph Hellwig @ 2021-11-10 12:55 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Christoph Hellwig, Darrick J . Wong, linux-xfs, linux-fsdevel,
	cluster-devel, stable

On Wed, Nov 10, 2021 at 12:38:42PM +0100, Andreas Gruenbacher wrote:
> +	if (iomap->type == IOMAP_INLINE) {
> +		/*
> +		 * The filesystem sets iomap->length to the size of the inline
> +		 * data.  We're at the end of the file, so we know that the
> +		 * rest of the page needs to be zeroed out.
> +		 */
> +		iomap->length = iomap_read_inline_data(iter, page);
> +		return iomap->length;

You can't just change iomap->length here.  Fix the file system to
return the right length, please.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [5.15 REGRESSION] iomap: Fix inline extent handling in iomap_readpage
  2021-11-10 12:55 ` Christoph Hellwig
@ 2021-11-10 14:52   ` Andreas Gruenbacher
  2021-11-11  7:25     ` Christoph Hellwig
  0 siblings, 1 reply; 5+ messages in thread
From: Andreas Gruenbacher @ 2021-11-10 14:52 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Darrick J . Wong, linux-xfs, linux-fsdevel, cluster-devel, stable

On Wed, Nov 10, 2021 at 1:55 PM Christoph Hellwig <hch@lst.de> wrote:
> On Wed, Nov 10, 2021 at 12:38:42PM +0100, Andreas Gruenbacher wrote:
> > +     if (iomap->type == IOMAP_INLINE) {
> > +             /*
> > +              * The filesystem sets iomap->length to the size of the inline
> > +              * data.  We're at the end of the file, so we know that the
> > +              * rest of the page needs to be zeroed out.
> > +              */
> > +             iomap->length = iomap_read_inline_data(iter, page);
> > +             return iomap->length;
>
> You can't just change iomap->length here.  Fix the file system to
> return the right length, please.

Hmm, that doesn't make sense to me: the filesystem doesn't know that
iomap_readpage will pad to page boundaries. This happens at the iomap
layer, so the iomap layer should also deal with the consequences.
We're using different alignment rules here and for direct I/O, so that
makes fake-aligning the extent size in iomap_begin even more
questionable.

"Fixing" the extent size the filesystem returns would also break
direct I/O. We could add some additional padding code to
iomap_dio_inline_iter to deal with that, but currently, there's no
need for that.

Thanks,
Andreas


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [5.15 REGRESSION] iomap: Fix inline extent handling in iomap_readpage
  2021-11-10 14:52   ` Andreas Gruenbacher
@ 2021-11-11  7:25     ` Christoph Hellwig
  2021-11-11 16:21       ` Andreas Grünbacher
  0 siblings, 1 reply; 5+ messages in thread
From: Christoph Hellwig @ 2021-11-11  7:25 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Christoph Hellwig, Darrick J . Wong, linux-xfs, linux-fsdevel,
	cluster-devel, stable

On Wed, Nov 10, 2021 at 03:52:01PM +0100, Andreas Gruenbacher wrote:
> Hmm, that doesn't make sense to me: the filesystem doesn't know that
> iomap_readpage will pad to page boundaries. This happens at the iomap
> layer, so the iomap layer should also deal with the consequences.
> We're using different alignment rules here and for direct I/O, so that
> makes fake-aligning the extent size in iomap_begin even more
> questionable.
> 
> "Fixing" the extent size the filesystem returns would also break
> direct I/O. We could add some additional padding code to
> iomap_dio_inline_iter to deal with that, but currently, there's no
> need for that.

The iomap mapping sizes are read-only to iomap for a good reason.  You
can't just break that design.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [5.15 REGRESSION] iomap: Fix inline extent handling in iomap_readpage
  2021-11-11  7:25     ` Christoph Hellwig
@ 2021-11-11 16:21       ` Andreas Grünbacher
  0 siblings, 0 replies; 5+ messages in thread
From: Andreas Grünbacher @ 2021-11-11 16:21 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Andreas Gruenbacher, Darrick J . Wong, linux-xfs, linux-fsdevel,
	cluster-devel, stable

Am Do., 11. Nov. 2021 um 08:26 Uhr schrieb Christoph Hellwig <hch@lst.de>:
> The iomap mapping sizes are read-only to iomap for a good reason.  You
> can't just break that design.

Right. We can stop iomap_iter by returning 0 now though; see v2.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-11-11 16:21 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-10 11:38 [5.15 REGRESSION] iomap: Fix inline extent handling in iomap_readpage Andreas Gruenbacher
2021-11-10 12:55 ` Christoph Hellwig
2021-11-10 14:52   ` Andreas Gruenbacher
2021-11-11  7:25     ` Christoph Hellwig
2021-11-11 16:21       ` Andreas Grünbacher

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).