Source kernel commit: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Source kernel commit: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Signed-off-by: Gao Xiang <[email protected]>
---
 dump/main.c              | 10 +++++++++-
 fsck/main.c              | 25 ++++++++++++++---------
 include/erofs/internal.h | 19 ++++++++++++------
 include/erofs_fs.h       | 12 ++++++++---
 lib/data.c               | 43 ++++++++++++++++++++++++++++++++++------
 lib/namei.c              |  5 +++--
 lib/super.c              | 29 +++++++++++++++++++++------
 lib/xattr.c              | 12 +++++------
 lib/zmap.c               | 15 ++++++++------
 9 files changed, 125 insertions(+), 45 deletions(-)

diff --git a/dump/main.c b/dump/main.c
index f0dab02e..38cc8a28 100644
--- a/dump/main.c
+++ b/dump/main.c
@@ -105,6 +105,7 @@ static struct erofsdump_feature feature_lists[] = {
        { false, EROFS_FEATURE_INCOMPAT_DEDUPE, "dedupe" },
        { false, EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES, "xattr_prefixes" },
        { false, EROFS_FEATURE_INCOMPAT_48BIT, "48bit" },
+       { false, EROFS_FEATURE_INCOMPAT_METABOX, "metabox" },
 };
 
 static int erofsdump_readdir(struct erofs_dir_context *ctx);
@@ -163,7 +164,11 @@ static int erofsdump_parse_options_cfg(int argc, char 
**argv)
                        exit(0);
                case 2:
                        dumpcfg.show_inode = true;
-                       dumpcfg.nid = (erofs_nid_t)atoll(optarg);
+                       dumpcfg.nid = strtoull(optarg, &endptr, 0);
+                       if (*endptr != '\0') {
+                               erofs_err("invalid NID %s", optarg);
+                               return -EINVAL;
+                       }
                        ++dumpcfg.totalshow;
                        break;
                case 'h':
@@ -643,6 +648,9 @@ static void erofsdump_show_superblock(void)
        if (erofs_sb_has_fragments(&g_sbi) && g_sbi.packed_nid > 0)
                fprintf(stdout, "Filesystem packed nid:                        
%llu\n",
                        g_sbi.packed_nid | 0ULL);
