Commit 269d1194 authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: fix to do sanity check on extent cache correctly



In do_read_inode(), sanity check for extent cache should be called after
f2fs_init_read_extent_tree(), fix it.

Fixes: 72840ccc ("f2fs: allocate the extent_cache by default")
Signed-off-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 9e615dbb
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -19,6 +19,31 @@
#include "node.h"
#include <trace/events/f2fs.h>

bool sanity_check_extent_cache(struct inode *inode)
{
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	struct f2fs_inode_info *fi = F2FS_I(inode);
	struct extent_info *ei;

	if (!fi->extent_tree[EX_READ])
		return true;

	ei = &fi->extent_tree[EX_READ]->largest;

	if (ei->len &&
		(!f2fs_is_valid_blkaddr(sbi, ei->blk,
					DATA_GENERIC_ENHANCE) ||
		!f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1,
					DATA_GENERIC_ENHANCE))) {
		set_sbi_flag(sbi, SBI_NEED_FSCK);
		f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix",
			  __func__, inode->i_ino,
			  ei->blk, ei->fofs, ei->len);
		return false;
	}
	return true;
}

static void __set_extent_info(struct extent_info *ei,
				unsigned int fofs, unsigned int len,
				block_t blk, bool keep_clen,
+1 −0
Original line number Diff line number Diff line
@@ -4137,6 +4137,7 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi);
/*
 * extent_cache.c
 */
bool sanity_check_extent_cache(struct inode *inode);
struct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root,
				struct rb_entry *cached_re, unsigned int ofs);
struct rb_node **f2fs_lookup_rb_tree_ext(struct f2fs_sb_info *sbi,
+6 −16
Original line number Diff line number Diff line
@@ -262,22 +262,6 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page)
		return false;
	}

	if (fi->extent_tree[EX_READ]) {
		struct extent_info *ei = &fi->extent_tree[EX_READ]->largest;

		if (ei->len &&
			(!f2fs_is_valid_blkaddr(sbi, ei->blk,
						DATA_GENERIC_ENHANCE) ||
			!f2fs_is_valid_blkaddr(sbi, ei->blk + ei->len - 1,
						DATA_GENERIC_ENHANCE))) {
			set_sbi_flag(sbi, SBI_NEED_FSCK);
			f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix",
				  __func__, inode->i_ino,
				  ei->blk, ei->fofs, ei->len);
			return false;
		}
	}

	if (f2fs_sanity_check_inline_data(inode)) {
		set_sbi_flag(sbi, SBI_NEED_FSCK);
		f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_data, run fsck to fix",
@@ -488,6 +472,12 @@ static int do_read_inode(struct inode *inode)
		return -EFSCORRUPTED;
	}

	if (!sanity_check_extent_cache(inode)) {
		f2fs_put_page(node_page, 1);
		f2fs_handle_error(sbi, ERROR_CORRUPTED_INODE);
		return -EFSCORRUPTED;
	}

	f2fs_put_page(node_page, 1);

	stat_inc_inline_xattr(inode);