erofs: do sanity check on m->type in z_erofs_load_compact_lcluster()

All below functions will do sanity check on m->type, let's move sanity
check to z_erofs_load_compact_lcluster() for cleanup.
- z_erofs_map_blocks_fo
- z_erofs_get_extent_compressedlen
- z_erofs_get_extent_decompressedlen
- z_erofs_extent_lookback

Reviewed-by: Hongbo Li <lihongbo22@huawei.com>
Signed-off-by: Chao Yu <chao@kernel.org>
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20250708110928.3110375-1-chao@kernel.org
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
This commit is contained in:
Chao Yu 2025-07-08 19:09:28 +08:00 committed by Gao Xiang
parent 96debe8c27
commit 1a5223c182

View File

@ -240,6 +240,13 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m,
static int z_erofs_load_lcluster_from_disk(struct z_erofs_maprecorder *m, static int z_erofs_load_lcluster_from_disk(struct z_erofs_maprecorder *m,
unsigned int lcn, bool lookahead) unsigned int lcn, bool lookahead)
{ {
if (m->type >= Z_EROFS_LCLUSTER_TYPE_MAX) {
erofs_err(m->inode->i_sb, "unknown type %u @ lcn %u of nid %llu",
m->type, lcn, EROFS_I(m->inode)->nid);
DBG_BUGON(1);
return -EOPNOTSUPP;
}
switch (EROFS_I(m->inode)->datalayout) { switch (EROFS_I(m->inode)->datalayout) {
case EROFS_INODE_COMPRESSED_FULL: case EROFS_INODE_COMPRESSED_FULL:
return z_erofs_load_full_lcluster(m, lcn); return z_erofs_load_full_lcluster(m, lcn);
@ -265,12 +272,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
if (err) if (err)
return err; return err;
if (m->type >= Z_EROFS_LCLUSTER_TYPE_MAX) { if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
erofs_err(sb, "unknown type %u @ lcn %lu of nid %llu",
m->type, lcn, vi->nid);
DBG_BUGON(1);
return -EOPNOTSUPP;
} else if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
lookback_distance = m->delta[0]; lookback_distance = m->delta[0];
if (!lookback_distance) if (!lookback_distance)
break; break;
@ -325,25 +327,18 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
DBG_BUGON(lcn == initial_lcn && DBG_BUGON(lcn == initial_lcn &&
m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD); m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD);
if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) { if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD && m->delta[0] != 1) {
if (m->delta[0] != 1) { erofs_err(sb, "bogus CBLKCNT @ lcn %lu of nid %llu", lcn, vi->nid);
erofs_err(sb, "bogus CBLKCNT @ lcn %lu of nid %llu", lcn, vi->nid); DBG_BUGON(1);
DBG_BUGON(1); return -EFSCORRUPTED;
return -EFSCORRUPTED;
}
if (m->compressedblks)
goto out;
} else if (m->type < Z_EROFS_LCLUSTER_TYPE_MAX) {
/*
* if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
* rather than CBLKCNT, it's a 1 block-sized pcluster.
*/
m->compressedblks = 1;
goto out;
} }
erofs_err(sb, "cannot found CBLKCNT @ lcn %lu of nid %llu", lcn, vi->nid);
DBG_BUGON(1); /*
return -EFSCORRUPTED; * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type rather
* than CBLKCNT, it's a 1 block-sized pcluster.
*/
if (m->type != Z_EROFS_LCLUSTER_TYPE_NONHEAD || !m->compressedblks)
m->compressedblks = 1;
out: out:
m->map->m_plen = erofs_pos(sb, m->compressedblks); m->map->m_plen = erofs_pos(sb, m->compressedblks);
return 0; return 0;
@ -379,11 +374,6 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
if (lcn != headlcn) if (lcn != headlcn)
break; /* ends at the next HEAD lcluster */ break; /* ends at the next HEAD lcluster */
m->delta[1] = 1; m->delta[1] = 1;
} else {
erofs_err(inode->i_sb, "unknown type %u @ lcn %llu of nid %llu",
m->type, lcn, vi->nid);
DBG_BUGON(1);
return -EOPNOTSUPP;
} }
lcn += m->delta[1]; lcn += m->delta[1];
} }
@ -428,44 +418,33 @@ static int z_erofs_map_blocks_fo(struct inode *inode,
map->m_flags = EROFS_MAP_MAPPED | EROFS_MAP_ENCODED; map->m_flags = EROFS_MAP_MAPPED | EROFS_MAP_ENCODED;
end = (m.lcn + 1ULL) << lclusterbits; end = (m.lcn + 1ULL) << lclusterbits;
switch (m.type) { if (m.type != Z_EROFS_LCLUSTER_TYPE_NONHEAD && endoff >= m.clusterofs) {
case Z_EROFS_LCLUSTER_TYPE_PLAIN: m.headtype = m.type;
case Z_EROFS_LCLUSTER_TYPE_HEAD1: map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
case Z_EROFS_LCLUSTER_TYPE_HEAD2: /*
if (endoff >= m.clusterofs) { * For ztailpacking files, in order to inline data more
m.headtype = m.type; * effectively, special EOF lclusters are now supported
map->m_la = (m.lcn << lclusterbits) | m.clusterofs; * which can have three parts at most.
/* */
* For ztailpacking files, in order to inline data more if (ztailpacking && end > inode->i_size)
* effectively, special EOF lclusters are now supported end = inode->i_size;
* which can have three parts at most. } else {
*/ if (m.type != Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
if (ztailpacking && end > inode->i_size) /* m.lcn should be >= 1 if endoff < m.clusterofs */
end = inode->i_size; if (!m.lcn) {
break; erofs_err(sb, "invalid logical cluster 0 at nid %llu",
vi->nid);
err = -EFSCORRUPTED;
goto unmap_out;
}
end = (m.lcn << lclusterbits) | m.clusterofs;
map->m_flags |= EROFS_MAP_FULL_MAPPED;
m.delta[0] = 1;
} }
/* m.lcn should be >= 1 if endoff < m.clusterofs */
if (!m.lcn) {
erofs_err(sb, "invalid logical cluster 0 at nid %llu",
vi->nid);
err = -EFSCORRUPTED;
goto unmap_out;
}
end = (m.lcn << lclusterbits) | m.clusterofs;
map->m_flags |= EROFS_MAP_FULL_MAPPED;
m.delta[0] = 1;
fallthrough;
case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
/* get the corresponding first chunk */ /* get the corresponding first chunk */
err = z_erofs_extent_lookback(&m, m.delta[0]); err = z_erofs_extent_lookback(&m, m.delta[0]);
if (err) if (err)
goto unmap_out; goto unmap_out;
break;
default:
erofs_err(sb, "unknown type %u @ offset %llu of nid %llu",
m.type, ofs, vi->nid);
err = -EOPNOTSUPP;
goto unmap_out;
} }
if (m.partialref) if (m.partialref)
map->m_flags |= EROFS_MAP_PARTIAL_REF; map->m_flags |= EROFS_MAP_PARTIAL_REF;