+       if (erofs_sb_has_metabox(&g_sbi))
+               fprintf(stdout, "Filesystem metabox nid:                       
%llu\n",
+                       g_sbi.metabox_nid | 0ULL);
        if (erofs_sb_has_compr_cfgs(&g_sbi)) {
                fprintf(stdout, "Filesystem compr_algs:                        
");
                erofsdump_print_supported_compressors(stdout,
diff --git a/fsck/main.c b/fsck/main.c
index 44719b95..d4f0fea7 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -333,12 +333,14 @@ static int erofs_verify_xattr(struct erofs_inode *inode)
        struct erofs_sb_info *sbi = inode->sbi;
        unsigned int xattr_hdr_size = sizeof(struct erofs_xattr_ibody_header);
        unsigned int xattr_entry_size = sizeof(struct erofs_xattr_entry);
-       erofs_off_t addr;
+       struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
        unsigned int ofs, xattr_shared_count;
        struct erofs_xattr_ibody_header *ih;
        struct erofs_xattr_entry *entry;
-       int i, remaining = inode->xattr_isize, ret = 0;
-       char buf[EROFS_MAX_BLOCK_SIZE];
+       int remaining = inode->xattr_isize, ret = 0;
+       erofs_off_t addr;
+       char *ptr;
+       int i;
 
        if (inode->xattr_isize == xattr_hdr_size) {
                erofs_err("xattr_isize %d of nid %llu is not supported yet",
@@ -355,13 +357,15 @@ static int erofs_verify_xattr(struct erofs_inode *inode)
        }
 
        addr = erofs_iloc(inode) + inode->inode_isize;
-       ret = erofs_dev_read(sbi, 0, buf, addr, xattr_hdr_size);
-       if (ret < 0) {
+       ptr = erofs_read_metabuf(&buf, sbi, addr,
+                                erofs_inode_in_metabox(inode));
+       if (IS_ERR(ptr)) {
+               ret = PTR_ERR(ptr);
                erofs_err("failed to read xattr header @ nid %llu: %d",
                          inode->nid | 0ULL, ret);
                goto out;
        }
-       ih = (struct erofs_xattr_ibody_header *)buf;
+       ih = (struct erofs_xattr_ibody_header *)ptr;
        xattr_shared_count = ih->h_shared_count;
 
        ofs = erofs_blkoff(sbi, addr) + xattr_hdr_size;
@@ -385,14 +389,16 @@ static int erofs_verify_xattr(struct erofs_inode *inode)
        while (remaining > 0) {
                unsigned int entry_sz;
 
-               ret = erofs_dev_read(sbi, 0, buf, addr, xattr_entry_size);
-               if (ret) {
+               ptr = erofs_read_metabuf(&buf, sbi, addr,
+                                erofs_inode_in_metabox(inode));
+               if (IS_ERR(ptr)) {
+                       ret = PTR_ERR(ptr);
                        erofs_err("failed to read xattr entry @ nid %llu: %d",
                                  inode->nid | 0ULL, ret);
                        goto out;
                }
 
-               entry = (struct erofs_xattr_entry *)buf;
+               entry = (struct erofs_xattr_entry *)ptr;
                entry_sz = erofs_xattr_entry_size(entry);
                if (remaining < entry_sz) {
                        erofs_err("xattr on-disk corruption: xattr entry beyond 
xattr_isize @ nid %llu",
@@ -404,6 +410,7 @@ static int erofs_verify_xattr(struct erofs_inode *inode)
                remaining -= entry_sz;
        }
 out:
+       erofs_put_metabuf(&buf);
        return ret;
 }
 
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index 3439a183..de6f4eae 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -126,6 +126,7 @@ struct erofs_sb_info {
                u16 device_id_mask;             /* used for others */
        };
        erofs_nid_t packed_nid;
+       erofs_nid_t metabox_nid;
 
        u32 xattr_prefix_start;
        u8 xattr_prefix_count;
@@ -153,8 +154,6 @@ struct erofs_sb_info {
        bool useqpl;
 };
 
-#define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct erofs_super_block))
-
 /* make sure that any user of the erofs headers has atleast 64bit off_t type */
 extern int erofs_assert_largefile[sizeof(off_t)-8];
 
@@ -182,6 +181,7 @@ 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(metabox, incompat, INCOMPAT_METABOX)
 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
 EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER)
 
@@ -295,12 +295,18 @@ struct erofs_inode {
 #endif
 };
 
+static inline bool erofs_inode_in_metabox(struct erofs_inode *inode)
+{
+       return inode->nid >> EROFS_DIRENT_NID_METABOX_BIT;
+}
+
 static inline erofs_off_t erofs_iloc(struct erofs_inode *inode)
 {
        struct erofs_sb_info *sbi = inode->sbi;
+       erofs_off_t base = erofs_inode_in_metabox(inode) ? 0 :
+                       erofs_pos(sbi, sbi->meta_blkaddr);
 
-       return erofs_pos(sbi, sbi->meta_blkaddr) +
-                       (inode->nid << EROFS_ISLOTBITS);
+       return base + ((inode->nid & EROFS_DIRENT_NID_MASK) << EROFS_ISLOTBITS);
 }
 
 static inline bool is_inode_layout_compression(struct erofs_inode *inode)
@@ -437,9 +443,10 @@ int erofs_ilookup(const char *path, struct erofs_inode 
*vi);
 static inline void erofs_unmap_metabuf(struct erofs_buf *buf) {}
 static inline 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 erofs_sb_info *sbi);
+void erofs_init_metabuf(struct erofs_buf *buf, struct erofs_sb_info *sbi,
+                       bool in_mbox);
 void *erofs_read_metabuf(struct erofs_buf *buf, struct erofs_sb_info *sbi,
-                        erofs_off_t offset);
+                        erofs_off_t offset, bool in_mbox);
 int erofs_iopen(struct erofs_vfile *vf, struct erofs_inode *inode);
 int erofs_map_blocks(struct erofs_inode *inode,
                struct erofs_map_blocks *map, int flags);
diff --git a/include/erofs_fs.h b/include/erofs_fs.h
index e180c5d4..56e268e5 100644
--- a/include/erofs_fs.h
+++ b/include/erofs_fs.h
@@ -32,8 +32,9 @@
 #define EROFS_FEATURE_INCOMPAT_DEDUPE          0x00000020
 #define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES  0x00000040
 #define EROFS_FEATURE_INCOMPAT_48BIT           0x00000080
+#define EROFS_FEATURE_INCOMPAT_METABOX         0x00000100
 #define EROFS_ALL_FEATURE_INCOMPAT             \
-       ((EROFS_FEATURE_INCOMPAT_48BIT << 1) - 1)
+       ((EROFS_FEATURE_INCOMPAT_METABOX << 1) - 1)
 
 #define EROFS_SB_EXTSLOT_SIZE  16
 
@@ -83,7 +84,9 @@ 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 reserved2;
+       __le64 metabox_nid;     /* (METABOX on) nid of the metabox inode */
+       __le64 reserved3;
 };
 
 /*
@@ -268,6 +271,9 @@ struct erofs_inode_chunk_index {
        __le32 startblk_lo;     /* starting block number of this chunk */
 };
 
+#define EROFS_DIRENT_NID_METABOX_BIT   63
+#define EROFS_DIRENT_NID_MASK          (BIT(EROFS_DIRENT_NID_METABOX_BIT) - 1)
+
 /* dirent sorts in alphabet order, thus we can do binary search */
 struct erofs_dirent {
        __le64 nid;     /* node number */
@@ -448,7 +454,7 @@ static inline void 
erofs_check_ondisk_layout_definitions(void)
        };
 #endif
 
-       BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128);
+       BUILD_BUG_ON(sizeof(struct erofs_super_block) != 144);
        BUILD_BUG_ON(sizeof(struct erofs_inode_compact) != 32);
        BUILD_BUG_ON(sizeof(struct erofs_inode_extended) != 64);
        BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12);
