[PATCH 1/2] erofs-utils: fsck: cleanup erofs_verify_inode_data()

Yue Hu zbestahu at gmail.com
Thu Jan 5 20:21:56 AEDT 2023


From: Yue Hu <huyue2 at coolpad.com>

We should reuse the main part of erofs_read_raw_data() and
z_erofs_read_data() to avoid duplicated code.

Note that fragment feature is supported correspondingly as well after
this change.

Signed-off-by: Yue Hu <huyue2 at coolpad.com>
---
 fsck/main.c              | 149 +++++++++++++++++----------------------
 include/erofs/internal.h |   4 ++
 lib/data.c               |   8 +--
 3 files changed, 71 insertions(+), 90 deletions(-)

diff --git a/fsck/main.c b/fsck/main.c
index 2a9c501..6c43816 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -361,36 +361,14 @@ out:
 	return ret;
 }
 
-static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
+static int erofs_verify_inode_data_mapping(struct erofs_inode *inode,
+					   bool compressed)
 {
 	struct erofs_map_blocks map = {
 		.index = UINT_MAX,
 	};
-	struct erofs_map_dev mdev;
 	int ret = 0;
-	bool compressed;
 	erofs_off_t pos = 0;
-	u64 pchunk_len = 0;
-	unsigned int raw_size = 0, buffer_size = 0;
-	char *raw = NULL, *buffer = NULL;
-
-	erofs_dbg("verify data chunk of nid(%llu): type(%d)",
-		  inode->nid | 0ULL, inode->datalayout);
-
-	switch (inode->datalayout) {
-	case EROFS_INODE_FLAT_PLAIN:
-	case EROFS_INODE_FLAT_INLINE:
-	case EROFS_INODE_CHUNK_BASED:
-		compressed = false;
-		break;
-	case EROFS_INODE_FLAT_COMPRESSION_LEGACY:
-	case EROFS_INODE_FLAT_COMPRESSION:
-		compressed = true;
-		break;
-	default:
-		erofs_err("unknown datalayout");
-		return -EINVAL;
-	}
 
 	while (pos < inode->i_size) {
 		map.m_la = pos;
@@ -401,102 +379,101 @@ static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
 			ret = erofs_map_blocks(inode, &map,
 					EROFS_GET_BLOCKS_FIEMAP);
 		if (ret)
-			goto out;
+			return ret;
 
 		if (!compressed && map.m_llen != map.m_plen) {
 			erofs_err("broken chunk length m_la %" PRIu64 " m_llen %" PRIu64 " m_plen %" PRIu64,
 				  map.m_la, map.m_llen, map.m_plen);
-			ret = -EFSCORRUPTED;
-			goto out;
+			return -EFSCORRUPTED;
 		}
 
 		/* the last lcluster can be divided into 3 parts */
 		if (map.m_la + map.m_llen > inode->i_size)
 			map.m_llen = inode->i_size - map.m_la;
 
-		pchunk_len += map.m_plen;
 		pos += map.m_llen;
+	}
+	return 0;
+}
 
