diff options
-rw-r--r-- | fs/ext4/ext4.h | 4 | ||||
-rw-r--r-- | fs/ext4/extents_status.c | 186 | ||||
-rw-r--r-- | fs/ext4/extents_status.h | 13 | ||||
-rw-r--r-- | fs/ext4/super.c | 11 | ||||
-rw-r--r-- | include/trace/events/ext4.h | 31 |
5 files changed, 224 insertions, 21 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index c07f43f8eb93..00fd822ac6e4 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -891,6 +891,7 @@ struct ext4_inode_info { | |||
891 | struct ext4_es_tree i_es_tree; | 891 | struct ext4_es_tree i_es_tree; |
892 | rwlock_t i_es_lock; | 892 | rwlock_t i_es_lock; |
893 | struct list_head i_es_lru; | 893 | struct list_head i_es_lru; |
894 | unsigned int i_es_all_nr; /* protected by i_es_lock */ | ||
894 | unsigned int i_es_lru_nr; /* protected by i_es_lock */ | 895 | unsigned int i_es_lru_nr; /* protected by i_es_lock */ |
895 | unsigned long i_touch_when; /* jiffies of last accessing */ | 896 | unsigned long i_touch_when; /* jiffies of last accessing */ |
896 | 897 | ||
@@ -1331,8 +1332,7 @@ struct ext4_sb_info { | |||
1331 | /* Reclaim extents from extent status tree */ | 1332 | /* Reclaim extents from extent status tree */ |
1332 | struct shrinker s_es_shrinker; | 1333 | struct shrinker s_es_shrinker; |
1333 | struct list_head s_es_lru; | 1334 | struct list_head s_es_lru; |
1334 | unsigned long s_es_last_sorted; | 1335 | struct ext4_es_stats s_es_stats; |
1335 | struct percpu_counter s_extent_cache_cnt; | ||
1336 | struct mb_cache *s_mb_cache; | 1336 | struct mb_cache *s_mb_cache; |
1337 | spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp; | 1337 | spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp; |
1338 | 1338 | ||
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index 95da65c60d83..09fd57667262 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c | |||
@@ -11,6 +11,8 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/rbtree.h> | 12 | #include <linux/rbtree.h> |
13 | #include <linux/list_sort.h> | 13 | #include <linux/list_sort.h> |
14 | #include <linux/proc_fs.h> | ||
15 | #include <linux/seq_file.h> | ||
14 | #include "ext4.h" | 16 | #include "ext4.h" |
15 | #include "extents_status.h" | 17 | #include "extents_status.h" |
16 | 18 | ||
@@ -313,19 +315,27 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len, | |||
313 | */ | 315 | */ |
314 | if (!ext4_es_is_delayed(es)) { | 316 | if (!ext4_es_is_delayed(es)) { |
315 | EXT4_I(inode)->i_es_lru_nr++; | 317 | EXT4_I(inode)->i_es_lru_nr++; |
316 | percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt); | 318 | percpu_counter_inc(&EXT4_SB(inode->i_sb)-> |
319 | s_es_stats.es_stats_lru_cnt); | ||
317 | } | 320 | } |
318 | 321 | ||
322 | EXT4_I(inode)->i_es_all_nr++; | ||
323 | percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_es_stats.es_stats_all_cnt); | ||
324 | |||
319 | return es; | 325 | return es; |
320 | } | 326 | } |
321 | 327 | ||
322 | static void ext4_es_free_extent(struct inode *inode, struct extent_status *es) | 328 | static void ext4_es_free_extent(struct inode *inode, struct extent_status *es) |
323 | { | 329 | { |
330 | EXT4_I(inode)->i_es_all_nr--; | ||
331 | percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_es_stats.es_stats_all_cnt); | ||
332 | |||
324 | /* Decrease the lru counter when this es is not delayed */ | 333 | /* Decrease the lru counter when this es is not delayed */ |
325 | if (!ext4_es_is_delayed(es)) { | 334 | if (!ext4_es_is_delayed(es)) { |
326 | BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0); | 335 | BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0); |
327 | EXT4_I(inode)->i_es_lru_nr--; | 336 | EXT4_I(inode)->i_es_lru_nr--; |
328 | percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt); | 337 | percpu_counter_dec(&EXT4_SB(inode->i_sb)-> |
338 | s_es_stats.es_stats_lru_cnt); | ||
329 | } | 339 | } |
330 | 340 | ||
331 | kmem_cache_free(ext4_es_cachep, es); | 341 | kmem_cache_free(ext4_es_cachep, es); |
@@ -729,6 +739,7 @@ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk, | |||
729 | struct extent_status *es) | 739 | struct extent_status *es) |
730 | { | 740 | { |
731 | struct ext4_es_tree *tree; | 741 | struct ext4_es_tree *tree; |
742 | struct ext4_es_stats *stats; | ||
732 | struct extent_status *es1 = NULL; | 743 | struct extent_status *es1 = NULL; |
733 | struct rb_node *node; | 744 | struct rb_node *node; |
734 | int found = 0; | 745 | int found = 0; |
@@ -765,11 +776,15 @@ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk, | |||
765 | } | 776 | } |
766 | 777 | ||
767 | out: | 778 | out: |
779 | stats = &EXT4_SB(inode->i_sb)->s_es_stats; | ||
768 | if (found) { | 780 | if (found) { |
769 | BUG_ON(!es1); | 781 | BUG_ON(!es1); |
770 | es->es_lblk = es1->es_lblk; | 782 | es->es_lblk = es1->es_lblk; |
771 | es->es_len = es1->es_len; | 783 | es->es_len = es1->es_len; |
772 | es->es_pblk = es1->es_pblk; | 784 | es->es_pblk = es1->es_pblk; |
785 | stats->es_stats_cache_hits++; | ||
786 | } else { | ||
787 | stats->es_stats_cache_misses++; | ||
773 | } | 788 | } |
774 | 789 | ||
775 | read_unlock(&EXT4_I(inode)->i_es_lock); | 790 | read_unlock(&EXT4_I(inode)->i_es_lock); |
@@ -931,11 +946,16 @@ static int __ext4_es_shrink(struct ext4_sb_info *sbi, int nr_to_scan, | |||
931 | struct ext4_inode_info *locked_ei) | 946 | struct ext4_inode_info *locked_ei) |
932 | { | 947 | { |
933 | struct ext4_inode_info *ei; | 948 | struct ext4_inode_info *ei; |
949 | struct ext4_es_stats *es_stats; | ||
934 | struct list_head *cur, *tmp; | 950 | struct list_head *cur, *tmp; |
935 | LIST_HEAD(skipped); | 951 | LIST_HEAD(skipped); |
952 | ktime_t start_time; | ||
953 | u64 scan_time; | ||
936 | int nr_shrunk = 0; | 954 | int nr_shrunk = 0; |
937 | int retried = 0, skip_precached = 1, nr_skipped = 0; | 955 | int retried = 0, skip_precached = 1, nr_skipped = 0; |
938 | 956 | ||
957 | es_stats = &sbi->s_es_stats; | ||
958 | start_time = ktime_get(); | ||
939 | spin_lock(&sbi->s_es_lru_lock); | 959 | spin_lock(&sbi->s_es_lru_lock); |
940 | 960 | ||
941 | retry: | 961 | retry: |
@@ -946,7 +966,8 @@ retry: | |||
946 | * If we have already reclaimed all extents from extent | 966 | * If we have already reclaimed all extents from extent |
947 | * status tree, just stop the loop immediately. | 967 | * status tree, just stop the loop immediately. |
948 | */ | 968 | */ |
949 | if (percpu_counter_read_positive(&sbi->s_extent_cache_cnt) == 0) | 969 | if (percpu_counter_read_positive( |
970 | &es_stats->es_stats_lru_cnt) == 0) | ||
950 | break; | 971 | break; |
951 | 972 | ||
952 | ei = list_entry(cur, struct ext4_inode_info, i_es_lru); | 973 | ei = list_entry(cur, struct ext4_inode_info, i_es_lru); |
@@ -956,7 +977,7 @@ retry: | |||
956 | * time. Normally we try hard to avoid shrinking | 977 | * time. Normally we try hard to avoid shrinking |
957 | * precached inodes, but we will as a last resort. | 978 | * precached inodes, but we will as a last resort. |
958 | */ | 979 | */ |
959 | if ((sbi->s_es_last_sorted < ei->i_touch_when) || | 980 | if ((es_stats->es_stats_last_sorted < ei->i_touch_when) || |
960 | (skip_precached && ext4_test_inode_state(&ei->vfs_inode, | 981 | (skip_precached && ext4_test_inode_state(&ei->vfs_inode, |
961 | EXT4_STATE_EXT_PRECACHED))) { | 982 | EXT4_STATE_EXT_PRECACHED))) { |
962 | nr_skipped++; | 983 | nr_skipped++; |
@@ -990,7 +1011,7 @@ retry: | |||
990 | if ((nr_shrunk == 0) && nr_skipped && !retried) { | 1011 | if ((nr_shrunk == 0) && nr_skipped && !retried) { |
991 | retried++; | 1012 | retried++; |
992 | list_sort(NULL, &sbi->s_es_lru, ext4_inode_touch_time_cmp); | 1013 | list_sort(NULL, &sbi->s_es_lru, ext4_inode_touch_time_cmp); |
993 | sbi->s_es_last_sorted = jiffies; | 1014 | es_stats->es_stats_last_sorted = jiffies; |
994 | ei = list_first_entry(&sbi->s_es_lru, struct ext4_inode_info, | 1015 | ei = list_first_entry(&sbi->s_es_lru, struct ext4_inode_info, |
995 | i_es_lru); | 1016 | i_es_lru); |
996 | /* | 1017 | /* |
@@ -1008,6 +1029,22 @@ retry: | |||
1008 | if (locked_ei && nr_shrunk == 0) | 1029 | if (locked_ei && nr_shrunk == 0) |
1009 | nr_shrunk = __es_try_to_reclaim_extents(locked_ei, nr_to_scan); | 1030 | nr_shrunk = __es_try_to_reclaim_extents(locked_ei, nr_to_scan); |
1010 | 1031 | ||
1032 | scan_time = ktime_to_ns(ktime_sub(ktime_get(), start_time)); | ||
1033 | if (likely(es_stats->es_stats_scan_time)) | ||
1034 | es_stats->es_stats_scan_time = (scan_time + | ||
1035 | es_stats->es_stats_scan_time*3) / 4; | ||
1036 | else | ||
1037 | es_stats->es_stats_scan_time = scan_time; | ||
1038 | if (scan_time > es_stats->es_stats_max_scan_time) | ||
1039 | es_stats->es_stats_max_scan_time = scan_time; | ||
1040 | if (likely(es_stats->es_stats_shrunk)) | ||
1041 | es_stats->es_stats_shrunk = (nr_shrunk + | ||
1042 | es_stats->es_stats_shrunk*3) / 4; | ||
1043 | else | ||
1044 | es_stats->es_stats_shrunk = nr_shrunk; | ||
1045 | |||
1046 | trace_ext4_es_shrink(sbi->s_sb, nr_shrunk, scan_time, skip_precached, | ||
1047 | nr_skipped, retried); | ||
1011 | return nr_shrunk; | 1048 | return nr_shrunk; |
1012 | } | 1049 | } |
1013 | 1050 | ||
@@ -1018,7 +1055,7 @@ static unsigned long ext4_es_count(struct shrinker *shrink, | |||
1018 | struct ext4_sb_info *sbi; | 1055 | struct ext4_sb_info *sbi; |
1019 | 1056 | ||
1020 | sbi = container_of(shrink, struct ext4_sb_info, s_es_shrinker); | 1057 | sbi = container_of(shrink, struct ext4_sb_info, s_es_shrinker); |
1021 | nr = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); | 1058 | nr = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_lru_cnt); |
1022 | trace_ext4_es_shrink_count(sbi->s_sb, sc->nr_to_scan, nr); | 1059 | trace_ext4_es_shrink_count(sbi->s_sb, sc->nr_to_scan, nr); |
1023 | return nr; | 1060 | return nr; |
1024 | } | 1061 | } |
@@ -1031,7 +1068,7 @@ static unsigned long ext4_es_scan(struct shrinker *shrink, | |||
1031 | int nr_to_scan = sc->nr_to_scan; | 1068 | int nr_to_scan = sc->nr_to_scan; |
1032 | int ret, nr_shrunk; | 1069 | int ret, nr_shrunk; |
1033 | 1070 | ||
1034 | ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt); | 1071 | ret = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_lru_cnt); |
1035 | trace_ext4_es_shrink_scan_enter(sbi->s_sb, nr_to_scan, ret); | 1072 | trace_ext4_es_shrink_scan_enter(sbi->s_sb, nr_to_scan, ret); |
1036 | 1073 | ||
1037 | if (!nr_to_scan) | 1074 | if (!nr_to_scan) |
@@ -1043,19 +1080,148 @@ static unsigned long ext4_es_scan(struct shrinker *shrink, | |||
1043 | return nr_shrunk; | 1080 | return nr_shrunk; |
1044 | } | 1081 | } |
1045 | 1082 | ||
1046 | void ext4_es_register_shrinker(struct ext4_sb_info *sbi) | 1083 | static void *ext4_es_seq_shrinker_info_start(struct seq_file *seq, loff_t *pos) |
1084 | { | ||
1085 | return *pos ? NULL : SEQ_START_TOKEN; | ||
1086 | } | ||
1087 | |||
1088 | static void * | ||
1089 | ext4_es_seq_shrinker_info_next(struct seq_file *seq, void *v, loff_t *pos) | ||
1090 | { | ||
1091 | return NULL; | ||
1092 | } | ||
1093 | |||
1094 | static int ext4_es_seq_shrinker_info_show(struct seq_file *seq, void *v) | ||
1095 | { | ||
1096 | struct ext4_sb_info *sbi = seq->private; | ||
1097 | struct ext4_es_stats *es_stats = &sbi->s_es_stats; | ||
1098 | struct ext4_inode_info *ei, *max = NULL; | ||
1099 | unsigned int inode_cnt = 0; | ||
1100 | |||
1101 | if (v != SEQ_START_TOKEN) | ||
1102 | return 0; | ||
1103 | |||
1104 | /* here we just find an inode that has the max nr. of objects */ | ||
1105 | spin_lock(&sbi->s_es_lru_lock); | ||
1106 | list_for_each_entry(ei, &sbi->s_es_lru, i_es_lru) { | ||
1107 | inode_cnt++; | ||
1108 | if (max && max->i_es_all_nr < ei->i_es_all_nr) | ||
1109 | max = ei; | ||
1110 | else if (!max) | ||
1111 | max = ei; | ||
1112 | } | ||
1113 | spin_unlock(&sbi->s_es_lru_lock); | ||
1114 | |||
1115 | seq_printf(seq, "stats:\n %lld objects\n %lld reclaimable objects\n", | ||
1116 | percpu_counter_sum_positive(&es_stats->es_stats_all_cnt), | ||
1117 | percpu_counter_sum_positive(&es_stats->es_stats_lru_cnt)); | ||
1118 | seq_printf(seq, " %lu/%lu cache hits/misses\n", | ||
1119 | es_stats->es_stats_cache_hits, | ||
1120 | es_stats->es_stats_cache_misses); | ||
1121 | if (es_stats->es_stats_last_sorted != 0) | ||
1122 | seq_printf(seq, " %u ms last sorted interval\n", | ||
1123 | jiffies_to_msecs(jiffies - | ||
1124 | es_stats->es_stats_last_sorted)); | ||
1125 | if (inode_cnt) | ||
1126 | seq_printf(seq, " %d inodes on lru list\n", inode_cnt); | ||
1127 | |||
1128 | seq_printf(seq, "average:\n %llu us scan time\n", | ||
1129 | div_u64(es_stats->es_stats_scan_time, 1000)); | ||
1130 | seq_printf(seq, " %lu shrunk objects\n", es_stats->es_stats_shrunk); | ||
1131 | if (inode_cnt) | ||
1132 | seq_printf(seq, | ||
1133 | "maximum:\n %lu inode (%u objects, %u reclaimable)\n" | ||
1134 | " %llu us max scan time\n", | ||
1135 | max->vfs_inode.i_ino, max->i_es_all_nr, max->i_es_lru_nr, | ||
1136 | div_u64(es_stats->es_stats_max_scan_time, 1000)); | ||
1137 | |||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | static void ext4_es_seq_shrinker_info_stop(struct seq_file *seq, void *v) | ||
1142 | { | ||
1143 | } | ||
1144 | |||
1145 | static const struct seq_operations ext4_es_seq_shrinker_info_ops = { | ||
1146 | .start = ext4_es_seq_shrinker_info_start, | ||
1147 | .next = ext4_es_seq_shrinker_info_next, | ||
1148 | .stop = ext4_es_seq_shrinker_info_stop, | ||
1149 | .show = ext4_es_seq_shrinker_info_show, | ||
1150 | }; | ||
1151 | |||
1152 | static int | ||
1153 | ext4_es_seq_shrinker_info_open(struct inode *inode, struct file *file) | ||
1154 | { | ||
1155 | int ret; | ||
1156 | |||
1157 | ret = seq_open(file, &ext4_es_seq_shrinker_info_ops); | ||
1158 | if (!ret) { | ||
1159 | struct seq_file *m = file->private_data; | ||
1160 | m->private = PDE_DATA(inode); | ||
1161 | } | ||
1162 | |||
1163 | return ret; | ||
1164 | } | ||
1165 | |||
1166 | static int | ||
1167 | ext4_es_seq_shrinker_info_release(struct inode *inode, struct file *file) | ||
1168 | { | ||
1169 | return seq_release(inode, file); | ||
1170 | } | ||
1171 | |||
1172 | static const struct file_operations ext4_es_seq_shrinker_info_fops = { | ||
1173 | .owner = THIS_MODULE, | ||
1174 | .open = ext4_es_seq_shrinker_info_open, | ||
1175 | .read = seq_read, | ||
1176 | .llseek = seq_lseek, | ||
1177 | .release = ext4_es_seq_shrinker_info_release, | ||
1178 | }; | ||
1179 | |||
1180 | int ext4_es_register_shrinker(struct ext4_sb_info *sbi) | ||
1047 | { | 1181 | { |
1182 | int err; | ||
1183 | |||
1048 | INIT_LIST_HEAD(&sbi->s_es_lru); | 1184 | INIT_LIST_HEAD(&sbi->s_es_lru); |
1049 | spin_lock_init(&sbi->s_es_lru_lock); | 1185 | spin_lock_init(&sbi->s_es_lru_lock); |
1050 | sbi->s_es_last_sorted = 0; | 1186 | sbi->s_es_stats.es_stats_last_sorted = 0; |
1187 | sbi->s_es_stats.es_stats_shrunk = 0; | ||
1188 | sbi->s_es_stats.es_stats_cache_hits = 0; | ||
1189 | sbi->s_es_stats.es_stats_cache_misses = 0; | ||
1190 | sbi->s_es_stats.es_stats_scan_time = 0; | ||
1191 | sbi->s_es_stats.es_stats_max_scan_time = 0; | ||
1192 | err = percpu_counter_init(&sbi->s_es_stats.es_stats_all_cnt, 0); | ||
1193 | if (err) | ||
1194 | return err; | ||
1195 | err = percpu_counter_init(&sbi->s_es_stats.es_stats_lru_cnt, 0); | ||
1196 | if (err) | ||
1197 | goto err1; | ||
1198 | |||
1051 | sbi->s_es_shrinker.scan_objects = ext4_es_scan; | 1199 | sbi->s_es_shrinker.scan_objects = ext4_es_scan; |
1052 | sbi->s_es_shrinker.count_objects = ext4_es_count; | 1200 | sbi->s_es_shrinker.count_objects = ext4_es_count; |
1053 | sbi->s_es_shrinker.seeks = DEFAULT_SEEKS; | 1201 | sbi->s_es_shrinker.seeks = DEFAULT_SEEKS; |
1054 | register_shrinker(&sbi->s_es_shrinker); | 1202 | err = register_shrinker(&sbi->s_es_shrinker); |
1203 | if (err) | ||
1204 | goto err2; | ||
1205 | |||
1206 | if (sbi->s_proc) | ||
1207 | proc_create_data("es_shrinker_info", S_IRUGO, sbi->s_proc, | ||
1208 | &ext4_es_seq_shrinker_info_fops, sbi); | ||
1209 | |||
1210 | return 0; | ||
1211 | |||
1212 | err2: | ||
1213 | percpu_counter_destroy(&sbi->s_es_stats.es_stats_lru_cnt); | ||
1214 | err1: | ||
1215 | percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt); | ||
1216 | return err; | ||
1055 | } | 1217 | } |
1056 | 1218 | ||
1057 | void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi) | 1219 | void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi) |
1058 | { | 1220 | { |
1221 | if (sbi->s_proc) | ||
1222 | remove_proc_entry("es_shrinker_info", sbi->s_proc); | ||
1223 | percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt); | ||
1224 | percpu_counter_destroy(&sbi->s_es_stats.es_stats_lru_cnt); | ||
1059 | unregister_shrinker(&sbi->s_es_shrinker); | 1225 | unregister_shrinker(&sbi->s_es_shrinker); |
1060 | } | 1226 | } |
1061 | 1227 | ||
diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h index f1b62a419920..efd5f970b501 100644 --- a/fs/ext4/extents_status.h +++ b/fs/ext4/extents_status.h | |||
@@ -64,6 +64,17 @@ struct ext4_es_tree { | |||
64 | struct extent_status *cache_es; /* recently accessed extent */ | 64 | struct extent_status *cache_es; /* recently accessed extent */ |
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct ext4_es_stats { | ||
68 | unsigned long es_stats_last_sorted; | ||
69 | unsigned long es_stats_shrunk; | ||
70 | unsigned long es_stats_cache_hits; | ||
71 | unsigned long es_stats_cache_misses; | ||
72 | u64 es_stats_scan_time; | ||
73 | u64 es_stats_max_scan_time; | ||
74 | struct percpu_counter es_stats_all_cnt; | ||
75 | struct percpu_counter es_stats_lru_cnt; | ||
76 | }; | ||
77 | |||
67 | extern int __init ext4_init_es(void); | 78 | extern int __init ext4_init_es(void); |
68 | extern void ext4_exit_es(void); | 79 | extern void ext4_exit_es(void); |
69 | extern void ext4_es_init_tree(struct ext4_es_tree *tree); | 80 | extern void ext4_es_init_tree(struct ext4_es_tree *tree); |
@@ -138,7 +149,7 @@ static inline void ext4_es_store_pblock_status(struct extent_status *es, | |||
138 | (pb & ~ES_MASK)); | 149 | (pb & ~ES_MASK)); |
139 | } | 150 | } |
140 | 151 | ||
141 | extern void ext4_es_register_shrinker(struct ext4_sb_info *sbi); | 152 | extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi); |
142 | extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi); | 153 | extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi); |
143 | extern void ext4_es_lru_add(struct inode *inode); | 154 | extern void ext4_es_lru_add(struct inode *inode); |
144 | extern void ext4_es_lru_del(struct inode *inode); | 155 | extern void ext4_es_lru_del(struct inode *inode); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 7194a51eb217..487c65b8cff0 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -820,7 +820,6 @@ static void ext4_put_super(struct super_block *sb) | |||
820 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 820 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
821 | percpu_counter_destroy(&sbi->s_dirs_counter); | 821 | percpu_counter_destroy(&sbi->s_dirs_counter); |
822 | percpu_counter_destroy(&sbi->s_dirtyclusters_counter); | 822 | percpu_counter_destroy(&sbi->s_dirtyclusters_counter); |
823 | percpu_counter_destroy(&sbi->s_extent_cache_cnt); | ||
824 | brelse(sbi->s_sbh); | 823 | brelse(sbi->s_sbh); |
825 | #ifdef CONFIG_QUOTA | 824 | #ifdef CONFIG_QUOTA |
826 | for (i = 0; i < MAXQUOTAS; i++) | 825 | for (i = 0; i < MAXQUOTAS; i++) |
@@ -885,6 +884,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
885 | ext4_es_init_tree(&ei->i_es_tree); | 884 | ext4_es_init_tree(&ei->i_es_tree); |
886 | rwlock_init(&ei->i_es_lock); | 885 | rwlock_init(&ei->i_es_lock); |
887 | INIT_LIST_HEAD(&ei->i_es_lru); | 886 | INIT_LIST_HEAD(&ei->i_es_lru); |
887 | ei->i_es_all_nr = 0; | ||
888 | ei->i_es_lru_nr = 0; | 888 | ei->i_es_lru_nr = 0; |
889 | ei->i_touch_when = 0; | 889 | ei->i_touch_when = 0; |
890 | ei->i_reserved_data_blocks = 0; | 890 | ei->i_reserved_data_blocks = 0; |
@@ -3890,12 +3890,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3890 | sbi->s_err_report.data = (unsigned long) sb; | 3890 | sbi->s_err_report.data = (unsigned long) sb; |
3891 | 3891 | ||
3892 | /* Register extent status tree shrinker */ | 3892 | /* Register extent status tree shrinker */ |
3893 | ext4_es_register_shrinker(sbi); | 3893 | if (ext4_es_register_shrinker(sbi)) |
3894 | |||
3895 | if ((err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0)) != 0) { | ||
3896 | ext4_msg(sb, KERN_ERR, "insufficient memory"); | ||
3897 | goto failed_mount3; | 3894 | goto failed_mount3; |
3898 | } | ||
3899 | 3895 | ||
3900 | sbi->s_stripe = ext4_get_stripe_size(sbi); | 3896 | sbi->s_stripe = ext4_get_stripe_size(sbi); |
3901 | sbi->s_extent_max_zeroout_kb = 32; | 3897 | sbi->s_extent_max_zeroout_kb = 32; |
@@ -4225,10 +4221,9 @@ failed_mount_wq: | |||
4225 | jbd2_journal_destroy(sbi->s_journal); | 4221 | jbd2_journal_destroy(sbi->s_journal); |
4226 | sbi->s_journal = NULL; | 4222 | sbi->s_journal = NULL; |
4227 | } | 4223 | } |
4228 | failed_mount3: | ||
4229 | ext4_es_unregister_shrinker(sbi); | 4224 | ext4_es_unregister_shrinker(sbi); |
4225 | failed_mount3: | ||
4230 | del_timer_sync(&sbi->s_err_report); | 4226 | del_timer_sync(&sbi->s_err_report); |
4231 | percpu_counter_destroy(&sbi->s_extent_cache_cnt); | ||
4232 | if (sbi->s_mmp_tsk) | 4227 | if (sbi->s_mmp_tsk) |
4233 | kthread_stop(sbi->s_mmp_tsk); | 4228 | kthread_stop(sbi->s_mmp_tsk); |
4234 | failed_mount2: | 4229 | failed_mount2: |
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h index 849aaba75dc8..ff4bd1b35246 100644 --- a/include/trace/events/ext4.h +++ b/include/trace/events/ext4.h | |||
@@ -2450,6 +2450,37 @@ TRACE_EVENT(ext4_collapse_range, | |||
2450 | __entry->offset, __entry->len) | 2450 | __entry->offset, __entry->len) |
2451 | ); | 2451 | ); |
2452 | 2452 | ||
2453 | TRACE_EVENT(ext4_es_shrink, | ||
2454 | TP_PROTO(struct super_block *sb, int nr_shrunk, u64 scan_time, | ||
2455 | int skip_precached, int nr_skipped, int retried), | ||
2456 | |||
2457 | TP_ARGS(sb, nr_shrunk, scan_time, skip_precached, nr_skipped, retried), | ||
2458 | |||
2459 | TP_STRUCT__entry( | ||
2460 | __field( dev_t, dev ) | ||
2461 | __field( int, nr_shrunk ) | ||
2462 | __field( unsigned long long, scan_time ) | ||
2463 | __field( int, skip_precached ) | ||
2464 | __field( int, nr_skipped ) | ||
2465 | __field( int, retried ) | ||
2466 | ), | ||
2467 | |||
2468 | TP_fast_assign( | ||
2469 | __entry->dev = sb->s_dev; | ||
2470 | __entry->nr_shrunk = nr_shrunk; | ||
2471 | __entry->scan_time = div_u64(scan_time, 1000); | ||
2472 | __entry->skip_precached = skip_precached; | ||
2473 | __entry->nr_skipped = nr_skipped; | ||
2474 | __entry->retried = retried; | ||
2475 | ), | ||
2476 | |||
2477 | TP_printk("dev %d,%d nr_shrunk %d, scan_time %llu skip_precached %d " | ||
2478 | "nr_skipped %d retried %d", | ||
2479 | MAJOR(__entry->dev), MINOR(__entry->dev), __entry->nr_shrunk, | ||
2480 | __entry->scan_time, __entry->skip_precached, | ||
2481 | __entry->nr_skipped, __entry->retried) | ||
2482 | ); | ||
2483 | |||
2453 | #endif /* _TRACE_EXT4_H */ | 2484 | #endif /* _TRACE_EXT4_H */ |
2454 | 2485 | ||
2455 | /* This part must be outside protection */ | 2486 | /* This part must be outside protection */ |