* [PATCH] erofs: fix metadata reads at the end of file-backed images
@ 2026-10-23 17:42 Hengyu Liang
2026-10-23 18:19 ` Gao Xiang
0 siblings, 1 reply; 2+ messages in thread
From: Hengyu Liang @ 2026-10-23 17:42 UTC (permalink / raw)
To: xiang
Cc: chao, zbestahu, jefflexu, dhavale, hongbohbli, guochunhai,
linux-erofs, linux-kernel, stable
Commit e587a984d332 ("erofs: use dedicated meta inodes for file-backed
mounts") made erofs_read_meta_folio() read the metadata of a
file-backed mount one whole folio at a time.
However, an image only has to be a multiple of its block size. With a
block size below the page size, it can end in the middle of a page. The
read of that last page is then short, and erofs_fileio_ki_complete()
fails it with -EIO. As of now, inodes in the last page of such an image
cannot be read, and an image smaller than a page cannot be mounted.
The issue can be reproduced with util-linux 2.41, whose mount uses the
image file directly:
mkdir src
for i in $(seq 50); do echo $i > src/$i; done
mkfs.erofs -b512 test.erofs src
mount -t erofs test.erofs /mnt
ls -l /mnt
Before that commit, ls -l lists all 50 files. After it, ls -l reports
"Input/output error" for 24 of them.
This patch reads the folio only up to the end of the backing file and
zeroes the rest, as the page cache of the backing file did before.
Fixes: e587a984d332 ("erofs: use dedicated meta inodes for file-backed mounts")
Cc: stable@vger.kernel.org
Signed-off-by: Hengyu Liang <hengyul@cs.unc.edu>
---
Tested in KVM with KASAN on a804c5742bff: file-backed mounts of images
with 512 to 4096 byte blocks, uncompressed and compressed, with and
without directio. With this patch every file reads back correctly;
without it, 24 of the 36 mounts give errors. Not tested on 16K or 64K
page kernels, where 4K-block images should be affected too.
fs/erofs/fileio.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c
index c36a90a1a4cb..b4ed7fe7347c 100644
--- a/fs/erofs/fileio.c
+++ b/fs/erofs/fileio.c
@@ -142,17 +142,26 @@ int erofs_read_meta_folio(struct file *file, struct folio *folio)
.dev = { .m_pa = folio_pos(folio), },
};
struct inode *inode = folio_inode(folio);
+ size_t len = folio_size(folio);
+ loff_t pos, isize;
int err;
err = erofs_map_dev(inode->i_sb, &io.dev);
if (err)
return err;
+ pos = io.dev.m_dif->fsoff + io.dev.m_pa;
+ isize = i_size_read(file_inode(io.dev.m_dif->file));
+ /* the image may end in the middle of the folio, zero the rest */
+ if (pos < isize && isize - pos < len) {
+ len = isize - pos;
+ folio_zero_segment(folio, len, folio_size(folio));
+ }
+
io.rq = erofs_fileio_rq_alloc(inode->i_sb, io.dev.m_dif->file);
io.rq->bio.bi_end_io = erofs_fileio_meta_endio;
- io.rq->bio.bi_iter.bi_sector =
- (io.dev.m_dif->fsoff + io.dev.m_pa) >> 9;
- bio_add_folio_nofail(&io.rq->bio, folio, folio_size(folio), 0);
+ io.rq->bio.bi_iter.bi_sector = pos >> 9;
+ bio_add_folio_nofail(&io.rq->bio, folio, len, 0);
erofs_fileio_rq_submit(io.rq);
return 0;
}
base-commit: a804c5742bff224d4cb4d25dd383554d598be32b
--
2.53.0
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] erofs: fix metadata reads at the end of file-backed images
2026-10-23 17:42 [PATCH] erofs: fix metadata reads at the end of file-backed images Hengyu Liang
@ 2026-10-23 18:19 ` Gao Xiang
0 siblings, 0 replies; 2+ messages in thread
From: Gao Xiang @ 2026-10-23 18:19 UTC (permalink / raw)
To: Hengyu Liang
Cc: xiang, chao, zbestahu, jefflexu, dhavale, hongbohbli, guochunhai,
linux-erofs, linux-kernel, stable
Hi Hengyu,
On Fri, Oct 23, 2026 at 01:42:31PM -0400, Hengyu Liang wrote:
> Commit e587a984d332 ("erofs: use dedicated meta inodes for file-backed
> mounts") made erofs_read_meta_folio() read the metadata of a
> file-backed mount one whole folio at a time.
>
> However, an image only has to be a multiple of its block size. With a
> block size below the page size, it can end in the middle of a page. The
> read of that last page is then short, and erofs_fileio_ki_complete()
> fails it with -EIO. As of now, inodes in the last page of such an image
> cannot be read, and an image smaller than a page cannot be mounted.
>
> The issue can be reproduced with util-linux 2.41, whose mount uses the
> image file directly:
>
> mkdir src
> for i in $(seq 50); do echo $i > src/$i; done
> mkfs.erofs -b512 test.erofs src
> mount -t erofs test.erofs /mnt
> ls -l /mnt
>
> Before that commit, ls -l lists all 50 files. After it, ls -l reports
> "Input/output error" for 24 of them.
>
> This patch reads the folio only up to the end of the backing file and
> zeroes the rest, as the page cache of the backing file did before.
>
> Fixes: e587a984d332 ("erofs: use dedicated meta inodes for file-backed mounts")
> Cc: stable@vger.kernel.org
> Signed-off-by: Hengyu Liang <hengyul@cs.unc.edu>
Thanks for catching this!
Yes, since we reject short read on the complete I/O path,
but it makes post-EOF behavior wrong.
> ---
> Tested in KVM with KASAN on a804c5742bff: file-backed mounts of images
> with 512 to 4096 byte blocks, uncompressed and compressed, with and
> without directio. With this patch every file reads back correctly;
> without it, 24 of the 36 mounts give errors. Not tested on 16K or 64K
> page kernels, where 4K-block images should be affected too.
>
> fs/erofs/fileio.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c
> index c36a90a1a4cb..b4ed7fe7347c 100644
> --- a/fs/erofs/fileio.c
> +++ b/fs/erofs/fileio.c
> @@ -142,17 +142,26 @@ int erofs_read_meta_folio(struct file *file, struct folio *folio)
> .dev = { .m_pa = folio_pos(folio), },
> };
> struct inode *inode = folio_inode(folio);
> + size_t len = folio_size(folio);
> + loff_t pos, isize;
> int err;
>
> err = erofs_map_dev(inode->i_sb, &io.dev);
> if (err)
> return err;
>
> + pos = io.dev.m_dif->fsoff + io.dev.m_pa;
> + isize = i_size_read(file_inode(io.dev.m_dif->file));
> + /* the image may end in the middle of the folio, zero the rest */
> + if (pos < isize && isize - pos < len) {
> + len = isize - pos;
> + folio_zero_segment(folio, len, folio_size(folio));
> + }
> +
Can you just
pos = folio_end_read(fi.folio, uptodate);
isize = i_size_read(file_inode(io.dev.m_dif->file));
if (pos + folio_size(folio) > isize) {
len = isize > pos ? isize - pos : 0;
folio_zero_segment(folio, len, folio_size(folio));
if (!len) {
folio_end_read(folio, true);
return 0;
}
}
...
Since post-EOF should be filled with zeroes all the time.
> io.rq = erofs_fileio_rq_alloc(inode->i_sb, io.dev.m_dif->file);
> io.rq->bio.bi_end_io = erofs_fileio_meta_endio;
> - io.rq->bio.bi_iter.bi_sector =
> - (io.dev.m_dif->fsoff + io.dev.m_pa) >> 9;
> - bio_add_folio_nofail(&io.rq->bio, folio, folio_size(folio), 0);
> + io.rq->bio.bi_iter.bi_sector = pos >> 9;
> + bio_add_folio_nofail(&io.rq->bio, folio, len, 0);
Thanks,
Gao Xiang
> erofs_fileio_rq_submit(io.rq);
> return 0;
> }
>
> base-commit: a804c5742bff224d4cb4d25dd383554d598be32b
> --
> 2.53.0
>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-23 18:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-23 17:42 [PATCH] erofs: fix metadata reads at the end of file-backed images Hengyu Liang
2026-10-23 18:19 ` Gao Xiang
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®