Commit 20cd1892 authored by Qi Zheng's avatar Qi Zheng Committed by Andrew Morton
Browse files

mm: shrinkers: make count and scan in shrinker debugfs lockless

Like global and memcg slab shrink, also use SRCU to make count and scan
operations in memory shrinker debugfs lockless.

Link: https://lkml.kernel.org/r/20230313112819.38938-6-zhengqi.arch@bytedance.com


Signed-off-by: default avatarQi Zheng <zhengqi.arch@bytedance.com>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Acked-by: default avatarKirill Tkhai <tkhai@ya.ru>
Acked-by: default avatarRoman Gushchin <roman.gushchin@linux.dev>
Cc: Christian König <christian.koenig@amd.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Paul E. McKenney <paulmck@kernel.org>
Cc: Shakeel Butt <shakeelb@google.com>
Cc: Sultan Alsawaf <sultan@kerneltoast.com>
Cc: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Cc: Yang Shi <shy828301@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 475733dd
Loading
Loading
Loading
Loading
+8 −17
Original line number Diff line number Diff line
@@ -5,10 +5,12 @@
#include <linux/seq_file.h>
#include <linux/shrinker.h>
#include <linux/memcontrol.h>
#include <linux/srcu.h>

/* 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 +51,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 = 0, 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 +88,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 +111,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 +141,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 +150,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;