diff options
| author | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-12-31 18:02:16 -0500 |
|---|---|---|
| committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2015-12-31 18:39:22 -0500 |
| commit | 137d09f002df7d4e52513d75f8910945a6c1bb08 (patch) | |
| tree | f813e69f77e566ac40bb2646bd893c4a5118811d | |
| parent | c00ba5548500a6f5dfd3c0e0300b338b584018ba (diff) | |
f2fs: introduce zombie list for fast shrinking extent trees
This patch removes refcount, and instead, adds zombie_list to shrink directly
without radix tree traverse.
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
| -rw-r--r-- | fs/f2fs/extent_cache.c | 49 | ||||
| -rw-r--r-- | fs/f2fs/f2fs.h | 3 |
2 files changed, 23 insertions, 29 deletions
diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index b37184f720e8..4dee2be9a648 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c | |||
| @@ -68,13 +68,13 @@ static struct extent_tree *__grab_extent_tree(struct inode *inode) | |||
| 68 | et->root = RB_ROOT; | 68 | et->root = RB_ROOT; |
| 69 | et->cached_en = NULL; | 69 | et->cached_en = NULL; |
| 70 | rwlock_init(&et->lock); | 70 | rwlock_init(&et->lock); |
| 71 | atomic_set(&et->refcount, 0); | 71 | INIT_LIST_HEAD(&et->list); |
| 72 | et->count = 0; | 72 | et->count = 0; |
| 73 | atomic_inc(&sbi->total_ext_tree); | 73 | atomic_inc(&sbi->total_ext_tree); |
| 74 | } else { | 74 | } else { |
| 75 | atomic_dec(&sbi->total_zombie_tree); | 75 | atomic_dec(&sbi->total_zombie_tree); |
| 76 | list_del_init(&et->list); | ||
| 76 | } | 77 | } |
| 77 | atomic_inc(&et->refcount); | ||
| 78 | up_write(&sbi->extent_tree_lock); | 78 | up_write(&sbi->extent_tree_lock); |
| 79 | 79 | ||
| 80 | /* never died until evict_inode */ | 80 | /* never died until evict_inode */ |
| @@ -551,9 +551,9 @@ static unsigned int f2fs_update_extent_tree_range(struct inode *inode, | |||
| 551 | unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) | 551 | unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) |
| 552 | { | 552 | { |
| 553 | struct extent_tree *treevec[EXT_TREE_VEC_SIZE]; | 553 | struct extent_tree *treevec[EXT_TREE_VEC_SIZE]; |
| 554 | struct extent_tree *et, *next; | ||
| 554 | struct extent_node *en, *tmp; | 555 | struct extent_node *en, *tmp; |
| 555 | unsigned long ino = F2FS_ROOT_INO(sbi); | 556 | unsigned long ino = F2FS_ROOT_INO(sbi); |
| 556 | struct radix_tree_root *root = &sbi->extent_tree_root; | ||
| 557 | unsigned int found; | 557 | unsigned int found; |
| 558 | unsigned int node_cnt = 0, tree_cnt = 0; | 558 | unsigned int node_cnt = 0, tree_cnt = 0; |
| 559 | int remained; | 559 | int remained; |
| @@ -569,29 +569,20 @@ unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) | |||
| 569 | goto out; | 569 | goto out; |
| 570 | 570 | ||
| 571 | /* 1. remove unreferenced extent tree */ | 571 | /* 1. remove unreferenced extent tree */ |
| 572 | while ((found = radix_tree_gang_lookup(root, | 572 | list_for_each_entry_safe(et, next, &sbi->zombie_list, list) { |
| 573 | (void **)treevec, ino, EXT_TREE_VEC_SIZE))) { | 573 | write_lock(&et->lock); |
| 574 | unsigned i; | 574 | node_cnt += __free_extent_tree(sbi, et, true); |
| 575 | 575 | write_unlock(&et->lock); | |
| 576 | ino = treevec[found - 1]->ino + 1; | ||
| 577 | for (i = 0; i < found; i++) { | ||
| 578 | struct extent_tree *et = treevec[i]; | ||
| 579 | |||
| 580 | if (!atomic_read(&et->refcount)) { | ||
| 581 | write_lock(&et->lock); | ||
| 582 | node_cnt += __free_extent_tree(sbi, et, true); | ||
| 583 | write_unlock(&et->lock); | ||
| 584 | 576 | ||
| 585 | radix_tree_delete(root, et->ino); | 577 | list_del_init(&et->list); |
| 586 | kmem_cache_free(extent_tree_slab, et); | 578 | radix_tree_delete(&sbi->extent_tree_root, et->ino); |
| 587 | atomic_dec(&sbi->total_ext_tree); | 579 | kmem_cache_free(extent_tree_slab, et); |
| 588 | atomic_dec(&sbi->total_zombie_tree); | 580 | atomic_dec(&sbi->total_ext_tree); |
| 589 | tree_cnt++; | 581 | atomic_dec(&sbi->total_zombie_tree); |
| 582 | tree_cnt++; | ||
| 590 | 583 | ||
| 591 | if (node_cnt + tree_cnt >= nr_shrink) | 584 | if (node_cnt + tree_cnt >= nr_shrink) |
| 592 | goto unlock_out; | 585 | goto unlock_out; |
| 593 | } | ||
| 594 | } | ||
| 595 | } | 586 | } |
| 596 | up_write(&sbi->extent_tree_lock); | 587 | up_write(&sbi->extent_tree_lock); |
| 597 | 588 | ||
| @@ -619,7 +610,7 @@ free_node: | |||
| 619 | */ | 610 | */ |
| 620 | ino = F2FS_ROOT_INO(sbi); | 611 | ino = F2FS_ROOT_INO(sbi); |
| 621 | 612 | ||
| 622 | while ((found = radix_tree_gang_lookup(root, | 613 | while ((found = radix_tree_gang_lookup(&sbi->extent_tree_root, |
| 623 | (void **)treevec, ino, EXT_TREE_VEC_SIZE))) { | 614 | (void **)treevec, ino, EXT_TREE_VEC_SIZE))) { |
| 624 | unsigned i; | 615 | unsigned i; |
| 625 | 616 | ||
| @@ -670,8 +661,10 @@ void f2fs_destroy_extent_tree(struct inode *inode) | |||
| 670 | return; | 661 | return; |
| 671 | 662 | ||
| 672 | if (inode->i_nlink && !is_bad_inode(inode) && et->count) { | 663 | if (inode->i_nlink && !is_bad_inode(inode) && et->count) { |
| 673 | atomic_dec(&et->refcount); | 664 | down_write(&sbi->extent_tree_lock); |
| 665 | list_add_tail(&et->list, &sbi->zombie_list); | ||
| 674 | atomic_inc(&sbi->total_zombie_tree); | 666 | atomic_inc(&sbi->total_zombie_tree); |
| 667 | up_write(&sbi->extent_tree_lock); | ||
| 675 | return; | 668 | return; |
| 676 | } | 669 | } |
| 677 | 670 | ||
| @@ -680,8 +673,7 @@ void f2fs_destroy_extent_tree(struct inode *inode) | |||
| 680 | 673 | ||
| 681 | /* delete extent tree entry in radix tree */ | 674 | /* delete extent tree entry in radix tree */ |
| 682 | down_write(&sbi->extent_tree_lock); | 675 | down_write(&sbi->extent_tree_lock); |
| 683 | atomic_dec(&et->refcount); | 676 | f2fs_bug_on(sbi, et->count); |
| 684 | f2fs_bug_on(sbi, atomic_read(&et->refcount) || et->count); | ||
| 685 | radix_tree_delete(&sbi->extent_tree_root, inode->i_ino); | 677 | radix_tree_delete(&sbi->extent_tree_root, inode->i_ino); |
| 686 | kmem_cache_free(extent_tree_slab, et); | 678 | kmem_cache_free(extent_tree_slab, et); |
| 687 | atomic_dec(&sbi->total_ext_tree); | 679 | atomic_dec(&sbi->total_ext_tree); |
| @@ -737,6 +729,7 @@ void init_extent_cache_info(struct f2fs_sb_info *sbi) | |||
| 737 | INIT_LIST_HEAD(&sbi->extent_list); | 729 | INIT_LIST_HEAD(&sbi->extent_list); |
| 738 | spin_lock_init(&sbi->extent_lock); | 730 | spin_lock_init(&sbi->extent_lock); |
| 739 | atomic_set(&sbi->total_ext_tree, 0); | 731 | atomic_set(&sbi->total_ext_tree, 0); |
| 732 | INIT_LIST_HEAD(&sbi->zombie_list); | ||
| 740 | atomic_set(&sbi->total_zombie_tree, 0); | 733 | atomic_set(&sbi->total_zombie_tree, 0); |
| 741 | atomic_set(&sbi->total_ext_node, 0); | 734 | atomic_set(&sbi->total_ext_node, 0); |
| 742 | } | 735 | } |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d81bf5a43714..e2990c978661 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
| @@ -359,8 +359,8 @@ struct extent_tree { | |||
| 359 | struct rb_root root; /* root of extent info rb-tree */ | 359 | struct rb_root root; /* root of extent info rb-tree */ |
| 360 | struct extent_node *cached_en; /* recently accessed extent node */ | 360 | struct extent_node *cached_en; /* recently accessed extent node */ |
| 361 | struct extent_info largest; /* largested extent info */ | 361 | struct extent_info largest; /* largested extent info */ |
| 362 | struct list_head list; /* to be used by sbi->zombie_list */ | ||
| 362 | rwlock_t lock; /* protect extent info rb-tree */ | 363 | rwlock_t lock; /* protect extent info rb-tree */ |
| 363 | atomic_t refcount; /* reference count of rb-tree */ | ||
| 364 | unsigned int count; /* # of extent node in rb-tree*/ | 364 | unsigned int count; /* # of extent node in rb-tree*/ |
| 365 | }; | 365 | }; |
| 366 | 366 | ||
| @@ -764,6 +764,7 @@ struct f2fs_sb_info { | |||
| 764 | struct list_head extent_list; /* lru list for shrinker */ | 764 | struct list_head extent_list; /* lru list for shrinker */ |
| 765 | spinlock_t extent_lock; /* locking extent lru list */ | 765 | spinlock_t extent_lock; /* locking extent lru list */ |
| 766 | atomic_t total_ext_tree; /* extent tree count */ | 766 | atomic_t total_ext_tree; /* extent tree count */ |
| 767 | struct list_head zombie_list; /* extent zombie tree list */ | ||
| 767 | atomic_t total_zombie_tree; /* extent zombie tree count */ | 768 | atomic_t total_zombie_tree; /* extent zombie tree count */ |
| 768 | atomic_t total_ext_node; /* extent info count */ | 769 | atomic_t total_ext_node; /* extent info count */ |
| 769 | 770 | ||
