Skip to content

Commit b44686c

Browse files
committed
erofs: fix large fragment handling
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 <[email protected]> Closes: erofs/erofs-utils#23 Fixes: 7c3ca18 ("erofs: restrict pcluster size limitations") Signed-off-by: Gao Xiang <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d31fbdc commit b44686c

File tree

3 files changed

+8
-7
lines changed

3 files changed

+8
-7
lines changed

fs/erofs/internal.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,12 @@ static inline struct folio *erofs_grab_folio_nowait(struct address_space *as,
315315
/* The length of extent is full */
316316
#define EROFS_MAP_FULL_MAPPED 0x0008
317317
/* Located in the special packed inode */
318-
#define EROFS_MAP_FRAGMENT 0x0010
318+
#define __EROFS_MAP_FRAGMENT 0x0010
319319
/* The extent refers to partial decompressed data */
320320
#define EROFS_MAP_PARTIAL_REF 0x0020
321321

322+
#define EROFS_MAP_FRAGMENT (EROFS_MAP_MAPPED | __EROFS_MAP_FRAGMENT)
323+
322324
struct erofs_map_blocks {
323325
struct erofs_buf buf;
324326

fs/erofs/zdata.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,7 @@ static int z_erofs_scan_folio(struct z_erofs_frontend *f,
10341034
if (!(map->m_flags & EROFS_MAP_MAPPED)) {
10351035
folio_zero_segment(folio, cur, end);
10361036
tight = false;
1037-
} else if (map->m_flags & EROFS_MAP_FRAGMENT) {
1037+
} else if (map->m_flags & __EROFS_MAP_FRAGMENT) {
10381038
erofs_off_t fpos = offset + cur - map->m_la;
10391039

10401040
err = z_erofs_read_fragment(inode->i_sb, folio, cur,

fs/erofs/zmap.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,7 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
413413
!vi->z_tailextent_headlcn) {
414414
map->m_la = 0;
415415
map->m_llen = inode->i_size;
416-
map->m_flags = EROFS_MAP_MAPPED |
417-
EROFS_MAP_FULL_MAPPED | EROFS_MAP_FRAGMENT;
416+
map->m_flags = EROFS_MAP_FRAGMENT;
418417
return 0;
419418
}
420419
initial_lcn = ofs >> lclusterbits;
@@ -489,7 +488,7 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
489488
goto unmap_out;
490489
}
491490
} else if (fragment && m.lcn == vi->z_tailextent_headlcn) {
492-
map->m_flags |= EROFS_MAP_FRAGMENT;
491+
map->m_flags = EROFS_MAP_FRAGMENT;
493492
} else {
494493
map->m_pa = erofs_pos(sb, m.pblk);
495494
err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
@@ -617,7 +616,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode,
617616
if (lstart < lend) {
618617
map->m_la = lstart;
619618
if (last && (vi->z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)) {
620-
map->m_flags |= EROFS_MAP_MAPPED | EROFS_MAP_FRAGMENT;
619+
map->m_flags = EROFS_MAP_FRAGMENT;
621620
vi->z_fragmentoff = map->m_plen;
622621
if (recsz > offsetof(struct z_erofs_extent, pstart_lo))
623622
vi->z_fragmentoff |= map->m_pa << 32;
@@ -797,7 +796,7 @@ static int z_erofs_iomap_begin_report(struct inode *inode, loff_t offset,
797796
iomap->length = map.m_llen;
798797
if (map.m_flags & EROFS_MAP_MAPPED) {
799798
iomap->type = IOMAP_MAPPED;
800-
iomap->addr = map.m_flags & EROFS_MAP_FRAGMENT ?
799+
iomap->addr = map.m_flags & __EROFS_MAP_FRAGMENT ?
801800
IOMAP_NULL_ADDR : map.m_pa;
802801
} else {
803802
iomap->type = IOMAP_HOLE;

0 commit comments

Comments
 (0)