Fragments aren't limited by Z_EROFS_PCLUSTER_MAX_DSIZE. However, if
a fragment's logical length is larger than Z_EROFS_PCLUSTER_MAX_DSIZE
but the fragment is not the whole inode, it currently returns
-EOPNOTSUPP because m_flags has the wrong EROFS_MAP_ENCODED flag set.
It is not intended by design but should be rare, as it can only be
reproduced by mkfs with `-Eall-fragments` in a specific case.

Let's normalize fragment m_flags using the new EROFS_MAP_FRAGMENT.

Reported-by: Axel Fontaine <a...@axelfontaine.com>
Closes: https://github.com/erofs/erofs-utils/issues/23
Fixes: 7c3ca1838a78 ("erofs: restrict pcluster size limitations")
Signed-off-by: Gao Xiang <hsiang...@linux.alibaba.com>
---
 fs/erofs/internal.h | 4 +++-
 fs/erofs/zmap.c     | 7 +++----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 0d19bde8c094..06b867d2fc3b 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -315,10 +315,12 @@ static inline struct folio 
*erofs_grab_folio_nowait(struct address_space *as,
 /* The length of extent is full */
 #define EROFS_MAP_FULL_MAPPED  0x0008
 /* Located in the special packed inode */
-#define EROFS_MAP_FRAGMENT     0x0010
+#define __EROFS_MAP_FRAGMENT   0x0010
 /* The extent refers to partial decompressed data */
 #define EROFS_MAP_PARTIAL_REF  0x0020
 
+#define EROFS_MAP_FRAGMENT     (EROFS_MAP_MAPPED | __EROFS_MAP_FRAGMENT)
+
 struct erofs_map_blocks {
        struct erofs_buf buf;
 
diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c
index 431199452542..07a6810a076b 100644
--- a/fs/erofs/zmap.c
+++ b/fs/erofs/zmap.c
@@ -403,8 +403,7 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
            !vi->z_tailextent_headlcn) {
                map->m_la = 0;
                map->m_llen = inode->i_size;
-               map->m_flags = EROFS_MAP_MAPPED |
-                       EROFS_MAP_FULL_MAPPED | EROFS_MAP_FRAGMENT;
+               map->m_flags = EROFS_MAP_FRAGMENT;
                return 0;
        }
        initial_lcn = ofs >> lclusterbits;
@@ -468,7 +467,7 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
                        goto unmap_out;
                }
        } else if (fragment && m.lcn == vi->z_tailextent_headlcn) {
-               map->m_flags |= EROFS_MAP_FRAGMENT;
+               map->m_flags = EROFS_MAP_FRAGMENT;
        } else {
                map->m_pa = erofs_pos(sb, m.pblk);
                err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
@@ -596,7 +595,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode,
        if (lstart < lend) {
                map->m_la = lstart;
                if (last && (vi->z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)) {
-                       map->m_flags |= EROFS_MAP_MAPPED | EROFS_MAP_FRAGMENT;
+                       map->m_flags = EROFS_MAP_FRAGMENT;
                        vi->z_fragmentoff = map->m_plen;
                        if (recsz > offsetof(struct z_erofs_extent, pstart_lo))
                                vi->z_fragmentoff |= map->m_pa << 32;
-- 
2.43.5


Reply via email to