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 e7aec2001ae5..16274b273c61 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5399,49 +5399,14 @@ __initcall(slab_sysfs_init);
5399 * The /proc/slabinfo ABI 5399 * The /proc/slabinfo ABI
5400 */ 5400 */
5401#ifdef CONFIG_SLABINFO 5401#ifdef CONFIG_SLABINFO
5402static void print_slabinfo_header(struct seq_file *m) 5402void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo)
5403{
5404 seq_puts(m, "slabinfo - version: 2.1\n");
5405 seq_puts(m, "# name <active_objs> <num_objs> <object_size> "
5406 "<objperslab> <pagesperslab>");
5407 seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
5408 seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
5409 seq_putc(m, '\n');
5410}
5411
5412static void *s_start(struct seq_file *m, loff_t *pos)
5413{
5414 loff_t n = *pos;
5415
5416 mutex_lock(&slab_mutex);
5417 if (!n)
5418 print_slabinfo_header(m);
5419
5420 return seq_list_start(&slab_caches, *pos);
5421}
5422
5423static void *s_next(struct seq_file *m, void *p, loff_t *pos)
5424{
5425 return seq_list_next(p, &slab_caches, pos);
5426}
5427
5428static void s_stop(struct seq_file *m, void *p)
5429{
5430 mutex_unlock(&slab_mutex);
5431}
5432
5433static int s_show(struct seq_file *m, void *p)
5434{ 5403{
5435 unsigned long nr_partials = 0; 5404 unsigned long nr_partials = 0;
5436 unsigned long nr_slabs = 0; 5405 unsigned long nr_slabs = 0;
5437 unsigned long nr_inuse = 0;
5438 unsigned long nr_objs = 0; 5406 unsigned long nr_objs = 0;
5439 unsigned long nr_free = 0; 5407 unsigned long nr_free = 0;
5440 struct kmem_cache *s;
5441 int node; 5408 int node;
5442 5409
5443 s = list_entry(p, struct kmem_cache, list);
5444
5445 for_each_online_node(node) { 5410 for_each_online_node(node) {
5446 struct kmem_cache_node *n = get_node(s, node); 5411 struct kmem_cache_node *n = get_node(s, node);
5447 5412
@@ -5454,41 +5419,21 @@ static int s_show(struct seq_file *m, void *p)
5454 nr_free += count_partial(n, count_free); 5419 nr_free += count_partial(n, count_free);
5455 } 5420 }
5456 5421
5457 nr_inuse = nr_objs - nr_free; 5422 sinfo->active_objs = nr_objs - nr_free;
5458 5423 sinfo->num_objs = nr_objs;
5459 seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, 5424 sinfo->active_slabs = nr_slabs;
5460 nr_objs, s->size, oo_objects(s->oo), 5425 sinfo->num_slabs = nr_slabs;
5461 (1 << oo_order(s->oo))); 5426 sinfo->objects_per_slab = oo_objects(s->oo);
5462 seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0); 5427 sinfo->cache_order = oo_order(s->oo);
5463 seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs,
5464 0UL);
5465 seq_putc(m, '\n');
5466 return 0;
5467} 5428}
5468 5429
5469static const struct seq_operations slabinfo_op = { 5430void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s)
5470 .start = s_start,
5471 .next = s_next,
5472 .stop = s_stop,
5473 .show = s_show,
5474};
5475
5476static int slabinfo_open(struct inode *inode, struct file *file)
5477{ 5431{
5478 return seq_open(file, &slabinfo_op);
5479} 5432}
5480 5433
5481static const struct file_operations proc_slabinfo_operations = { 5434ssize_t slabinfo_write(struct file *file, const char __user *buffer,
5482 .open = slabinfo_open, 5435 size_t count, loff_t *ppos)
5483 .read = seq_read,
5484 .llseek = seq_lseek,
5485 .release = seq_release,
5486};
5487
5488static int __init slab_proc_init(void)
5489{ 5436{
5490 proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); 5437 return -EIO;
5491 return 0;
5492} 5438}
5493module_init(slab_proc_init);
5494#endif /* CONFIG_SLABINFO */ 5439#endif /* CONFIG_SLABINFO */