aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-03-02 10:27:46 -0500
committerTheodore Ts'o <tytso@mit.edu>2013-03-02 10:27:46 -0500
commit1ac6466f253ef7bd063b7877fb056afe1820841c (patch)
tree8202e2ba849b72236ea186cfbfd4c4098aa7d699 /fs
parent246307745c406379996e6ed6411f0e20f1ce1449 (diff)
ext4: use percpu counter for extent cache count
Use a percpu counter rather than atomic types for shrinker accounting. There's no need for ultimate accuracy in the shrinker, so this should come a little more cheaply. The percpu struct is somewhat large, but there was a big gap before the cache-aligned s_es_lru_lock anyway, and it fits nicely in there. Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/ext4.h2
-rw-r--r--fs/ext4/extents_status.c8
-rw-r--r--fs/ext4/super.c5
3 files changed, 10 insertions, 5 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 96c10934bb96..4a01ba315262 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1268,7 +1268,6 @@ 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;
1272 1271
1273 /* locality groups */ 1272 /* locality groups */
1274 struct ext4_locality_group __percpu *s_locality_groups; 1273 struct ext4_locality_group __percpu *s_locality_groups;
@@ -1310,6 +1309,7 @@ struct ext4_sb_info {
1310 /* Reclaim extents from extent status tree */ 1309 /* Reclaim extents from extent status tree */
1311 struct shrinker s_es_shrinker; 1310 struct shrinker s_es_shrinker;
1312 struct list_head s_es_lru; 1311 struct list_head s_es_lru;
1312 struct percpu_counter s_extent_cache_cnt;
1313 spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp; 1313 spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp;
1314}; 1314};
1315 1315
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 27fcdd2b2607..95796a1b7522 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -305,7 +305,7 @@ ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
305 */ 305 */
306 if (!ext4_es_is_delayed(es)) { 306 if (!ext4_es_is_delayed(es)) {
307 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); 308 percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
309 } 309 }
310 310
311 return es; 311 return es;
@@ -317,7 +317,7 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
317 if (!ext4_es_is_delayed(es)) { 317 if (!ext4_es_is_delayed(es)) {
318 BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0); 318 BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0);
319 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); 320 percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
321 } 321 }
322 322
323 kmem_cache_free(ext4_es_cachep, es); 323 kmem_cache_free(ext4_es_cachep, es);
@@ -678,7 +678,7 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
678 int nr_to_scan = sc->nr_to_scan; 678 int nr_to_scan = sc->nr_to_scan;
679 int ret, nr_shrunk = 0; 679 int ret, nr_shrunk = 0;
680 680
681 ret = atomic_read(&sbi->s_extent_cache_cnt); 681 ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
682 trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret); 682 trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
683 683
684 if (!nr_to_scan) 684 if (!nr_to_scan)
@@ -711,7 +711,7 @@ static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
711 list_splice_tail(&scanned, &sbi->s_es_lru); 711 list_splice_tail(&scanned, &sbi->s_es_lru);
712 spin_unlock(&sbi->s_es_lru_lock); 712 spin_unlock(&sbi->s_es_lru_lock);
713 713
714 ret = atomic_read(&sbi->s_extent_cache_cnt); 714 ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
715 trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret); 715 trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
716 return ret; 716 return ret;
717} 717}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 373d46cd5d3f..1ae5860b30a3 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -783,6 +783,7 @@ static void ext4_put_super(struct super_block *sb)
783 percpu_counter_destroy(&sbi->s_freeinodes_counter); 783 percpu_counter_destroy(&sbi->s_freeinodes_counter);
784 percpu_counter_destroy(&sbi->s_dirs_counter); 784 percpu_counter_destroy(&sbi->s_dirs_counter);
785 percpu_counter_destroy(&sbi->s_dirtyclusters_counter); 785 percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
786 percpu_counter_destroy(&sbi->s_extent_cache_cnt);
786 brelse(sbi->s_sbh); 787 brelse(sbi->s_sbh);
787#ifdef CONFIG_QUOTA 788#ifdef CONFIG_QUOTA
788 for (i = 0; i < MAXQUOTAS; i++) 789 for (i = 0; i < MAXQUOTAS; i++)
@@ -3688,6 +3689,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3688 if (!err) { 3689 if (!err) {
3689 err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0); 3690 err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0);
3690 } 3691 }
3692 if (!err) {
3693 err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0);
3694 }
3691 if (err) { 3695 if (err) {
3692 ext4_msg(sb, KERN_ERR, "insufficient memory"); 3696 ext4_msg(sb, KERN_ERR, "insufficient memory");
3693 goto failed_mount3; 3697 goto failed_mount3;
@@ -3993,6 +3997,7 @@ failed_mount3:
3993 percpu_counter_destroy(&sbi->s_freeinodes_counter); 3997 percpu_counter_destroy(&sbi->s_freeinodes_counter);
3994 percpu_counter_destroy(&sbi->s_dirs_counter); 3998 percpu_counter_destroy(&sbi->s_dirs_counter);
3995 percpu_counter_destroy(&sbi->s_dirtyclusters_counter); 3999 percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
4000 percpu_counter_destroy(&sbi->s_extent_cache_cnt);
3996 if (sbi->s_mmp_tsk) 4001 if (sbi->s_mmp_tsk)
3997 kthread_stop(sbi->s_mmp_tsk); 4002 kthread_stop(sbi->s_mmp_tsk);
3998failed_mount2: 4003failed_mount2: