Commit 2aaea533 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: compress: do sanity check on cluster when CONFIG_F2FS_CHECK_FS is on



This patch covers sanity check logic on cluster w/ CONFIG_F2FS_CHECK_FS,
otherwise, there will be performance regression while querying cluster
mapping info.

Callers of f2fs_is_compressed_cluster() only care about whether cluster
is compressed or not, rather than # of valid blocks in compressed cluster,
so, let's adjust f2fs_is_compressed_cluster()'s logic according to
caller's requirement.

Signed-off-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent b0327c84
Loading
Loading
Loading
Loading
+34 −27
Original line number Diff line number Diff line
@@ -893,14 +893,15 @@ static bool cluster_has_invalid_data(struct compress_ctx *cc)

bool f2fs_sanity_check_cluster(struct dnode_of_data *dn)
{
#ifdef CONFIG_F2FS_CHECK_FS
	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
	unsigned int cluster_size = F2FS_I(dn->inode)->i_cluster_size;
	bool compressed = dn->data_blkaddr == COMPRESS_ADDR;
	int cluster_end = 0;
	unsigned int count;
	int i;
	char *reason = "";

	if (!compressed)
	if (dn->data_blkaddr != COMPRESS_ADDR)
		return false;

	/* [..., COMPR_ADDR, ...] */
@@ -909,7 +910,7 @@ bool f2fs_sanity_check_cluster(struct dnode_of_data *dn)
		goto out;
	}

	for (i = 1; i < cluster_size; i++) {
	for (i = 1, count = 1; i < cluster_size; i++, count++) {
		block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
							dn->ofs_in_node + i);

@@ -929,19 +930,42 @@ bool f2fs_sanity_check_cluster(struct dnode_of_data *dn)
			goto out;
		}
	}

	f2fs_bug_on(F2FS_I_SB(dn->inode), count != cluster_size &&
		!is_inode_flag_set(dn->inode, FI_COMPRESS_RELEASED));

	return false;
out:
	f2fs_warn(sbi, "access invalid cluster, ino:%lu, nid:%u, ofs_in_node:%u, reason:%s",
			dn->inode->i_ino, dn->nid, dn->ofs_in_node, reason);
	set_sbi_flag(sbi, SBI_NEED_FSCK);
	return true;
#else
	return false;
#endif
}

static int __f2fs_get_cluster_blocks(struct inode *inode,
					struct dnode_of_data *dn)
{
	unsigned int cluster_size = F2FS_I(inode)->i_cluster_size;
	int count, i;

	for (i = 1, count = 1; i < cluster_size; i++) {
		block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
							dn->ofs_in_node + i);

		if (__is_valid_data_blkaddr(blkaddr))
			count++;
	}

	return count;
}

static int __f2fs_cluster_blocks(struct inode *inode,
				unsigned int cluster_idx, bool compr)
				unsigned int cluster_idx, bool compr_blks)
{
	struct dnode_of_data dn;
	unsigned int cluster_size = F2FS_I(inode)->i_cluster_size;
	unsigned int start_idx = cluster_idx <<
				F2FS_I(inode)->i_log_cluster_size;
	int ret;
@@ -956,31 +980,14 @@ static int __f2fs_cluster_blocks(struct inode *inode,

	if (f2fs_sanity_check_cluster(&dn)) {
		ret = -EFSCORRUPTED;
		f2fs_handle_error(F2FS_I_SB(inode), ERROR_CORRUPTED_CLUSTER);
		goto fail;
	}

	if (dn.data_blkaddr == COMPRESS_ADDR) {
		int i;

		if (compr_blks)
			ret = __f2fs_get_cluster_blocks(inode, &dn);
		else
			ret = 1;
		for (i = 1; i < cluster_size; i++) {
			block_t blkaddr;

			blkaddr = data_blkaddr(dn.inode,
					dn.node_page, dn.ofs_in_node + i);
			if (compr) {
				if (__is_valid_data_blkaddr(blkaddr))
					ret++;
			} else {
				if (blkaddr != NULL_ADDR)
					ret++;
			}
		}

		f2fs_bug_on(F2FS_I_SB(inode),
			!compr && ret != cluster_size &&
			!is_inode_flag_set(inode, FI_COMPRESS_RELEASED));
	}
fail:
	f2fs_put_dnode(&dn);
@@ -993,7 +1000,7 @@ static int f2fs_compressed_blocks(struct compress_ctx *cc)
	return __f2fs_cluster_blocks(cc->inode, cc->cluster_idx, true);
}

/* return # of valid blocks in compressed cluster */
/* return whether cluster is compressed one or not */
int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index)
{
	return __f2fs_cluster_blocks(inode,
+1 −3
Original line number Diff line number Diff line
@@ -1690,9 +1690,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag)
			map->m_flags |= F2FS_MAP_NEW;
	} else if (is_hole) {
		if (f2fs_compressed_file(inode) &&
		    f2fs_sanity_check_cluster(&dn) &&
		    (flag != F2FS_GET_BLOCK_FIEMAP ||
		     IS_ENABLED(CONFIG_F2FS_CHECK_FS))) {
		    f2fs_sanity_check_cluster(&dn)) {
			err = -EFSCORRUPTED;
			f2fs_handle_error(sbi,
					ERROR_CORRUPTED_CLUSTER);