-		/* should skip decomp? */
-		if (!(map.m_flags & EROFS_MAP_MAPPED) || !fsckcfg.check_decomp)
-			continue;
+static int erofs_do_verify_inode_data(struct erofs_inode *inode, int outfd,
+				      bool compressed)
+{
+	int ret = 0;
+	erofs_off_t pos = 0;
+	unsigned int buffer_size = 0;
+	char *buffer = NULL;
 
-		if (map.m_plen > raw_size) {
-			raw_size = map.m_plen;
-			raw = realloc(raw, raw_size);
-			BUG_ON(!raw);
-		}
+	/* no option --extract */
+	if (!fsckcfg.check_decomp)
+		return erofs_verify_inode_data_mapping(inode, compressed);
 
-		mdev = (struct erofs_map_dev) {
-			.m_deviceid = map.m_deviceid,
-			.m_pa = map.m_pa,
-		};
-		ret = erofs_map_dev(&sbi, &mdev);
-		if (ret) {
-			erofs_err("failed to map device of m_pa %" PRIu64 ", m_deviceid %u @ nid %llu: %d",
-				  map.m_pa, map.m_deviceid, inode->nid | 0ULL,
-				  ret);
-			goto out;
-		}
+	while (pos < inode->i_size) {
+		erofs_off_t maxsize = min_t(erofs_off_t, inode->i_size - pos,
+					    EROFS_CONFIG_COMPR_MAX_SZ);
 
-		if (compressed && map.m_llen > buffer_size) {
-			buffer_size = map.m_llen;
+		if (maxsize > buffer_size) {
+			buffer_size = maxsize;
 			buffer = realloc(buffer, buffer_size);
 			BUG_ON(!buffer);
 		}
 
-		ret = dev_read(mdev.m_deviceid, raw, mdev.m_pa, map.m_plen);
-		if (ret < 0) {
-			erofs_err("failed to read data of m_pa %" PRIu64 ", m_plen %" PRIu64 " @ nid %llu: %d",
-				  mdev.m_pa, map.m_plen, inode->nid | 0ULL,
-				  ret);
+		if (compressed)
+			ret = z_erofs_read_data(inode, buffer, maxsize, pos);
+		else
+			ret = erofs_read_raw_data(inode, buffer, maxsize, pos);
+		if (ret)
 			goto out;
-		}
 
-		if (compressed) {
-			struct z_erofs_decompress_req rq = {
-				.in = raw,
-				.out = buffer,
-				.decodedskip = 0,
-				.interlaced_offset =
-					map.m_algorithmformat == Z_EROFS_COMPRESSION_INTERLACED ?
-						erofs_blkoff(map.m_la) : 0,
-				.inputsize = map.m_plen,
-				.decodedlength = map.m_llen,
-				.alg = map.m_algorithmformat,
-				.partial_decoding = 0
-			};
-
-			ret = z_erofs_decompress(&rq);
-			if (ret < 0) {
-				erofs_err("failed to decompress data of m_pa %" PRIu64 ", m_plen %" PRIu64 " @ nid %llu: %s",
-					  mdev.m_pa, map.m_plen,
-					  inode->nid | 0ULL, strerror(-ret));
-				goto out;
-			}
-		}
+		pos += maxsize;
 
-		if (outfd >= 0 && write(outfd, compressed ? buffer : raw,
-					map.m_llen) < 0) {
+		if (outfd >= 0 && write(outfd, buffer, maxsize) < 0) {
 			erofs_err("I/O error occurred when verifying data chunk @ nid %llu",
 				  inode->nid | 0ULL);
 			ret = -EIO;
 			goto out;
 		}
 	}
-
-	if (fsckcfg.print_comp_ratio) {
-		fsckcfg.logical_blocks += BLK_ROUND_UP(inode->i_size);
-		fsckcfg.physical_blocks += BLK_ROUND_UP(pchunk_len);
-	}
 out:
-	if (raw)
-		free(raw);
 	if (buffer)
 		free(buffer);
 	return ret < 0 ? ret : 0;
 }
 
+static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
+{
+	int ret;
+	bool compressed;
+
+	erofs_dbg("verify data chunk of nid(%llu): type(%d)",
+		  inode->nid | 0ULL, inode->datalayout);
+
+	switch (inode->datalayout) {
+	case EROFS_INODE_FLAT_PLAIN:
+	case EROFS_INODE_FLAT_INLINE:
+	case EROFS_INODE_CHUNK_BASED:
+		compressed = false;
+		break;
+	case EROFS_INODE_FLAT_COMPRESSION_LEGACY:
+	case EROFS_INODE_FLAT_COMPRESSION:
+		compressed = true;
+		break;
+	default:
+		erofs_err("unknown datalayout");
+		return -EINVAL;
+	}
+	ret = erofs_do_verify_inode_data(inode, outfd, compressed);
+	if (ret < 0)
+		return ret;
+
+	if (fsckcfg.print_comp_ratio) {
+		fsckcfg.logical_blocks += BLK_ROUND_UP(inode->i_size);
+		fsckcfg.physical_blocks += compressed ? inode->u.i_blocks :
+					   BLK_ROUND_UP(inode->i_size);
+	}
+	return 0;
+}
+
 static inline int erofs_extract_dir(struct erofs_inode *inode)
 {
 	int ret;
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 947894d..4b962af 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -352,6 +352,10 @@ int erofs_read_inode_from_disk(struct erofs_inode *vi);
 /* data.c */
 int erofs_pread(struct erofs_inode *inode, char *buf,
 		erofs_off_t count, erofs_off_t offset);
+int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
+                        erofs_off_t size, erofs_off_t offset);
+int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
+                      erofs_off_t size, erofs_off_t offset);
 int erofs_map_blocks(struct erofs_inode *inode,
 		struct erofs_map_blocks *map, int flags);
 int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map);
diff --git a/lib/data.c b/lib/data.c
index 76a6677..a9b2240 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -158,8 +158,8 @@ int erofs_map_dev(struct erofs_sb_info *sbi, struct erofs_map_dev *map)
 	return 0;
 }
 
-static int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
-			       erofs_off_t size, erofs_off_t offset)
+int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
+			erofs_off_t size, erofs_off_t offset)
 {
 	struct erofs_map_blocks map = {
 		.index = UINT_MAX,
@@ -217,8 +217,8 @@ static int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
 	return 0;
 }
 
-static int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
-			     erofs_off_t size, erofs_off_t offset)
+int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
+		      erofs_off_t size, erofs_off_t offset)
 {
 	erofs_off_t end, length, skip;
 	struct erofs_map_blocks map = {
-- 
2.17.1



More information about the Linux-erofs mailing list