[WIP] [PATCH v4 05/12] erofs: clean up compress data read

Gao Xiang hsiangkao at aol.com
Sun Nov 15 05:25:10 AEDT 2020


Signed-off-by: Gao Xiang <hsiangkao at aol.com>
---
 fuse/Makefile.am         |  2 +-
 fuse/namei.c             | 17 ++++++--
 fuse/read.c              | 87 +++++++++++-----------------------------
 include/erofs/internal.h | 22 ++++++++--
 lib/Makefile.am          |  2 +-
 lib/data.c               | 73 +++++++++++++++++++++++++++++++++
 {fuse => lib}/zmap.c     | 36 ++++++++---------
 7 files changed, 147 insertions(+), 92 deletions(-)
 rename {fuse => lib}/zmap.c (94%)

diff --git a/fuse/Makefile.am b/fuse/Makefile.am
index 84e5f834d6a4..d6e6d60cbfdc 100644
--- a/fuse/Makefile.am
+++ b/fuse/Makefile.am
@@ -3,7 +3,7 @@
 
 AUTOMAKE_OPTIONS = foreign
 bin_PROGRAMS     = erofsfuse
-erofsfuse_SOURCES = main.c namei.c read.c readir.c zmap.c
+erofsfuse_SOURCES = main.c namei.c read.c readir.c
 erofsfuse_CFLAGS = -Wall -Werror \
                    -I$(top_srcdir)/include \
                    $(shell pkg-config fuse --cflags) \
diff --git a/fuse/namei.c b/fuse/namei.c
index 37cf549cd2a6..fd5ae7bfc410 100644
--- a/fuse/namei.c
+++ b/fuse/namei.c
@@ -71,9 +71,20 @@ static int erofs_iget_by_nid(erofs_nid_t nid, struct erofs_vnode *vi)
 	}
 
 	vi->z_inited = false;
-	if (erofs_inode_is_data_compressed(vi->datalayout))
-		z_erofs_fill_inode(vi);
-
+	if (erofs_inode_is_data_compressed(vi->datalayout)) {
+		struct erofs_inode ei = { .datalayout = vi->datalayout };
+
+		z_erofs_fill_inode(&ei);
+
+		/* XXX: will be dropped after erofs_vnode is removed */
+		vi->z_advise = ei.z_advise;
+		vi->z_algorithmtype[0] = ei.z_algorithmtype[0];
+		vi->z_algorithmtype[1] = ei.z_algorithmtype[1];
+		vi->z_logical_clusterbits = ei.z_logical_clusterbits;
+		vi->z_physical_clusterbits[0] = ei.z_physical_clusterbits[0];
+		vi->z_physical_clusterbits[1] = ei.z_physical_clusterbits[1];
+		vi->z_inited = (ei.flags != 0);
+	}
 	return 0;
 }
 
