aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZheng Liu <wenqing.lz@taobao.com>2014-09-01 22:26:49 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-09-01 22:26:49 -0400
commiteb68d0e2fc5a4e5c06324ea5f485fccbae626d05 (patch)
tree2615b7518bebee73f197efbf32df9b4b21f9969e
parente963bb1de415ab06693357336c1bec664753e1e2 (diff)
ext4: track extent status tree shrinker delay statictics
This commit adds some statictics in extent status tree shrinker. The purpose to add these is that we want to collect more details when we encounter a stall caused by extent status tree shrinker. Here we count the following statictics: stats: the number of all objects on all extent status trees the number of reclaimable objects on lru list cache hits/misses the last sorted interval the number of inodes on lru list average: scan time for shrinking some objects the number of shrunk objects maximum: the inode that has max nr. of objects on lru list the maximum scan time for shrinking some objects The output looks like below: $ cat /proc/fs/ext4/sda1/es_shrinker_info stats: 28228 objects 6341 reclaimable objects 5281/631 cache hits/misses 586 ms last sorted interval 250 inodes on lru list average: 153 us scan time 128 shrunk objects maximum: 255 inode (255 objects, 198 reclaimable) 125723 us max scan time If the lru list has never been sorted, the following line will not be printed: 586ms last sorted interval If there is an empty lru list, the following lines also will not be printed: 250 inodes on lru list ... maximum: 255 inode (255 objects, 198 reclaimable) 0 us max scan time Meanwhile in this commit a new trace point is defined to print some details in __ext4_es_shrink(). Cc: Andreas Dilger <adilger.kernel@dilger.ca> Cc: Jan Kara <jack@suse.cz> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Zheng Liu <wenqing.lz@taobao.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/ext4.h4
-rw-r--r--fs/ext4/extents_status.c186
-rw-r--r--fs/ext4/extents_status.h13
-rw-r--r--fs/ext4/super.c11
-rw-r--r--include/trace/events/ext4.h31
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
322static void ext4_es_free_extent(struct inode *inode, struct extent_status *es) 328static 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
767out: 778out:
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
941retry: 961retry:
@@ -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
1046void ext4_es_register_shrinker(struct ext4_sb_info *sbi) 1083static void *ext4_es_seq_shrinker_info_start(struct seq_file *seq, loff_t *pos)
1084{
1085 return *pos ? NULL : SEQ_START_TOKEN;
1086}
1087
1088static void *
1089ext4_es_seq_shrinker_info_next(struct seq_file *seq, void *v, loff_t *pos)
1090{
1091 return NULL;
1092}
1093
1094static 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
1141static void ext4_es_seq_shrinker_info_stop(struct seq_file *seq, void *v)
1142{
1143}
1144
1145static 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
1152static int
1153ext4_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
1166static int
1167ext4_es_seq_shrinker_info_release(struct inode *inode, struct file *file)
1168{
1169 return seq_release(inode, file);
1170}
1171
1172static 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
1180int 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
1212err2:
1213 percpu_counter_destroy(&sbi->s_es_stats.es_stats_lru_cnt);
1214err1:
1215 percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt);
1216 return err;
1055} 1217}
1056 1218
1057void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi) 1219void 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
67struct 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
67extern int __init ext4_init_es(void); 78extern int __init ext4_init_es(void);
68extern void ext4_exit_es(void); 79extern void ext4_exit_es(void);
69extern void ext4_es_init_tree(struct ext4_es_tree *tree); 80extern 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
141extern void ext4_es_register_shrinker(struct ext4_sb_info *sbi); 152extern int ext4_es_register_shrinker(struct ext4_sb_info *sbi);
142extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi); 153extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi);
143extern void ext4_es_lru_add(struct inode *inode); 154extern void ext4_es_lru_add(struct inode *inode);
144extern void ext4_es_lru_del(struct inode *inode); 155extern 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 }
4228failed_mount3:
4229 ext4_es_unregister_shrinker(sbi); 4224 ext4_es_unregister_shrinker(sbi);
4225failed_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);
4234failed_mount2: 4229failed_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
2453TRACE_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 */