diff --git a/lib/data.c b/lib/data.c
index 87ced24f..6791fda5 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -14,6 +14,8 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, 
bool need_kmap)
 {
        struct erofs_sb_info *sbi = buf->sbi;
        u32 blksiz = erofs_blksiz(sbi);
+       struct erofs_vfile vfm, *vf;
+       struct erofs_inode vi;
        erofs_blk_t blknr;
        int err;
 
@@ -22,7 +24,22 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, 
bool need_kmap)
        blknr = erofs_blknr(sbi, offset);
        if (blknr != buf->blocknr) {
                buf->blocknr = ~0ULL;
-               err = erofs_pread(buf->vf, buf->base, blksiz,
+               vf = buf->vf;
+               /*
+                * TODO: introduce a metabox cache like the current fragment
+                *       cache to improve userspace metadata performance.
+                */
+               if (!vf) {
+                       vi = (struct erofs_inode) { .sbi = sbi,
+                                                   .nid = sbi->metabox_nid };
+                       err = erofs_read_inode_from_disk(&vi);
+                       if (!err)
+                               err = erofs_iopen(&vfm, &vi);
+                       if (err)
+                               return ERR_PTR(err);
+                       vf = &vfm;
+               }
+               err = erofs_pread(vf, buf->base, blksiz,
                                  round_down(offset, blksiz));
                if (err)
                        return ERR_PTR(err);
@@ -31,16 +48,17 @@ void *erofs_bread(struct erofs_buf *buf, erofs_off_t 
offset, bool need_kmap)
        return buf->base + erofs_blkoff(sbi, offset);
 }
 
-void erofs_init_metabuf(struct erofs_buf *buf, struct erofs_sb_info *sbi)
+void erofs_init_metabuf(struct erofs_buf *buf, struct erofs_sb_info *sbi,
+                       bool in_mbox)
 {
        buf->sbi = sbi;
-       buf->vf = &sbi->bdev;
+       buf->vf = in_mbox ? NULL : &sbi->bdev;
 }
 
 void *erofs_read_metabuf(struct erofs_buf *buf, struct erofs_sb_info *sbi,
-                        erofs_off_t offset)
+                        erofs_off_t offset, bool in_mbox)
 {
-       erofs_init_metabuf(buf, sbi);
+       erofs_init_metabuf(buf, sbi, in_mbox);
        return erofs_bread(buf, offset, true);
 }
 
