Skip to content

Commit ab474fc

Browse files
committed
erofs: clean up z_erofs_extent_lookback
Avoid the unnecessary tail recursion since it can be converted into a loop directly in order to prevent potential stack overflow. It's a pretty straightforward conversion. Link: https://lore.kernel.org/r/20220310182743.102365-1-hsiangkao@linux.alibaba.com Reviewed-by: Yue Hu <huyue2@coolpad.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
1 parent d467e98 commit ab474fc

1 file changed

Lines changed: 33 additions & 34 deletions

File tree

fs/erofs/zmap.c

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -431,48 +431,47 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
431431
unsigned int lookback_distance)
432432
{
433433
struct erofs_inode *const vi = EROFS_I(m->inode);
434-
struct erofs_map_blocks *const map = m->map;
435434
const unsigned int lclusterbits = vi->z_logical_clusterbits;
436-
unsigned long lcn = m->lcn;
437-
int err;
438435

439-
if (lcn < lookback_distance) {
440-
erofs_err(m->inode->i_sb,
441-
"bogus lookback distance @ nid %llu", vi->nid);
442-
DBG_BUGON(1);
443-
return -EFSCORRUPTED;
444-
}
436+
while (m->lcn >= lookback_distance) {
437+
unsigned long lcn = m->lcn - lookback_distance;
438+
int err;
445439

446-
/* load extent head logical cluster if needed */
447-
lcn -= lookback_distance;
448-
err = z_erofs_load_cluster_from_disk(m, lcn, false);
449-
if (err)
450-
return err;
440+
/* load extent head logical cluster if needed */
441+
err = z_erofs_load_cluster_from_disk(m, lcn, false);
442+
if (err)
443+
return err;
451444

452-
switch (m->type) {
453-
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
454-
if (!m->delta[0]) {
445+
switch (m->type) {
446+
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
447+
if (!m->delta[0]) {
448+
erofs_err(m->inode->i_sb,
449+
"invalid lookback distance 0 @ nid %llu",
450+
vi->nid);
451+
DBG_BUGON(1);
452+
return -EFSCORRUPTED;
453+
}
454+
lookback_distance = m->delta[0];
455+
continue;
456+
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
457+
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
458+
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
459+
m->headtype = m->type;
460+
m->map->m_la = (lcn << lclusterbits) | m->clusterofs;
461+
return 0;
462+
default:
455463
erofs_err(m->inode->i_sb,
456-
"invalid lookback distance 0 @ nid %llu",
457-
vi->nid);
464+
"unknown type %u @ lcn %lu of nid %llu",
465+
m->type, lcn, vi->nid);
458466
DBG_BUGON(1);
459-
return -EFSCORRUPTED;
467+
return -EOPNOTSUPP;
460468
}
461-
return z_erofs_extent_lookback(m, m->delta[0]);
462-
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
463-
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
464-
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
465-
m->headtype = m->type;
466-
map->m_la = (lcn << lclusterbits) | m->clusterofs;
467-
break;
468-
default:
469-
erofs_err(m->inode->i_sb,
470-
"unknown type %u @ lcn %lu of nid %llu",
471-
m->type, lcn, vi->nid);
472-
DBG_BUGON(1);
473-
return -EOPNOTSUPP;
474469
}
475-
return 0;
470+
471+
erofs_err(m->inode->i_sb, "bogus lookback distance @ nid %llu",
472+
vi->nid);
473+
DBG_BUGON(1);
474+
return -EFSCORRUPTED;
476475
}
477476

478477
static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,

0 commit comments

Comments
 (0)