diff options
author | Chao Yu <chao2.yu@samsung.com> | 2014-04-01 20:55:00 -0400 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-04-01 20:56:12 -0400 |
commit | cf0ee0f09bc09f54b9852dda1088b9cdcd4f8683 (patch) | |
tree | 2f816e75d32c40fbaff30fea217ace4bef0001f4 /fs/f2fs/checkpoint.c | |
parent | 6e452d69d421e10e99446c6de16a19604149c40f (diff) |
f2fs: avoid free slab cache under spinlock
Move kmem_cache_free out of spinlock protection region for better performance.
Change log from v1:
o remove spinlock protection for kmem_cache_free in destroy_node_manager
suggested by Jaegeuk Kim.
Signed-off-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/checkpoint.c')
-rw-r--r-- | fs/f2fs/checkpoint.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index a80be5121e8a..d877f46c75ed 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -347,10 +347,11 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) | |||
347 | list_for_each_entry(orphan, head, list) { | 347 | list_for_each_entry(orphan, head, list) { |
348 | if (orphan->ino == ino) { | 348 | if (orphan->ino == ino) { |
349 | list_del(&orphan->list); | 349 | list_del(&orphan->list); |
350 | kmem_cache_free(orphan_entry_slab, orphan); | ||
351 | f2fs_bug_on(sbi->n_orphans == 0); | 350 | f2fs_bug_on(sbi->n_orphans == 0); |
352 | sbi->n_orphans--; | 351 | sbi->n_orphans--; |
353 | break; | 352 | spin_unlock(&sbi->orphan_inode_lock); |
353 | kmem_cache_free(orphan_entry_slab, orphan); | ||
354 | return; | ||
354 | } | 355 | } |
355 | } | 356 | } |
356 | spin_unlock(&sbi->orphan_inode_lock); | 357 | spin_unlock(&sbi->orphan_inode_lock); |
@@ -577,6 +578,7 @@ void set_dirty_dir_page(struct inode *inode, struct page *page) | |||
577 | { | 578 | { |
578 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 579 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
579 | struct dir_inode_entry *new; | 580 | struct dir_inode_entry *new; |
581 | int ret = 0; | ||
580 | 582 | ||
581 | if (!S_ISDIR(inode->i_mode)) | 583 | if (!S_ISDIR(inode->i_mode)) |
582 | return; | 584 | return; |
@@ -586,12 +588,13 @@ void set_dirty_dir_page(struct inode *inode, struct page *page) | |||
586 | INIT_LIST_HEAD(&new->list); | 588 | INIT_LIST_HEAD(&new->list); |
587 | 589 | ||
588 | spin_lock(&sbi->dir_inode_lock); | 590 | spin_lock(&sbi->dir_inode_lock); |
589 | if (__add_dirty_inode(inode, new)) | 591 | ret = __add_dirty_inode(inode, new); |
590 | kmem_cache_free(inode_entry_slab, new); | ||
591 | |||
592 | inode_inc_dirty_dents(inode); | 592 | inode_inc_dirty_dents(inode); |
593 | SetPagePrivate(page); | 593 | SetPagePrivate(page); |
594 | spin_unlock(&sbi->dir_inode_lock); | 594 | spin_unlock(&sbi->dir_inode_lock); |
595 | |||
596 | if (ret) | ||
597 | kmem_cache_free(inode_entry_slab, new); | ||
595 | } | 598 | } |
596 | 599 | ||
597 | void add_dirty_dir_inode(struct inode *inode) | 600 | void add_dirty_dir_inode(struct inode *inode) |
@@ -599,20 +602,22 @@ void add_dirty_dir_inode(struct inode *inode) | |||
599 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 602 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
600 | struct dir_inode_entry *new = | 603 | struct dir_inode_entry *new = |
601 | f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); | 604 | f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); |
605 | int ret = 0; | ||
602 | 606 | ||
603 | new->inode = inode; | 607 | new->inode = inode; |
604 | INIT_LIST_HEAD(&new->list); | 608 | INIT_LIST_HEAD(&new->list); |
605 | 609 | ||
606 | spin_lock(&sbi->dir_inode_lock); | 610 | spin_lock(&sbi->dir_inode_lock); |
607 | if (__add_dirty_inode(inode, new)) | 611 | ret = __add_dirty_inode(inode, new); |
608 | kmem_cache_free(inode_entry_slab, new); | ||
609 | spin_unlock(&sbi->dir_inode_lock); | 612 | spin_unlock(&sbi->dir_inode_lock); |
613 | |||
614 | if (ret) | ||
615 | kmem_cache_free(inode_entry_slab, new); | ||
610 | } | 616 | } |
611 | 617 | ||
612 | void remove_dirty_dir_inode(struct inode *inode) | 618 | void remove_dirty_dir_inode(struct inode *inode) |
613 | { | 619 | { |
614 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 620 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
615 | |||
616 | struct list_head *this, *head; | 621 | struct list_head *this, *head; |
617 | 622 | ||
618 | if (!S_ISDIR(inode->i_mode)) | 623 | if (!S_ISDIR(inode->i_mode)) |
@@ -630,13 +635,15 @@ void remove_dirty_dir_inode(struct inode *inode) | |||
630 | entry = list_entry(this, struct dir_inode_entry, list); | 635 | entry = list_entry(this, struct dir_inode_entry, list); |
631 | if (entry->inode == inode) { | 636 | if (entry->inode == inode) { |
632 | list_del(&entry->list); | 637 | list_del(&entry->list); |
633 | kmem_cache_free(inode_entry_slab, entry); | ||
634 | stat_dec_dirty_dir(sbi); | 638 | stat_dec_dirty_dir(sbi); |
635 | break; | 639 | spin_unlock(&sbi->dir_inode_lock); |
640 | kmem_cache_free(inode_entry_slab, entry); | ||
641 | goto done; | ||
636 | } | 642 | } |
637 | } | 643 | } |
638 | spin_unlock(&sbi->dir_inode_lock); | 644 | spin_unlock(&sbi->dir_inode_lock); |
639 | 645 | ||
646 | done: | ||
640 | /* Only from the recovery routine */ | 647 | /* Only from the recovery routine */ |
641 | if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT)) { | 648 | if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT)) { |
642 | clear_inode_flag(F2FS_I(inode), FI_DELAY_IPUT); | 649 | clear_inode_flag(F2FS_I(inode), FI_DELAY_IPUT); |