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>
        atomic_t s_mb_preallocated;
        atomic_t s_mb_discarded;
        atomic_t s_lock_busy;
-       atomic_t s_extent_cache_cnt;
 
        /* locality groups */
        struct ext4_locality_group __percpu *s_locality_groups;
        /* Reclaim extents from extent status tree */
        struct shrinker s_es_shrinker;
        struct list_head s_es_lru;
+       struct percpu_counter s_extent_cache_cnt;
        spinlock_t s_es_lru_lock ____cacheline_aligned_in_smp;
 };
 
 
         */
        if (!ext4_es_is_delayed(es)) {
                EXT4_I(inode)->i_es_lru_nr++;
-               atomic_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
+               percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
        }
 
        return es;
        if (!ext4_es_is_delayed(es)) {
                BUG_ON(EXT4_I(inode)->i_es_lru_nr == 0);
                EXT4_I(inode)->i_es_lru_nr--;
-               atomic_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
+               percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_extent_cache_cnt);
        }
 
        kmem_cache_free(ext4_es_cachep, es);
        int nr_to_scan = sc->nr_to_scan;
        int ret, nr_shrunk = 0;
 
-       ret = atomic_read(&sbi->s_extent_cache_cnt);
+       ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
        trace_ext4_es_shrink_enter(sbi->s_sb, nr_to_scan, ret);
 
        if (!nr_to_scan)
        list_splice_tail(&scanned, &sbi->s_es_lru);
        spin_unlock(&sbi->s_es_lru_lock);
 
-       ret = atomic_read(&sbi->s_extent_cache_cnt);
+       ret = percpu_counter_read_positive(&sbi->s_extent_cache_cnt);
        trace_ext4_es_shrink_exit(sbi->s_sb, nr_shrunk, ret);
        return ret;
 }
 
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
        percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+       percpu_counter_destroy(&sbi->s_extent_cache_cnt);
        brelse(sbi->s_sbh);
 #ifdef CONFIG_QUOTA
        for (i = 0; i < MAXQUOTAS; i++)
        if (!err) {
                err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0);
        }
+       if (!err) {
+               err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0);
+       }
        if (err) {
                ext4_msg(sb, KERN_ERR, "insufficient memory");
                goto failed_mount3;
        percpu_counter_destroy(&sbi->s_freeinodes_counter);
        percpu_counter_destroy(&sbi->s_dirs_counter);
        percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+       percpu_counter_destroy(&sbi->s_extent_cache_cnt);
        if (sbi->s_mmp_tsk)
                kthread_stop(sbi->s_mmp_tsk);
 failed_mount2: