Like global and memcg slab shrink, also use SRCU to
make count and scan operations in memory shrinker
debugfs lockless.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
---
mm/shrinker_debug.c | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
diff --git a/mm/shrinker_debug.c b/mm/shrinker_debug.c
index 39c3491e28a3..6a26e8ac40aa 100644
--- a/mm/shrinker_debug.c
+++ b/mm/shrinker_debug.c
@@ -9,6 +9,7 @@
/* defined in vmscan.c */
extern struct rw_semaphore shrinker_rwsem;
extern struct list_head shrinker_list;
+extern struct srcu_struct shrinker_srcu;
static DEFINE_IDA(shrinker_debugfs_ida);
static struct dentry *shrinker_debugfs_root;
@@ -49,18 +50,13 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)
struct mem_cgroup *memcg;
unsigned long total;
bool memcg_aware;
- int ret, nid;
+ int ret, nid, srcu_idx;
count_per_node = kcalloc(nr_node_ids, sizeof(unsigned long), GFP_KERNEL);
if (!count_per_node)
return -ENOMEM;
- ret = down_read_killable(&shrinker_rwsem);
- if (ret) {
- kfree(count_per_node);
- return ret;
- }
- rcu_read_lock();
+ srcu_idx = srcu_read_lock(&shrinker_srcu);
memcg_aware = shrinker->flags & SHRINKER_MEMCG_AWARE;
@@ -91,8 +87,7 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)
}
} while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL);
- rcu_read_unlock();
- up_read(&shrinker_rwsem);
+ srcu_read_unlock(&shrinker_srcu, srcu_idx);
kfree(count_per_node);
return ret;
@@ -115,9 +110,8 @@ static ssize_t shrinker_debugfs_scan_write(struct file *file,
.gfp_mask = GFP_KERNEL,
};
struct mem_cgroup *memcg = NULL;
- int nid;
+ int nid, srcu_idx;
char kbuf[72];
- ssize_t ret;
read_len = size < (sizeof(kbuf) - 1) ? size : (sizeof(kbuf) - 1);
if (copy_from_user(kbuf, buf, read_len))
@@ -146,11 +140,7 @@ static ssize_t shrinker_debugfs_scan_write(struct file *file,
return -EINVAL;
}
- ret = down_read_killable(&shrinker_rwsem);
- if (ret) {
- mem_cgroup_put(memcg);
- return ret;
- }
+ srcu_idx = srcu_read_lock(&shrinker_srcu);
sc.nid = nid;
sc.memcg = memcg;
@@ -159,7 +149,7 @@ static ssize_t shrinker_debugfs_scan_write(struct file *file,
shrinker->scan_objects(shrinker, &sc);
- up_read(&shrinker_rwsem);
+ srcu_read_unlock(&shrinker_srcu, srcu_idx);
mem_cgroup_put(memcg);
return size;
--
2.20.1
Hi Qi, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on akpm-mm/mm-everything] [also build test WARNING on next-20230220] [cannot apply to device-mapper-dm/for-next linus/master v6.2] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Qi-Zheng/mm-vmscan-make-global-slab-shrink-lockless/20230220-171954 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/20230220091637.64865-4-zhengqi.arch%40bytedance.com patch subject: [PATCH 3/5] mm: shrinkers: make count and scan in shrinker debugfs lockless config: riscv-randconfig-r036-20230219 (https://download.01.org/0day-ci/archive/20230220/202302202134.OFjSh3rl-lkp@intel.com/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project db89896bbbd2251fff457699635acbbedeead27f) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install riscv cross compiling tool for clang build # apt-get install binutils-riscv64-linux-gnu # https://github.com/intel-lab-lkp/linux/commit/b5b7259339a7a5cfae5a120356750c5a9e151d12 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Qi-Zheng/mm-vmscan-make-global-slab-shrink-lockless/20230220-171954 git checkout b5b7259339a7a5cfae5a120356750c5a9e151d12 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202302202134.OFjSh3rl-lkp@intel.com/ All warnings (new ones prefixed by >>): >> mm/shrinker_debug.c:88:11: warning: variable 'ret' is used uninitialized whenever 'do' loop exits because its condition is false [-Wsometimes-uninitialized] } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mm/shrinker_debug.c:93:9: note: uninitialized use occurs here return ret; ^~~ mm/shrinker_debug.c:88:11: note: remove the condition if it is always true } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 >> mm/shrinker_debug.c:78:7: warning: variable 'ret' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized] if (!memcg_aware) { ^~~~~~~~~~~~ mm/shrinker_debug.c:93:9: note: uninitialized use occurs here return ret; ^~~ mm/shrinker_debug.c:78:3: note: remove the 'if' if its condition is always false if (!memcg_aware) { ^~~~~~~~~~~~~~~~~~~ mm/shrinker_debug.c:53:9: note: initialize the variable 'ret' to silence this warning int ret, nid, srcu_idx; ^ = 0 2 warnings generated. vim +88 mm/shrinker_debug.c 5035ebc644aec9 Roman Gushchin 2022-05-31 45 5035ebc644aec9 Roman Gushchin 2022-05-31 46 static int shrinker_debugfs_count_show(struct seq_file *m, void *v) 5035ebc644aec9 Roman Gushchin 2022-05-31 47 { 5035ebc644aec9 Roman Gushchin 2022-05-31 48 struct shrinker *shrinker = m->private; 5035ebc644aec9 Roman Gushchin 2022-05-31 49 unsigned long *count_per_node; 5035ebc644aec9 Roman Gushchin 2022-05-31 50 struct mem_cgroup *memcg; 5035ebc644aec9 Roman Gushchin 2022-05-31 51 unsigned long total; 5035ebc644aec9 Roman Gushchin 2022-05-31 52 bool memcg_aware; b5b7259339a7a5 Qi Zheng 2023-02-20 53 int ret, nid, srcu_idx; 5035ebc644aec9 Roman Gushchin 2022-05-31 54 5035ebc644aec9 Roman Gushchin 2022-05-31 55 count_per_node = kcalloc(nr_node_ids, sizeof(unsigned long), GFP_KERNEL); 5035ebc644aec9 Roman Gushchin 2022-05-31 56 if (!count_per_node) 5035ebc644aec9 Roman Gushchin 2022-05-31 57 return -ENOMEM; 5035ebc644aec9 Roman Gushchin 2022-05-31 58 b5b7259339a7a5 Qi Zheng 2023-02-20 59 srcu_idx = srcu_read_lock(&shrinker_srcu); 5035ebc644aec9 Roman Gushchin 2022-05-31 60 5035ebc644aec9 Roman Gushchin 2022-05-31 61 memcg_aware = shrinker->flags & SHRINKER_MEMCG_AWARE; 5035ebc644aec9 Roman Gushchin 2022-05-31 62 5035ebc644aec9 Roman Gushchin 2022-05-31 63 memcg = mem_cgroup_iter(NULL, NULL, NULL); 5035ebc644aec9 Roman Gushchin 2022-05-31 64 do { 5035ebc644aec9 Roman Gushchin 2022-05-31 65 if (memcg && !mem_cgroup_online(memcg)) 5035ebc644aec9 Roman Gushchin 2022-05-31 66 continue; 5035ebc644aec9 Roman Gushchin 2022-05-31 67 5035ebc644aec9 Roman Gushchin 2022-05-31 68 total = shrinker_count_objects(shrinker, 5035ebc644aec9 Roman Gushchin 2022-05-31 69 memcg_aware ? memcg : NULL, 5035ebc644aec9 Roman Gushchin 2022-05-31 70 count_per_node); 5035ebc644aec9 Roman Gushchin 2022-05-31 71 if (total) { 5035ebc644aec9 Roman Gushchin 2022-05-31 72 seq_printf(m, "%lu", mem_cgroup_ino(memcg)); 5035ebc644aec9 Roman Gushchin 2022-05-31 73 for_each_node(nid) 5035ebc644aec9 Roman Gushchin 2022-05-31 74 seq_printf(m, " %lu", count_per_node[nid]); 5035ebc644aec9 Roman Gushchin 2022-05-31 75 seq_putc(m, '\n'); 5035ebc644aec9 Roman Gushchin 2022-05-31 76 } 5035ebc644aec9 Roman Gushchin 2022-05-31 77 5035ebc644aec9 Roman Gushchin 2022-05-31 @78 if (!memcg_aware) { 5035ebc644aec9 Roman Gushchin 2022-05-31 79 mem_cgroup_iter_break(NULL, memcg); 5035ebc644aec9 Roman Gushchin 2022-05-31 80 break; 5035ebc644aec9 Roman Gushchin 2022-05-31 81 } 5035ebc644aec9 Roman Gushchin 2022-05-31 82 5035ebc644aec9 Roman Gushchin 2022-05-31 83 if (signal_pending(current)) { 5035ebc644aec9 Roman Gushchin 2022-05-31 84 mem_cgroup_iter_break(NULL, memcg); 5035ebc644aec9 Roman Gushchin 2022-05-31 85 ret = -EINTR; 5035ebc644aec9 Roman Gushchin 2022-05-31 86 break; 5035ebc644aec9 Roman Gushchin 2022-05-31 87 } 5035ebc644aec9 Roman Gushchin 2022-05-31 @88 } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL); 5035ebc644aec9 Roman Gushchin 2022-05-31 89 b5b7259339a7a5 Qi Zheng 2023-02-20 90 srcu_read_unlock(&shrinker_srcu, srcu_idx); 5035ebc644aec9 Roman Gushchin 2022-05-31 91 5035ebc644aec9 Roman Gushchin 2022-05-31 92 kfree(count_per_node); 5035ebc644aec9 Roman Gushchin 2022-05-31 @93 return ret; 5035ebc644aec9 Roman Gushchin 2022-05-31 94 } 5035ebc644aec9 Roman Gushchin 2022-05-31 95 DEFINE_SHOW_ATTRIBUTE(shrinker_debugfs_count); 5035ebc644aec9 Roman Gushchin 2022-05-31 96 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests
© 2016 - 2025 Red Hat, Inc.