Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3cc2aca3 authored by Gao Xiang's avatar Gao Xiang Committed by Gao Xiang
Browse files

erofs: support parsing big pcluster compress indexes

When INCOMPAT_BIG_PCLUSTER sb feature is enabled, legacy compress indexes
will also have the same on-disk header compact indexes to keep per-file
configurations instead of leaving it zeroed.

If ADVISE_BIG_PCLUSTER is set for a file, CBLKCNT will be loaded for each
pcluster in this file by parsing 1st non-head lcluster.

Link: https://lore.kernel.org/r/20210407043927.10623-8-xiang@kernel.org


Acked-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarGao Xiang <hsiangkao@redhat.com>
parent 725d21c4
Loading
Loading
Loading
Loading
+73 −6
Original line number Diff line number Diff line
@@ -10,8 +10,10 @@
int z_erofs_fill_inode(struct inode *inode)
{
	struct erofs_inode *const vi = EROFS_I(inode);
	struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);

	if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) {
	if (!erofs_sb_has_big_pcluster(sbi) &&
	    vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) {
		vi->z_advise = 0;
		vi->z_algorithmtype[0] = 0;
		vi->z_algorithmtype[1] = 0;
@@ -48,7 +50,8 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
	if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags))
		goto out_unlock;

	DBG_BUGON(vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY);
	DBG_BUGON(!erofs_sb_has_big_pcluster(EROFS_SB(sb)) &&
		  vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY);

	pos = ALIGN(iloc(EROFS_SB(sb), vi->nid) + vi->inode_isize +
		    vi->xattr_isize, 8);
@@ -95,7 +98,7 @@ struct z_erofs_maprecorder {
	u8  type;
	u16 clusterofs;
	u16 delta[2];
	erofs_blk_t pblk;
	erofs_blk_t pblk, compressedlcs;
};

static int z_erofs_reload_indexes(struct z_erofs_maprecorder *m,
@@ -158,6 +161,15 @@ static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m,
	case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
		m->clusterofs = 1 << vi->z_logical_clusterbits;
		m->delta[0] = le16_to_cpu(di->di_u.delta[0]);
		if (m->delta[0] & Z_EROFS_VLE_DI_D0_CBLKCNT) {
			if (!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) {
				DBG_BUGON(1);
				return -EFSCORRUPTED;
			}
			m->compressedlcs = m->delta[0] &
				~Z_EROFS_VLE_DI_D0_CBLKCNT;
			m->delta[0] = 1;
		}
		m->delta[1] = le16_to_cpu(di->di_u.delta[1]);
		break;
	case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
@@ -365,6 +377,58 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
	return 0;
}

static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
					    unsigned int initial_lcn)
{
	struct erofs_inode *const vi = EROFS_I(m->inode);
	struct erofs_map_blocks *const map = m->map;
	const unsigned int lclusterbits = vi->z_logical_clusterbits;
	unsigned long lcn;
	int err;

	DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN &&
		  m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD);
	if (!(map->m_flags & EROFS_MAP_ZIPPED) ||
	    !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) {
		map->m_plen = 1 << lclusterbits;
		return 0;
	}

	lcn = m->lcn + 1;
	if (m->compressedlcs)
		goto out;
	if (lcn == initial_lcn)
		goto err_bonus_cblkcnt;

	err = z_erofs_load_cluster_from_disk(m, lcn);
	if (err)
		return err;

	switch (m->type) {
	case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
		if (m->delta[0] != 1)
			goto err_bonus_cblkcnt;
		if (m->compressedlcs)
			break;
		/* fallthrough */
	default:
		erofs_err(m->inode->i_sb,
			  "cannot found CBLKCNT @ lcn %lu of nid %llu",
			  lcn, vi->nid);
		DBG_BUGON(1);
		return -EFSCORRUPTED;
	}
out:
	map->m_plen = m->compressedlcs << lclusterbits;
	return 0;
err_bonus_cblkcnt:
	erofs_err(m->inode->i_sb,
		  "bogus CBLKCNT @ lcn %lu of nid %llu",
		  lcn, vi->nid);
	DBG_BUGON(1);
	return -EFSCORRUPTED;
}

int z_erofs_map_blocks_iter(struct inode *inode,
			    struct erofs_map_blocks *map,
			    int flags)
@@ -376,6 +440,7 @@ int z_erofs_map_blocks_iter(struct inode *inode,
	};
	int err = 0;
	unsigned int lclusterbits, endoff;
	unsigned long initial_lcn;
	unsigned long long ofs, end;

	trace_z_erofs_map_blocks_iter_enter(inode, map, flags);
@@ -394,10 +459,10 @@ int z_erofs_map_blocks_iter(struct inode *inode,

	lclusterbits = vi->z_logical_clusterbits;
	ofs = map->m_la;
	m.lcn = ofs >> lclusterbits;
	initial_lcn = ofs >> lclusterbits;
	endoff = ofs & ((1 << lclusterbits) - 1);

	err = z_erofs_load_cluster_from_disk(&m, m.lcn);
	err = z_erofs_load_cluster_from_disk(&m, initial_lcn);
	if (err)
		goto unmap_out;

@@ -441,10 +506,12 @@ int z_erofs_map_blocks_iter(struct inode *inode,
	}

	map->m_llen = end - map->m_la;
	map->m_plen = 1 << lclusterbits;
	map->m_pa = blknr_to_addr(m.pblk);
	map->m_flags |= EROFS_MAP_MAPPED;

	err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
	if (err)
		goto out;
unmap_out:
	if (m.kaddr)
		kunmap_atomic(m.kaddr);