diff options
-rw-r--r-- | mm/slab.c | 118 | ||||
-rw-r--r-- | mm/slab.h | 20 | ||||
-rw-r--r-- | mm/slab_common.c | 109 | ||||
-rw-r--r-- | mm/slub.c | 77 |
4 files changed, 166 insertions, 158 deletions
@@ -4276,54 +4276,8 @@ out: | |||
4276 | } | 4276 | } |
4277 | 4277 | ||
4278 | #ifdef CONFIG_SLABINFO | 4278 | #ifdef CONFIG_SLABINFO |
4279 | 4279 | void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo) | |
4280 | static 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 | |||
4303 | static 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 | |||
4314 | static void *s_next(struct seq_file *m, void *p, loff_t *pos) | ||
4315 | { | ||
4316 | return seq_list_next(p, &slab_caches, pos); | ||
4317 | } | ||
4318 | |||
4319 | static void s_stop(struct seq_file *m, void *p) | ||
4320 | { | ||
4321 | mutex_unlock(&slab_mutex); | ||
4322 | } | ||
4323 | |||
4324 | static 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 | |||
4347 | void 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 | |||
4435 | static 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 | */ |
4450 | static ssize_t slabinfo_write(struct file *file, const char __user *buffer, | 4388 | ssize_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 | ||
4493 | static int slabinfo_open(struct inode *inode, struct file *file) | ||
4494 | { | ||
4495 | return seq_open(file, &slabinfo_op); | ||
4496 | } | ||
4497 | |||
4498 | static 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 | ||
4508 | static void *leaks_start(struct seq_file *m, loff_t *pos) | 4433 | static 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 | ||
4559 | static void *s_next(struct seq_file *m, void *p, loff_t *pos) | ||
4560 | { | ||
4561 | return seq_list_next(p, &slab_caches, pos); | ||
4562 | } | ||
4563 | |||
4564 | static void s_stop(struct seq_file *m, void *p) | ||
4565 | { | ||
4566 | mutex_unlock(&slab_mutex); | ||
4567 | } | ||
4568 | |||
4634 | static const struct seq_operations slabstats_op = { | 4569 | static 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 | ||
4666 | static int __init slab_proc_init(void) | 4601 | static 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 |
@@ -47,4 +47,24 @@ static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t siz | |||
47 | 47 | ||
48 | int __kmem_cache_shutdown(struct kmem_cache *); | 48 | int __kmem_cache_shutdown(struct kmem_cache *); |
49 | 49 | ||
50 | struct seq_file; | ||
51 | struct file; | ||
52 | |||
53 | struct 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 | |||
66 | void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo); | ||
67 | void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s); | ||
68 | ssize_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 | ||
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 */ | ||
@@ -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 |
5402 | static void print_slabinfo_header(struct seq_file *m) | 5402 | void 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 | |||
5412 | static 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 | |||
5423 | static void *s_next(struct seq_file *m, void *p, loff_t *pos) | ||
5424 | { | ||
5425 | return seq_list_next(p, &slab_caches, pos); | ||
5426 | } | ||
5427 | |||
5428 | static void s_stop(struct seq_file *m, void *p) | ||
5429 | { | ||
5430 | mutex_unlock(&slab_mutex); | ||
5431 | } | ||
5432 | |||
5433 | static 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 | ||
5469 | static const struct seq_operations slabinfo_op = { | 5430 | void 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 | |||
5476 | static int slabinfo_open(struct inode *inode, struct file *file) | ||
5477 | { | 5431 | { |
5478 | return seq_open(file, &slabinfo_op); | ||
5479 | } | 5432 | } |
5480 | 5433 | ||
5481 | static const struct file_operations proc_slabinfo_operations = { | 5434 | ssize_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 | |||
5488 | static 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 | } |
5493 | module_init(slab_proc_init); | ||
5494 | #endif /* CONFIG_SLABINFO */ | 5439 | #endif /* CONFIG_SLABINFO */ |