[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