aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/slab.c118
-rw-r--r--mm/slab.h20
-rw-r--r--mm/slab_common.c109
-rw-r--r--mm/slub.c77
4 files changed, 166 insertions, 158 deletions
diff --git a/mm/slab.c b/mm/slab.c
index 33d3363658df..6d5c83c6ddd5 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -4276,54 +4276,8 @@ out:
4276} 4276}
4277 4277
4278#ifdef CONFIG_SLABINFO 4278#ifdef CONFIG_SLABINFO
4279 4279void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
4280static void print_slabinfo_header(struct seq_file *m)
4281{ 4280{
4282 /*
4283 * Output format version, so at least we can change it
4284 * without _too_ many complaints.
4285 */
4286#if STATS
4287 seq_puts(m, "slabinfo - version: 2.1 (statistics)\n");
4288#else
4289 seq_puts(m, "slabinfo - version: 2.1\n");
4290#endif
4291 seq_puts(m, "# name <active_objs> <num_objs> <objsize> "
4292 "<objperslab> <pagesperslab>");
4293 seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
4294 seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
4295#if STATS
4296 seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
4297 "<error> <maxfreeable> <nodeallocs> <remotefrees> <alienoverflow>");
4298 seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
4299#endif
4300 seq_putc(m, '\n');
4301}
4302
4303static void *s_start(struct seq_file *m, loff_t *pos)
4304{
4305 loff_t n = *pos;
4306
4307 mutex_lock(&slab_mutex);
4308 if (!n)
4309 print_slabinfo_header(m);
4310
4311 return seq_list_start(&slab_caches, *pos);
4312}
4313
4314static void *s_next(struct seq_file *m, void *p, loff_t *pos)
4315{
4316 return seq_list_next(p, &slab_caches, pos);
4317}
4318
4319static void s_stop(struct seq_file *m, void *p)
4320{
4321 mutex_unlock(&slab_mutex);
4322}
4323
4324static int s_show(struct seq_file *m, void *p)
4325{
4326 struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list);
4327 struct slab *slabp; 4281 struct slab *slabp;
4328 unsigned long active_objs; 4282 unsigned long active_objs;
4329 unsigned long num_objs; 4283 unsigned long num_objs;
@@ -4378,13 +4332,20 @@ static int s_show(struct seq_file *m, void *p)
4378 if (error) 4332 if (error)
4379 printk(KERN_ERR "slab: cache %s error: %s\n", name, error); 4333 printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
4380 4334
4381 seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", 4335 sinfo->active_objs = active_objs;
4382 name, active_objs, num_objs, cachep->size, 4336 sinfo->num_objs = num_objs;
4383 cachep->num, (1 << cachep->gfporder)); 4337 sinfo->active_slabs = active_slabs;
4384 seq_printf(m, " : tunables %4u %4u %4u", 4338 sinfo->num_slabs = num_slabs;
4385 cachep->limit, cachep->batchcount, cachep->shared); 4339 sinfo->shared_avail = shared_avail;
4386 seq_printf(m, " : slabdata %6lu %6lu %6lu", 4340 sinfo->limit = cachep->limit;
4387 active_slabs, num_slabs, shared_avail); 4341 sinfo->batchcount = cachep->batchcount;
4342 sinfo->shared = cachep->shared;
4343 sinfo->objects_per_slab = cachep->num;
4344 sinfo->cache_order = cachep->gfporder;
4345}
4346
4347void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep)
4348{
4388#if STATS 4349#if STATS
4389 { /* list3 stats */ 4350 { /* list3 stats */
4390 unsigned long high = cachep->high_mark; 4351 unsigned long high = cachep->high_mark;
@@ -4414,31 +4375,8 @@ static int s_show(struct seq_file *m, void *p)
4414 allochit, allocmiss, freehit, freemiss); 4375 allochit, allocmiss, freehit, freemiss);
4415 } 4376 }
4416#endif 4377#endif
4417 seq_putc(m, '\n');
4418 return 0;
4419} 4378}
4420 4379
4421/*
4422 * slabinfo_op - iterator that generates /proc/slabinfo
4423 *
4424 * Output layout:
4425 * cache-name
4426 * num-active-objs
4427 * total-objs
4428 * object size
4429 * num-active-slabs
4430 * total-slabs
4431 * num-pages-per-slab
4432 * + further values on SMP and with statistics enabled
4433 */
4434
4435static const struct seq_operations slabinfo_op = {
4436 .start = s_start,
4437 .next = s_next,
4438 .stop = s_stop,
4439 .show = s_show,
4440};
4441
4442#define MAX_SLABINFO_WRITE 128 4380#define MAX_SLABINFO_WRITE 128
4443/** 4381/**
4444 * slabinfo_write - Tuning for the slab allocator 4382 * slabinfo_write - Tuning for the slab allocator
@@ -4447,7 +4385,7 @@ static const struct seq_operations slabinfo_op = {
4447 * @count: data length 4385 * @count: data length
4448 * @ppos: unused 4386 * @ppos: unused
4449 */ 4387 */
4450static ssize_t slabinfo_write(struct file *file, const char __user *buffer, 4388ssize_t slabinfo_write(struct file *file, const char __user *buffer,
4451 size_t count, loff_t *ppos) 4389 size_t count, loff_t *ppos)
4452{ 4390{
4453 char kbuf[MAX_SLABINFO_WRITE + 1], *tmp; 4391 char kbuf[MAX_SLABINFO_WRITE + 1], *tmp;
@@ -4490,19 +4428,6 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer,
4490 return res; 4428 return res;
4491} 4429}
4492 4430
4493static int slabinfo_open(struct inode *inode, struct file *file)
4494{
4495 return seq_open(file, &slabinfo_op);
4496}
4497
4498static const struct file_operations proc_slabinfo_operations = {
4499 .open = slabinfo_open,
4500 .read = seq_read,
4501 .write = slabinfo_write,
4502 .llseek = seq_lseek,
4503 .release = seq_release,
4504};
4505
4506#ifdef CONFIG_DEBUG_SLAB_LEAK 4431#ifdef CONFIG_DEBUG_SLAB_LEAK
4507 4432
4508static void *leaks_start(struct seq_file *m, loff_t *pos) 4433static void *leaks_start(struct seq_file *m, loff_t *pos)
@@ -4631,6 +4556,16 @@ static int leaks_show(struct seq_file *m, void *p)
4631 return 0; 4556 return 0;
4632} 4557}
4633 4558
4559static void *s_next(struct seq_file *m, void *p, loff_t *pos)
4560{
4561 return seq_list_next(p, &slab_caches, pos);
4562}
4563
4564static void s_stop(struct seq_file *m, void *p)
4565{
4566 mutex_unlock(&slab_mutex);
4567}
4568
4634static const struct seq_operations slabstats_op = { 4569static const struct seq_operations slabstats_op = {
4635 .start = leaks_start, 4570 .start = leaks_start,
4636 .next = s_next, 4571 .next = s_next,
@@ -4665,7 +4600,6 @@ static const struct file_operations proc_slabstats_operations = {
4665 4600
4666static int __init slab_proc_init(void) 4601static int __init slab_proc_init(void)
4667{ 4602{
4668 proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations);
4669#ifdef CONFIG_DEBUG_SLAB_LEAK 4603#ifdef CONFIG_DEBUG_SLAB_LEAK
4670 proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations); 4604 proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
4671#endif 4605#endif
diff --git a/mm/slab.h b/mm/slab.h
index 7deeb449a301..5a43c2f13621 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -47,4 +47,24 @@ static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t siz
47 47
48int __kmem_cache_shutdown(struct kmem_cache *); 48int __kmem_cache_shutdown(struct kmem_cache *);
49 49
50struct seq_file;
51struct file;
52
53struct slabinfo {
54 unsigned long active_objs;
55 unsigned long num_objs;
56 unsigned long active_slabs;
57 unsigned long num_slabs;
58 unsigned long shared_avail;
59 unsigned int limit;
60 unsigned int batchcount;
61 unsigned int shared;
62 unsigned int objects_per_slab;
63 unsigned int cache_order;
64};
65
66void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo);
67void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s);
68ssize_t slabinfo_write(struct file *file, const char __user *buffer,
69 size_t count, loff_t *ppos);
50#endif 70#endif
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 */
diff --git a/mm/slub.c b/mm/slub.c
index a0d698467f70..472e739278b4 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5405,49 +5405,14 @@ __initcall(slab_sysfs_init);
5405 * The /proc/slabinfo ABI 5405 * The /proc/slabinfo ABI
5406 */ 5406 */
5407#ifdef CONFIG_SLABINFO 5407#ifdef CONFIG_SLABINFO
5408static void print_slabinfo_header(struct seq_file *m) 5408void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo)
5409{
5410 seq_puts(m, "slabinfo - version: 2.1\n");
5411 seq_puts(m, "# name <active_objs> <num_objs> <object_size> "
5412 "<objperslab> <pagesperslab>");
5413 seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
5414 seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
5415 seq_putc(m, '\n');
5416}
5417
5418static void *s_start(struct seq_file *m, loff_t *pos)
5419{
5420 loff_t n = *pos;
5421
5422 mutex_lock(&slab_mutex);
5423 if (!n)
5424 print_slabinfo_header(m);
5425
5426 return seq_list_start(&slab_caches, *pos);
5427}
5428
5429static void *s_next(struct seq_file *m, void *p, loff_t *pos)
5430{
5431 return seq_list_next(p, &slab_caches, pos);
5432}
5433
5434static void s_stop(struct seq_file *m, void *p)
5435{
5436 mutex_unlock(&slab_mutex);
5437}
5438
5439static int s_show(struct seq_file *m, void *p)
5440{ 5409{
5441 unsigned long nr_partials = 0; 5410 unsigned long nr_partials = 0;
5442 unsigned long nr_slabs = 0; 5411 unsigned long nr_slabs = 0;
5443 unsigned long nr_inuse = 0;
5444 unsigned long nr_objs = 0; 5412 unsigned long nr_objs = 0;
5445 unsigned long nr_free = 0; 5413 unsigned long nr_free = 0;
5446 struct kmem_cache *s;
5447 int node; 5414 int node;
5448 5415
5449 s = list_entry(p, struct kmem_cache, list);
5450
5451 for_each_online_node(node) { 5416 for_each_online_node(node) {
5452 struct kmem_cache_node *n = get_node(s, node); 5417 struct kmem_cache_node *n = get_node(s, node);
5453 5418
@@ -5460,41 +5425,21 @@ static int s_show(struct seq_file *m, void *p)
5460 nr_free += count_partial(n, count_free); 5425 nr_free += count_partial(n, count_free);
5461 } 5426 }
5462 5427
5463 nr_inuse = nr_objs - nr_free; 5428 sinfo->active_objs = nr_objs - nr_free;
5464 5429 sinfo->num_objs = nr_objs;
5465 seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, 5430 sinfo->active_slabs = nr_slabs;
5466 nr_objs, s->size, oo_objects(s->oo), 5431 sinfo->num_slabs = nr_slabs;
5467 (1 << oo_order(s->oo))); 5432 sinfo->objects_per_slab = oo_objects(s->oo);
5468 seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0); 5433 sinfo->cache_order = oo_order(s->oo);
5469 seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs,
5470 0UL);
5471 seq_putc(m, '\n');
5472 return 0;
5473} 5434}
5474 5435
5475static const struct seq_operations slabinfo_op = { 5436void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s)
5476 .start = s_start,
5477 .next = s_next,
5478 .stop = s_stop,
5479 .show = s_show,
5480};
5481
5482static int slabinfo_open(struct inode *inode, struct file *file)
5483{ 5437{
5484 return seq_open(file, &slabinfo_op);
5485} 5438}
5486 5439
5487static const struct file_operations proc_slabinfo_operations = { 5440ssize_t slabinfo_write(struct file *file, const char __user *buffer,
5488 .open = slabinfo_open, 5441 size_t count, loff_t *ppos)
5489 .read = seq_read,
5490 .llseek = seq_lseek,
5491 .release = seq_release,
5492};
5493
5494static int __init slab_proc_init(void)
5495{ 5442{
5496 proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); 5443 return -EIO;
5497 return 0;
5498} 5444}
5499module_init(slab_proc_init);
5500#endif /* CONFIG_SLABINFO */ 5445#endif /* CONFIG_SLABINFO */