1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/slab.h>
4 #include <linux/debugfs.h>
5 #include <linux/seq_file.h>
6 #include <linux/shrinker.h>
7 #include <linux/memcontrol.h>
8 #include <linux/srcu.h>
10 /* defined in vmscan.c */
11 extern struct mutex shrinker_mutex
;
12 extern struct list_head shrinker_list
;
13 extern struct srcu_struct shrinker_srcu
;
15 static DEFINE_IDA(shrinker_debugfs_ida
);
16 static struct dentry
*shrinker_debugfs_root
;
18 static unsigned long shrinker_count_objects(struct shrinker
*shrinker
,
19 struct mem_cgroup
*memcg
,
20 unsigned long *count_per_node
)
22 unsigned long nr
, total
= 0;
26 if (nid
== 0 || (shrinker
->flags
& SHRINKER_NUMA_AWARE
)) {
27 struct shrink_control sc
= {
28 .gfp_mask
= GFP_KERNEL
,
33 nr
= shrinker
->count_objects(shrinker
, &sc
);
34 if (nr
== SHRINK_EMPTY
)
40 count_per_node
[nid
] = nr
;
47 static int shrinker_debugfs_count_show(struct seq_file
*m
, void *v
)
49 struct shrinker
*shrinker
= m
->private;
50 unsigned long *count_per_node
;
51 struct mem_cgroup
*memcg
;
54 int ret
= 0, nid
, srcu_idx
;
56 count_per_node
= kcalloc(nr_node_ids
, sizeof(unsigned long), GFP_KERNEL
);
60 srcu_idx
= srcu_read_lock(&shrinker_srcu
);
62 memcg_aware
= shrinker
->flags
& SHRINKER_MEMCG_AWARE
;
64 memcg
= mem_cgroup_iter(NULL
, NULL
, NULL
);
66 if (memcg
&& !mem_cgroup_online(memcg
))
69 total
= shrinker_count_objects(shrinker
,
70 memcg_aware
? memcg
: NULL
,
73 seq_printf(m
, "%lu", mem_cgroup_ino(memcg
));
75 seq_printf(m
, " %lu", count_per_node
[nid
]);
80 mem_cgroup_iter_break(NULL
, memcg
);
84 if (signal_pending(current
)) {
85 mem_cgroup_iter_break(NULL
, memcg
);
89 } while ((memcg
= mem_cgroup_iter(NULL
, memcg
, NULL
)) != NULL
);
91 srcu_read_unlock(&shrinker_srcu
, srcu_idx
);
93 kfree(count_per_node
);
96 DEFINE_SHOW_ATTRIBUTE(shrinker_debugfs_count
);
98 static int shrinker_debugfs_scan_open(struct inode
*inode
, struct file
*file
)
100 file
->private_data
= inode
->i_private
;
101 return nonseekable_open(inode
, file
);
104 static ssize_t
shrinker_debugfs_scan_write(struct file
*file
,
105 const char __user
*buf
,
106 size_t size
, loff_t
*pos
)
108 struct shrinker
*shrinker
= file
->private_data
;
109 unsigned long nr_to_scan
= 0, ino
, read_len
;
110 struct shrink_control sc
= {
111 .gfp_mask
= GFP_KERNEL
,
113 struct mem_cgroup
*memcg
= NULL
;
117 read_len
= size
< (sizeof(kbuf
) - 1) ? size
: (sizeof(kbuf
) - 1);
118 if (copy_from_user(kbuf
, buf
, read_len
))
120 kbuf
[read_len
] = '\0';
122 if (sscanf(kbuf
, "%lu %d %lu", &ino
, &nid
, &nr_to_scan
) != 3)
125 if (nid
< 0 || nid
>= nr_node_ids
)
131 if (shrinker
->flags
& SHRINKER_MEMCG_AWARE
) {
132 memcg
= mem_cgroup_get_from_ino(ino
);
133 if (!memcg
|| IS_ERR(memcg
))
136 if (!mem_cgroup_online(memcg
)) {
137 mem_cgroup_put(memcg
);
140 } else if (ino
!= 0) {
144 srcu_idx
= srcu_read_lock(&shrinker_srcu
);
148 sc
.nr_to_scan
= nr_to_scan
;
149 sc
.nr_scanned
= nr_to_scan
;
151 shrinker
->scan_objects(shrinker
, &sc
);
153 srcu_read_unlock(&shrinker_srcu
, srcu_idx
);
154 mem_cgroup_put(memcg
);
159 static const struct file_operations shrinker_debugfs_scan_fops
= {
160 .owner
= THIS_MODULE
,
161 .open
= shrinker_debugfs_scan_open
,
162 .write
= shrinker_debugfs_scan_write
,
165 int shrinker_debugfs_add(struct shrinker
*shrinker
)
167 struct dentry
*entry
;
171 lockdep_assert_held(&shrinker_mutex
);
173 /* debugfs isn't initialized yet, add debugfs entries later. */
174 if (!shrinker_debugfs_root
)
177 id
= ida_alloc(&shrinker_debugfs_ida
, GFP_KERNEL
);
180 shrinker
->debugfs_id
= id
;
182 snprintf(buf
, sizeof(buf
), "%s-%d", shrinker
->name
, id
);
184 /* create debugfs entry */
185 entry
= debugfs_create_dir(buf
, shrinker_debugfs_root
);
187 ida_free(&shrinker_debugfs_ida
, id
);
188 return PTR_ERR(entry
);
190 shrinker
->debugfs_entry
= entry
;
192 debugfs_create_file("count", 0440, entry
, shrinker
,
193 &shrinker_debugfs_count_fops
);
194 debugfs_create_file("scan", 0220, entry
, shrinker
,
195 &shrinker_debugfs_scan_fops
);
199 int shrinker_debugfs_rename(struct shrinker
*shrinker
, const char *fmt
, ...)
201 struct dentry
*entry
;
203 const char *new, *old
;
208 new = kvasprintf_const(GFP_KERNEL
, fmt
, ap
);
214 mutex_lock(&shrinker_mutex
);
216 old
= shrinker
->name
;
217 shrinker
->name
= new;
219 if (shrinker
->debugfs_entry
) {
220 snprintf(buf
, sizeof(buf
), "%s-%d", shrinker
->name
,
221 shrinker
->debugfs_id
);
223 entry
= debugfs_rename(shrinker_debugfs_root
,
224 shrinker
->debugfs_entry
,
225 shrinker_debugfs_root
, buf
);
227 ret
= PTR_ERR(entry
);
229 shrinker
->debugfs_entry
= entry
;
232 mutex_unlock(&shrinker_mutex
);
238 EXPORT_SYMBOL(shrinker_debugfs_rename
);
240 struct dentry
*shrinker_debugfs_remove(struct shrinker
*shrinker
)
242 struct dentry
*entry
= shrinker
->debugfs_entry
;
244 lockdep_assert_held(&shrinker_mutex
);
246 kfree_const(shrinker
->name
);
247 shrinker
->name
= NULL
;
250 ida_free(&shrinker_debugfs_ida
, shrinker
->debugfs_id
);
251 shrinker
->debugfs_entry
= NULL
;
257 static int __init
shrinker_debugfs_init(void)
259 struct shrinker
*shrinker
;
260 struct dentry
*dentry
;
263 dentry
= debugfs_create_dir("shrinker", NULL
);
265 return PTR_ERR(dentry
);
266 shrinker_debugfs_root
= dentry
;
268 /* Create debugfs entries for shrinkers registered at boot */
269 mutex_lock(&shrinker_mutex
);
270 list_for_each_entry(shrinker
, &shrinker_list
, list
)
271 if (!shrinker
->debugfs_entry
) {
272 ret
= shrinker_debugfs_add(shrinker
);
276 mutex_unlock(&shrinker_mutex
);
280 late_initcall(shrinker_debugfs_init
);