aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChao Yu <chao2.yu@samsung.com>2014-04-01 20:55:00 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2014-04-01 20:56:12 -0400
commitcf0ee0f09bc09f54b9852dda1088b9cdcd4f8683 (patch)
tree2f816e75d32c40fbaff30fea217ace4bef0001f4
parent6e452d69d421e10e99446c6de16a19604149c40f (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>
-rw-r--r--fs/f2fs/checkpoint.c27
-rw-r--r--fs/f2fs/node.c17
2 files changed, 33 insertions, 11 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
597void add_dirty_dir_inode(struct inode *inode) 600void 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
612void remove_dirty_dir_inode(struct inode *inode) 618void 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
646done:
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);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 065cd99cc723..4b27e36e40fc 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1313,7 +1313,6 @@ static void __del_from_free_nid_list(struct f2fs_nm_info *nm_i,
1313{ 1313{
1314 list_del(&i->list); 1314 list_del(&i->list);
1315 radix_tree_delete(&nm_i->free_nid_root, i->nid); 1315 radix_tree_delete(&nm_i->free_nid_root, i->nid);
1316 kmem_cache_free(free_nid_slab, i);
1317} 1316}
1318 1317
1319static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build) 1318static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
@@ -1360,13 +1359,19 @@ static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
1360static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) 1359static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
1361{ 1360{
1362 struct free_nid *i; 1361 struct free_nid *i;
1362 bool need_free = false;
1363
1363 spin_lock(&nm_i->free_nid_list_lock); 1364 spin_lock(&nm_i->free_nid_list_lock);
1364 i = __lookup_free_nid_list(nm_i, nid); 1365 i = __lookup_free_nid_list(nm_i, nid);
1365 if (i && i->state == NID_NEW) { 1366 if (i && i->state == NID_NEW) {
1366 __del_from_free_nid_list(nm_i, i); 1367 __del_from_free_nid_list(nm_i, i);
1367 nm_i->fcnt--; 1368 nm_i->fcnt--;
1369 need_free = true;
1368 } 1370 }
1369 spin_unlock(&nm_i->free_nid_list_lock); 1371 spin_unlock(&nm_i->free_nid_list_lock);
1372
1373 if (need_free)
1374 kmem_cache_free(free_nid_slab, i);
1370} 1375}
1371 1376
1372static void scan_nat_page(struct f2fs_nm_info *nm_i, 1377static void scan_nat_page(struct f2fs_nm_info *nm_i,
@@ -1491,6 +1496,8 @@ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
1491 f2fs_bug_on(!i || i->state != NID_ALLOC); 1496 f2fs_bug_on(!i || i->state != NID_ALLOC);
1492 __del_from_free_nid_list(nm_i, i); 1497 __del_from_free_nid_list(nm_i, i);
1493 spin_unlock(&nm_i->free_nid_list_lock); 1498 spin_unlock(&nm_i->free_nid_list_lock);
1499
1500 kmem_cache_free(free_nid_slab, i);
1494} 1501}
1495 1502
1496/* 1503/*
@@ -1500,6 +1507,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
1500{ 1507{
1501 struct f2fs_nm_info *nm_i = NM_I(sbi); 1508 struct f2fs_nm_info *nm_i = NM_I(sbi);
1502 struct free_nid *i; 1509 struct free_nid *i;
1510 bool need_free = false;
1503 1511
1504 if (!nid) 1512 if (!nid)
1505 return; 1513 return;
@@ -1509,11 +1517,15 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
1509 f2fs_bug_on(!i || i->state != NID_ALLOC); 1517 f2fs_bug_on(!i || i->state != NID_ALLOC);
1510 if (!available_free_memory(nm_i, FREE_NIDS)) { 1518 if (!available_free_memory(nm_i, FREE_NIDS)) {
1511 __del_from_free_nid_list(nm_i, i); 1519 __del_from_free_nid_list(nm_i, i);
1520 need_free = true;
1512 } else { 1521 } else {
1513 i->state = NID_NEW; 1522 i->state = NID_NEW;
1514 nm_i->fcnt++; 1523 nm_i->fcnt++;
1515 } 1524 }
1516 spin_unlock(&nm_i->free_nid_list_lock); 1525 spin_unlock(&nm_i->free_nid_list_lock);
1526
1527 if (need_free)
1528 kmem_cache_free(free_nid_slab, i);
1517} 1529}
1518 1530
1519void recover_node_page(struct f2fs_sb_info *sbi, struct page *page, 1531void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
@@ -1925,6 +1937,9 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
1925 f2fs_bug_on(i->state == NID_ALLOC); 1937 f2fs_bug_on(i->state == NID_ALLOC);
1926 __del_from_free_nid_list(nm_i, i); 1938 __del_from_free_nid_list(nm_i, i);
1927 nm_i->fcnt--; 1939 nm_i->fcnt--;
1940 spin_unlock(&nm_i->free_nid_list_lock);
1941 kmem_cache_free(free_nid_slab, i);
1942 spin_lock(&nm_i->free_nid_list_lock);
1928 } 1943 }
1929 f2fs_bug_on(nm_i->fcnt); 1944 f2fs_bug_on(nm_i->fcnt);
1930 spin_unlock(&nm_i->free_nid_list_lock); 1945 spin_unlock(&nm_i->free_nid_list_lock);