diff options
author | Joonsoo Kim <js1304@gmail.com> | 2013-04-29 18:07:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 18:54:34 -0400 |
commit | d4033afdf8282802ad28b0ed854393454115a071 (patch) | |
tree | 6a2995430f294e8349c02f5b5c2b4e460ce2bb7b /mm/vmalloc.c | |
parent | f98782ddd31ac6f938386b79d8bd7aa7c8a78c50 (diff) |
mm, vmalloc: iterate vmap_area_list, instead of vmlist, in vmallocinfo()
This patch is a preparatory step for removing vmlist entirely. For
above purpose, we change iterating a vmap_list codes to iterating a
vmap_area_list. It is somewhat trivial change, but just one thing
should be noticed.
Using vmap_area_list in vmallocinfo() introduce ordering problem in SMP
system. In s_show(), we retrieve some values from vm_struct.
vm_struct's values is not fully setup when va->vm is assigned. Full
setup is notified by removing VM_UNLIST flag without holding a lock.
When we see that VM_UNLIST is removed, it is not ensured that vm_struct
has proper values in view of other CPUs. So we need smp_[rw]mb for
ensuring that proper values is assigned when we see that VM_UNLIST is
removed.
Therefore, this patch not only change a iteration list, but also add a
appropriate smp_[rw]mb to right places.
Signed-off-by: Joonsoo Kim <js1304@gmail.com>
Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Atsushi Kumagai <kumagai-atsushi@mxc.nes.nec.co.jp>
Cc: Chris Metcalf <cmetcalf@tilera.com>
Cc: Dave Anderson <anderson@redhat.com>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r-- | mm/vmalloc.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index aee1f61727a3..bda6cef5b97f 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -1304,7 +1304,14 @@ static void insert_vmalloc_vmlist(struct vm_struct *vm) | |||
1304 | { | 1304 | { |
1305 | struct vm_struct *tmp, **p; | 1305 | struct vm_struct *tmp, **p; |
1306 | 1306 | ||
1307 | /* | ||
1308 | * Before removing VM_UNLIST, | ||
1309 | * we should make sure that vm has proper values. | ||
1310 | * Pair with smp_rmb() in show_numa_info(). | ||
1311 | */ | ||
1312 | smp_wmb(); | ||
1307 | vm->flags &= ~VM_UNLIST; | 1313 | vm->flags &= ~VM_UNLIST; |
1314 | |||
1308 | write_lock(&vmlist_lock); | 1315 | write_lock(&vmlist_lock); |
1309 | for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) { | 1316 | for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) { |
1310 | if (tmp->addr >= vm->addr) | 1317 | if (tmp->addr >= vm->addr) |
@@ -2542,19 +2549,19 @@ void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms) | |||
2542 | 2549 | ||
2543 | #ifdef CONFIG_PROC_FS | 2550 | #ifdef CONFIG_PROC_FS |
2544 | static void *s_start(struct seq_file *m, loff_t *pos) | 2551 | static void *s_start(struct seq_file *m, loff_t *pos) |
2545 | __acquires(&vmlist_lock) | 2552 | __acquires(&vmap_area_lock) |
2546 | { | 2553 | { |
2547 | loff_t n = *pos; | 2554 | loff_t n = *pos; |
2548 | struct vm_struct *v; | 2555 | struct vmap_area *va; |
2549 | 2556 | ||
2550 | read_lock(&vmlist_lock); | 2557 | spin_lock(&vmap_area_lock); |
2551 | v = vmlist; | 2558 | va = list_entry((&vmap_area_list)->next, typeof(*va), list); |
2552 | while (n > 0 && v) { | 2559 | while (n > 0 && &va->list != &vmap_area_list) { |
2553 | n--; | 2560 | n--; |
2554 | v = v->next; | 2561 | va = list_entry(va->list.next, typeof(*va), list); |
2555 | } | 2562 | } |
2556 | if (!n) | 2563 | if (!n && &va->list != &vmap_area_list) |
2557 | return v; | 2564 | return va; |
2558 | 2565 | ||
2559 | return NULL; | 2566 | return NULL; |
2560 | 2567 | ||
@@ -2562,16 +2569,20 @@ static void *s_start(struct seq_file *m, loff_t *pos) | |||
2562 | 2569 | ||
2563 | static void *s_next(struct seq_file *m, void *p, loff_t *pos) | 2570 | static void *s_next(struct seq_file *m, void *p, loff_t *pos) |
2564 | { | 2571 | { |
2565 | struct vm_struct *v = p; | 2572 | struct vmap_area *va = p, *next; |
2566 | 2573 | ||
2567 | ++*pos; | 2574 | ++*pos; |
2568 | return v->next; | 2575 | next = list_entry(va->list.next, typeof(*va), list); |
2576 | if (&next->list != &vmap_area_list) | ||
2577 | return next; | ||
2578 | |||
2579 | return NULL; | ||
2569 | } | 2580 | } |
2570 | 2581 | ||
2571 | static void s_stop(struct seq_file *m, void *p) | 2582 | static void s_stop(struct seq_file *m, void *p) |
2572 | __releases(&vmlist_lock) | 2583 | __releases(&vmap_area_lock) |
2573 | { | 2584 | { |
2574 | read_unlock(&vmlist_lock); | 2585 | spin_unlock(&vmap_area_lock); |
2575 | } | 2586 | } |
2576 | 2587 | ||
2577 | static void show_numa_info(struct seq_file *m, struct vm_struct *v) | 2588 | static void show_numa_info(struct seq_file *m, struct vm_struct *v) |
@@ -2582,6 +2593,11 @@ static void show_numa_info(struct seq_file *m, struct vm_struct *v) | |||
2582 | if (!counters) | 2593 | if (!counters) |
2583 | return; | 2594 | return; |
2584 | 2595 | ||
2596 | /* Pair with smp_wmb() in insert_vmalloc_vmlist() */ | ||
2597 | smp_rmb(); | ||
2598 | if (v->flags & VM_UNLIST) | ||
2599 | return; | ||
2600 | |||
2585 | memset(counters, 0, nr_node_ids * sizeof(unsigned int)); | 2601 | memset(counters, 0, nr_node_ids * sizeof(unsigned int)); |
2586 | 2602 | ||
2587 | for (nr = 0; nr < v->nr_pages; nr++) | 2603 | for (nr = 0; nr < v->nr_pages; nr++) |
@@ -2595,7 +2611,20 @@ static void show_numa_info(struct seq_file *m, struct vm_struct *v) | |||
2595 | 2611 | ||
2596 | static int s_show(struct seq_file *m, void *p) | 2612 | static int s_show(struct seq_file *m, void *p) |
2597 | { | 2613 | { |
2598 | struct vm_struct *v = p; | 2614 | struct vmap_area *va = p; |
2615 | struct vm_struct *v; | ||
2616 | |||
2617 | if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING)) | ||
2618 | return 0; | ||
2619 | |||
2620 | if (!(va->flags & VM_VM_AREA)) { | ||
2621 | seq_printf(m, "0x%pK-0x%pK %7ld vm_map_ram\n", | ||
2622 | (void *)va->va_start, (void *)va->va_end, | ||
2623 | va->va_end - va->va_start); | ||
2624 | return 0; | ||
2625 | } | ||
2626 | |||
2627 | v = va->vm; | ||
2599 | 2628 | ||
2600 | seq_printf(m, "0x%pK-0x%pK %7ld", | 2629 | seq_printf(m, "0x%pK-0x%pK %7ld", |
2601 | v->addr, v->addr + v->size, v->size); | 2630 | v->addr, v->addr + v->size, v->size); |