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

Commit 8c14bfad authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: handle error of f2fs_iget correctly



In recover_orphan_inode, whenever f2fs_iget fail, we will make kernel panic,
but it's not reasonable, because f2fs_iget can fail due to a lot of reasons
including out of memory.

So we change error handling method as below:
a) when finding no entry for the orphan inode, bug_on for catching bugs;
b) for other reasons, report it to caller.

Signed-off-by: default avatarChao Yu <chao2.yu@samsung.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 47e70ca4
Loading
Loading
Loading
Loading
+24 −7
Original line number Diff line number Diff line
@@ -468,22 +468,34 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
	__remove_ino_entry(sbi, ino, ORPHAN_INO);
}

static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
{
	struct inode *inode = f2fs_iget(sbi->sb, ino);
	f2fs_bug_on(sbi, IS_ERR(inode));
	struct inode *inode;

	inode = f2fs_iget(sbi->sb, ino);
	if (IS_ERR(inode)) {
		/*
		 * there should be a bug that we can't find the entry
		 * to orphan inode.
		 */
		f2fs_bug_on(sbi, PTR_ERR(inode) == -ENOENT);
		return PTR_ERR(inode);
	}

	clear_nlink(inode);

	/* truncate all the data during iput */
	iput(inode);
	return 0;
}

void recover_orphan_inodes(struct f2fs_sb_info *sbi)
int recover_orphan_inodes(struct f2fs_sb_info *sbi)
{
	block_t start_blk, orphan_blocks, i, j;
	int err;

	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
		return;
		return 0;

	set_sbi_flag(sbi, SBI_POR_DOING);

@@ -499,14 +511,19 @@ void recover_orphan_inodes(struct f2fs_sb_info *sbi)
		orphan_blk = (struct f2fs_orphan_block *)page_address(page);
		for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
			nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
			recover_orphan_inode(sbi, ino);
			err = recover_orphan_inode(sbi, ino);
			if (err) {
				f2fs_put_page(page, 1);
				clear_sbi_flag(sbi, SBI_POR_DOING);
				return err;
			}
		}
		f2fs_put_page(page, 1);
	}
	/* clear Orphan Flag */
	clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG);
	clear_sbi_flag(sbi, SBI_POR_DOING);
	return;
	return 0;
}

static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
+1 −1
Original line number Diff line number Diff line
@@ -1748,7 +1748,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *);
void release_orphan_inode(struct f2fs_sb_info *);
void add_orphan_inode(struct f2fs_sb_info *, nid_t);
void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
void recover_orphan_inodes(struct f2fs_sb_info *);
int recover_orphan_inodes(struct f2fs_sb_info *);
int get_valid_checkpoint(struct f2fs_sb_info *);
void update_dirty_page(struct inode *, struct page *);
void add_dirty_dir_inode(struct inode *);
+3 −1
Original line number Diff line number Diff line
@@ -1245,7 +1245,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
	f2fs_join_shrinker(sbi);

	/* if there are nt orphan nodes free them */
	recover_orphan_inodes(sbi);
	err = recover_orphan_inodes(sbi);
	if (err)
		goto free_node_inode;

	/* read root inode and dentry */
	root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));