1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/idr.h> 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 9 #include "internal.h" 10 11 /* defined in vmscan.c */ 12 extern struct mutex shrinker_mutex; 13 extern struct list_head shrinker_list; 14 15 static DEFINE_IDA(shrinker_debugfs_ida); 16 static struct dentry *shrinker_debugfs_root; 17 18 static unsigned long shrinker_count_objects(struct shrinker *shrinker, 19 struct mem_cgroup *memcg, 20 unsigned long *count_per_node) 21 { 22 unsigned long nr, total = 0; 23 int nid; 24 25 for_each_node(nid) { 26 if (nid == 0 || (shrinker->flags & SHRINKER_NUMA_AWARE)) { 27 struct shrink_control sc = { 28 .gfp_mask = GFP_KERNEL, 29 .nid = nid, 30 .memcg = memcg, 31 }; 32 33 nr = shrinker->count_objects(shrinker, &sc); 34 if (nr == SHRINK_EMPTY) 35 nr = 0; 36 } else { 37 nr = 0; 38 } 39 40 count_per_node[nid] = nr; 41 total += nr; 42 } 43 44 return total; 45 } 46 47 static int shrinker_debugfs_count_show(struct seq_file *m, void *v) 48 { 49 struct shrinker *shrinker = m->private; 50 unsigned long *count_per_node; 51 struct mem_cgroup *memcg; 52 unsigned long total; 53 bool memcg_aware; 54 int ret = 0, nid; 55 56 count_per_node = kcalloc(nr_node_ids, sizeof(unsigned long), GFP_KERNEL); 57 if (!count_per_node) 58 return -ENOMEM; 59 60 memcg_aware = shrinker->flags & SHRINKER_MEMCG_AWARE; 61 62 memcg = mem_cgroup_iter(NULL, NULL, NULL); 63 do { 64 if (memcg && !mem_cgroup_online(memcg)) 65 continue; 66 67 total = shrinker_count_objects(shrinker, 68 memcg_aware ? memcg : NULL, 69 count_per_node); 70 if (total) { 71 seq_printf(m, "%llu", mem_cgroup_id(memcg)); 72 for_each_node(nid) 73 seq_printf(m, " %lu", count_per_node[nid]); 74 seq_putc(m, '\n'); 75 } 76 77 if (!memcg_aware) { 78 mem_cgroup_iter_break(NULL, memcg); 79 break; 80 } 81 82 if (signal_pending(current)) { 83 mem_cgroup_iter_break(NULL, memcg); 84 ret = -EINTR; 85 break; 86 } 87 } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL)) != NULL); 88 89 kfree(count_per_node); 90 return ret; 91 } 92 DEFINE_SHOW_ATTRIBUTE(shrinker_debugfs_count); 93 94 static int shrinker_debugfs_scan_open(struct inode *inode, struct file *file) 95 { 96 file->private_data = inode->i_private; 97 return nonseekable_open(inode, file); 98 } 99 100 static ssize_t shrinker_debugfs_scan_write(struct file *file, 101 const char __user *buf, 102 size_t size, loff_t *pos) 103 { 104 struct shrinker *shrinker = file->private_data; 105 unsigned long nr_to_scan = 0, read_len; 106 u64 id; 107 struct shrink_control sc = { 108 .gfp_mask = GFP_KERNEL, 109 }; 110 struct mem_cgroup *memcg = NULL; 111 int nid; 112 char kbuf[72]; 113 114 read_len = min(size, sizeof(kbuf) - 1); 115 if (copy_from_user(kbuf, buf, read_len)) 116 return -EFAULT; 117 kbuf[read_len] = '\0'; 118 119 if (sscanf(kbuf, "%llu %d %lu", &id, &nid, &nr_to_scan) != 3) 120 return -EINVAL; 121 122 if (nid < 0 || nid >= nr_node_ids) 123 return -EINVAL; 124 125 if (nr_to_scan == 0) 126 return size; 127 128 if (shrinker->flags & SHRINKER_MEMCG_AWARE) { 129 memcg = mem_cgroup_get_from_id(id); 130 if (!memcg) 131 return -ENOENT; 132 133 if (!mem_cgroup_online(memcg)) { 134 mem_cgroup_put(memcg); 135 return -ENOENT; 136 } 137 } else if (id != 0) { 138 return -EINVAL; 139 } 140 141 sc.nid = nid; 142 sc.memcg = memcg; 143 sc.nr_to_scan = nr_to_scan; 144 sc.nr_scanned = nr_to_scan; 145 146 shrinker->scan_objects(shrinker, &sc); 147 148 mem_cgroup_put(memcg); 149 150 return size; 151 } 152 153 static const struct file_operations shrinker_debugfs_scan_fops = { 154 .owner = THIS_MODULE, 155 .open = shrinker_debugfs_scan_open, 156 .write = shrinker_debugfs_scan_write, 157 }; 158 159 int shrinker_debugfs_add(struct shrinker *shrinker) 160 { 161 struct dentry *entry; 162 char buf[128]; 163 int id; 164 165 lockdep_assert_held(&shrinker_mutex); 166 167 /* debugfs isn't initialized yet, add debugfs entries later. */ 168 if (!shrinker_debugfs_root) 169 return 0; 170 171 id = ida_alloc(&shrinker_debugfs_ida, GFP_KERNEL); 172 if (id < 0) 173 return id; 174 shrinker->debugfs_id = id; 175 176 snprintf(buf, sizeof(buf), "%s-%d", shrinker->name, id); 177 178 /* create debugfs entry */ 179 entry = debugfs_create_dir(buf, shrinker_debugfs_root); 180 if (IS_ERR(entry)) { 181 ida_free(&shrinker_debugfs_ida, id); 182 return PTR_ERR(entry); 183 } 184 shrinker->debugfs_entry = entry; 185 186 debugfs_create_file("count", 0440, entry, shrinker, 187 &shrinker_debugfs_count_fops); 188 debugfs_create_file("scan", 0220, entry, shrinker, 189 &shrinker_debugfs_scan_fops); 190 return 0; 191 } 192 193 int shrinker_debugfs_rename(struct shrinker *shrinker, const char *fmt, ...) 194 { 195 const char *new, *old; 196 va_list ap; 197 int ret = 0; 198 199 va_start(ap, fmt); 200 new = kvasprintf_const(GFP_KERNEL, fmt, ap); 201 va_end(ap); 202 203 if (!new) 204 return -ENOMEM; 205 206 mutex_lock(&shrinker_mutex); 207 208 old = shrinker->name; 209 shrinker->name = new; 210 211 ret = debugfs_change_name(shrinker->debugfs_entry, "%s-%d", 212 shrinker->name, shrinker->debugfs_id); 213 214 if (ret) { 215 shrinker->name = old; 216 kfree_const(new); 217 } else { 218 kfree_const(old); 219 } 220 mutex_unlock(&shrinker_mutex); 221 222 return ret; 223 } 224 EXPORT_SYMBOL(shrinker_debugfs_rename); 225 226 struct dentry *shrinker_debugfs_detach(struct shrinker *shrinker, 227 int *debugfs_id) 228 { 229 struct dentry *entry = shrinker->debugfs_entry; 230 231 lockdep_assert_held(&shrinker_mutex); 232 233 *debugfs_id = entry ? shrinker->debugfs_id : -1; 234 shrinker->debugfs_entry = NULL; 235 236 return entry; 237 } 238 239 void shrinker_debugfs_remove(struct dentry *debugfs_entry, int debugfs_id) 240 { 241 debugfs_remove_recursive(debugfs_entry); 242 ida_free(&shrinker_debugfs_ida, debugfs_id); 243 } 244 245 static int __init shrinker_debugfs_init(void) 246 { 247 struct shrinker *shrinker; 248 struct dentry *dentry; 249 int ret = 0; 250 251 dentry = debugfs_create_dir("shrinker", NULL); 252 if (IS_ERR(dentry)) 253 return PTR_ERR(dentry); 254 shrinker_debugfs_root = dentry; 255 256 /* Create debugfs entries for shrinkers registered at boot */ 257 mutex_lock(&shrinker_mutex); 258 list_for_each_entry(shrinker, &shrinker_list, list) 259 if (!shrinker->debugfs_entry) { 260 ret = shrinker_debugfs_add(shrinker); 261 if (ret) 262 break; 263 } 264 mutex_unlock(&shrinker_mutex); 265 266 return ret; 267 } 268 late_initcall(shrinker_debugfs_init); 269