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: Chao Yu <chao2.yu@samsung.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
47e70ca46f
commit
8c14bfadea
@ -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)
|
||||
|
@ -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 *);
|
||||
|
@ -1245,7 +1245,9 @@ try_onemore:
|
||||
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));
|
||||
|
Loading…
Reference in New Issue
Block a user