[PATCH 4/5] erofs-utils: handle mmap failure when packing a whole file

Gao Xiang hsiangkao at linux.alibaba.com
Sun Mar 5 06:58:11 AEDT 2023


Directly read/write if mmap failure.

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 lib/fragments.c | 43 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/lib/fragments.c b/lib/fragments.c
index ebff4b5..30e9ba6 100644
--- a/lib/fragments.c
+++ b/lib/fragments.c
@@ -223,14 +223,39 @@ int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd,
 	if (offset < 0)
 		return -errno;
 
-	memblock = mmap(NULL, inode->i_size, PROT_READ, MAP_SHARED, fd, 0);
-	if (memblock == MAP_FAILED)
-		return -EFAULT;
-
 	inode->fragmentoff = (erofs_off_t)offset;
 	inode->fragment_size = inode->i_size;
 
-	if (fwrite(memblock, inode->fragment_size, 1, packedfile) != 1) {
+	memblock = mmap(NULL, inode->i_size, PROT_READ, MAP_SHARED, fd, 0);
+	if (memblock == MAP_FAILED || !memblock) {
+		unsigned long long remaining = inode->fragment_size;
+
+		memblock = NULL;
+		while (remaining) {
+			char buf[32768];
+			unsigned int sz = min_t(unsigned int, remaining,
+						sizeof(buf));
+
+			rc = read(fd, buf, sz);
+			if (rc != sz) {
+				if (rc < 0)
+					rc = -errno;
+				else
+					rc = -EAGAIN;
+				goto out;
+			}
+			if (fwrite(buf, sz, 1, packedfile) != 1) {
+				rc = -EIO;
+				goto out;
+			}
+			remaining -= sz;
+		}
+		rc = lseek(fd, 0, SEEK_SET);
+		if (rc < 0) {
+			rc = -errno;
+			goto out;
+		}
+	} else if (fwrite(memblock, inode->fragment_size, 1, packedfile) != 1) {
 		rc = -EIO;
 		goto out;
 	}
@@ -238,10 +263,12 @@ int z_erofs_pack_file_from_fd(struct erofs_inode *inode, int fd,
 	erofs_dbg("Recording %u fragment data at %lu", inode->fragment_size,
 		  inode->fragmentoff);
 
-	rc = z_erofs_fragments_dedupe_insert(memblock, inode->fragment_size,
-					     inode->fragmentoff, tofcrc);
+	if (memblock)
+		rc = z_erofs_fragments_dedupe_insert(memblock,
+			inode->fragment_size, inode->fragmentoff, tofcrc);
 out:
-	munmap(memblock, inode->i_size);
+	if (memblock)
+		munmap(memblock, inode->i_size);
 	return rc;
 }
 
-- 
2.24.4



More information about the Linux-erofs mailing list