Re: [PATCH 1/3] erofs: get compression algorithms directly on mapping

From: Yue Hu
Date: Thu Oct 07 2021 - 23:00:40 EST


On Fri, 8 Oct 2021 01:06:03 +0800
Gao Xiang <xiang@xxxxxxxxxx> wrote:

> From: Gao Xiang <hsiangkao@xxxxxxxxxxxxxxxxx>
>
> Currently, z_erofs_map_blocks returns whether extents are compressed

Mapping function is z_erofs_map_blocks_iter()?

> or not, and the decompression frontend gets the specific algorithms
> then.
>
> It works but not quite well in many aspests, for example:
> - The decompression frontend has to deal with whether extents are
> compressed or not again and lookup the algorithms if compressed.
> It's duplicated and too detailed about the on-disk mapping.
>
> - A new secondary compression head will be introduced later so that
> each file can have 2 compression algorithms at most for different
> type of data. It could increase the complexity of the decompression
> frontend if still handled in this way;
>
> - A new readmore decompression strategy will be introduced to get
> better performance for much bigger pcluster and lzma, which needs
> the specific algorithm in advance as well.
>
> Let's look up compression algorithms directly in z_erofs_map_blocks()

Same mapping function name mistake?

> instead.
>
> Signed-off-by: Gao Xiang <hsiangkao@xxxxxxxxxxxxxxxxx>
> ---
> fs/erofs/compress.h | 5 -----
> fs/erofs/internal.h | 12 +++++++++---
> fs/erofs/zdata.c | 12 ++++++------
> fs/erofs/zmap.c | 19 ++++++++++---------
> include/trace/events/erofs.h | 2 +-
> 5 files changed, 26 insertions(+), 24 deletions(-)
>
> diff --git a/fs/erofs/compress.h b/fs/erofs/compress.h
> index 3701c72bacb2..ad62d1b4d371 100644
> --- a/fs/erofs/compress.h
> +++ b/fs/erofs/compress.h
> @@ -8,11 +8,6 @@
>
> #include "internal.h"
>
> -enum {
> - Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
> - Z_EROFS_COMPRESSION_RUNTIME_MAX
> -};
> -
> struct z_erofs_decompress_req {
> struct super_block *sb;
> struct page **in, **out;
> diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
> index 9524e155b38f..48bfc6eb2b02 100644
> --- a/fs/erofs/internal.h
> +++ b/fs/erofs/internal.h
> @@ -338,7 +338,7 @@ extern const struct address_space_operations z_erofs_aops;
> * of the corresponding uncompressed data in the file.
> */
> enum {
> - BH_Zipped = BH_PrivateStart,
> + BH_Encoded = BH_PrivateStart,
> BH_FullMapped,
> };
>
> @@ -346,8 +346,8 @@ enum {
> #define EROFS_MAP_MAPPED (1 << BH_Mapped)
> /* Located in metadata (could be copied from bd_inode) */
> #define EROFS_MAP_META (1 << BH_Meta)
> -/* The extent has been compressed */
> -#define EROFS_MAP_ZIPPED (1 << BH_Zipped)
> +/* The extent is encoded */
> +#define EROFS_MAP_ENCODED (1 << BH_Encoded)
> /* The length of extent is full */
> #define EROFS_MAP_FULL_MAPPED (1 << BH_FullMapped)
>
> @@ -355,6 +355,7 @@ struct erofs_map_blocks {
> erofs_off_t m_pa, m_la;
> u64 m_plen, m_llen;
>
> + char m_algorithmformat;
> unsigned int m_flags;
>
> struct page *mpage;
> @@ -368,6 +369,11 @@ struct erofs_map_blocks {
> */
> #define EROFS_GET_BLOCKS_FIEMAP 0x0002
>
> +enum {
> + Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
> + Z_EROFS_COMPRESSION_RUNTIME_MAX
> +};
> +
> /* zmap.c */
> extern const struct iomap_ops z_erofs_iomap_report_ops;
>
> diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
> index 11c7a1aaebad..5c34ef66677f 100644
> --- a/fs/erofs/zdata.c
> +++ b/fs/erofs/zdata.c
> @@ -476,6 +476,11 @@ static int z_erofs_register_collection(struct z_erofs_collector *clt,
> struct erofs_workgroup *grp;
> int err;
>
> + if (!(map->m_flags & EROFS_MAP_ENCODED)) {
> + DBG_BUGON(1);
> + return -EFSCORRUPTED;
> + }
> +
> /* no available pcluster, let's allocate one */
> pcl = z_erofs_alloc_pcluster(map->m_plen >> PAGE_SHIFT);
> if (IS_ERR(pcl))
> @@ -483,16 +488,11 @@ static int z_erofs_register_collection(struct z_erofs_collector *clt,
>
> atomic_set(&pcl->obj.refcount, 1);
> pcl->obj.index = map->m_pa >> PAGE_SHIFT;
> -
> + pcl->algorithmformat = map->m_algorithmformat;
> pcl->length = (map->m_llen << Z_EROFS_PCLUSTER_LENGTH_BIT) |
> (map->m_flags & EROFS_MAP_FULL_MAPPED ?
> Z_EROFS_PCLUSTER_FULL_LENGTH : 0);
>
> - if (map->m_flags & EROFS_MAP_ZIPPED)
> - pcl->algorithmformat = Z_EROFS_COMPRESSION_LZ4;
> - else
> - pcl->algorithmformat = Z_EROFS_COMPRESSION_SHIFTED;
> -
> /* new pclusters should be claimed as type 1, primary and followed */
> pcl->next = clt->owned_head;
> clt->mode = COLLECT_PRIMARY_FOLLOWED;
> diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c
> index 7a6df35fdc91..9d9c26343dab 100644
> --- a/fs/erofs/zmap.c
> +++ b/fs/erofs/zmap.c
> @@ -111,7 +111,7 @@ struct z_erofs_maprecorder {
>
> unsigned long lcn;
> /* compression extent information gathered */
> - u8 type;
> + u8 type, headtype;
> u16 clusterofs;
> u16 delta[2];
> erofs_blk_t pblk, compressedlcs;
> @@ -446,9 +446,8 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
> }
> return z_erofs_extent_lookback(m, m->delta[0]);
> case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
> - map->m_flags &= ~EROFS_MAP_ZIPPED;
> - fallthrough;
> case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
> + m->headtype = m->type;
> map->m_la = (lcn << lclusterbits) | m->clusterofs;
> break;
> default:
> @@ -472,7 +471,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
>
> DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN &&
> m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD);
> - if (!(map->m_flags & EROFS_MAP_ZIPPED) ||
> + if (m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
> !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) {
> map->m_plen = 1 << lclusterbits;
> return 0;
> @@ -609,16 +608,13 @@ int z_erofs_map_blocks_iter(struct inode *inode,
> if (err)
> goto unmap_out;
>
> - map->m_flags = EROFS_MAP_ZIPPED; /* by default, compressed */
> end = (m.lcn + 1ULL) << lclusterbits;
>
> switch (m.type) {
> case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
> - if (endoff >= m.clusterofs)
> - map->m_flags &= ~EROFS_MAP_ZIPPED;
> - fallthrough;
> case Z_EROFS_VLE_CLUSTER_TYPE_HEAD:
> if (endoff >= m.clusterofs) {
> + m.headtype = m.type;
> map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
> break;
> }
> @@ -650,12 +646,17 @@ int z_erofs_map_blocks_iter(struct inode *inode,
>
> map->m_llen = end - map->m_la;
> map->m_pa = blknr_to_addr(m.pblk);
> - map->m_flags |= EROFS_MAP_MAPPED;
> + map->m_flags = EROFS_MAP_MAPPED | EROFS_MAP_ENCODED;

Seems the new flag EROFS_MAP_ENCODED may be a little redundant?

It is used only for checking whether the file system is corrupted or not when
entering z_erofs_register_collection().

And before collection begins, we will check whether the EROFS_MAP_MAPPED is set
or not. We will do the collection only if EROFS_MAP_MAPPED is set. That's to say,
the above checking to EROFS_MAP_ENCODED should be not possible?

Thanks.

>
> err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
> if (err)
> goto out;
>
> + if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN)
> + map->m_algorithmformat = Z_EROFS_COMPRESSION_SHIFTED;
> + else
> + map->m_algorithmformat = vi->z_algorithmtype[0];
> +
> if (flags & EROFS_GET_BLOCKS_FIEMAP) {
> err = z_erofs_get_extent_decompressedlen(&m);
> if (!err)
> diff --git a/include/trace/events/erofs.h b/include/trace/events/erofs.h
> index db4f2cec8360..16ae7b666810 100644
> --- a/include/trace/events/erofs.h
> +++ b/include/trace/events/erofs.h
> @@ -24,7 +24,7 @@ struct erofs_map_blocks;
> #define show_mflags(flags) __print_flags(flags, "", \
> { EROFS_MAP_MAPPED, "M" }, \
> { EROFS_MAP_META, "I" }, \
> - { EROFS_MAP_ZIPPED, "Z" })
> + { EROFS_MAP_ENCODED, "E" })
>
> TRACE_EVENT(erofs_lookup,
>