aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/extents_status.c51
1 files changed, 39 insertions, 12 deletions
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 4b8df7fbb10a..91cb110da1b4 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -148,6 +148,8 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
148 ext4_lblk_t end); 148 ext4_lblk_t end);
149static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, 149static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
150 int nr_to_scan); 150 int nr_to_scan);
151static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
152 struct ext4_inode_info *locked_ei);
151 153
152int __init ext4_init_es(void) 154int __init ext4_init_es(void)
153{ 155{
@@ -665,7 +667,13 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
665 err = __es_remove_extent(inode, lblk, end); 667 err = __es_remove_extent(inode, lblk, end);
666 if (err != 0) 668 if (err != 0)
667 goto error; 669 goto error;
670retry:
668 err = __es_insert_extent(inode, &newes); 671 err = __es_insert_extent(inode, &newes);
672 if (err == -ENOMEM && __ext4_es_shrink(EXT4_SB(inode->i_sb), 1,
673 EXT4_I(inode)))
674 goto retry;
675 if (err == -ENOMEM && !ext4_es_is_delayed(&newes))
676 err = 0;
669 677
670error: 678error:
671 write_unlock(&EXT4_I(inode)->i_es_lock); 679 write_unlock(&EXT4_I(inode)->i_es_lock);
@@ -744,8 +752,10 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
744 struct extent_status orig_es; 752 struct extent_status orig_es;
745 ext4_lblk_t len1, len2; 753 ext4_lblk_t len1, len2;
746 ext4_fsblk_t block; 754 ext4_fsblk_t block;
747 int err = 0; 755 int err;
748 756
757retry:
758 err = 0;
749 es = __es_tree_search(&tree->root, lblk); 759 es = __es_tree_search(&tree->root, lblk);
750 if (!es) 760 if (!es)
751 goto out; 761 goto out;
@@ -780,6 +790,10 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
780 if (err) { 790 if (err) {
781 es->es_lblk = orig_es.es_lblk; 791 es->es_lblk = orig_es.es_lblk;
782 es->es_len = orig_es.es_len; 792 es->es_len = orig_es.es_len;
793 if ((err == -ENOMEM) &&
794 __ext4_es_shrink(EXT4_SB(inode->i_sb), 1,
795 EXT4_I(inode)))
796 goto retry;
783 goto out; 797 goto out;
784 } 798 }
785 } else { 799 } else {
@@ -889,22 +903,14 @@ static int ext4_inode_touch_time_cmp(void *priv, struct list_head *a,
889 return -1; 903 return -1;
890} 904}
891 905
892static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc) 906static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
907 struct ext4_inode_info *locked_ei)
893{ 908{
894 struct ext4_sb_info *sbi = container_of(shrink,
895 struct ext4_sb_info, s_es_shrinker);
896 struct ext4_inode_info *ei; 909 struct ext4_inode_info *ei;
897 struct list_head *cur, *tmp; 910 struct list_head *cur, *tmp;
898 LIST_HEAD(skiped); 911 LIST_HEAD(skiped);
899 int nr_to_scan = sc->nr_to_scan;
900 int ret, nr_shrunk = 0; 912 int ret, nr_shrunk = 0;
901 913
902 ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
903 trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
904
905 if (!nr_to_scan)
906 return ret;
907
908 spin_lock(&sbi->s_es_lru_lock); 914 spin_lock(&sbi->s_es_lru_lock);
909 915
910 /* 916 /*
@@ -933,7 +939,7 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
933 continue; 939 continue;
934 } 940 }
935 941
936 if (ei->i_es_lru_nr == 0) 942 if (ei->i_es_lru_nr == 0 || ei == locked_ei)
937 continue; 943 continue;
938 944
939 write_lock(&ei->i_es_lock); 945 write_lock(&ei->i_es_lock);
@@ -952,6 +958,27 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
952 list_splice_tail(&skiped, &sbi->s_es_lru); 958 list_splice_tail(&skiped, &sbi->s_es_lru);
953 spin_unlock(&sbi->s_es_lru_lock); 959 spin_unlock(&sbi->s_es_lru_lock);
954 960
961 if (locked_ei && nr_shrunk == 0)
962 nr_shrunk = __es_try_to_reclaim_extents(ei, nr_to_scan);
963
964 return nr_shrunk;
965}
966
967static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
968{
969 struct ext4_sb_info *sbi = container_of(shrink,
970 struct ext4_sb_info, s_es_shrinker);
971 int nr_to_scan = sc->nr_to_scan;
972 int ret, nr_shrunk;
973
974 ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
975 trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
976
977 if (!nr_to_scan)
978 return ret;
979
980 nr_shrunk = __ext4_es_shrink(sbi, nr_to_scan, NULL);
981
955 ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); 982 ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
956 trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret); 983 trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
957 return ret; 984 return ret;