diff --git a/fuse/read.c b/fuse/read.c
index aa5221a60d4e..21fbd2eea662 100644
--- a/fuse/read.c
+++ b/fuse/read.c
@@ -43,72 +43,31 @@ size_t erofs_read_data_wrapper(struct erofs_vnode *vnode, char *buffer,
 size_t erofs_read_data_compression(struct erofs_vnode *vnode, char *buffer,
 				   erofs_off_t size, erofs_off_t offset)
 {
-	int ret;
-	erofs_off_t end, length, skip;
-	struct erofs_map_blocks map = {
-		.index = UINT_MAX,
+	struct erofs_inode tmp = {
+		.nid = vnode->nid,
+		.i_size = vnode->i_size,
+		.datalayout = vnode->datalayout,
+		.inode_isize = vnode->inode_isize,
+		.xattr_isize = vnode->xattr_isize,
+		.z_advise = vnode->z_advise,
+		.z_algorithmtype = {
+			[0] = vnode->z_algorithmtype[0],
+			[1] = vnode->z_algorithmtype[1],
+		},
+		.z_logical_clusterbits = vnode->z_logical_clusterbits,
+		.z_physical_clusterbits = {
+			[0] = vnode->z_physical_clusterbits[0],
+			[1] = vnode->z_physical_clusterbits[1],
+		},
 	};
-	bool partial;
-	unsigned int algorithmformat;
-	char raw[EROFS_BLKSIZ];
-
-	end = offset + size;
-	while (end > offset) {
-		map.m_la = end - 1;
-
-		ret = z_erofs_map_blocks_iter(vnode, &map);
-		if (ret)
-			return ret;
-
-		if (!(map.m_flags & EROFS_MAP_MAPPED)) {
-			end = map.m_la;
-			continue;
-		}
-
-		ret = dev_read(raw, map.m_pa, EROFS_BLKSIZ);
-		if (ret < 0)
-			return -EIO;
-
-		algorithmformat = map.m_flags & EROFS_MAP_ZIPPED ?
-						Z_EROFS_COMPRESSION_LZ4 :
-						Z_EROFS_COMPRESSION_SHIFTED;
-
-		/*
-		 * trim to the needed size if the returned extent is quite
-		 * larger than requested, and set up partial flag as well.
-		 */
-		if (end < map.m_la + map.m_llen) {
-			length = end - map.m_la;
-			partial = true;
-		} else {
-			DBG_BUGON(end != map.m_la + map.m_llen);
-			length = map.m_llen;
-			partial = !(map.m_flags & EROFS_MAP_FULL_MAPPED);
-		}
-
-		if (map.m_la < offset) {
-			skip = offset - map.m_la;
-			end = offset;
-		} else {
-			skip = 0;
-			end = map.m_la;
-		}
-
-		ret = z_erofs_decompress(&(struct z_erofs_decompress_req) {
-					.in = raw,
-					.out = buffer + end - offset,
-					.decodedskip = skip,
-					.inputsize = map.m_plen,
-					.decodedlength = length,
-					.alg = algorithmformat,
-					.partial_decoding = partial
-					 });
-		if (ret < 0)
-			return ret;
-	}
 
-	erofs_info("nid:%llu size=%zd offset=%llu done",
-	     (unsigned long long)vnode->nid, size, (long long)offset);
+	if (vnode->z_inited)
+		tmp.flags |= EROFS_I_Z_INITED;
+
+	int ret = z_erofs_read_data(&tmp, buffer, offset, size);
+	if (ret)
+		return ret;
+
 	return size;
 }
 
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index fc28d82490a1..98e1263fa19c 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -108,9 +108,13 @@ static inline void erofs_sb_clear_##name(void) \
 EROFS_FEATURE_FUNCS(lz4_0padding, incompat, INCOMPAT_LZ4_0PADDING)
 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
 
+#define EROFS_I_EA_INITED	(1 << 0)
+#define EROFS_I_Z_INITED	(1 << 1)
+
 struct erofs_inode {
 	struct list_head i_hash, i_subdirs, i_xattrs;
 
+	unsigned int flags;
 	unsigned int i_count;
 	struct erofs_inode *i_parent;
 
@@ -145,7 +149,16 @@ struct erofs_inode {
 	struct erofs_buffer_head *bh_inline, *bh_data;
 
 	void *idata;
-	void *compressmeta;
+
+	union {
+		void *compressmeta;
+		struct {
+			uint16_t z_advise;
+			uint8_t  z_algorithmtype[2];
+			uint8_t  z_logical_clusterbits;
+			uint8_t  z_physical_clusterbits[2];
+		};
+	};
 #ifdef WITH_ANDROID
 	uint64_t capabilities;
 #endif
@@ -265,10 +278,11 @@ int erofs_read_superblock(void);
 /* data.c */
 int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
 			erofs_off_t offset, erofs_off_t size);
-
+int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
+		      erofs_off_t size, erofs_off_t offset);
 /* zmap.c */
-int z_erofs_fill_inode(struct erofs_vnode *vi);
-int z_erofs_map_blocks_iter(struct erofs_vnode *vi,
+int z_erofs_fill_inode(struct erofs_inode *vi);
+int z_erofs_map_blocks_iter(struct erofs_inode *vi,
 			    struct erofs_map_blocks *map);
 
 #define EFSCORRUPTED	EUCLEAN		/* Filesystem is corrupted */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 487c4944479d..7d9446b3cbcf 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -3,7 +3,7 @@
 
 noinst_LTLIBRARIES = liberofs.la
 liberofs_la_SOURCES = config.c io.c cache.c super.c inode.c xattr.c exclude.c \
-		      data.c compress.c compressor.c decompress.c
+		      data.c compress.c compressor.c zmap.c decompress.c
 liberofs_la_CFLAGS = -Wall -Werror -I$(top_srcdir)/include
 if ENABLE_LZ4
 liberofs_la_CFLAGS += ${LZ4_CFLAGS}
diff --git a/lib/data.c b/lib/data.c
index 56b208513980..62fd057185ee 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -3,11 +3,13 @@
  * erofs-utils/lib/data.c
  *
  * Copyright (C) 2020 Gao Xiang <hsiangkao at aol.com>
+ * Compression support by Huang Jianan <huangjianan at oppo.com>
  */
 #include "erofs/print.h"
 #include "erofs/internal.h"
 #include "erofs/io.h"
 #include "erofs/trace.h"
+#include "erofs/decompress.h"
 
 static int erofs_map_blocks_flatmode(struct erofs_inode *inode,
 				     struct erofs_map_blocks *map,
@@ -115,3 +117,74 @@ int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
 	return 0;
 }
 
+int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
+		      erofs_off_t offset, erofs_off_t size)
+{
+	int ret;
+	erofs_off_t end, length, skip;
+	struct erofs_map_blocks map = {
+		.index = UINT_MAX,
+	};
+	bool partial;
+	unsigned int algorithmformat;
+	char raw[EROFS_BLKSIZ];
+
+	end = offset + size;
+	while (end > offset) {
+		map.m_la = end - 1;
+
+		ret = z_erofs_map_blocks_iter(inode, &map);
+		if (ret)
+			return ret;
+
+		if (!(map.m_flags & EROFS_MAP_MAPPED)) {
+			end = map.m_la;
+			continue;
+		}
+
+		ret = dev_read(raw, map.m_pa, EROFS_BLKSIZ);
+		if (ret < 0)
+			return -EIO;
+
+		algorithmformat = map.m_flags & EROFS_MAP_ZIPPED ?
+						Z_EROFS_COMPRESSION_LZ4 :
+						Z_EROFS_COMPRESSION_SHIFTED;
+
+		/*
+		 * trim to the needed size if the returned extent is quite
+		 * larger than requested, and set up partial flag as well.
+		 */
+		if (end < map.m_la + map.m_llen) {
+			length = end - map.m_la;
+			partial = true;
+		} else {
+			DBG_BUGON(end != map.m_la + map.m_llen);
+			length = map.m_llen;
+			partial = !(map.m_flags & EROFS_MAP_FULL_MAPPED);
+		}
+
+		if (map.m_la < offset) {
+			skip = offset - map.m_la;
+			end = offset;
+		} else {
+			skip = 0;
+			end = map.m_la;
+		}
+
+		ret = z_erofs_decompress(&(struct z_erofs_decompress_req) {
+					.in = raw,
+					.out = buffer + end - offset,
+					.decodedskip = skip,
+					.inputsize = map.m_plen,
+					.decodedlength = length,
+					.alg = algorithmformat,
+					.partial_decoding = partial
+					 });
+		if (ret < 0)
+			return ret;
+	}
+	erofs_dbg("nid:%llu size=%zd offset=%llu done",
+		  inode->nid | 0ULL, size, (long long)offset);
+	return 0;
+}
+
diff --git a/fuse/zmap.c b/lib/zmap.c
similarity index 94%
rename from fuse/zmap.c
rename to lib/zmap.c
index ba5c457278a8..ee63de74cab2 100644
--- a/fuse/zmap.c
+++ b/lib/zmap.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * erofs-utils/fuse/zmap.c
+ * erofs-utils/lib/zmap.c
  *
  * (a large amount of code was adapted from Linux kernel. )
  *
@@ -12,7 +12,7 @@
 #include "erofs/io.h"
 #include "erofs/print.h"
 
-int z_erofs_fill_inode(struct erofs_vnode *vi)
+int z_erofs_fill_inode(struct erofs_inode *vi)
 {
 	if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) {
 		vi->z_advise = 0;
@@ -21,27 +21,26 @@ int z_erofs_fill_inode(struct erofs_vnode *vi)
 		vi->z_logical_clusterbits = LOG_BLOCK_SIZE;
 		vi->z_physical_clusterbits[0] = vi->z_logical_clusterbits;
 		vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits;
-		vi->z_inited = true;
-	}
 
+		vi->flags |= EROFS_I_Z_INITED;
+	}
 	return 0;
 }
 
