erofs: get compression algorithms directly on mapping
authorGao Xiang <hsiangkao@linux.alibaba.com>
Fri, 8 Oct 2021 20:08:37 +0000 (04:08 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Sun, 17 Oct 2021 16:15:55 +0000 (00:15 +0800)
Currently, z_erofs_map_blocks_iter() returns whether extents are
compressed 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 in z_erofs_map_blocks_iter()
directly instead.

Link: https://lore.kernel.org/r/20211008200839.24541-2-xiang@kernel.org
Reviewed-by: Chao Yu <chao@kernel.org>
Reviewed-by: Yue Hu <huyue2@yulong.com>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
fs/erofs/compress.h
fs/erofs/internal.h
fs/erofs/zdata.c
fs/erofs/zmap.c
include/trace/events/erofs.h

index 3701c72bacb2e0b33b3d9657f3c3f1f6ef68eaf9..ad62d1b4d371f1e890e9a74d1a277ef5049a4963 100644 (file)
@@ -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;
index 0661d7d6969a7e34c2757a205db068aebfd5ec3b..f8537ffdefeb438450838b03e60a2b511466d3d8 100644 (file)
@@ -363,7 +363,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,
 };
 
@@ -371,8 +371,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)
 
@@ -381,6 +381,7 @@ struct erofs_map_blocks {
        u64 m_plen, m_llen;
 
        unsigned short m_deviceid;
+       char m_algorithmformat;
        unsigned int m_flags;
 
        struct page *mpage;
@@ -394,6 +395,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;
 
index 8c947ed492996222b440f703f185f7bbe30d4797..a9dced07c3c6751aa7933cf77afd8583a0380411 100644 (file)
@@ -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;
index 7a6df35fdc915baaacfee640f469895e2086fa74..1c3b068e5a420f0e8b9857ab0b8245814b6c84da 100644 (file)
@@ -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,14 @@ int z_erofs_map_blocks_iter(struct inode *inode,
        if (err)
                goto unmap_out;
 
-       map->m_flags = EROFS_MAP_ZIPPED;        /* by default, compressed */
+       map->m_flags = EROFS_MAP_MAPPED | EROFS_MAP_ENCODED;
        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 +647,16 @@ 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;
 
        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)
index db4f2cec8360629e5d7d19b6208b13a86e4c271c..16ae7b6668105b71b668730d5eab05099b3699de 100644 (file)
@@ -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,