| From: Jaegeuk Kim <jaegeuk@kernel.org> |
| Date: Thu, 25 Sep 2014 11:55:53 -0700 |
| Subject: f2fs: call f2fs_unlock_op after error was handled |
| |
| commit 44c16156512f33c81e382a1e1df9524e26a7026a upstream. |
| |
| This patch relocates f2fs_unlock_op in every directory operations to be called |
| after any error was processed. |
| Otherwise, the checkpoint can be entered with valid node ids without its |
| dentry when -ENOSPC is occurred. |
| |
| Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> |
| [bwh: Backported to 3.16: |
| - Drop changes in f2fs_tmpfile() |
| - Use F2FS_SB() instead of F2FS_I_SB()] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| fs/f2fs/f2fs.h | 1 + |
| fs/f2fs/inode.c | 23 +++++++++++++++++++++++ |
| fs/f2fs/namei.c | 32 +++++++++++--------------------- |
| 3 files changed, 35 insertions(+), 21 deletions(-) |
| |
| --- a/fs/f2fs/f2fs.h |
| +++ b/fs/f2fs/f2fs.h |
| @@ -1121,6 +1121,7 @@ void update_inode(struct inode *, struct |
| void update_inode_page(struct inode *); |
| int f2fs_write_inode(struct inode *, struct writeback_control *); |
| void f2fs_evict_inode(struct inode *); |
| +void handle_failed_inode(struct inode *); |
| |
| /* |
| * namei.c |
| --- a/fs/f2fs/inode.c |
| +++ b/fs/f2fs/inode.c |
| @@ -299,3 +299,26 @@ no_delete: |
| clear_inode(inode); |
| invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino); |
| } |
| + |
| +/* caller should call f2fs_lock_op() */ |
| +void handle_failed_inode(struct inode *inode) |
| +{ |
| + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
| + |
| + clear_nlink(inode); |
| + make_bad_inode(inode); |
| + unlock_new_inode(inode); |
| + |
| + i_size_write(inode, 0); |
| + if (F2FS_HAS_BLOCKS(inode)) |
| + f2fs_truncate(inode); |
| + |
| + remove_inode_page(inode); |
| + stat_dec_inline_inode(inode); |
| + |
| + alloc_nid_failed(sbi, inode->i_ino); |
| + f2fs_unlock_op(sbi); |
| + |
| + /* iput will drop the inode object */ |
| + iput(inode); |
| +} |
| --- a/fs/f2fs/namei.c |
| +++ b/fs/f2fs/namei.c |
| @@ -124,9 +124,9 @@ static int f2fs_create(struct inode *dir |
| |
| f2fs_lock_op(sbi); |
| err = f2fs_add_link(dentry, inode); |
| - f2fs_unlock_op(sbi); |
| if (err) |
| goto out; |
| + f2fs_unlock_op(sbi); |
| |
| alloc_nid_done(sbi, ino); |
| |
| @@ -134,9 +134,7 @@ static int f2fs_create(struct inode *dir |
| unlock_new_inode(inode); |
| return 0; |
| out: |
| - clear_nlink(inode); |
| - iget_failed(inode); |
| - alloc_nid_failed(sbi, ino); |
| + handle_failed_inode(inode); |
| return err; |
| } |
| |
| @@ -156,15 +154,16 @@ static int f2fs_link(struct dentry *old_ |
| set_inode_flag(F2FS_I(inode), FI_INC_LINK); |
| f2fs_lock_op(sbi); |
| err = f2fs_add_link(dentry, inode); |
| - f2fs_unlock_op(sbi); |
| if (err) |
| goto out; |
| + f2fs_unlock_op(sbi); |
| |
| d_instantiate(dentry, inode); |
| return 0; |
| out: |
| clear_inode_flag(F2FS_I(inode), FI_INC_LINK); |
| iput(inode); |
| + f2fs_unlock_op(sbi); |
| return err; |
| } |
| |
| @@ -257,9 +256,9 @@ static int f2fs_symlink(struct inode *di |
| |
| f2fs_lock_op(sbi); |
| err = f2fs_add_link(dentry, inode); |
| - f2fs_unlock_op(sbi); |
| if (err) |
| goto out; |
| + f2fs_unlock_op(sbi); |
| |
| err = page_symlink(inode, symname, symlen); |
| alloc_nid_done(sbi, inode->i_ino); |
| @@ -268,9 +267,7 @@ static int f2fs_symlink(struct inode *di |
| unlock_new_inode(inode); |
| return err; |
| out: |
| - clear_nlink(inode); |
| - iget_failed(inode); |
| - alloc_nid_failed(sbi, inode->i_ino); |
| + handle_failed_inode(inode); |
| return err; |
| } |
| |
| @@ -294,9 +291,9 @@ static int f2fs_mkdir(struct inode *dir, |
| set_inode_flag(F2FS_I(inode), FI_INC_LINK); |
| f2fs_lock_op(sbi); |
| err = f2fs_add_link(dentry, inode); |
| - f2fs_unlock_op(sbi); |
| if (err) |
| goto out_fail; |
| + f2fs_unlock_op(sbi); |
| |
| alloc_nid_done(sbi, inode->i_ino); |
| |
| @@ -307,9 +304,7 @@ static int f2fs_mkdir(struct inode *dir, |
| |
| out_fail: |
| clear_inode_flag(F2FS_I(inode), FI_INC_LINK); |
| - clear_nlink(inode); |
| - iget_failed(inode); |
| - alloc_nid_failed(sbi, inode->i_ino); |
| + handle_failed_inode(inode); |
| return err; |
| } |
| |
| @@ -343,18 +338,16 @@ static int f2fs_mknod(struct inode *dir, |
| |
| f2fs_lock_op(sbi); |
| err = f2fs_add_link(dentry, inode); |
| - f2fs_unlock_op(sbi); |
| if (err) |
| goto out; |
| + f2fs_unlock_op(sbi); |
| |
| alloc_nid_done(sbi, inode->i_ino); |
| d_instantiate(dentry, inode); |
| unlock_new_inode(inode); |
| return 0; |
| out: |
| - clear_nlink(inode); |
| - iget_failed(inode); |
| - alloc_nid_failed(sbi, inode->i_ino); |
| + handle_failed_inode(inode); |
| return err; |
| } |
| |