f2fs: avoid double lock in truncate_blocks
Jaegeuk Kim [Thu, 14 Aug 2014 23:32:54 +0000 (16:32 -0700)]
The init_inode_metadata calls truncate_blocks when error is occurred.
The callers holds f2fs_lock_op, so we should not call it again in
truncate_blocks.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

Conflicts:
fs/f2fs/data.c
fs/f2fs/file.c

Change-Id: Ia07c84bbbf04bd5a9fc38e1395245aa1a347ce0f

fs/f2fs/data.c
fs/f2fs/dir.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/inline.c

index 9f26116..8e09c8b 100644 (file)
@@ -941,7 +941,7 @@ static void f2fs_write_failed(struct address_space *mapping, loff_t to)
 
        if (to > inode->i_size) {
                truncate_pagecache(inode, to, inode->i_size);
-               truncate_blocks(inode, inode->i_size);
+               truncate_blocks(inode, inode->i_size, true);
        }
 }
 
index 8a2779e..99c6c8f 100644 (file)
@@ -408,7 +408,7 @@ put_error:
 error:
        /* once the failed inode becomes a bad inode, i_mode is S_IFREG */
        truncate_inode_pages(&inode->i_data, 0);
-       truncate_blocks(inode, 0);
+       truncate_blocks(inode, 0, false);
        remove_dirty_dir_inode(inode);
        remove_inode_page(inode);
        return ERR_PTR(err);
index f0a4d93..16fdb2f 100644 (file)
@@ -1185,7 +1185,7 @@ static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi)
  */
 int f2fs_sync_file(struct file *, loff_t, loff_t, int);
 void truncate_data_blocks(struct dnode_of_data *);
-int truncate_blocks(struct inode *, u64);
+int truncate_blocks(struct inode *, u64, bool);
 void f2fs_truncate(struct inode *);
 int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int f2fs_setattr(struct dentry *, struct iattr *);
index 80a53ca..b96c5a6 100644 (file)
@@ -421,7 +421,7 @@ out:
        f2fs_put_page(page, 1);
 }
 
-int truncate_blocks(struct inode *inode, u64 from)
+int truncate_blocks(struct inode *inode, u64 from, bool lock)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        unsigned int blocksize = inode->i_sb->s_blocksize;
@@ -437,14 +437,16 @@ int truncate_blocks(struct inode *inode, u64 from)
        free_from = (pgoff_t)
                        ((from + blocksize - 1) >> (sbi->log_blocksize));
 
-       f2fs_lock_op(sbi);
+       if (lock)
+               f2fs_lock_op(sbi);
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
        err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
        if (err) {
                if (err == -ENOENT)
                        goto free_next;
-               f2fs_unlock_op(sbi);
+               if (lock)
+                       f2fs_unlock_op(sbi);
                trace_f2fs_truncate_blocks_exit(inode, err);
                return err;
        }
@@ -462,7 +464,8 @@ int truncate_blocks(struct inode *inode, u64 from)
        f2fs_put_dnode(&dn);
 free_next:
        err = truncate_inode_blocks(inode, free_from);
-       f2fs_unlock_op(sbi);
+       if (lock)
+               f2fs_unlock_op(sbi);
 done:
        /* lastly zero out the first data page */
        truncate_partial_data_page(inode, from);
@@ -481,7 +484,7 @@ void f2fs_truncate(struct inode *inode)
 
        trace_f2fs_truncate(inode);
 
-       err = truncate_blocks(inode, i_size_read(inode));
+       err = truncate_blocks(inode, i_size_read(inode), true);
        if (err) {
                f2fs_msg(inode->i_sb, KERN_ERR, "truncate failed with %d",
                                err);
index 520758b..4d1f39f 100644 (file)
@@ -247,7 +247,7 @@ process_inline:
                update_inode(inode, ipage);
                f2fs_put_page(ipage, 1);
        } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) {
-               truncate_blocks(inode, 0);
+               truncate_blocks(inode, 0, false);
                set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
                goto process_inline;
        }