aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/namei.c
diff options
context:
space:
mode:
authorGu Zheng <guz.fnst@cn.fujitsu.com>2013-09-27 06:08:30 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-10-06 22:33:05 -0400
commite479556bfdd136669854292eb57ed0139d7253d5 (patch)
tree95772ba1ac8cf1e79c89145daf40c417814896da /fs/f2fs/namei.c
parent2e5558f4a5cf16a7394fd5770087303db8912c66 (diff)
f2fs: use rw_sem instead of fs_lock(locks mutex)
The fs_locks is used to block other ops(ex, recovery) when doing checkpoint. And each other operate routine(besides checkpoint) needs to acquire a fs_lock, there is a terrible problem here, if these are too many concurrency threads acquiring fs_lock, so that they will block each other and may lead to some performance problem, but this is not the phenomenon we want to see. Though there are some optimization patches introduced to enhance the usage of fs_lock, but the thorough solution is using a *rw_sem* to replace the fs_lock. Checkpoint routine takes write_sem, and other ops take read_sem, so that we can block other ops(ex, recovery) when doing checkpoint, and other ops will not disturb each other, this can avoid the problem described above completely. Because of the weakness of rw_sem, the above change may introduce a potential problem that the checkpoint thread might get starved if other threads are intensively locking the read semaphore for I/O.(Pointed out by Xu Jin) In order to avoid this, a wait_list is introduced, the appending read semaphore ops will be dropped into the wait_list if checkpoint thread is waiting for write semaphore, and will be waked up when checkpoint thread gives up write semaphore. Thanks to Kim's previous review and test, and will be very glad to see other guys' performance tests about this patch. V2: -fix the potential starvation problem. -use more suitable func name suggested by Xu Jin. Signed-off-by: Gu Zheng <guz.fnst@cn.fujitsu.com> [Jaegeuk Kim: adjust minor coding standard] Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/namei.c')
-rw-r--r--fs/f2fs/namei.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 2a5359c990fc..29f73fdf958e 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -27,19 +27,19 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
27 nid_t ino; 27 nid_t ino;
28 struct inode *inode; 28 struct inode *inode;
29 bool nid_free = false; 29 bool nid_free = false;
30 int err, ilock; 30 int err;
31 31
32 inode = new_inode(sb); 32 inode = new_inode(sb);
33 if (!inode) 33 if (!inode)
34 return ERR_PTR(-ENOMEM); 34 return ERR_PTR(-ENOMEM);
35 35
36 ilock = mutex_lock_op(sbi); 36 f2fs_lock_op(sbi);
37 if (!alloc_nid(sbi, &ino)) { 37 if (!alloc_nid(sbi, &ino)) {
38 mutex_unlock_op(sbi, ilock); 38 f2fs_unlock_op(sbi);
39 err = -ENOSPC; 39 err = -ENOSPC;
40 goto fail; 40 goto fail;
41 } 41 }
42 mutex_unlock_op(sbi, ilock); 42 f2fs_unlock_op(sbi);
43 43
44 inode->i_uid = current_fsuid(); 44 inode->i_uid = current_fsuid();
45 45
@@ -115,7 +115,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
115 struct f2fs_sb_info *sbi = F2FS_SB(sb); 115 struct f2fs_sb_info *sbi = F2FS_SB(sb);
116 struct inode *inode; 116 struct inode *inode;
117 nid_t ino = 0; 117 nid_t ino = 0;
118 int err, ilock; 118 int err;
119 119
120 f2fs_balance_fs(sbi); 120 f2fs_balance_fs(sbi);
121 121
@@ -131,9 +131,9 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
131 inode->i_mapping->a_ops = &f2fs_dblock_aops; 131 inode->i_mapping->a_ops = &f2fs_dblock_aops;
132 ino = inode->i_ino; 132 ino = inode->i_ino;
133 133
134 ilock = mutex_lock_op(sbi); 134 f2fs_lock_op(sbi);
135 err = f2fs_add_link(dentry, inode); 135 err = f2fs_add_link(dentry, inode);
136 mutex_unlock_op(sbi, ilock); 136 f2fs_unlock_op(sbi);
137 if (err) 137 if (err)
138 goto out; 138 goto out;
139 139
@@ -157,7 +157,7 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
157 struct inode *inode = old_dentry->d_inode; 157 struct inode *inode = old_dentry->d_inode;
158 struct super_block *sb = dir->i_sb; 158 struct super_block *sb = dir->i_sb;
159 struct f2fs_sb_info *sbi = F2FS_SB(sb); 159 struct f2fs_sb_info *sbi = F2FS_SB(sb);
160 int err, ilock; 160 int err;
161 161
162 f2fs_balance_fs(sbi); 162 f2fs_balance_fs(sbi);
163 163
@@ -165,9 +165,9 @@ static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
165 ihold(inode); 165 ihold(inode);
166 166
167 set_inode_flag(F2FS_I(inode), FI_INC_LINK); 167 set_inode_flag(F2FS_I(inode), FI_INC_LINK);
168 ilock = mutex_lock_op(sbi); 168 f2fs_lock_op(sbi);
169 err = f2fs_add_link(dentry, inode); 169 err = f2fs_add_link(dentry, inode);
170 mutex_unlock_op(sbi, ilock); 170 f2fs_unlock_op(sbi);
171 if (err) 171 if (err)
172 goto out; 172 goto out;
173 173
@@ -220,7 +220,6 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
220 struct f2fs_dir_entry *de; 220 struct f2fs_dir_entry *de;
221 struct page *page; 221 struct page *page;
222 int err = -ENOENT; 222 int err = -ENOENT;
223 int ilock;
224 223
225 trace_f2fs_unlink_enter(dir, dentry); 224 trace_f2fs_unlink_enter(dir, dentry);
226 f2fs_balance_fs(sbi); 225 f2fs_balance_fs(sbi);
@@ -236,9 +235,9 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
236 goto fail; 235 goto fail;
237 } 236 }
238 237
239 ilock = mutex_lock_op(sbi); 238 f2fs_lock_op(sbi);
240 f2fs_delete_entry(de, page, inode); 239 f2fs_delete_entry(de, page, inode);
241 mutex_unlock_op(sbi, ilock); 240 f2fs_unlock_op(sbi);
242 241
243 /* In order to evict this inode, we set it dirty */ 242 /* In order to evict this inode, we set it dirty */
244 mark_inode_dirty(inode); 243 mark_inode_dirty(inode);
@@ -254,7 +253,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
254 struct f2fs_sb_info *sbi = F2FS_SB(sb); 253 struct f2fs_sb_info *sbi = F2FS_SB(sb);
255 struct inode *inode; 254 struct inode *inode;
256 size_t symlen = strlen(symname) + 1; 255 size_t symlen = strlen(symname) + 1;
257 int err, ilock; 256 int err;
258 257
259 f2fs_balance_fs(sbi); 258 f2fs_balance_fs(sbi);
260 259
@@ -265,9 +264,9 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
265 inode->i_op = &f2fs_symlink_inode_operations; 264 inode->i_op = &f2fs_symlink_inode_operations;
266 inode->i_mapping->a_ops = &f2fs_dblock_aops; 265 inode->i_mapping->a_ops = &f2fs_dblock_aops;
267 266
268 ilock = mutex_lock_op(sbi); 267 f2fs_lock_op(sbi);
269 err = f2fs_add_link(dentry, inode); 268 err = f2fs_add_link(dentry, inode);
270 mutex_unlock_op(sbi, ilock); 269 f2fs_unlock_op(sbi);
271 if (err) 270 if (err)
272 goto out; 271 goto out;
273 272
@@ -290,7 +289,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
290{ 289{
291 struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); 290 struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
292 struct inode *inode; 291 struct inode *inode;
293 int err, ilock; 292 int err;
294 293
295 f2fs_balance_fs(sbi); 294 f2fs_balance_fs(sbi);
296 295
@@ -304,9 +303,9 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
304 mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); 303 mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
305 304
306 set_inode_flag(F2FS_I(inode), FI_INC_LINK); 305 set_inode_flag(F2FS_I(inode), FI_INC_LINK);
307 ilock = mutex_lock_op(sbi); 306 f2fs_lock_op(sbi);
308 err = f2fs_add_link(dentry, inode); 307 err = f2fs_add_link(dentry, inode);
309 mutex_unlock_op(sbi, ilock); 308 f2fs_unlock_op(sbi);
310 if (err) 309 if (err)
311 goto out_fail; 310 goto out_fail;
312 311
@@ -342,7 +341,6 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
342 struct f2fs_sb_info *sbi = F2FS_SB(sb); 341 struct f2fs_sb_info *sbi = F2FS_SB(sb);
343 struct inode *inode; 342 struct inode *inode;
344 int err = 0; 343 int err = 0;
345 int ilock;
346 344
347 if (!new_valid_dev(rdev)) 345 if (!new_valid_dev(rdev))
348 return -EINVAL; 346 return -EINVAL;
@@ -356,9 +354,9 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
356 init_special_inode(inode, inode->i_mode, rdev); 354 init_special_inode(inode, inode->i_mode, rdev);
357 inode->i_op = &f2fs_special_inode_operations; 355 inode->i_op = &f2fs_special_inode_operations;
358 356
359 ilock = mutex_lock_op(sbi); 357 f2fs_lock_op(sbi);
360 err = f2fs_add_link(dentry, inode); 358 err = f2fs_add_link(dentry, inode);
361 mutex_unlock_op(sbi, ilock); 359 f2fs_unlock_op(sbi);
362 if (err) 360 if (err)
363 goto out; 361 goto out;
364 362
@@ -387,7 +385,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
387 struct f2fs_dir_entry *old_dir_entry = NULL; 385 struct f2fs_dir_entry *old_dir_entry = NULL;
388 struct f2fs_dir_entry *old_entry; 386 struct f2fs_dir_entry *old_entry;
389 struct f2fs_dir_entry *new_entry; 387 struct f2fs_dir_entry *new_entry;
390 int err = -ENOENT, ilock = -1; 388 int err = -ENOENT;
391 389
392 f2fs_balance_fs(sbi); 390 f2fs_balance_fs(sbi);
393 391
@@ -402,7 +400,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
402 goto out_old; 400 goto out_old;
403 } 401 }
404 402
405 ilock = mutex_lock_op(sbi); 403 f2fs_lock_op(sbi);
406 404
407 if (new_inode) { 405 if (new_inode) {
408 406
@@ -467,7 +465,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
467 update_inode_page(old_dir); 465 update_inode_page(old_dir);
468 } 466 }
469 467
470 mutex_unlock_op(sbi, ilock); 468 f2fs_unlock_op(sbi);
471 return 0; 469 return 0;
472 470
473put_out_dir: 471put_out_dir:
@@ -477,7 +475,7 @@ out_dir:
477 kunmap(old_dir_page); 475 kunmap(old_dir_page);
478 f2fs_put_page(old_dir_page, 0); 476 f2fs_put_page(old_dir_page, 0);
479 } 477 }
480 mutex_unlock_op(sbi, ilock); 478 f2fs_unlock_op(sbi);
481out_old: 479out_old:
482 kunmap(old_page); 480 kunmap(old_page);
483 f2fs_put_page(old_page, 0); 481 f2fs_put_page(old_page, 0);