aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/checkpoint.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2014-04-14 22:19:28 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2014-05-06 21:21:54 -0400
commited57c27f736f6d8a51e442610c800ee0c3d83977 (patch)
treef1d453fae0ba5b9d5ca938fb0d57aedd762a5c58 /fs/f2fs/checkpoint.c
parent15c6e3aae68d6167cba063387a59968f811c8268 (diff)
f2fs: remove costly dirty_dir_inode operations
This patch removes list opeations in handling dirty dir inodes. Previously, F2FS traverses whole the list of dirty dir inodes to check whether there is an existing inode or not, resulting in heavy CPU overheads. So this patch removes such the traverse operations by adding FI_DIRTY_DIR to indicate the inode lies on the list or not. Through this simple flag, we can remove redundant operations gracefully. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/checkpoint.c')
-rw-r--r--fs/f2fs/checkpoint.c52
1 files changed, 13 insertions, 39 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 2902f7d50770..744c68be2e15 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -552,14 +552,13 @@ fail_no_cp:
552static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new) 552static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new)
553{ 553{
554 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); 554 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
555 struct list_head *head = &sbi->dir_inode_list;
556 struct dir_inode_entry *entry;
557 555
558 list_for_each_entry(entry, head, list) 556 if (is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR))
559 if (unlikely(entry->inode == inode)) 557 return -EEXIST;
560 return -EEXIST;
561 558
562 list_add_tail(&new->list, head); 559 set_inode_flag(F2FS_I(inode), FI_DIRTY_DIR);
560 F2FS_I(inode)->dirty_dir = new;
561 list_add_tail(&new->list, &sbi->dir_inode_list);
563 stat_inc_dirty_dir(sbi); 562 stat_inc_dirty_dir(sbi);
564 return 0; 563 return 0;
565} 564}
@@ -608,31 +607,26 @@ void add_dirty_dir_inode(struct inode *inode)
608void remove_dirty_dir_inode(struct inode *inode) 607void remove_dirty_dir_inode(struct inode *inode)
609{ 608{
610 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); 609 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
611 struct list_head *head;
612 struct dir_inode_entry *entry; 610 struct dir_inode_entry *entry;
613 611
614 if (!S_ISDIR(inode->i_mode)) 612 if (!S_ISDIR(inode->i_mode))
615 return; 613 return;
616 614
617 spin_lock(&sbi->dir_inode_lock); 615 spin_lock(&sbi->dir_inode_lock);
618 if (get_dirty_dents(inode)) { 616 if (get_dirty_dents(inode) ||
617 !is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR)) {
619 spin_unlock(&sbi->dir_inode_lock); 618 spin_unlock(&sbi->dir_inode_lock);
620 return; 619 return;
621 } 620 }
622 621
623 head = &sbi->dir_inode_list; 622 entry = F2FS_I(inode)->dirty_dir;
624 list_for_each_entry(entry, head, list) { 623 list_del(&entry->list);
625 if (entry->inode == inode) { 624 F2FS_I(inode)->dirty_dir = NULL;
626 list_del(&entry->list); 625 clear_inode_flag(F2FS_I(inode), FI_DIRTY_DIR);
627 stat_dec_dirty_dir(sbi); 626 stat_dec_dirty_dir(sbi);
628 spin_unlock(&sbi->dir_inode_lock);
629 kmem_cache_free(inode_entry_slab, entry);
630 goto done;
631 }
632 }
633 spin_unlock(&sbi->dir_inode_lock); 627 spin_unlock(&sbi->dir_inode_lock);
628 kmem_cache_free(inode_entry_slab, entry);
634 629
635done:
636 /* Only from the recovery routine */ 630 /* Only from the recovery routine */
637 if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT)) { 631 if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT)) {
638 clear_inode_flag(F2FS_I(inode), FI_DELAY_IPUT); 632 clear_inode_flag(F2FS_I(inode), FI_DELAY_IPUT);
@@ -640,26 +634,6 @@ done:
640 } 634 }
641} 635}
642 636
643struct inode *check_dirty_dir_inode(struct f2fs_sb_info *sbi, nid_t ino)
644{
645
646 struct list_head *head;
647 struct inode *inode = NULL;
648 struct dir_inode_entry *entry;
649
650 spin_lock(&sbi->dir_inode_lock);
651
652 head = &sbi->dir_inode_list;
653 list_for_each_entry(entry, head, list) {
654 if (entry->inode->i_ino == ino) {
655 inode = entry->inode;
656 break;
657 }
658 }
659 spin_unlock(&sbi->dir_inode_lock);
660 return inode;
661}
662
663void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi) 637void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
664{ 638{
665 struct list_head *head; 639 struct list_head *head;