[PATCH v3] erofs-utils: lib: fix infinite loop on EOF in erofs_io_xcopy

Ajay Rajera newajay.11r at gmail.com
Sun Mar 22 17:03:58 AEDT 2026


erofs_io_xcopy() has a fallback loop for when the kernel fast-paths
(copy_file_range/sendfile) do not handle all the data.

When erofs_io_read() returned 0 (source exhausted before all
bytes were copied), the old logic checked `ret < 0` and
`ret > 0`, ignoring `0`. Since `len -= 0` is a no-op, the
loop would spin forever at 100% CPU with no progress.

v2 fixed the loop but unconditionally trapped a 0-byte read
by returning -EIO. However, if copy_file_range completely
exhausts the bytes, `len` becomes 0. The do-while loop
was then forced to execute once, making a 0-byte read,
which returned 0. v2 falsely trapped this success as an
-EIO error, causing mkfs.erofs to fail in CI.

Fix this regression by replacing `do-while(len)` with a
standard `while(len)` loop. This safely bypasses the block
if `len` is 0 (avoiding fake -EIO errors), while correctly
catching premature EOFs with -EIO.

Also fix the 'pading' -> 'padding' typo in erofs_dev_read().

Signed-off-by: Ajay Rajera <newajay.11r at gmail.com>
---
v3: Replace do-while loop to avoid 0-byte read -EIO regression.
v2: Return -EIO instead of -ENODATA, use cleaner if/else.
---
 lib/io.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lib/io.c b/lib/io.c
index 583f52d..ae6a600 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -660,22 +660,22 @@ int erofs_io_xcopy(struct erofs_vfile *vout, off_t pos,
 #endif
 	}
 
-	do {
+	while (len) {
 		char buf[32768];
 		int ret = min_t(unsigned int, len, sizeof(buf));
 
 		ret = erofs_io_read(vin, buf, ret);
-		if (ret <= 0) {
-			if (!ret)
-				return -ENODATA;
+		if (ret < 0)
 			return ret;
-		}
+		if (ret == 0)
+			return -EIO;
+
 		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



More information about the Linux-erofs mailing list