From: Ajay Rajera <newajay.11r@gmail.com>
To: linux-erofs@lists.ozlabs.org
Cc: xiang@kernel.org, Ajay Rajera <newajay.11r@gmail.com>,
Ajay Rajera <ajayrajera007@gmail.com>
Subject: [PATCH] erofs-utils: lib: fix infinite loop on EOF in erofs_io_xcopy
Date: Fri, 20 Mar 2026 05:38:55 +0530 [thread overview]
Message-ID: <20260320000855.1653-1-newajay.11r@gmail.com> (raw)
erofs_io_xcopy() has a fallback do-while loop for when the
kernel fast-paths (copy_file_range/sendfile) do not handle all
the data. The loop does:
ret = erofs_io_read(vin, buf, ret);
if (ret < 0)
return ret;
if (ret > 0) { ... pos += ret; }
len -= ret;
} while (len);
When erofs_io_read() returns 0 (EOF -- source exhausted before
all bytes were copied), only the ret < 0 and ret > 0 branches
were handled. Since ret == 0, `len -= ret` is a no-op and
`while (len)` stays true, causing the loop to spin forever at
100% CPU with no error and no progress.
This can be triggered when building an EROFS image from an input
file that is shorter than expected -- e.g. a truncated source
file, a pipe/FIFO that closes early, or a file being modified
concurrently during mkfs.
Fix it by treating a zero return as an error (-ENODATA) so the
caller fails cleanly instead of hanging indefinitely.
Also fix the long-standing 'pading' -> 'padding' typo in the
short-read diagnostic message of erofs_dev_read().
Signed-off-by: Ajay Rajera <ajayrajera007@gmail.com>
---
lib/io.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/lib/io.c b/lib/io.c
index 0c5eb2c..583f52d 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -430,7 +430,7 @@ ssize_t erofs_dev_read(struct erofs_sb_info *sbi, int device_id,
if (read < 0)
return read;
if (read < len) {
- erofs_info("reach EOF of device @ %llu, pading with zeroes",
+ erofs_info("reach EOF of device @ %llu, padding with zeroes",
offset | 0ULL);
memset(buf + read, 0, len - read);
}
@@ -665,14 +665,15 @@ int erofs_io_xcopy(struct erofs_vfile *vout, off_t pos,
int ret = min_t(unsigned int, len, sizeof(buf));
ret = erofs_io_read(vin, buf, ret);
- if (ret < 0)
+ if (ret <= 0) {
+ if (!ret)
+ return -ENODATA;
return ret;
- if (ret > 0) {
- ret = erofs_io_pwrite(vout, buf, pos, ret);
- if (ret < 0)
- return ret;
- pos += ret;
}
+ ret = erofs_io_pwrite(vout, buf, pos, ret);
+ if (ret < 0)
+ return ret;
+ pos += ret;
len -= ret;
} while (len);
return 0;
--
2.51.0.windows.1
next reply other threads:[~2026-03-20 0:09 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-20 0:08 Ajay Rajera [this message]
-- strict thread matches above, loose matches on Subject: below --
2026-03-20 0:20 [PATCH] erofs-utils: lib: fix infinite loop on EOF in erofs_io_xcopy Ajay Rajera
2026-03-20 15:31 ` Lucas Karpinski
2026-03-20 18:54 ` Ajay Rajera
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=20260320000855.1653-1-newajay.11r@gmail.com \
--to=newajay.11r@gmail.com \
--cc=ajayrajera007@gmail.com \
--cc=linux-erofs@lists.ozlabs.org \
--cc=xiang@kernel.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