summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/inode.c
diff options
context:
space:
mode:
authorJaegeuk Kim2015-06-23 19:36:08 +0200
committerJaegeuk Kim2015-08-04 23:09:53 +0200
commitc9b63bd01dd8da096d079c490771ad8a049fd480 (patch)
treeb6fda13486d2aec3011a7ceafa3755304eda6ec1 /fs/f2fs/inode.c
parentf2fs: avoid freed stat information (diff)
downloadkernel-qcow2-linux-c9b63bd01dd8da096d079c490771ad8a049fd480.tar.gz
kernel-qcow2-linux-c9b63bd01dd8da096d079c490771ad8a049fd480.tar.xz
kernel-qcow2-linux-c9b63bd01dd8da096d079c490771ad8a049fd480.zip
f2fs: avoid to use failed inode immediately
Before iput is called, the inode number used by a bad inode can be reassigned to other new inode, resulting in any abnormal behaviors on the new inode. This should not happen for the new inode. Reviewed-by: Chao Yu <chao2.yu@samsung.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/inode.c')
-rw-r--r--fs/f2fs/inode.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 2550868dc651..757fed253697 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -314,7 +314,8 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
void f2fs_evict_inode(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
- nid_t xnid = F2FS_I(inode)->i_xattr_nid;
+ struct f2fs_inode_info *fi = F2FS_I(inode);
+ nid_t xnid = fi->i_xattr_nid;
/* some remained atomic pages should discarded */
if (f2fs_is_atomic_file(inode))
@@ -334,7 +335,7 @@ void f2fs_evict_inode(struct inode *inode)
goto no_delete;
sb_start_intwrite(inode->i_sb);
- set_inode_flag(F2FS_I(inode), FI_NO_ALLOC);
+ set_inode_flag(fi, FI_NO_ALLOC);
i_size_write(inode, 0);
if (F2FS_HAS_BLOCKS(inode))
@@ -357,14 +358,18 @@ no_delete:
invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino);
if (xnid)
invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid);
- if (is_inode_flag_set(F2FS_I(inode), FI_APPEND_WRITE))
+ if (is_inode_flag_set(fi, FI_APPEND_WRITE))
add_dirty_inode(sbi, inode->i_ino, APPEND_INO);
- if (is_inode_flag_set(F2FS_I(inode), FI_UPDATE_WRITE))
+ if (is_inode_flag_set(fi, FI_UPDATE_WRITE))
add_dirty_inode(sbi, inode->i_ino, UPDATE_INO);
+ if (is_inode_flag_set(fi, FI_FREE_NID)) {
+ alloc_nid_failed(sbi, inode->i_ino);
+ clear_inode_flag(fi, FI_FREE_NID);
+ }
out_clear:
#ifdef CONFIG_F2FS_FS_ENCRYPTION
- if (F2FS_I(inode)->i_crypt_info)
- f2fs_free_encryption_info(inode, F2FS_I(inode)->i_crypt_info);
+ if (fi->i_crypt_info)
+ f2fs_free_encryption_info(inode, fi->i_crypt_info);
#endif
clear_inode(inode);
}
@@ -384,9 +389,9 @@ void handle_failed_inode(struct inode *inode)
remove_inode_page(inode);
+ set_inode_flag(F2FS_I(inode), FI_FREE_NID);
clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
clear_inode_flag(F2FS_I(inode), FI_INLINE_DENTRY);
- alloc_nid_failed(sbi, inode->i_ino);
f2fs_unlock_op(sbi);
/* iput will drop the inode object */