-static int z_erofs_fill_inode_lazy(struct erofs_vnode *vi)
+static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
 {
 	int ret;
 	erofs_off_t pos;
 	struct z_erofs_map_header *h;
-	char buf[8];
+	char buf[sizeof(struct z_erofs_map_header)];
 
-	if (vi->z_inited)
+	if (vi->flags & EROFS_I_Z_INITED)
 		return 0;
 
 	DBG_BUGON(vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY);
-
 	pos = round_up(iloc(vi->nid) + vi->inode_isize + vi->xattr_isize, 8);
 
-	ret = dev_read(buf, pos, 8);
+	ret = dev_read(buf, pos, sizeof(buf));
 	if (ret < 0)
 		return -EIO;
 
@@ -68,13 +67,12 @@ static int z_erofs_fill_inode_lazy(struct erofs_vnode *vi)
 
 	vi->z_physical_clusterbits[1] = vi->z_logical_clusterbits +
 					((h->h_clusterbits >> 5) & 7);
-	vi->z_inited = true;
-
+	vi->flags |= EROFS_I_Z_INITED;
 	return 0;
 }
 
 struct z_erofs_maprecorder {
-	struct erofs_vnode *vnode;
+	struct erofs_inode *inode;
 	struct erofs_map_blocks *map;
 	void *kaddr;
 
@@ -108,7 +106,7 @@ static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m,
 static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m,
 					 unsigned long lcn)
 {
-	struct erofs_vnode *const vi = m->vnode;
+	struct erofs_inode *const vi = m->inode;
 	const erofs_off_t ibase = iloc(vi->nid);
 	const erofs_off_t pos =
 		Z_EROFS_VLE_LEGACY_INDEX_ALIGN(ibase + vi->inode_isize +
@@ -162,7 +160,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
 				  unsigned int amortizedshift,
 				  unsigned int eofs)
 {
-	struct erofs_vnode *const vi = m->vnode;
+	struct erofs_inode *const vi = m->inode;
 	const unsigned int lclusterbits = vi->z_logical_clusterbits;
 	const unsigned int lomask = (1 << lclusterbits) - 1;
 	unsigned int vcnt, base, lo, encodebits, nblk;
@@ -225,7 +223,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
 static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
 					    unsigned long lcn)
 {
-	struct erofs_vnode *const vi = m->vnode;
+	struct erofs_inode *const vi = m->inode;
 	const unsigned int lclusterbits = vi->z_logical_clusterbits;
 	const erofs_off_t ebase = round_up(iloc(vi->nid) + vi->inode_isize +
 					   vi->xattr_isize, 8) +
@@ -279,7 +277,7 @@ out:
 static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
 					  unsigned int lcn)
 {
-	const unsigned int datamode = m->vnode->datalayout;
+	const unsigned int datamode = m->inode->datalayout;
 
 	if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
 		return legacy_load_cluster_from_disk(m, lcn);
@@ -293,7 +291,7 @@ static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
 static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
 				   unsigned int lookback_distance)
 {
-	struct erofs_vnode *const vi = m->vnode;
+	struct erofs_inode *const vi = m->inode;
 	struct erofs_map_blocks *const map = m->map;
 	const unsigned int lclusterbits = vi->z_logical_clusterbits;
 	unsigned long lcn = m->lcn;
@@ -335,11 +333,11 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
 	return 0;
 }
 
-int z_erofs_map_blocks_iter(struct erofs_vnode *vi,
+int z_erofs_map_blocks_iter(struct erofs_inode *vi,
 			    struct erofs_map_blocks *map)
 {
 	struct z_erofs_maprecorder m = {
-		.vnode = vi,
+		.inode = vi,
 		.map = map,
 		.kaddr = map->mpage,
 	};
-- 
2.24.0



More information about the Linux-erofs mailing list