aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-02-28 23:58:56 -0500
committerTheodore Ts'o <tytso@mit.edu>2013-02-28 23:58:56 -0500
commit246307745c406379996e6ed6411f0e20f1ce1449 (patch)
tree71b78d765ba7406c6755cad807944da6a99e5980
parent8e919d13048cd5acaadb2b15b48acbfb8832d3c2 (diff)
ext4: optimize ext4_es_shrink()
When the system is under memory pressure, ext4_es_srhink() will get called very often. So optimize returning the number of items in the file system's extent status cache by keeping a per-filesystem count, instead of calculating it each time by scanning all of the inodes in the extent status cache. Also rename the slab used for the extent status cache to be "ext4_extent_status" so it's obviousl the slab in question is created by ext4. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: Zheng Liu <gnehzuil.liu@gmail.com>
-rw-r--r--fs/ext4/ext4.h1
-rw-r--r--fs/ext4/extents_status.c39
-rw-r--r--include/trace/events/ext4.h40
3 files changed, 26 insertions, 54 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 6e16c1867959..96c10934bb96 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1268,6 +1268,7 @@ struct ext4_sb_info {
1268 atomic_t s_mb_preallocated; 1268 atomic_t s_mb_preallocated;
1269 atomic_t s_mb_discarded; 1269 atomic_t s_mb_discarded;
1270 atomic_t s_lock_busy; 1270 atomic_t s_lock_busy;
1271 atomic_t s_extent_cache_cnt;
1271 1272
1272 /* locality groups */ 1273 /* locality groups */
1273 struct ext4_locality_group __percpu *s_locality_groups; 1274 struct ext4_locality_group __percpu *s_locality_groups;
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index f768f4a98a2b..27fcdd2b2607 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -147,11 +147,12 @@ static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
147 ext4_lblk_t end); 147 ext4_lblk_t end);
148static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, 148static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
149 int nr_to_scan); 149 int nr_to_scan);
150static int ext4_es_reclaim_extents_count(struct super_block *sb);
151 150
152int __init ext4_init_es(void) 151int __init ext4_init_es(void)
153{ 152{
154 ext4_es_cachep = KMEM_CACHE(extent_status, SLAB_RECLAIM_ACCOUNT); 153 ext4_es_cachep = kmem_cache_create("ext4_extent_status",
154 sizeof(struct extent_status),
155 0, (SLAB_RECLAIM_ACCOUNT), NULL);
155 if (ext4_es_cachep == NULL) 156 if (ext4_es_cachep == NULL)
156 return -ENOMEM; 157 return -ENOMEM;
157 return 0; 158 return 0;
@@ -302,8 +303,10 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
302 /* 303 /*
303 * We don't count delayed extent because we never try to reclaim them 304 * We don't count delayed extent because we never try to reclaim them
304 */ 305 */
305 if (!ext4_es_is_delayed(es)) 306 if (!ext4_es_is_delayed(es)) {
306 EXT4_I(inode)->i_es_lru_nr++; 307 EXT4_I(inode)->i_es_lru_nr++;
308 atomic_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
309 }
307 310
308 return es; 311 return es;
309} 312}
@@ -314,6 +317,7 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
314 if (!ext4_es_is_delayed(es)) { 317 if (!ext4_es_is_delayed(es)) {
315 BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0); 318 BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0);
316 EXT4_I(inode)->i_es_lru_nr--; 319 EXT4_I(inode)->i_es_lru_nr--;
320 atomic_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
317 } 321 }
318 322
319 kmem_cache_free(ext4_es_cachep, es); 323 kmem_cache_free(ext4_es_cachep, es);
@@ -674,10 +678,11 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
674 int nr_to_scan = sc->nr_to_scan; 678 int nr_to_scan = sc->nr_to_scan;
675 int ret, nr_shrunk = 0; 679 int ret, nr_shrunk = 0;
676 680
677 trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan); 681 ret = atomic_read(&sbi->s_extent_cache_cnt);
682 trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
678 683
679 if (!nr_to_scan) 684 if (!nr_to_scan)
680 return ext4_es_reclaim_extents_count(sbi->s_sb); 685 return ret;
681 686
682 INIT_LIST_HEAD(&scanned); 687 INIT_LIST_HEAD(&scanned);
683 688
@@ -705,9 +710,10 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
705 } 710 }
706 list_splice_tail(&scanned, &sbi->s_es_lru); 711 list_splice_tail(&scanned, &sbi->s_es_lru);
707 spin_unlock(&sbi->s_es_lru_lock); 712 spin_unlock(&sbi->s_es_lru_lock);
708 trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk);
709 713
710 return ext4_es_reclaim_extents_count(sbi->s_sb); 714 ret = atomic_read(&sbi->s_extent_cache_cnt);
715 trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
716 return ret;
711} 717}
712 718
713void ext4_es_register_shrinker(struct super_block *sb) 719void ext4_es_register_shrinker(struct super_block *sb)
@@ -751,25 +757,6 @@ void ext4_es_lru_del(struct inode *inode)
751 spin_unlock(&sbi->s_es_lru_lock); 757 spin_unlock(&sbi->s_es_lru_lock);
752} 758}
753 759
754static int ext4_es_reclaim_extents_count(struct super_block *sb)
755{
756 struct ext4_sb_info *sbi = EXT4_SB(sb);
757 struct ext4_inode_info *ei;
758 struct list_head *cur;
759 int nr_cached = 0;
760
761 spin_lock(&sbi->s_es_lru_lock);
762 list_for_each(cur, &sbi->s_es_lru) {
763 ei = list_entry(cur, struct ext4_inode_info, i_es_lru);
764 read_lock(&ei->i_es_lock);
765 nr_cached += ei->i_es_lru_nr;
766 read_unlock(&ei->i_es_lock);
767 }
768 spin_unlock(&sbi->s_es_lru_lock);
769 trace_ext4_es_reclaim_extents_count(sb, nr_cached);
770 return nr_cached;
771}
772
773static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei, 760static int __es_try_to_reclaim_extents(struct ext4_inode_info *ei,
774 int nr_to_scan) 761 int nr_to_scan)
775{ 762{
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index c0457c0d1a68..4ee471003859 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -2255,64 +2255,48 @@ TRACE_EVENT(ext4_es_lookup_extent_exit,
2255 __entry->found ? __entry->status : 0) 2255 __entry->found ? __entry->status : 0)
2256); 2256);
2257 2257
2258TRACE_EVENT(ext4_es_reclaim_extents_count,
2259 TP_PROTO(struct super_block *sb, int nr_cached),
2260
2261 TP_ARGS(sb, nr_cached),
2262
2263 TP_STRUCT__entry(
2264 __field( dev_t, dev )
2265 __field( int, nr_cached )
2266 ),
2267
2268 TP_fast_assign(
2269 __entry->dev = sb->s_dev;
2270 __entry->nr_cached = nr_cached;
2271 ),
2272
2273 TP_printk("dev %d,%d cached objects nr %d",
2274 MAJOR(__entry->dev), MINOR(__entry->dev),
2275 __entry->nr_cached)
2276);
2277
2278TRACE_EVENT(ext4_es_shrink_enter, 2258TRACE_EVENT(ext4_es_shrink_enter,
2279 TP_PROTO(struct super_block *sb, int nr_to_scan), 2259 TP_PROTO(struct super_block *sb, int nr_to_scan, int cache_cnt),
2280 2260
2281 TP_ARGS(sb, nr_to_scan), 2261 TP_ARGS(sb, nr_to_scan, cache_cnt),
2282 2262
2283 TP_STRUCT__entry( 2263 TP_STRUCT__entry(
2284 __field( dev_t, dev ) 2264 __field( dev_t, dev )
2285 __field( int, nr_to_scan ) 2265 __field( int, nr_to_scan )
2266 __field( int, cache_cnt )
2286 ), 2267 ),
2287 2268
2288 TP_fast_assign( 2269 TP_fast_assign(
2289 __entry->dev = sb->s_dev; 2270 __entry->dev = sb->s_dev;
2290 __entry->nr_to_scan = nr_to_scan; 2271 __entry->nr_to_scan = nr_to_scan;
2272 __entry->cache_cnt = cache_cnt;
2291 ), 2273 ),
2292 2274
2293 TP_printk("dev %d,%d nr to scan %d", 2275 TP_printk("dev %d,%d nr_to_scan %d cache_cnt %d",
2294 MAJOR(__entry->dev), MINOR(__entry->dev), 2276 MAJOR(__entry->dev), MINOR(__entry->dev),
2295 __entry->nr_to_scan) 2277 __entry->nr_to_scan, __entry->cache_cnt)
2296); 2278);
2297 2279
2298TRACE_EVENT(ext4_es_shrink_exit, 2280TRACE_EVENT(ext4_es_shrink_exit,
2299 TP_PROTO(struct super_block *sb, int shrunk_nr), 2281 TP_PROTO(struct super_block *sb, int shrunk_nr, int cache_cnt),
2300 2282
2301 TP_ARGS(sb, shrunk_nr), 2283 TP_ARGS(sb, shrunk_nr, cache_cnt),
2302 2284
2303 TP_STRUCT__entry( 2285 TP_STRUCT__entry(
2304 __field( dev_t, dev ) 2286 __field( dev_t, dev )
2305 __field( int, shrunk_nr ) 2287 __field( int, shrunk_nr )
2288 __field( int, cache_cnt )
2306 ), 2289 ),
2307 2290
2308 TP_fast_assign( 2291 TP_fast_assign(
2309 __entry->dev = sb->s_dev; 2292 __entry->dev = sb->s_dev;
2310 __entry->shrunk_nr = shrunk_nr; 2293 __entry->shrunk_nr = shrunk_nr;
2294 __entry->cache_cnt = cache_cnt;
2311 ), 2295 ),
2312 2296
2313 TP_printk("dev %d,%d nr to scan %d", 2297 TP_printk("dev %d,%d shrunk_nr %d cache_cnt %d",
2314 MAJOR(__entry->dev), MINOR(__entry->dev), 2298 MAJOR(__entry->dev), MINOR(__entry->dev),
2315 __entry->shrunk_nr) 2299 __entry->shrunk_nr, __entry->cache_cnt)
2316); 2300);
2317 2301
2318#endif /* _TRACE_EXT4_H */ 2302#endif /* _TRACE_EXT4_H */