diff options
| author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-03-20 06:10:08 -0400 |
|---|---|---|
| committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-03-20 09:10:11 -0400 |
| commit | d928bfbfe77aa457b765c19e9db8cd4cc72b3c89 (patch) | |
| tree | f56763175e0fbee1e2079c9a330f3d73f971bc5c /fs | |
| parent | 58c410351eba3d24f741c85a0eb9eaf15c94047d (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')
| -rw-r--r-- | fs/f2fs/dir.c | 6 | ||||
| -rw-r--r-- | fs/f2fs/f2fs.h | 1 | ||||
| -rw-r--r-- | fs/f2fs/file.c | 14 | ||||
| -rw-r--r-- | fs/f2fs/namei.c | 7 | ||||
| -rw-r--r-- | fs/f2fs/super.c | 1 | ||||
| -rw-r--r-- | fs/f2fs/xattr.c | 3 |
6 files changed, 28 insertions, 4 deletions
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 7c9b17c03675..972fd0ef230f 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
| @@ -493,6 +493,7 @@ start: | |||
| 493 | add_dentry: | 493 | add_dentry: |
| 494 | f2fs_wait_on_page_writeback(dentry_page, DATA); | 494 | f2fs_wait_on_page_writeback(dentry_page, DATA); |
| 495 | 495 | ||
| 496 | down_write(&F2FS_I(inode)->i_sem); | ||
| 496 | page = init_inode_metadata(inode, dir, name); | 497 | page = init_inode_metadata(inode, dir, name); |
| 497 | if (IS_ERR(page)) { | 498 | if (IS_ERR(page)) { |
| 498 | err = PTR_ERR(page); | 499 | err = PTR_ERR(page); |
| @@ -515,6 +516,8 @@ add_dentry: | |||
| 515 | 516 | ||
| 516 | update_parent_metadata(dir, inode, current_depth); | 517 | update_parent_metadata(dir, inode, current_depth); |
| 517 | fail: | 518 | fail: |
| 519 | up_write(&F2FS_I(inode)->i_sem); | ||
| 520 | |||
| 518 | if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) { | 521 | if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) { |
| 519 | update_inode_page(dir); | 522 | update_inode_page(dir); |
| 520 | clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); | 523 | clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); |
| @@ -559,6 +562,8 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, | |||
| 559 | if (inode) { | 562 | if (inode) { |
| 560 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); | 563 | struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); |
| 561 | 564 | ||
| 565 | down_write(&F2FS_I(inode)->i_sem); | ||
| 566 | |||
| 562 | if (S_ISDIR(inode->i_mode)) { | 567 | if (S_ISDIR(inode->i_mode)) { |
| 563 | drop_nlink(dir); | 568 | drop_nlink(dir); |
| 564 | update_inode_page(dir); | 569 | update_inode_page(dir); |
| @@ -569,6 +574,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, | |||
| 569 | drop_nlink(inode); | 574 | drop_nlink(inode); |
| 570 | i_size_write(inode, 0); | 575 | i_size_write(inode, 0); |
| 571 | } | 576 | } |
| 577 | up_write(&F2FS_I(inode)->i_sem); | ||
| 572 | update_inode_page(inode); | 578 | update_inode_page(inode); |
| 573 | 579 | ||
| 574 | if (inode->i_nlink == 0) | 580 | if (inode->i_nlink == 0) |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 05c652493f04..469779ab1d77 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
| @@ -210,6 +210,7 @@ struct f2fs_inode_info { | |||
| 210 | 210 | ||
| 211 | /* Use below internally in f2fs*/ | 211 | /* Use below internally in f2fs*/ |
| 212 | unsigned long flags; /* use to pass per-file flags */ | 212 | unsigned long flags; /* use to pass per-file flags */ |
| 213 | struct rw_semaphore i_sem; /* protect fi info */ | ||
| 213 | atomic_t dirty_dents; /* # of dirty dentry pages */ | 214 | atomic_t dirty_dents; /* # of dirty dentry pages */ |
| 214 | f2fs_hash_t chash; /* hash value of given file name */ | 215 | f2fs_hash_t chash; /* hash value of given file name */ |
| 215 | unsigned int clevel; /* maximum level of given file name */ | 216 | unsigned int clevel; /* maximum level of given file name */ |
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) | |||
| 111 | int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | 111 | int 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 | } |
| 182 | out: | 189 | out: |
| 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 | } |
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 397d459e97bf..0cea87437a60 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c | |||
| @@ -424,12 +424,17 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | f2fs_set_link(new_dir, new_entry, new_page, old_inode); | 426 | f2fs_set_link(new_dir, new_entry, new_page, old_inode); |
| 427 | down_write(&F2FS_I(old_inode)->i_sem); | ||
| 427 | F2FS_I(old_inode)->i_pino = new_dir->i_ino; | 428 | F2FS_I(old_inode)->i_pino = new_dir->i_ino; |
| 429 | up_write(&F2FS_I(old_inode)->i_sem); | ||
| 428 | 430 | ||
| 429 | new_inode->i_ctime = CURRENT_TIME; | 431 | new_inode->i_ctime = CURRENT_TIME; |
| 432 | down_write(&F2FS_I(new_inode)->i_sem); | ||
| 430 | if (old_dir_entry) | 433 | if (old_dir_entry) |
| 431 | drop_nlink(new_inode); | 434 | drop_nlink(new_inode); |
| 432 | drop_nlink(new_inode); | 435 | drop_nlink(new_inode); |
| 436 | up_write(&F2FS_I(new_inode)->i_sem); | ||
| 437 | |||
| 433 | mark_inode_dirty(new_inode); | 438 | mark_inode_dirty(new_inode); |
| 434 | 439 | ||
| 435 | if (!new_inode->i_nlink) | 440 | if (!new_inode->i_nlink) |
| @@ -459,7 +464,9 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 459 | if (old_dir != new_dir) { | 464 | if (old_dir != new_dir) { |
| 460 | f2fs_set_link(old_inode, old_dir_entry, | 465 | f2fs_set_link(old_inode, old_dir_entry, |
| 461 | old_dir_page, new_dir); | 466 | old_dir_page, new_dir); |
| 467 | down_write(&F2FS_I(old_inode)->i_sem); | ||
| 462 | F2FS_I(old_inode)->i_pino = new_dir->i_ino; | 468 | F2FS_I(old_inode)->i_pino = new_dir->i_ino; |
| 469 | up_write(&F2FS_I(old_inode)->i_sem); | ||
| 463 | update_inode_page(old_inode); | 470 | update_inode_page(old_inode); |
| 464 | } else { | 471 | } else { |
| 465 | kunmap(old_dir_page); | 472 | kunmap(old_dir_page); |
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 34c47b2010bc..89ea046c846d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
| @@ -360,6 +360,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) | |||
| 360 | fi->i_current_depth = 1; | 360 | fi->i_current_depth = 1; |
| 361 | fi->i_advise = 0; | 361 | fi->i_advise = 0; |
| 362 | rwlock_init(&fi->ext.ext_lock); | 362 | rwlock_init(&fi->ext.ext_lock); |
| 363 | init_rwsem(&fi->i_sem); | ||
| 363 | 364 | ||
| 364 | set_inode_flag(fi, FI_NEW_INODE); | 365 | set_inode_flag(fi, FI_NEW_INODE); |
| 365 | 366 | ||
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 89d0422a91a8..84191307a670 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
| @@ -590,7 +590,10 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
| 590 | f2fs_balance_fs(sbi); | 590 | f2fs_balance_fs(sbi); |
| 591 | 591 | ||
| 592 | f2fs_lock_op(sbi); | 592 | f2fs_lock_op(sbi); |
| 593 | /* protect xattr_ver */ | ||
| 594 | down_write(&F2FS_I(inode)->i_sem); | ||
| 593 | err = __f2fs_setxattr(inode, name_index, name, value, value_len, ipage); | 595 | err = __f2fs_setxattr(inode, name_index, name, value, value_len, ipage); |
| 596 | up_write(&F2FS_I(inode)->i_sem); | ||
| 594 | f2fs_unlock_op(sbi); | 597 | f2fs_unlock_op(sbi); |
| 595 | 598 | ||
| 596 | return err; | 599 | return err; |
