diff mbox series

[v2,1/2] iomap: Don't create iomap_page objects for inline files

Message ID 20210705181824.2174165-2-agruenba@redhat.com (mailing list archive)
State Superseded, archived
Headers show
Series iomap: small block problems | expand

Commit Message

Andreas Gruenbacher July 5, 2021, 6:18 p.m. UTC
In iomap_readpage_actor, don't create iop objects for inline inodes.
Otherwise, iomap_read_inline_data will set PageUptodate without setting
iop->uptodate, and iomap_page_release will eventually complain.

To prevent this kind of bug from occurring in the future, make sure the
page doesn't have private data attached in iomap_read_inline_data.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 fs/iomap/buffered-io.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Christoph Hellwig July 6, 2021, 5:03 a.m. UTC | #1
On Mon, Jul 05, 2021 at 08:18:23PM +0200, Andreas Gruenbacher wrote:
> In iomap_readpage_actor, don't create iop objects for inline inodes.
> Otherwise, iomap_read_inline_data will set PageUptodate without setting
> iop->uptodate, and iomap_page_release will eventually complain.
> 
> To prevent this kind of bug from occurring in the future, make sure the
> page doesn't have private data attached in iomap_read_inline_data.
> 
> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
> Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>

As mentioned last round I'd prefer to simply not create the iomap_page
at all in the readpage/readpages path.

Also this patch needs to go after the current patch 2 to be bisection
clean.
Andreas Gruenbacher July 6, 2021, 4:01 p.m. UTC | #2
On Tue, Jul 6, 2021 at 7:07 AM Christoph Hellwig <hch@infradead.org> wrote:
> On Mon, Jul 05, 2021 at 08:18:23PM +0200, Andreas Gruenbacher wrote:
> > In iomap_readpage_actor, don't create iop objects for inline inodes.
> > Otherwise, iomap_read_inline_data will set PageUptodate without setting
> > iop->uptodate, and iomap_page_release will eventually complain.
> >
> > To prevent this kind of bug from occurring in the future, make sure the
> > page doesn't have private data attached in iomap_read_inline_data.
> >
> > Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
> > Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
>
> As mentioned last round I'd prefer to simply not create the iomap_page
> at all in the readpage/readpages path.

I've tried that by replacing the iomap_page_create with to_iomap_page
in iomap_readpage_actor and with that, I'm getting a
VM_BUG_ON_PAGE(!PageLocked(page)) in iomap_read_end_io -> unlock_page
with generic/029. So there's obviously more to it than just not
creating the iomap_page in iomap_readpage_actor.

Getting rid of the iomap_page_create in iomap_readpage_actor
completely isn't a necessary part of the bug fix. So can we focus on
the bug fix for now, and worry about the improvement later?

> Also this patch needs to go after the current patch 2 to be bisection clean.

Yes, makes sense.

Thanks,
Andreas
diff mbox series

Patch

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 9023717c5188..03537ecb2a94 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -215,6 +215,7 @@  iomap_read_inline_data(struct inode *inode, struct page *page,
 	if (PageUptodate(page))
 		return;
 
+	BUG_ON(page_has_private(page));
 	BUG_ON(page->index);
 	BUG_ON(size > PAGE_SIZE - offset_in_page(iomap->inline_data));
 
@@ -239,7 +240,7 @@  iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 {
 	struct iomap_readpage_ctx *ctx = data;
 	struct page *page = ctx->cur_page;
-	struct iomap_page *iop = iomap_page_create(inode, page);
+	struct iomap_page *iop;
 	bool same_page = false, is_contig = false;
 	loff_t orig_pos = pos;
 	unsigned poff, plen;
@@ -252,6 +253,7 @@  iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
 	}
 
 	/* zero post-eof blocks as the page may be mapped */
+	iop = iomap_page_create(inode, page);
 	iomap_adjust_read_range(inode, iop, &pos, length, &poff, &plen);
 	if (plen == 0)
 		goto done;