aboutsummaryrefslogtreecommitdiffstats
path: root/mm/slab_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/slab_common.c')
-rw-r--r--mm/slab_common.c109
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
199static 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
222static 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
233static void *s_next(struct seq_file *m, void *p, loff_t *pos)
234{
235 return seq_list_next(p, &slab_caches, pos);
236}
237
238static void s_stop(struct seq_file *m, void *p)
239{
240 mutex_unlock(&slab_mutex);
241}
242
243static 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 */
277static const struct seq_operations slabinfo_op = {
278 .start = s_start,
279 .next = s_next,
280 .stop = s_stop,
281 .show = s_show,
282};
283
284static int slabinfo_open(struct inode *inode, struct file *file)
285{
286 return seq_open(file, &slabinfo_op);
287}
288
289static 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
297static int __init slab_proc_init(void)
298{
299 proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations);
300 return 0;
301}
302module_init(slab_proc_init);
303#endif /* CONFIG_SLABINFO */