[PATCH v2] erofs: support metadata compression
Hongbo Li
lihongbo22 at huawei.com
Mon Jul 14 13:10:35 AEST 2025
Hi Bo,
On 2025/7/11 17:40, Bo Liu wrote:
> Filesystem metadata has a high degree of redundancy, so
> should compress well in the general case.
> To implement this feature, we make a special on-disk inode
> which keeps all metadata as its data, and then compress the
> special on-disk inode with the given algorithm.
>
Does metadata compression mean the common inode base will be dedup?
Thanks,
Hongbo
> Signed-off-by: Bo Liu <liubo03 at inspur.com>
> ---
> v1: https://lore.kernel.org/linux-erofs/00fc488bbdd1489ca94f4d0bcd416403@inspur.com/T/#t
>
> change since v1:
> - add a check to determine if the bit 63 of nid is set
>
> ---
> fs/erofs/data.c | 20 ++++++++++++--------
> fs/erofs/decompressor.c | 2 +-
> fs/erofs/erofs_fs.h | 4 +++-
> fs/erofs/fileio.c | 2 +-
> fs/erofs/fscache.c | 2 +-
> fs/erofs/inode.c | 9 +++++----
> fs/erofs/internal.h | 27 +++++++++++++++++++++++----
> fs/erofs/super.c | 14 ++++++++++++--
> fs/erofs/sysfs.c | 2 ++
> fs/erofs/xattr.c | 29 +++++++++++++++++++++++------
> fs/erofs/zdata.c | 2 +-
> fs/erofs/zmap.c | 24 ++++++++++++++----------
> include/trace/events/erofs.h | 7 +++++--
> 13 files changed, 103 insertions(+), 41 deletions(-)
>
> diff --git a/fs/erofs/data.c b/fs/erofs/data.c
> index 6a329c329f43..4699bfc6ff2a 100644
> --- a/fs/erofs/data.c
> +++ b/fs/erofs/data.c
> @@ -49,13 +49,16 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap)
> return buf->base + (offset & ~PAGE_MASK);
> }
>
> -void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb)
> +void erofs_init_metabuf(struct erofs_buf *buf,
> + struct super_block *sb, bool meta_compr)
> {
> struct erofs_sb_info *sbi = EROFS_SB(sb);
>
> buf->file = NULL;
> buf->off = sbi->dif0.fsoff;
> - if (erofs_is_fileio_mode(sbi)) {
> + if (meta_compr)
> + buf->mapping = sbi->meta_inode->i_mapping;
> + else if (erofs_is_fileio_mode(sbi)) {
> buf->file = sbi->dif0.file; /* some fs like FUSE needs it */
> buf->mapping = buf->file->f_mapping;
> } else if (erofs_is_fscache_mode(sb))
> @@ -65,9 +68,9 @@ void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb)
> }
>
> void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
> - erofs_off_t offset, bool need_kmap)
> + erofs_off_t offset, bool need_kmap, bool meta_compr)
> {
> - erofs_init_metabuf(buf, sb);
> + erofs_init_metabuf(buf, sb, meta_compr);
> return erofs_bread(buf, offset, need_kmap);
> }
>
> @@ -83,6 +86,7 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
> erofs_off_t pos;
> u64 chunknr;
> int err = 0;
> + bool meta_compr = false;
>
> trace_erofs_map_blocks_enter(inode, map, 0);
> map->m_deviceid = 0;
> @@ -101,7 +105,7 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
> map->m_pa = erofs_pos(sb, vi->startblk) + map->m_la;
> map->m_llen = pos - map->m_la;
> } else {
> - map->m_pa = erofs_iloc(inode) + vi->inode_isize +
> + map->m_pa = erofs_iloc(inode, &meta_compr) + vi->inode_isize +
> vi->xattr_isize + erofs_blkoff(sb, map->m_la);
> map->m_llen = inode->i_size - map->m_la;
> map->m_flags |= EROFS_MAP_META;
> @@ -115,10 +119,10 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
> unit = EROFS_BLOCK_MAP_ENTRY_SIZE; /* block map */
>
> chunknr = map->m_la >> vi->chunkbits;
> - pos = ALIGN(erofs_iloc(inode) + vi->inode_isize +
> + pos = ALIGN(erofs_iloc(inode, &meta_compr) + vi->inode_isize +
> vi->xattr_isize, unit) + unit * chunknr;
>
> - idx = erofs_read_metabuf(&buf, sb, pos, true);
> + idx = erofs_read_metabuf(&buf, sb, pos, true, meta_compr);
> if (IS_ERR(idx)) {
> err = PTR_ERR(idx);
> goto out;
> @@ -293,7 +297,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
> struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
>
> iomap->type = IOMAP_INLINE;
> - ptr = erofs_read_metabuf(&buf, sb, mdev.m_pa, true);
> + ptr = erofs_read_metabuf(&buf, sb, mdev.m_pa, true, false);
> if (IS_ERR(ptr))
> return PTR_ERR(ptr);
> iomap->inline_data = ptr;
> diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c
> index bf62e2836b60..e15f39f0769d 100644
> --- a/fs/erofs/decompressor.c
> +++ b/fs/erofs/decompressor.c
> @@ -471,7 +471,7 @@ int z_erofs_parse_cfgs(struct super_block *sb, struct erofs_super_block *dsb)
> return -EOPNOTSUPP;
> }
>
> - erofs_init_metabuf(&buf, sb);
> + erofs_init_metabuf(&buf, sb, false);
> offset = EROFS_SUPER_OFFSET + sbi->sb_size;
> alg = 0;
> for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) {
> diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h
> index 767fb4acdc93..9294ff3dabd6 100644
> --- a/fs/erofs/erofs_fs.h
> +++ b/fs/erofs/erofs_fs.h
> @@ -15,6 +15,7 @@
> #define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001
> #define EROFS_FEATURE_COMPAT_MTIME 0x00000002
> #define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004
> +#define EROFS_FEATURE_COMPAT_XATTR_COMPR 0x00000008
>
> /*
> * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should
> @@ -31,6 +32,7 @@
> #define EROFS_FEATURE_INCOMPAT_DEDUPE 0x00000020
> #define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040
> #define EROFS_FEATURE_INCOMPAT_48BIT 0x00000080
> +#define EROFS_FEATURE_INCOMPAT_META_COMPR 0X00000100
> #define EROFS_ALL_FEATURE_INCOMPAT \
> ((EROFS_FEATURE_INCOMPAT_48BIT << 1) - 1)
>
> @@ -82,7 +84,7 @@ struct erofs_super_block {
> __u8 reserved[3];
> __le32 build_time; /* seconds added to epoch for mkfs time */
> __le64 rootnid_8b; /* (48BIT on) nid of root directory */
> - __u8 reserved2[8];
> + __le64 meta_nid; /* meta data nid */
> };
>
> /*
> diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c
> index df5cc63f2c01..89229ef171b4 100644
> --- a/fs/erofs/fileio.c
> +++ b/fs/erofs/fileio.c
> @@ -117,7 +117,7 @@ static int erofs_fileio_scan_folio(struct erofs_fileio *io, struct folio *folio)
> void *src;
>
> src = erofs_read_metabuf(&buf, inode->i_sb,
> - map->m_pa + ofs, true);
> + map->m_pa + ofs, true, false);
> if (IS_ERR(src)) {
> err = PTR_ERR(src);
> break;
> diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c
> index 34517ca9df91..f33a782af74b 100644
> --- a/fs/erofs/fscache.c
> +++ b/fs/erofs/fscache.c
> @@ -274,7 +274,7 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_rq *req)
> size_t size = map.m_llen;
> void *src;
>
> - src = erofs_read_metabuf(&buf, sb, map.m_pa, true);
> + src = erofs_read_metabuf(&buf, sb, map.m_pa, true, false);
> if (IS_ERR(src))
> return PTR_ERR(src);
>
> diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c
> index a0ae0b4f7b01..8f4fe3dd1e9a 100644
> --- a/fs/erofs/inode.c
> +++ b/fs/erofs/inode.c
> @@ -27,8 +27,9 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,
> static int erofs_read_inode(struct inode *inode)
> {
> struct super_block *sb = inode->i_sb;
> - erofs_blk_t blkaddr = erofs_blknr(sb, erofs_iloc(inode));
> - unsigned int ofs = erofs_blkoff(sb, erofs_iloc(inode));
> + bool meta_compr = false;
> + erofs_blk_t blkaddr = erofs_blknr(sb, erofs_iloc(inode, &meta_compr));
> + unsigned int ofs= erofs_blkoff(sb, erofs_iloc(inode, &meta_compr));
How about using erofs_iloc only once? like:
erofs_off_t ioff = erofs_iloc(inode, &meta_compr);
erofs_blk_t blkaddr = erofs_blknr(sb, ioff);
unsigned int ofs= erofs_blkoff(sb, ioff);
Thanks,
Hongbo
> struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
> struct erofs_sb_info *sbi = EROFS_SB(sb);
> erofs_blk_t addrmask = BIT_ULL(48) - 1;
> @@ -39,7 +40,7 @@ static int erofs_read_inode(struct inode *inode)
> void *ptr;
> int err = 0;
>
> - ptr = erofs_read_metabuf(&buf, sb, erofs_pos(sb, blkaddr), true);
> + ptr = erofs_read_metabuf(&buf, sb, erofs_pos(sb, blkaddr), true, meta_compr);
> if (IS_ERR(ptr)) {
> err = PTR_ERR(ptr);
> erofs_err(sb, "failed to get inode (nid: %llu) page, err %d",
> @@ -78,7 +79,7 @@ static int erofs_read_inode(struct inode *inode)
>
> memcpy(&copied, dic, gotten);
> ptr = erofs_read_metabuf(&buf, sb,
> - erofs_pos(sb, blkaddr + 1), true);
> + erofs_pos(sb, blkaddr + 1), true, meta_compr);
> if (IS_ERR(ptr)) {
> err = PTR_ERR(ptr);
> erofs_err(sb, "failed to get inode payload block (nid: %llu), err %d",
> diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
> index a32c03a80c70..e853f916566c 100644
> --- a/fs/erofs/internal.h
> +++ b/fs/erofs/internal.h
> @@ -125,6 +125,7 @@ struct erofs_sb_info {
> struct erofs_sb_lz4_info lz4;
> #endif /* CONFIG_EROFS_FS_ZIP */
> struct inode *packed_inode;
> + struct inode *meta_inode;
> struct erofs_dev_context *devs;
> u64 total_blocks;
>
> @@ -148,6 +149,7 @@ struct erofs_sb_info {
> /* what we really care is nid, rather than ino.. */
> erofs_nid_t root_nid;
> erofs_nid_t packed_nid;
> + erofs_nid_t meta_nid;
> /* used for statfs, f_files - f_favail */
> u64 inos;
>
> @@ -227,8 +229,10 @@ EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
> EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
> EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
> EROFS_FEATURE_FUNCS(48bit, incompat, INCOMPAT_48BIT)
> +EROFS_FEATURE_FUNCS(meta_compr, incompat, INCOMPAT_META_COMPR)
> EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
> EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER)
> +EROFS_FEATURE_FUNCS(xattr_compr, compat, COMPAT_XATTR_COMPR)
>
> /* atomic flag definitions */
> #define EROFS_I_EA_INITED_BIT 0
> @@ -279,12 +283,26 @@ struct erofs_inode {
>
> #define EROFS_I(ptr) container_of(ptr, struct erofs_inode, vfs_inode)
>
> -static inline erofs_off_t erofs_iloc(struct inode *inode)
> +static inline bool erofs_is_metacompr_mode(struct inode *inode)
> +{
> + return EROFS_I(inode)->nid >> 63;
> +}
> +
> +static inline erofs_off_t erofs_iloc(struct inode *inode, bool *meta_compr)
> {
> struct erofs_sb_info *sbi = EROFS_I_SB(inode);
> + erofs_nid_t nid;
> +
> + if (erofs_is_metacompr_mode(inode)) {
> + *meta_compr = true;
> + nid = EROFS_I(inode)->nid & ~(0x1ULL << 63);
> + } else {
> + *meta_compr = false;
> + nid = EROFS_I(inode)->nid;
> + }
>
> return erofs_pos(inode->i_sb, sbi->meta_blkaddr) +
> - (EROFS_I(inode)->nid << sbi->islotbits);
> + (nid << sbi->islotbits);
> }
>
> static inline unsigned int erofs_inode_version(unsigned int ifmt)
> @@ -381,9 +399,10 @@ void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
> void erofs_unmap_metabuf(struct erofs_buf *buf);
> void erofs_put_metabuf(struct erofs_buf *buf);
> void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap);
> -void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb);
> +void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb,
> + bool meta_compr);
> void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
> - erofs_off_t offset, bool need_kmap);
> + erofs_off_t offset, bool need_kmap, bool meta_compr);
> int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev);
> int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
> u64 start, u64 len);
> diff --git a/fs/erofs/super.c b/fs/erofs/super.c
> index e1e9f06e8342..434dec1cbd1b 100644
> --- a/fs/erofs/super.c
> +++ b/fs/erofs/super.c
> @@ -141,7 +141,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
> struct erofs_deviceslot *dis;
> struct file *file;
>
> - dis = erofs_read_metabuf(buf, sb, *pos, true);
> + dis = erofs_read_metabuf(buf, sb, *pos, true, false);
> if (IS_ERR(dis))
> return PTR_ERR(dis);
>
> @@ -258,7 +258,7 @@ static int erofs_read_superblock(struct super_block *sb)
> void *data;
> int ret;
>
> - data = erofs_read_metabuf(&buf, sb, 0, true);
> + data = erofs_read_metabuf(&buf, sb, 0, true, false);
> if (IS_ERR(data)) {
> erofs_err(sb, "cannot read erofs superblock");
> return PTR_ERR(data);
> @@ -324,6 +324,7 @@ static int erofs_read_superblock(struct super_block *sb)
> sbi->epoch = (s64)le64_to_cpu(dsb->epoch);
> sbi->fixed_nsec = le32_to_cpu(dsb->fixed_nsec);
> super_set_uuid(sb, (void *)dsb->uuid, sizeof(dsb->uuid));
> + sbi->meta_nid = le64_to_cpu(dsb->meta_nid);
>
> /* parse on-disk compression configurations */
> ret = z_erofs_parse_cfgs(sb, dsb);
> @@ -691,6 +692,13 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
> sbi->packed_inode = inode;
> }
>
> + if (erofs_sb_has_meta_compr(sbi) && sbi->meta_nid) {
> + inode = erofs_iget(sb, sbi->meta_nid);
> + if (IS_ERR(inode))
> + return PTR_ERR(inode);
> + sbi->meta_inode = inode;
> + }
> +
> inode = erofs_iget(sb, sbi->root_nid);
> if (IS_ERR(inode))
> return PTR_ERR(inode);
> @@ -845,6 +853,8 @@ static void erofs_drop_internal_inodes(struct erofs_sb_info *sbi)
> {
> iput(sbi->packed_inode);
> sbi->packed_inode = NULL;
> + iput(sbi->meta_inode);
> + sbi->meta_inode = NULL;
> #ifdef CONFIG_EROFS_FS_ZIP
> iput(sbi->managed_cache);
> sbi->managed_cache = NULL;
> diff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c
> index eed8797a193f..0f65fe8204be 100644
> --- a/fs/erofs/sysfs.c
> +++ b/fs/erofs/sysfs.c
> @@ -95,6 +95,7 @@ EROFS_ATTR_FEATURE(ztailpacking);
> EROFS_ATTR_FEATURE(fragments);
> EROFS_ATTR_FEATURE(dedupe);
> EROFS_ATTR_FEATURE(48bit);
> +EROFS_ATTR_FEATURE(meta_compr);
>
> static struct attribute *erofs_feat_attrs[] = {
> ATTR_LIST(zero_padding),
> @@ -108,6 +109,7 @@ static struct attribute *erofs_feat_attrs[] = {
> ATTR_LIST(fragments),
> ATTR_LIST(dedupe),
> ATTR_LIST(48bit),
> + ATTR_LIST(meta_compr),
> NULL,
> };
> ATTRIBUTE_GROUPS(erofs_feat);
> diff --git a/fs/erofs/xattr.c b/fs/erofs/xattr.c
> index 9cf84717a92e..1c2659e3a2ce 100644
> --- a/fs/erofs/xattr.c
> +++ b/fs/erofs/xattr.c
> @@ -33,6 +33,7 @@ static int erofs_init_inode_xattrs(struct inode *inode)
> struct erofs_xattr_ibody_header *ih;
> struct super_block *sb = inode->i_sb;
> int ret = 0;
> + bool meta_compr = false;
>
> /* the most case is that xattrs of this inode are initialized. */
> if (test_bit(EROFS_I_EA_INITED_BIT, &vi->flags)) {
> @@ -77,8 +78,10 @@ static int erofs_init_inode_xattrs(struct inode *inode)
> }
>
> it.buf = __EROFS_BUF_INITIALIZER;
> - erofs_init_metabuf(&it.buf, sb);
> - it.pos = erofs_iloc(inode) + vi->inode_isize;
> + it.pos = erofs_iloc(inode, &meta_compr) + vi->inode_isize;
> + if (!erofs_is_metacompr_mode(inode))
This is extra, because metacompr_mode has been check before.
> + meta_compr = false;
> + erofs_init_metabuf(&it.buf, sb, meta_compr);
>
> /* read in shared xattr array (non-atomic, see kmalloc below) */
> it.kaddr = erofs_bread(&it.buf, it.pos, true);
> @@ -318,6 +321,7 @@ static int erofs_xattr_iter_inline(struct erofs_xattr_iter *it,
> unsigned int xattr_header_sz, remaining, entry_sz;
> erofs_off_t next_pos;
> int ret;
> + bool meta_compr = false;
>
> xattr_header_sz = sizeof(struct erofs_xattr_ibody_header) +
> sizeof(u32) * vi->xattr_shared_count;
> @@ -327,7 +331,7 @@ static int erofs_xattr_iter_inline(struct erofs_xattr_iter *it,
> }
>
> remaining = vi->xattr_isize - xattr_header_sz;
> - it->pos = erofs_iloc(inode) + vi->inode_isize + xattr_header_sz;
> + it->pos = erofs_iloc(inode, &meta_compr) + vi->inode_isize + xattr_header_sz;
>
> while (remaining) {
> it->kaddr = erofs_bread(&it->buf, it->pos, true);
> @@ -389,6 +393,7 @@ int erofs_getxattr(struct inode *inode, int index, const char *name,
> struct erofs_xattr_iter it;
> struct erofs_inode *vi = EROFS_I(inode);
> struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
> + bool meta_compr = false;
>
> if (!name)
> return -EINVAL;
> @@ -411,9 +416,12 @@ int erofs_getxattr(struct inode *inode, int index, const char *name,
> if (it.name.len > EROFS_NAME_LEN)
> return -ERANGE;
>
> + if (erofs_sb_has_xattr_compr(sbi))
Is xattr_compr another feature under meta compr? In my opinion, how
about splitting it with another patch?
Thanks,
Hongbo
> + meta_compr = erofs_is_metacompr_mode(inode);
> +
> it.sb = inode->i_sb;
> it.buf = __EROFS_BUF_INITIALIZER;
> - erofs_init_metabuf(&it.buf, it.sb);
> + erofs_init_metabuf(&it.buf, it.sb, meta_compr);
> it.buffer = buffer;
> it.buffer_size = buffer_size;
> it.buffer_ofs = 0;
> @@ -430,16 +438,21 @@ ssize_t erofs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
> int ret;
> struct erofs_xattr_iter it;
> struct inode *inode = d_inode(dentry);
> + struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
> + bool meta_compr = false;
>
> ret = erofs_init_inode_xattrs(inode);
> if (ret == -ENOATTR)
> return 0;
> if (ret)
> +
unused blank line.
> return ret;
> + if (erofs_sb_has_xattr_compr(sbi))
> + meta_compr = erofs_is_metacompr_mode(inode);
>
> it.sb = dentry->d_sb;
> it.buf = __EROFS_BUF_INITIALIZER;
> - erofs_init_metabuf(&it.buf, it.sb);
> + erofs_init_metabuf(&it.buf, it.sb, meta_compr);
> it.dentry = dentry;
> it.buffer = buffer;
> it.buffer_size = buffer_size;
> @@ -474,6 +487,7 @@ int erofs_xattr_prefixes_init(struct super_block *sb)
> erofs_off_t pos = (erofs_off_t)sbi->xattr_prefix_start << 2;
> struct erofs_xattr_prefix_item *pfs;
> int ret = 0, i, len;
> + bool meta_compr = false;
>
> if (!sbi->xattr_prefix_count)
> return 0;
> @@ -482,10 +496,13 @@ int erofs_xattr_prefixes_init(struct super_block *sb)
> if (!pfs)
> return -ENOMEM;
>
> + if (erofs_sb_has_xattr_compr(sbi) && sbi->meta_inode)
> + meta_compr = true;
> +
> if (sbi->packed_inode)
> buf.mapping = sbi->packed_inode->i_mapping;
> else
> - erofs_init_metabuf(&buf, sb);
> + erofs_init_metabuf(&buf, sb, meta_compr);
>
> for (i = 0; i < sbi->xattr_prefix_count; i++) {
> void *ptr = erofs_read_metadata(sb, &buf, &pos, &len);
> diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
> index d80e3bf4fa79..cf0111ecbd94 100644
> --- a/fs/erofs/zdata.c
> +++ b/fs/erofs/zdata.c
> @@ -855,7 +855,7 @@ static int z_erofs_pcluster_begin(struct z_erofs_frontend *fe)
> /* bind cache first when cached decompression is preferred */
> z_erofs_bind_cache(fe);
> } else {
> - ptr = erofs_read_metabuf(&map->buf, sb, map->m_pa, false);
> + ptr = erofs_read_metabuf(&map->buf, sb, map->m_pa, false, false);
> if (IS_ERR(ptr)) {
> ret = PTR_ERR(ptr);
> erofs_err(sb, "failed to get inline data %d", ret);
> diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c
> index 0bebc6e3a4d7..ea8670953b0d 100644
> --- a/fs/erofs/zmap.c
> +++ b/fs/erofs/zmap.c
> @@ -24,14 +24,15 @@ static int z_erofs_load_full_lcluster(struct z_erofs_maprecorder *m,
> unsigned long lcn)
> {
> struct inode *const inode = m->inode;
> + bool meta_compr = false;
> struct erofs_inode *const vi = EROFS_I(inode);
> - const erofs_off_t pos = Z_EROFS_FULL_INDEX_START(erofs_iloc(inode) +
> + const erofs_off_t pos = Z_EROFS_FULL_INDEX_START(erofs_iloc(inode, &meta_compr) +
> vi->inode_isize + vi->xattr_isize) +
> lcn * sizeof(struct z_erofs_lcluster_index);
> struct z_erofs_lcluster_index *di;
> unsigned int advise;
>
> - di = erofs_read_metabuf(&m->map->buf, inode->i_sb, pos, true);
> + di = erofs_read_metabuf(&m->map->buf, inode->i_sb, pos, true, meta_compr);
> if (IS_ERR(di))
> return PTR_ERR(di);
> m->lcn = lcn;
> @@ -102,7 +103,8 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m,
> {
> struct inode *const inode = m->inode;
> struct erofs_inode *const vi = EROFS_I(inode);
> - const erofs_off_t ebase = Z_EROFS_MAP_HEADER_END(erofs_iloc(inode) +
> + bool meta_compr = false;
> + const erofs_off_t ebase = Z_EROFS_MAP_HEADER_END(erofs_iloc(inode, &meta_compr) +
> vi->inode_isize + vi->xattr_isize);
> const unsigned int lclusterbits = vi->z_lclusterbits;
> const unsigned int totalidx = erofs_iblks(inode);
> @@ -146,7 +148,7 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m,
> else
> return -EOPNOTSUPP;
>
> - in = erofs_read_metabuf(&m->map->buf, m->inode->i_sb, pos, true);
> + in = erofs_read_metabuf(&m->map->buf, m->inode->i_sb, pos, true, meta_compr);
> if (IS_ERR(in))
> return PTR_ERR(in);
>
> @@ -540,8 +542,9 @@ static int z_erofs_map_blocks_ext(struct inode *inode,
> struct erofs_inode *vi = EROFS_I(inode);
> struct super_block *sb = inode->i_sb;
> bool interlaced = vi->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER;
> + bool meta_compr = false;
> unsigned int recsz = z_erofs_extent_recsize(vi->z_advise);
> - erofs_off_t pos = round_up(Z_EROFS_MAP_HEADER_END(erofs_iloc(inode) +
> + erofs_off_t pos = round_up(Z_EROFS_MAP_HEADER_END(erofs_iloc(inode, &meta_compr) +
> vi->inode_isize + vi->xattr_isize), recsz);
> erofs_off_t lend = inode->i_size;
> erofs_off_t l, r, mid, pa, la, lstart;
> @@ -552,7 +555,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode,
> map->m_flags = 0;
> if (recsz <= offsetof(struct z_erofs_extent, pstart_hi)) {
> if (recsz <= offsetof(struct z_erofs_extent, pstart_lo)) {
> - ext = erofs_read_metabuf(&map->buf, sb, pos, true);
> + ext = erofs_read_metabuf(&map->buf, sb, pos, true, meta_compr);
> if (IS_ERR(ext))
> return PTR_ERR(ext);
> pa = le64_to_cpu(*(__le64 *)ext);
> @@ -565,7 +568,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode,
> }
>
> for (; lstart <= map->m_la; lstart += 1 << vi->z_lclusterbits) {
> - ext = erofs_read_metabuf(&map->buf, sb, pos, true);
> + ext = erofs_read_metabuf(&map->buf, sb, pos, true, meta_compr);
> if (IS_ERR(ext))
> return PTR_ERR(ext);
> map->m_plen = le32_to_cpu(ext->plen);
> @@ -585,7 +588,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode,
> for (l = 0, r = vi->z_extents; l < r; ) {
> mid = l + (r - l) / 2;
> ext = erofs_read_metabuf(&map->buf, sb,
> - pos + mid * recsz, true);
> + pos + mid * recsz, true, meta_compr);
> if (IS_ERR(ext))
> return PTR_ERR(ext);
>
> @@ -650,6 +653,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
> erofs_off_t pos;
> struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
> struct z_erofs_map_header *h;
> + bool meta_compr = false;
>
> if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) {
> /*
> @@ -667,8 +671,8 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
> if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags))
> goto out_unlock;
>
> - pos = ALIGN(erofs_iloc(inode) + vi->inode_isize + vi->xattr_isize, 8);
> - h = erofs_read_metabuf(&buf, sb, pos, true);
> + pos = ALIGN(erofs_iloc(inode, &meta_compr) + vi->inode_isize + vi->xattr_isize, 8);
> + h = erofs_read_metabuf(&buf, sb, pos, true, meta_compr);
> if (IS_ERR(h)) {
> err = PTR_ERR(h);
> goto out_unlock;
> diff --git a/include/trace/events/erofs.h b/include/trace/events/erofs.h
> index dad7360f42f9..260c949880d5 100644
> --- a/include/trace/events/erofs.h
> +++ b/include/trace/events/erofs.h
> @@ -66,13 +66,16 @@ TRACE_EVENT(erofs_fill_inode,
> __field(erofs_nid_t, nid )
> __field(erofs_blk_t, blkaddr )
> __field(unsigned int, ofs )
> + __field(bool, meta_compr )
> ),
>
> TP_fast_assign(
> __entry->dev = inode->i_sb->s_dev;
> __entry->nid = EROFS_I(inode)->nid;
> - __entry->blkaddr = erofs_blknr(inode->i_sb, erofs_iloc(inode));
> - __entry->ofs = erofs_blkoff(inode->i_sb, erofs_iloc(inode));
> + __entry->blkaddr =
> + erofs_blknr(inode->i_sb, erofs_iloc(inode, &__entry->meta_compr));
> + __entry->ofs =
> + erofs_blkoff(inode->i_sb, erofs_iloc(inode, &__entry->meta_compr));
> ),
>
> TP_printk("dev = (%d,%d), nid = %llu, blkaddr %llu ofs %u",
More information about the Linux-erofs
mailing list