diff options
author | Theodore Ts'o <tytso@mit.edu> | 2013-03-02 10:27:46 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-03-02 10:27:46 -0500 |
commit | 1ac6466f253ef7bd063b7877fb056afe1820841c (patch) | |
tree | 8202e2ba849b72236ea186cfbfd4c4098aa7d699 /fs | |
parent | 246307745c406379996e6ed6411f0e20f1ce1449 (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.h | 2 | ||||
-rw-r--r-- | fs/ext4/extents_status.c | 8 | ||||
-rw-r--r-- | fs/ext4/super.c | 5 |
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); |
3998 | failed_mount2: | 4003 | failed_mount2: |