aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/file.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2014-03-20 06:10:08 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2014-03-20 09:10:11 -0400
commitd928bfbfe77aa457b765c19e9db8cd4cc72b3c89 (patch)
treef56763175e0fbee1e2079c9a330f3d73f971bc5c /fs/f2fs/file.c
parent58c410351eba3d24f741c85a0eb9eaf15c94047d (diff)
f2fs: introduce fi->i_sem to protect fi's info
This patch introduces fi->i_sem to protect fi's info that includes xattr_ver, pino, i_nlink. This enables to remove i_mutex during f2fs_sync_file, resulting in performance improvement when a number of fsync calls are triggered from many concurrent threads. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/file.c')
-rw-r--r--fs/f2fs/file.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index e755ee57e042..a9474cd4e0db 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -111,6 +111,7 @@ static int get_parent_ino(struct inode *inode, nid_t *pino)
111int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) 111int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
112{ 112{
113 struct inode *inode = file->f_mapping->host; 113 struct inode *inode = file->f_mapping->host;
114 struct f2fs_inode_info *fi = F2FS_I(inode);
114 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); 115 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
115 int ret = 0; 116 int ret = 0;
116 bool need_cp = false; 117 bool need_cp = false;
@@ -133,7 +134,7 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
133 /* guarantee free sections for fsync */ 134 /* guarantee free sections for fsync */
134 f2fs_balance_fs(sbi); 135 f2fs_balance_fs(sbi);
135 136
136 mutex_lock(&inode->i_mutex); 137 down_read(&fi->i_sem);
137 138
138 /* 139 /*
139 * Both of fdatasync() and fsync() are able to be recovered from 140 * Both of fdatasync() and fsync() are able to be recovered from
@@ -150,21 +151,27 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
150 else if (F2FS_I(inode)->xattr_ver == cur_cp_version(F2FS_CKPT(sbi))) 151 else if (F2FS_I(inode)->xattr_ver == cur_cp_version(F2FS_CKPT(sbi)))
151 need_cp = true; 152 need_cp = true;
152 153
154 up_read(&fi->i_sem);
155
153 if (need_cp) { 156 if (need_cp) {
154 nid_t pino; 157 nid_t pino;
155 158
156 F2FS_I(inode)->xattr_ver = 0;
157
158 /* all the dirty node pages should be flushed for POR */ 159 /* all the dirty node pages should be flushed for POR */
159 ret = f2fs_sync_fs(inode->i_sb, 1); 160 ret = f2fs_sync_fs(inode->i_sb, 1);
161
162 down_write(&fi->i_sem);
163 F2FS_I(inode)->xattr_ver = 0;
160 if (file_wrong_pino(inode) && inode->i_nlink == 1 && 164 if (file_wrong_pino(inode) && inode->i_nlink == 1 &&
161 get_parent_ino(inode, &pino)) { 165 get_parent_ino(inode, &pino)) {
162 F2FS_I(inode)->i_pino = pino; 166 F2FS_I(inode)->i_pino = pino;
163 file_got_pino(inode); 167 file_got_pino(inode);
168 up_write(&fi->i_sem);
164 mark_inode_dirty_sync(inode); 169 mark_inode_dirty_sync(inode);
165 ret = f2fs_write_inode(inode, NULL); 170 ret = f2fs_write_inode(inode, NULL);
166 if (ret) 171 if (ret)
167 goto out; 172 goto out;
173 } else {
174 up_write(&fi->i_sem);
168 } 175 }
169 } else { 176 } else {
170 /* if there is no written node page, write its inode page */ 177 /* if there is no written node page, write its inode page */
@@ -180,7 +187,6 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
180 ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); 187 ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
181 } 188 }
182out: 189out:
183 mutex_unlock(&inode->i_mutex);
184 trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); 190 trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret);
185 return ret; 191 return ret;
186} 192}