In preparation for implementing lockless slab shrink, use new APIs to
dynamically allocate the ext4-es shrinker, so that it can be freed
asynchronously using kfree_rcu(). Then it doesn't need to wait for RCU
read-side critical section when releasing the struct ext4_sb_info.

Signed-off-by: Qi Zheng <zhengqi.a...@bytedance.com>
Reviewed-by: Muchun Song <songmuc...@bytedance.com>
---
 fs/ext4/ext4.h           |  2 +-
 fs/ext4/extents_status.c | 24 ++++++++++++++----------
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 481491e892df..48baf03eb1a6 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1657,7 +1657,7 @@ struct ext4_sb_info {
        __u32 s_csum_seed;
 
        /* Reclaim extents from extent status tree */
-       struct shrinker s_es_shrinker;
+       struct shrinker *s_es_shrinker;
        struct list_head s_es_list;     /* List of inodes with reclaimable 
extents */
        long s_es_nr_inode;
        struct ext4_es_stats s_es_stats;
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index 9b5b8951afb4..0532a81a7669 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -1596,7 +1596,7 @@ static unsigned long ext4_es_count(struct shrinker 
*shrink,
        unsigned long nr;
        struct ext4_sb_info *sbi;
 
-       sbi = container_of(shrink, struct ext4_sb_info, s_es_shrinker);
+       sbi = shrink->private_data;
        nr = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_shk_cnt);
        trace_ext4_es_shrink_count(sbi->s_sb, sc->nr_to_scan, nr);
        return nr;
@@ -1605,8 +1605,7 @@ static unsigned long ext4_es_count(struct shrinker 
*shrink,
 static unsigned long ext4_es_scan(struct shrinker *shrink,
                                  struct shrink_control *sc)
 {
-       struct ext4_sb_info *sbi = container_of(shrink,
-                                       struct ext4_sb_info, s_es_shrinker);
+       struct ext4_sb_info *sbi = shrink->private_data;
        int nr_to_scan = sc->nr_to_scan;
        int ret, nr_shrunk;
 
@@ -1690,13 +1689,18 @@ int ext4_es_register_shrinker(struct ext4_sb_info *sbi)
        if (err)
                goto err3;
 
-       sbi->s_es_shrinker.scan_objects = ext4_es_scan;
-       sbi->s_es_shrinker.count_objects = ext4_es_count;
-       sbi->s_es_shrinker.seeks = DEFAULT_SEEKS;
-       err = register_shrinker(&sbi->s_es_shrinker, "ext4-es:%s",
-                               sbi->s_sb->s_id);
-       if (err)
+       sbi->s_es_shrinker = shrinker_alloc(0, "ext4-es:%s", sbi->s_sb->s_id);
+       if (!sbi->s_es_shrinker) {
+               err = -ENOMEM;
                goto err4;
+       }
+
+       sbi->s_es_shrinker->scan_objects = ext4_es_scan;
+       sbi->s_es_shrinker->count_objects = ext4_es_count;
+       sbi->s_es_shrinker->seeks = DEFAULT_SEEKS;
+       sbi->s_es_shrinker->private_data = sbi;
+
+       shrinker_register(sbi->s_es_shrinker);
 
        return 0;
 err4:
@@ -1716,7 +1720,7 @@ void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi)
        percpu_counter_destroy(&sbi->s_es_stats.es_stats_cache_misses);
        percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt);
        percpu_counter_destroy(&sbi->s_es_stats.es_stats_shk_cnt);
-       unregister_shrinker(&sbi->s_es_shrinker);
+       shrinker_free(sbi->s_es_shrinker);
 }
 
 /*
-- 
2.30.2

Reply via email to