aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/extent_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/extent_cache.c')
-rw-r--r--fs/f2fs/extent_cache.c122
1 files changed, 68 insertions, 54 deletions
diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
index 7ddba812e11b..ccd5c636d3fe 100644
--- a/fs/f2fs/extent_cache.c
+++ b/fs/f2fs/extent_cache.c
@@ -36,7 +36,7 @@ static struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi,
36 36
37 rb_link_node(&en->rb_node, parent, p); 37 rb_link_node(&en->rb_node, parent, p);
38 rb_insert_color(&en->rb_node, &et->root); 38 rb_insert_color(&en->rb_node, &et->root);
39 et->count++; 39 atomic_inc(&et->node_cnt);
40 atomic_inc(&sbi->total_ext_node); 40 atomic_inc(&sbi->total_ext_node);
41 return en; 41 return en;
42} 42}
@@ -45,7 +45,7 @@ static void __detach_extent_node(struct f2fs_sb_info *sbi,
45 struct extent_tree *et, struct extent_node *en) 45 struct extent_tree *et, struct extent_node *en)
46{ 46{
47 rb_erase(&en->rb_node, &et->root); 47 rb_erase(&en->rb_node, &et->root);
48 et->count--; 48 atomic_dec(&et->node_cnt);
49 atomic_dec(&sbi->total_ext_node); 49 atomic_dec(&sbi->total_ext_node);
50 50
51 if (et->cached_en == en) 51 if (et->cached_en == en)
@@ -68,11 +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 atomic_set(&et->node_cnt, 0);
73 sbi->total_ext_tree++; 73 atomic_inc(&sbi->total_ext_tree);
74 } else {
75 atomic_dec(&sbi->total_zombie_tree);
76 list_del_init(&et->list);
74 } 77 }
75 atomic_inc(&et->refcount);
76 up_write(&sbi->extent_tree_lock); 78 up_write(&sbi->extent_tree_lock);
77 79
78 /* never died until evict_inode */ 80 /* never died until evict_inode */
@@ -131,7 +133,7 @@ static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi,
131{ 133{
132 struct rb_node *node, *next; 134 struct rb_node *node, *next;
133 struct extent_node *en; 135 struct extent_node *en;
134 unsigned int count = et->count; 136 unsigned int count = atomic_read(&et->node_cnt);
135 137
136 node = rb_first(&et->root); 138 node = rb_first(&et->root);
137 while (node) { 139 while (node) {
@@ -152,7 +154,7 @@ static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi,
152 node = next; 154 node = next;
153 } 155 }
154 156
155 return count - et->count; 157 return count - atomic_read(&et->node_cnt);
156} 158}
157 159
158static void __drop_largest_extent(struct inode *inode, 160static void __drop_largest_extent(struct inode *inode,
@@ -164,34 +166,33 @@ static void __drop_largest_extent(struct inode *inode,
164 largest->len = 0; 166 largest->len = 0;
165} 167}
166 168
167void f2fs_drop_largest_extent(struct inode *inode, pgoff_t fofs) 169/* return true, if inode page is changed */
168{ 170bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
169 if (!f2fs_may_extent_tree(inode))
170 return;
171
172 __drop_largest_extent(inode, fofs, 1);
173}
174
175void f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
176{ 171{
177 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 172 struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
178 struct extent_tree *et; 173 struct extent_tree *et;
179 struct extent_node *en; 174 struct extent_node *en;
180 struct extent_info ei; 175 struct extent_info ei;
181 176
182 if (!f2fs_may_extent_tree(inode)) 177 if (!f2fs_may_extent_tree(inode)) {
183 return; 178 /* drop largest extent */
179 if (i_ext && i_ext->len) {
180 i_ext->len = 0;
181 return true;
182 }
183 return false;
184 }
184 185
185 et = __grab_extent_tree(inode); 186 et = __grab_extent_tree(inode);
186 187
187 if (!i_ext || le32_to_cpu(i_ext->len) < F2FS_MIN_EXTENT_LEN) 188 if (!i_ext || !i_ext->len)
188 return; 189 return false;
189 190
190 set_extent_info(&ei, le32_to_cpu(i_ext->fofs), 191 set_extent_info(&ei, le32_to_cpu(i_ext->fofs),
191 le32_to_cpu(i_ext->blk), le32_to_cpu(i_ext->len)); 192 le32_to_cpu(i_ext->blk), le32_to_cpu(i_ext->len));
192 193
193 write_lock(&et->lock); 194 write_lock(&et->lock);
194 if (et->count) 195 if (atomic_read(&et->node_cnt))
195 goto out; 196 goto out;
196 197
197 en = __init_extent_tree(sbi, et, &ei); 198 en = __init_extent_tree(sbi, et, &ei);
@@ -202,6 +203,7 @@ void f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext)
202 } 203 }
203out: 204out:
204 write_unlock(&et->lock); 205 write_unlock(&et->lock);
206 return false;
205} 207}
206 208
207static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs, 209static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs,
@@ -549,45 +551,44 @@ static unsigned int f2fs_update_extent_tree_range(struct inode *inode,
549unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) 551unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink)
550{ 552{
551 struct extent_tree *treevec[EXT_TREE_VEC_SIZE]; 553 struct extent_tree *treevec[EXT_TREE_VEC_SIZE];
554 struct extent_tree *et, *next;
552 struct extent_node *en, *tmp; 555 struct extent_node *en, *tmp;
553 unsigned long ino = F2FS_ROOT_INO(sbi); 556 unsigned long ino = F2FS_ROOT_INO(sbi);
554 struct radix_tree_root *root = &sbi->extent_tree_root;
555 unsigned int found; 557 unsigned int found;
556 unsigned int node_cnt = 0, tree_cnt = 0; 558 unsigned int node_cnt = 0, tree_cnt = 0;
557 int remained; 559 int remained;
560 bool do_free = false;
558 561
559 if (!test_opt(sbi, EXTENT_CACHE)) 562 if (!test_opt(sbi, EXTENT_CACHE))
560 return 0; 563 return 0;
561 564
565 if (!atomic_read(&sbi->total_zombie_tree))
566 goto free_node;
567
562 if (!down_write_trylock(&sbi->extent_tree_lock)) 568 if (!down_write_trylock(&sbi->extent_tree_lock))
563 goto out; 569 goto out;
564 570
565 /* 1. remove unreferenced extent tree */ 571 /* 1. remove unreferenced extent tree */
566 while ((found = radix_tree_gang_lookup(root, 572 list_for_each_entry_safe(et, next, &sbi->zombie_list, list) {
567 (void **)treevec, ino, EXT_TREE_VEC_SIZE))) { 573 if (atomic_read(&et->node_cnt)) {
568 unsigned i; 574 write_lock(&et->lock);
569 575 node_cnt += __free_extent_tree(sbi, et, true);
570 ino = treevec[found - 1]->ino + 1; 576 write_unlock(&et->lock);
571 for (i = 0; i < found; i++) { 577 }
572 struct extent_tree *et = treevec[i];
573
574 if (!atomic_read(&et->refcount)) {
575 write_lock(&et->lock);
576 node_cnt += __free_extent_tree(sbi, et, true);
577 write_unlock(&et->lock);
578 578
579 radix_tree_delete(root, et->ino); 579 list_del_init(&et->list);
580 kmem_cache_free(extent_tree_slab, et); 580 radix_tree_delete(&sbi->extent_tree_root, et->ino);
581 sbi->total_ext_tree--; 581 kmem_cache_free(extent_tree_slab, et);
582 tree_cnt++; 582 atomic_dec(&sbi->total_ext_tree);
583 atomic_dec(&sbi->total_zombie_tree);
584 tree_cnt++;
583 585
584 if (node_cnt + tree_cnt >= nr_shrink) 586 if (node_cnt + tree_cnt >= nr_shrink)
585 goto unlock_out; 587 goto unlock_out;
586 }
587 }
588 } 588 }
589 up_write(&sbi->extent_tree_lock); 589 up_write(&sbi->extent_tree_lock);
590 590
591free_node:
591 /* 2. remove LRU extent entries */ 592 /* 2. remove LRU extent entries */
592 if (!down_write_trylock(&sbi->extent_tree_lock)) 593 if (!down_write_trylock(&sbi->extent_tree_lock))
593 goto out; 594 goto out;
@@ -599,15 +600,19 @@ unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink)
599 if (!remained--) 600 if (!remained--)
600 break; 601 break;
601 list_del_init(&en->list); 602 list_del_init(&en->list);
603 do_free = true;
602 } 604 }
603 spin_unlock(&sbi->extent_lock); 605 spin_unlock(&sbi->extent_lock);
604 606
607 if (do_free == false)
608 goto unlock_out;
609
605 /* 610 /*
606 * reset ino for searching victims from beginning of global extent tree. 611 * reset ino for searching victims from beginning of global extent tree.
607 */ 612 */
608 ino = F2FS_ROOT_INO(sbi); 613 ino = F2FS_ROOT_INO(sbi);
609 614
610 while ((found = radix_tree_gang_lookup(root, 615 while ((found = radix_tree_gang_lookup(&sbi->extent_tree_root,
611 (void **)treevec, ino, EXT_TREE_VEC_SIZE))) { 616 (void **)treevec, ino, EXT_TREE_VEC_SIZE))) {
612 unsigned i; 617 unsigned i;
613 618
@@ -615,9 +620,13 @@ unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink)
615 for (i = 0; i < found; i++) { 620 for (i = 0; i < found; i++) {
616 struct extent_tree *et = treevec[i]; 621 struct extent_tree *et = treevec[i];
617 622
618 write_lock(&et->lock); 623 if (!atomic_read(&et->node_cnt))
619 node_cnt += __free_extent_tree(sbi, et, false); 624 continue;
620 write_unlock(&et->lock); 625
626 if (write_trylock(&et->lock)) {
627 node_cnt += __free_extent_tree(sbi, et, false);
628 write_unlock(&et->lock);
629 }
621 630
622 if (node_cnt + tree_cnt >= nr_shrink) 631 if (node_cnt + tree_cnt >= nr_shrink)
623 goto unlock_out; 632 goto unlock_out;
@@ -637,7 +646,7 @@ unsigned int f2fs_destroy_extent_node(struct inode *inode)
637 struct extent_tree *et = F2FS_I(inode)->extent_tree; 646 struct extent_tree *et = F2FS_I(inode)->extent_tree;
638 unsigned int node_cnt = 0; 647 unsigned int node_cnt = 0;
639 648
640 if (!et) 649 if (!et || !atomic_read(&et->node_cnt))
641 return 0; 650 return 0;
642 651
643 write_lock(&et->lock); 652 write_lock(&et->lock);
@@ -656,8 +665,12 @@ void f2fs_destroy_extent_tree(struct inode *inode)
656 if (!et) 665 if (!et)
657 return; 666 return;
658 667
659 if (inode->i_nlink && !is_bad_inode(inode) && et->count) { 668 if (inode->i_nlink && !is_bad_inode(inode) &&
660 atomic_dec(&et->refcount); 669 atomic_read(&et->node_cnt)) {
670 down_write(&sbi->extent_tree_lock);
671 list_add_tail(&et->list, &sbi->zombie_list);
672 atomic_inc(&sbi->total_zombie_tree);
673 up_write(&sbi->extent_tree_lock);
661 return; 674 return;
662 } 675 }
663 676
@@ -666,11 +679,10 @@ void f2fs_destroy_extent_tree(struct inode *inode)
666 679
667 /* delete extent tree entry in radix tree */ 680 /* delete extent tree entry in radix tree */
668 down_write(&sbi->extent_tree_lock); 681 down_write(&sbi->extent_tree_lock);
669 atomic_dec(&et->refcount); 682 f2fs_bug_on(sbi, atomic_read(&et->node_cnt));
670 f2fs_bug_on(sbi, atomic_read(&et->refcount) || et->count);
671 radix_tree_delete(&sbi->extent_tree_root, inode->i_ino); 683 radix_tree_delete(&sbi->extent_tree_root, inode->i_ino);
672 kmem_cache_free(extent_tree_slab, et); 684 kmem_cache_free(extent_tree_slab, et);
673 sbi->total_ext_tree--; 685 atomic_dec(&sbi->total_ext_tree);
674 up_write(&sbi->extent_tree_lock); 686 up_write(&sbi->extent_tree_lock);
675 687
676 F2FS_I(inode)->extent_tree = NULL; 688 F2FS_I(inode)->extent_tree = NULL;
@@ -722,7 +734,9 @@ void init_extent_cache_info(struct f2fs_sb_info *sbi)
722 init_rwsem(&sbi->extent_tree_lock); 734 init_rwsem(&sbi->extent_tree_lock);
723 INIT_LIST_HEAD(&sbi->extent_list); 735 INIT_LIST_HEAD(&sbi->extent_list);
724 spin_lock_init(&sbi->extent_lock); 736 spin_lock_init(&sbi->extent_lock);
725 sbi->total_ext_tree = 0; 737 atomic_set(&sbi->total_ext_tree, 0);
738 INIT_LIST_HEAD(&sbi->zombie_list);
739 atomic_set(&sbi->total_zombie_tree, 0);
726 atomic_set(&sbi->total_ext_node, 0); 740 atomic_set(&sbi->total_ext_node, 0);
727} 741}
728 742