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 | |
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>
-rw-r--r-- | fs/f2fs/checkpoint.c | 27 | ||||
-rw-r--r-- | fs/f2fs/node.c | 17 |
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 | ||
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); |
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 | ||
1319 | static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build) | 1318 | static 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) | |||
1360 | static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) | 1359 | static 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 | ||
1372 | static void scan_nat_page(struct f2fs_nm_info *nm_i, | 1377 | static 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 | ||
1519 | void recover_node_page(struct f2fs_sb_info *sbi, struct page *page, | 1531 | void 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); |