[PATCH] erofs-utils: erofs-utils: lib: fix dev_read

Chen Linxuan chenlinxuan at uniontech.com
Fri Oct 21 17:43:32 AEDT 2022


When using `fsck.erofs` to extract some image have a very large file
inside, for example 2G, my fsck.erofs report some thing like this:

<E> erofs_io: Failed to read data from device - erofs.image:[4096,
2147483648].
<E> erofs: failed to read data of m_pa 4096, m_plen 2147483648 @ nid 40: -17
<E> erofs: Failed to extract filesystem

You can use this script to reproduce this issue.

mkdir tmp extract
dd if=/dev/urandom of=tmp/big_file bs=1M count=2048

mkfs.erofs erofs.image tmp
fsck.erofs erofs.image --extract=extract

I found that dev_open will failed if we can not get all data we want
with one pread call.

I write this little patch try to fix this issue.

Signed-off-by: Chen Linxuan <chenlinxuan at uniontech.com>
---
 lib/io.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/lib/io.c b/lib/io.c
index 524cfb4..ccd433f 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -256,7 +256,7 @@ int dev_resize(unsigned int blocks)
 
 int dev_read(int device_id, void *buf, u64 offset, size_t len)
 {
-	int ret, fd;
+	int read_count, fd;
 
 	if (cfg.c_dry_run)
 		return 0;
@@ -278,15 +278,27 @@ int dev_read(int device_id, void *buf, u64 offset, size_t len)
 		fd = erofs_blobfd[device_id - 1];
 	}
 
+	while (len > 0) {
 #ifdef HAVE_PREAD64
-	ret = pread64(fd, buf, len, (off64_t)offset);
+		read_count = pread64(fd, buf, len, (off64_t)offset);
 #else
-	ret = pread(fd, buf, len, (off_t)offset);
+		read_count = pread(fd, buf, len, (off_t)offset);
 #endif
-	if (ret != (int)len) {
-		erofs_err("Failed to read data from device - %s:[%" PRIu64 ", %zd].",
-			  erofs_devname, offset, len);
-		return -errno;
+		if (read_count == -1 || read_count == 0) {
+			if (errno) {
+				erofs_err("Failed to read data from device - %s:[%" PRIu64 ", %zd].",
+					  erofs_devname, offset, len);
+				return -errno;
+			} else {
+				erofs_err("Reach EOF of device - %s:[%" PRIu64 ", %zd].",
+					  erofs_devname, offset, len);
+				return -EINVAL;
+			}
+		}
+
+		offset += read_count;
+		len -= read_count;
+		buf += read_count;
 	}
 	return 0;
 }
-- 
2.37.3



More information about the Linux-erofs mailing list