diff options
Diffstat (limited to 'mm/slab_common.c')
-rw-r--r-- | mm/slab_common.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/mm/slab_common.c b/mm/slab_common.c index 069a24e64403..5fb753da6cf0 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c | |||
@@ -13,6 +13,8 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/cpu.h> | 14 | #include <linux/cpu.h> |
15 | #include <linux/uaccess.h> | 15 | #include <linux/uaccess.h> |
16 | #include <linux/seq_file.h> | ||
17 | #include <linux/proc_fs.h> | ||
16 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> |
17 | #include <asm/tlbflush.h> | 19 | #include <asm/tlbflush.h> |
18 | #include <asm/page.h> | 20 | #include <asm/page.h> |
@@ -192,3 +194,110 @@ int slab_is_available(void) | |||
192 | { | 194 | { |
193 | return slab_state >= UP; | 195 | return slab_state >= UP; |
194 | } | 196 | } |
197 | |||
198 | #ifdef CONFIG_SLABINFO | ||
199 | static void print_slabinfo_header(struct seq_file *m) | ||
200 | { | ||
201 | /* | ||
202 | * Output format version, so at least we can change it | ||
203 | * without _too_ many complaints. | ||
204 | */ | ||
205 | #ifdef CONFIG_DEBUG_SLAB | ||
206 | seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); | ||
207 | #else | ||
208 | seq_puts(m, "slabinfo - version: 2.1\n"); | ||
209 | #endif | ||
210 | seq_puts(m, "# name <active_objs> <num_objs> <objsize> " | ||
211 | "<objperslab> <pagesperslab>"); | ||
212 | seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>"); | ||
213 | seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>"); | ||
214 | #ifdef CONFIG_DEBUG_SLAB | ||
215 | seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> " | ||
216 | "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>"); | ||
217 | seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>"); | ||
218 | #endif | ||
219 | seq_putc(m, '\n'); | ||
220 | } | ||
221 | |||
222 | static void *s_start(struct seq_file *m, loff_t *pos) | ||
223 | { | ||
224 | loff_t n = *pos; | ||
225 | |||
226 | mutex_lock(&slab_mutex); | ||
227 | if (!n) | ||
228 | print_slabinfo_header(m); | ||
229 | |||
230 | return seq_list_start(&slab_caches, *pos); | ||
231 | } | ||
232 | |||
233 | static void *s_next(struct seq_file *m, void *p, loff_t *pos) | ||
234 | { | ||
235 | return seq_list_next(p, &slab_caches, pos); | ||
236 | } | ||
237 | |||
238 | static void s_stop(struct seq_file *m, void *p) | ||
239 | { | ||
240 | mutex_unlock(&slab_mutex); | ||
241 | } | ||
242 | |||
243 | static int s_show(struct seq_file *m, void *p) | ||
244 | { | ||
245 | struct kmem_cache *s = list_entry(p, struct kmem_cache, list); | ||
246 | struct slabinfo sinfo; | ||
247 | |||
248 | memset(&sinfo, 0, sizeof(sinfo)); | ||
249 | get_slabinfo(s, &sinfo); | ||
250 | |||
251 | seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", | ||
252 | s->name, sinfo.active_objs, sinfo.num_objs, s->size, | ||
253 | sinfo.objects_per_slab, (1 << sinfo.cache_order)); | ||
254 | |||
255 | seq_printf(m, " : tunables %4u %4u %4u", | ||
256 | sinfo.limit, sinfo.batchcount, sinfo.shared); | ||
257 | seq_printf(m, " : slabdata %6lu %6lu %6lu", | ||
258 | sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail); | ||
259 | slabinfo_show_stats(m, s); | ||
260 | seq_putc(m, '\n'); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * slabinfo_op - iterator that generates /proc/slabinfo | ||
266 | * | ||
267 | * Output layout: | ||
268 | * cache-name | ||
269 | * num-active-objs | ||
270 | * total-objs | ||
271 | * object size | ||
272 | * num-active-slabs | ||
273 | * total-slabs | ||
274 | * num-pages-per-slab | ||
275 | * + further values on SMP and with statistics enabled | ||
276 | */ | ||
277 | static const struct seq_operations slabinfo_op = { | ||
278 | .start = s_start, | ||
279 | .next = s_next, | ||
280 | .stop = s_stop, | ||
281 | .show = s_show, | ||
282 | }; | ||
283 | |||
284 | static int slabinfo_open(struct inode *inode, struct file *file) | ||
285 | { | ||
286 | return seq_open(file, &slabinfo_op); | ||
287 | } | ||
288 | |||
289 | static const struct file_operations proc_slabinfo_operations = { | ||
290 | .open = slabinfo_open, | ||
291 | .read = seq_read, | ||
292 | .write = slabinfo_write, | ||
293 | .llseek = seq_lseek, | ||
294 | .release = seq_release, | ||
295 | }; | ||
296 | |||
297 | static int __init slab_proc_init(void) | ||
298 | { | ||
299 | proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); | ||
300 | return 0; | ||
301 | } | ||
302 | module_init(slab_proc_init); | ||
303 | #endif /* CONFIG_SLABINFO */ | ||