Skip to content

Commit 5b9654e

Browse files
committed
erofs: teach z_erofs_scan_folios() to handle multi-page folios
Previously, a folio just contains one page. In order to enable large folios, z_erofs_scan_folios() needs to handle multi-page folios. First, this patch eliminates all gotos. Instead, the new loop deal with multiple parts in each folio. It's simple to handle the parts which belong to unmapped extents or fragment extents; but for encoded extents, the page boundaries needs to be considered for `tight` and `split` to keep inplace I/Os work correctly: when a part crosses the page boundary, they needs to be reseted properly. Besides, simplify `tight` derivation since Z_EROFS_PCLUSTER_HOOKED has been removed for quite a while. Signed-off-by: Gao Xiang <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 90cd33d commit 5b9654e

File tree

1 file changed

+82
-85
lines changed

1 file changed

+82
-85
lines changed

fs/erofs/zdata.c

Lines changed: 82 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -950,100 +950,97 @@ static int z_erofs_read_fragment(struct super_block *sb, struct folio *folio,
950950
return 0;
951951
}
952952

953-
static int z_erofs_scan_folio(struct z_erofs_decompress_frontend *fe,
953+
static int z_erofs_scan_folio(struct z_erofs_decompress_frontend *f,
954954
struct folio *folio, bool ra)
955955
{
956-
struct inode *const inode = fe->inode;
957-
struct erofs_map_blocks *const map = &fe->map;
956+
struct inode *const inode = f->inode;
957+
struct erofs_map_blocks *const map = &f->map;
958958
const loff_t offset = folio_pos(folio);
959-
const unsigned int bs = i_blocksize(inode), fs = folio_size(folio);
960-
bool tight = true, exclusive;
961-
unsigned int cur, end, split;
962-
int err = 0;
959+
const unsigned int bs = i_blocksize(inode);
960+
unsigned int end = folio_size(folio), split = 0, cur, pgs;
961+
bool tight, excl;
962+
int err;
963963

964+
tight = (bs == PAGE_SIZE);
964965
z_erofs_onlinefolio_init(folio);
965-
split = 0;
966-
end = fs;
967-
repeat:
968-
if (offset + end - 1 < map->m_la ||
969-
offset + end - 1 >= map->m_la + map->m_llen) {
970-
z_erofs_pcluster_end(fe);
971-
map->m_la = offset + end - 1;
972-
map->m_llen = 0;
973-
err = z_erofs_map_blocks_iter(inode, map, 0);
974-
if (err)
975-
goto out;
976-
}
977-
978-
cur = offset > map->m_la ? 0 : map->m_la - offset;
979-
/* bump split parts first to avoid several separate cases */
980-
++split;
981-
982-
if (!(map->m_flags & EROFS_MAP_MAPPED)) {
983-
folio_zero_segment(folio, cur, end);
984-
tight = false;
985-
goto next_part;
986-
}
987-
988-
if (map->m_flags & EROFS_MAP_FRAGMENT) {
989-
erofs_off_t fpos = offset + cur - map->m_la;
966+
do {
967+
if (offset + end - 1 < map->m_la ||
968+
offset + end - 1 >= map->m_la + map->m_llen) {
969+
z_erofs_pcluster_end(f);
970+
map->m_la = offset + end - 1;
971+
map->m_llen = 0;
972+
err = z_erofs_map_blocks_iter(inode, map, 0);
973+
if (err)
974+
break;
975+
}
990976

991-
err = z_erofs_read_fragment(inode->i_sb, folio, cur,
992-
cur + min(map->m_llen - fpos, end - cur),
993-
EROFS_I(inode)->z_fragmentoff + fpos);
994-
if (err)
995-
goto out;
996-
tight = false;
997-
goto next_part;
998-
}
977+
cur = offset > map->m_la ? 0 : map->m_la - offset;
978+
pgs = round_down(cur, PAGE_SIZE);
979+
/* bump split parts first to avoid several separate cases */
980+
++split;
981+
982+
if (!(map->m_flags & EROFS_MAP_MAPPED)) {
983+
folio_zero_segment(folio, cur, end);
984+
tight = false;
985+
} else if (map->m_flags & EROFS_MAP_FRAGMENT) {
986+
erofs_off_t fpos = offset + cur - map->m_la;
987+
988+
err = z_erofs_read_fragment(inode->i_sb, folio, cur,
989+
cur + min(map->m_llen - fpos, end - cur),
990+
EROFS_I(inode)->z_fragmentoff + fpos);
991+
if (err)
992+
break;
993+
tight = false;
994+
} else {
995+
if (!f->pcl) {
996+
err = z_erofs_pcluster_begin(f);
997+
if (err)
998+
break;
999+
f->pcl->besteffort |= !ra;
1000+
}
9991001

1000-
if (!fe->pcl) {
1001-
err = z_erofs_pcluster_begin(fe);
1002-
if (err)
1003-
goto out;
1004-
fe->pcl->besteffort |= !ra;
1005-
}
1002+
pgs = round_down(end - 1, PAGE_SIZE);
1003+
/*
1004+
* Ensure this partial page belongs to this submit chain
1005+
* rather than other concurrent submit chains or
1006+
* noio(bypass) chains since those chains are handled
1007+
* asynchronously thus it cannot be used for inplace I/O
1008+
* or bvpage (should be processed in the strict order.)
1009+
*/
1010+
tight &= (f->mode >= Z_EROFS_PCLUSTER_FOLLOWED);
1011+
excl = false;
1012+
if (cur <= pgs) {
1013+
excl = (split <= 1) || tight;
1014+
cur = pgs;
1015+
}
10061016

1007-
/*
1008-
* Ensure the current partial folio belongs to this submit chain rather
1009-
* than other concurrent submit chains or the noio(bypass) chain since
1010-
* those chains are handled asynchronously thus the folio cannot be used
1011-
* for inplace I/O or bvpage (should be processed in a strict order.)
1012-
*/
1013-
tight &= (fe->mode > Z_EROFS_PCLUSTER_FOLLOWED_NOINPLACE);
1014-
exclusive = (!cur && ((split <= 1) || (tight && bs == fs)));
1015-
if (cur)
1016-
tight &= (fe->mode >= Z_EROFS_PCLUSTER_FOLLOWED);
1017-
1018-
err = z_erofs_attach_page(fe, &((struct z_erofs_bvec) {
1019-
.page = &folio->page,
1020-
.offset = offset - map->m_la,
1021-
.end = end,
1022-
}), exclusive);
1023-
if (err)
1024-
goto out;
1025-
1026-
z_erofs_onlinefolio_split(folio);
1027-
if (fe->pcl->pageofs_out != (map->m_la & ~PAGE_MASK))
1028-
fe->pcl->multibases = true;
1029-
if (fe->pcl->length < offset + end - map->m_la) {
1030-
fe->pcl->length = offset + end - map->m_la;
1031-
fe->pcl->pageofs_out = map->m_la & ~PAGE_MASK;
1032-
}
1033-
if ((map->m_flags & EROFS_MAP_FULL_MAPPED) &&
1034-
!(map->m_flags & EROFS_MAP_PARTIAL_REF) &&
1035-
fe->pcl->length == map->m_llen)
1036-
fe->pcl->partial = false;
1037-
next_part:
1038-
/* shorten the remaining extent to update progress */
1039-
map->m_llen = offset + cur - map->m_la;
1040-
map->m_flags &= ~EROFS_MAP_FULL_MAPPED;
1041-
1042-
end = cur;
1043-
if (end > 0)
1044-
goto repeat;
1017+
err = z_erofs_attach_page(f, &((struct z_erofs_bvec) {
1018+
.page = folio_page(folio, pgs >> PAGE_SHIFT),
1019+
.offset = offset + pgs - map->m_la,
1020+
.end = end - pgs, }), excl);
1021+
if (err)
1022+
break;
10451023

1046-
out:
1024+
z_erofs_onlinefolio_split(folio);
1025+
if (f->pcl->pageofs_out != (map->m_la & ~PAGE_MASK))
1026+
f->pcl->multibases = true;
1027+
if (f->pcl->length < offset + end - map->m_la) {
1028+
f->pcl->length = offset + end - map->m_la;
1029+
f->pcl->pageofs_out = map->m_la & ~PAGE_MASK;
1030+
}
1031+
if ((map->m_flags & EROFS_MAP_FULL_MAPPED) &&
1032+
!(map->m_flags & EROFS_MAP_PARTIAL_REF) &&
1033+
f->pcl->length == map->m_llen)
1034+
f->pcl->partial = false;
1035+
}
1036+
/* shorten the remaining extent to update progress */
1037+
map->m_llen = offset + cur - map->m_la;
1038+
map->m_flags &= ~EROFS_MAP_FULL_MAPPED;
1039+
if (cur <= pgs) {
1040+
split = cur < pgs;
1041+
tight = (bs == PAGE_SIZE);
1042+
}
1043+
} while ((end = cur) > 0);
10471044
z_erofs_onlinefolio_end(folio, err);
10481045
return err;
10491046
}

0 commit comments

Comments
 (0)