@@ -215,7 +233,20 @@ static int erofs_read_raw_data(struct erofs_inode *inode, 
char *buffer,
                eend = min(offset + size, map.m_la + map.m_llen);
                DBG_BUGON(ptr < map.m_la);
 
-               if (!(map.m_flags & EROFS_MAP_MAPPED)) {
+               if ((map.m_flags & EROFS_MAP_META) &&
+                   erofs_inode_in_metabox(inode)) {
+                       struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
+                       void *src;
+
+                       src = erofs_read_metabuf(&buf, inode->sbi,
+                                                map.m_pa, true);
+                       if (IS_ERR(src))
+                               return PTR_ERR(src);
+                       memcpy(estart, src, eend - ptr);
+                       erofs_put_metabuf(&buf);
+                       ptr = eend;
+                       continue;
+               } else if (!(map.m_flags & EROFS_MAP_MAPPED)) {
                        if (!map.m_llen) {
                                /* reached EOF */
                                memset(estart, 0, offset + size - ptr);
diff --git a/lib/namei.c b/lib/namei.c
index 8de0a908..e0a60853 100644
--- a/lib/namei.c
+++ b/lib/namei.c
@@ -27,6 +27,7 @@ int erofs_read_inode_from_disk(struct erofs_inode *vi)
        struct erofs_sb_info *sbi = vi->sbi;
        erofs_blk_t blkaddr = erofs_blknr(sbi, erofs_iloc(vi));
        unsigned int ofs = erofs_blkoff(sbi, erofs_iloc(vi));
+       bool in_mbox = erofs_inode_in_metabox(vi);
        struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
        erofs_blk_t addrmask = BIT_ULL(48) - 1;
        struct erofs_inode_extended *die, copied;
@@ -35,7 +36,7 @@ int erofs_read_inode_from_disk(struct erofs_inode *vi)
        void *ptr;
        int err = 0;
 
-       ptr = erofs_read_metabuf(&buf, sbi, erofs_pos(sbi, blkaddr));
+       ptr = erofs_read_metabuf(&buf, sbi, erofs_pos(sbi, blkaddr), in_mbox);
        if (IS_ERR(ptr)) {
                err = PTR_ERR(ptr);
                erofs_err("failed to get inode (nid: %llu) page, err %d",
@@ -74,7 +75,7 @@ int erofs_read_inode_from_disk(struct erofs_inode *vi)
 
                        memcpy(&copied, dic, gotten);
                        ptr = erofs_read_metabuf(&buf, sbi,
-                                       erofs_pos(sbi, blkaddr + 1));
+                                       erofs_pos(sbi, blkaddr + 1), in_mbox);
                        if (IS_ERR(ptr)) {
                                err = PTR_ERR(ptr);
                                erofs_err("failed to get inode payload block 
(nid: %llu), err %d",
diff --git a/lib/super.c b/lib/super.c
index 1d13e6e3..57849fbf 100644
--- a/lib/super.c
+++ b/lib/super.c
@@ -79,7 +79,7 @@ int erofs_read_superblock(struct erofs_sb_info *sbi)
        int read, ret;
 
        read = erofs_io_pread(&sbi->bdev, data, EROFS_MAX_BLOCK_SIZE, 0);
-       if (read < EROFS_SUPER_END) {
+       if (read < EROFS_SUPER_OFFSET + sizeof(*dsb)) {
                ret = read < 0 ? read : -EIO;
                erofs_err("cannot read erofs superblock: %s",
                          erofs_strerror(ret));
@@ -123,6 +123,12 @@ int erofs_read_superblock(struct erofs_sb_info *sbi)
                sbi->root_nid = le16_to_cpu(dsb->rb.rootnid_2b);
        }
        sbi->packed_nid = le64_to_cpu(dsb->packed_nid);
+       if (erofs_sb_has_metabox(sbi)) {
+               if (sbi->sb_size <= offsetof(struct erofs_super_block,
+                                            metabox_nid))
+                       return -EFSCORRUPTED;
+               sbi->metabox_nid = le64_to_cpu(dsb->metabox_nid);
+       }
        sbi->inos = le64_to_cpu(dsb->inos);
        sbi->checksum = le32_to_cpu(dsb->checksum);
 
@@ -187,7 +193,6 @@ int erofs_writesb(struct erofs_sb_info *sbi, struct 
erofs_buffer_head *sb_bh)
                .devt_slotoff = cpu_to_le16(sbi->devt_slotoff),
                .packed_nid = cpu_to_le64(sbi->packed_nid),
        };
-       const u32 sb_blksize = round_up(EROFS_SUPER_END, erofs_blksiz(sbi));
        char *buf;
        int ret;
 
@@ -205,16 +210,21 @@ int erofs_writesb(struct erofs_sb_info *sbi, struct 
erofs_buffer_head *sb_bh)
        else
                sb.u1.lz4_max_distance = cpu_to_le16(sbi->lz4.max_distance);
 
-       buf = calloc(sb_blksize, 1);
+       if (erofs_sb_has_metabox(sbi))
+               sb.metabox_nid = cpu_to_le64(sbi->metabox_nid);
+       sb.sb_extslots = (sbi->sb_size - 128) >> 4;
+
+       buf = calloc(round_up(EROFS_SUPER_OFFSET + sbi->sb_size,
+                             erofs_blksiz(sbi)), 1);
        if (!buf) {
                erofs_err("failed to allocate memory for sb: %s",
                          erofs_strerror(-errno));
                return -ENOMEM;
        }
-       memcpy(buf + EROFS_SUPER_OFFSET, &sb, sizeof(sb));
+       memcpy(buf + EROFS_SUPER_OFFSET, &sb, sbi->sb_size);
 
        ret = erofs_dev_write(sbi, buf, sb_bh ? erofs_btell(sb_bh, false) : 0,
-                             EROFS_SUPER_END);
+                             EROFS_SUPER_OFFSET + sbi->sb_size);
        free(buf);
        if (sb_bh)
                erofs_bdrop(sb_bh, false);
@@ -223,9 +233,16 @@ int erofs_writesb(struct erofs_sb_info *sbi, struct 
erofs_buffer_head *sb_bh)
 
 struct erofs_buffer_head *erofs_reserve_sb(struct erofs_bufmgr *bmgr)
 {
+       struct erofs_sb_info *sbi = bmgr->sbi;
        struct erofs_buffer_head *bh;
+       unsigned int sb_size = 128;
        int err;
 
+       if (erofs_sb_has_metabox(sbi) &&
+           sb_size <= offsetof(struct erofs_super_block, metabox_nid))
+               sb_size = offsetof(struct erofs_super_block, metabox_nid) + 8;
+       sbi->sb_size = round_up(sb_size, 16);
+
        bh = erofs_balloc(bmgr, META, 0, 0);
        if (IS_ERR(bh)) {
                erofs_err("failed to allocate super: %s",
@@ -233,7 +250,7 @@ struct erofs_buffer_head *erofs_reserve_sb(struct 
erofs_bufmgr *bmgr)
                return bh;
        }
        bh->op = &erofs_skip_write_bhops;
-       err = erofs_bh_balloon(bh, EROFS_SUPER_END);
+       err = erofs_bh_balloon(bh, EROFS_SUPER_OFFSET + sbi->sb_size);
        if (err < 0) {
                erofs_err("failed to balloon super: %s", erofs_strerror(err));
                goto err_bdrop;
diff --git a/lib/xattr.c b/lib/xattr.c
index a2ef8d20..1f6a83f6 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -1079,7 +1079,7 @@ static int init_inode_xattrs(struct erofs_inode *vi)
        it.ofs = erofs_blkoff(sbi, erofs_iloc(vi) + vi->inode_isize);
 
        /* read in shared xattr array (non-atomic, see kmalloc below) */
-       it.kaddr = erofs_read_metabuf(&it.buf, sbi, erofs_pos(sbi, it.blkaddr));
+       it.kaddr = erofs_read_metabuf(&it.buf, sbi, erofs_pos(sbi, it.blkaddr), 
false);
        if (IS_ERR(it.kaddr))
                return PTR_ERR(it.kaddr);
 
@@ -1101,7 +1101,7 @@ static int init_inode_xattrs(struct erofs_inode *vi)
                        DBG_BUGON(it.ofs != erofs_blksiz(sbi));
 
                        it.kaddr = erofs_read_metabuf(&it.buf, sbi,
-                                       erofs_pos(sbi, ++it.blkaddr));
+                                       erofs_pos(sbi, ++it.blkaddr), false);
                        if (IS_ERR(it.kaddr)) {
                                free(vi->xattr_shared_xattrs);
                                vi->xattr_shared_xattrs = NULL;
@@ -1143,7 +1143,7 @@ static inline int xattr_iter_fixup(struct xattr_iter *it)
 
        it->blkaddr += erofs_blknr(sbi, it->ofs);
        it->kaddr = erofs_read_metabuf(&it->buf, sbi,
-                                      erofs_pos(sbi, it->blkaddr));
+                                      erofs_pos(sbi, it->blkaddr), false);
        if (IS_ERR(it->kaddr))
                return PTR_ERR(it->kaddr);
        it->ofs = erofs_blkoff(sbi, it->ofs);
@@ -1168,7 +1168,7 @@ static int inline_xattr_iter_begin(struct xattr_iter *it,
        it->ofs = erofs_blkoff(sbi, erofs_iloc(vi) + inline_xattr_ofs);
 
        it->kaddr = erofs_read_metabuf(&it->buf, sbi,
-                                      erofs_pos(sbi, it->blkaddr));
+                                      erofs_pos(sbi, it->blkaddr), false);
        if (IS_ERR(it->kaddr))
                return PTR_ERR(it->kaddr);
        return vi->xattr_isize - xattr_header_sz;
@@ -1393,7 +1393,7 @@ static int shared_getxattr(struct erofs_inode *vi, struct 
getxattr_iter *it)
 
                it->it.ofs = xattrblock_offset(vi, vi->xattr_shared_xattrs[i]);
                it->it.kaddr = erofs_read_metabuf(&it->it.buf, sbi,
-                                                 erofs_pos(sbi, blkaddr));
+                                                 erofs_pos(sbi, blkaddr), 
false);
                if (IS_ERR(it->it.kaddr))
                        return PTR_ERR(it->it.kaddr);
                it->it.blkaddr = blkaddr;
@@ -1548,7 +1548,7 @@ static int shared_listxattr(struct erofs_inode *vi, 
struct listxattr_iter *it)
 
                it->it.ofs = xattrblock_offset(vi, vi->xattr_shared_xattrs[i]);
                it->it.kaddr = erofs_read_metabuf(&it->it.buf, sbi,
-                                                 erofs_pos(sbi, blkaddr));
+                                                 erofs_pos(sbi, blkaddr), 
false);
                if (IS_ERR(it->it.kaddr))
                        return PTR_ERR(it->it.kaddr);
                it->it.blkaddr = blkaddr;
diff --git a/lib/zmap.c b/lib/zmap.c
index db8561be..916b0d25 100644
--- a/lib/zmap.c
+++ b/lib/zmap.c
@@ -35,7 +35,8 @@ static int z_erofs_load_full_lcluster(struct 
z_erofs_maprecorder *m,
        struct z_erofs_lcluster_index *di;
        unsigned int advise;
 
-       di = erofs_read_metabuf(&m->map->buf, sbi, pos);
+       di = erofs_read_metabuf(&m->map->buf, sbi, pos,
+                               erofs_inode_in_metabox(vi));
        if (IS_ERR(di))
                return PTR_ERR(di);
        m->lcn = lcn;
@@ -150,7 +151,8 @@ static int z_erofs_load_compact_lcluster(struct 
z_erofs_maprecorder *m,
        else
                return -EOPNOTSUPP;
 
-       in = erofs_read_metabuf(&m->map->buf, sbi, pos);
+       in = erofs_read_metabuf(&m->map->buf, sbi, pos,
+                               erofs_inode_in_metabox(vi));
        if (IS_ERR(in))
                return PTR_ERR(in);
 
@@ -541,6 +543,7 @@ static int z_erofs_map_blocks_ext(struct erofs_inode *vi,
        unsigned int recsz = z_erofs_extent_recsize(vi->z_advise);
        erofs_off_t pos = round_up(Z_EROFS_MAP_HEADER_END(erofs_iloc(vi) +
                                   vi->inode_isize + vi->xattr_isize), recsz);
+       bool in_mbox = erofs_inode_in_metabox(vi);
        erofs_off_t lend = vi->i_size;
        erofs_off_t l, r, mid, pa, la, lstart;
        struct z_erofs_extent *ext;
@@ -550,7 +553,7 @@ static int z_erofs_map_blocks_ext(struct erofs_inode *vi,
        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, sbi, pos);
+                       ext = erofs_read_metabuf(&map->buf, sbi, pos, in_mbox);
                        if (IS_ERR(ext))
                                return PTR_ERR(ext);
                        pa = le64_to_cpu(*(__le64 *)ext);
@@ -562,7 +565,7 @@ static int z_erofs_map_blocks_ext(struct erofs_inode *vi,
                }
 
                for (; lstart <= map->m_la; lstart += 1 << vi->z_lclusterbits) {
-                       ext = erofs_read_metabuf(&map->buf, sbi, pos);
+                       ext = erofs_read_metabuf(&map->buf, sbi, pos, in_mbox);
                        if (IS_ERR(ext))
                                return PTR_ERR(ext);
                        map->m_plen = le32_to_cpu(ext->plen);
@@ -582,7 +585,7 @@ static int z_erofs_map_blocks_ext(struct erofs_inode *vi,
                for (l = 0, r = vi->z_extents; l < r; ) {
                        mid = l + (r - l) / 2;
                        ext = erofs_read_metabuf(&map->buf, sbi,
-                                                pos + mid * recsz);
+                                                pos + mid * recsz, in_mbox);
                        if (IS_ERR(ext))
                                return PTR_ERR(ext);
 
@@ -651,7 +654,7 @@ static int z_erofs_fill_inode_lazy(struct erofs_inode *vi)
                return 0;
 
        pos = round_up(erofs_iloc(vi) + vi->inode_isize + vi->xattr_isize, 8);
-       h = erofs_read_metabuf(&buf, sbi, pos);
+       h = erofs_read_metabuf(&buf, sbi, pos, erofs_inode_in_metabox(vi));
        if (IS_ERR(h))
                return PTR_ERR(h);
 
-- 
2.43.5


Reply via email to