mm: vmalloc: support multiple nodes in vmallocinfo
authorUladzislau Rezki (Sony) <urezki@gmail.com>
Tue, 2 Jan 2024 18:46:31 +0000 (19:46 +0100)
committerAndrew Morton <akpm@linux-foundation.org>
Sat, 24 Feb 2024 01:48:20 +0000 (17:48 -0800)
Allocated areas are spread among nodes, it implies that the scanning has
to be performed individually of each node in order to dump all existing
VAs.

Link: https://lkml.kernel.org/r/20240102184633.748113-10-urezki@gmail.com
Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Joel Fernandes (Google) <joel@joelfernandes.org>
Cc: Kazuhito Hagio <k-hagio-ab@nec.com>
Cc: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Oleksiy Avramchenko <oleksiy.avramchenko@sony.com>
Cc: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/vmalloc.c

index 5a2db5b66333b951175943e71a3f36daa5dc21f8..41f924a9b52e95cce22c279b96494d46ca0b20eb 100644 (file)
@@ -4709,30 +4709,6 @@ bool vmalloc_dump_obj(void *object)
 #endif
 
 #ifdef CONFIG_PROC_FS
-static void *s_start(struct seq_file *m, loff_t *pos)
-{
-       struct vmap_node *vn = addr_to_node(0);
-
-       mutex_lock(&vmap_purge_lock);
-       spin_lock(&vn->busy.lock);
-
-       return seq_list_start(&vn->busy.head, *pos);
-}
-
-static void *s_next(struct seq_file *m, void *p, loff_t *pos)
-{
-       struct vmap_node *vn = addr_to_node(0);
-       return seq_list_next(p, &vn->busy.head, pos);
-}
-
-static void s_stop(struct seq_file *m, void *p)
-{
-       struct vmap_node *vn = addr_to_node(0);
-
-       spin_unlock(&vn->busy.lock);
-       mutex_unlock(&vmap_purge_lock);
-}
-
 static void show_numa_info(struct seq_file *m, struct vm_struct *v)
 {
        if (IS_ENABLED(CONFIG_NUMA)) {
@@ -4776,84 +4752,82 @@ static void show_purge_info(struct seq_file *m)
        }
 }
 
-static int s_show(struct seq_file *m, void *p)
+static int vmalloc_info_show(struct seq_file *m, void *p)
 {
        struct vmap_node *vn;
        struct vmap_area *va;
        struct vm_struct *v;
+       int i;
 
-       vn = addr_to_node(0);
-       va = list_entry(p, struct vmap_area, list);
+       for (i = 0; i < nr_vmap_nodes; i++) {
+               vn = &vmap_nodes[i];
 
-       if (!va->vm) {
-               if (va->flags & VMAP_RAM)
-                       seq_printf(m, "0x%pK-0x%pK %7ld vm_map_ram\n",
-                               (void *)va->va_start, (void *)va->va_end,
-                               va->va_end - va->va_start);
+               spin_lock(&vn->busy.lock);
+               list_for_each_entry(va, &vn->busy.head, list) {
+                       if (!va->vm) {
+                               if (va->flags & VMAP_RAM)
+                                       seq_printf(m, "0x%pK-0x%pK %7ld vm_map_ram\n",
+                                               (void *)va->va_start, (void *)va->va_end,
+                                               va->va_end - va->va_start);
 
-               goto final;
-       }
+                               continue;
+                       }
 
-       v = va->vm;
+                       v = va->vm;
 
-       seq_printf(m, "0x%pK-0x%pK %7ld",
-               v->addr, v->addr + v->size, v->size);
+                       seq_printf(m, "0x%pK-0x%pK %7ld",
+                               v->addr, v->addr + v->size, v->size);
 
-       if (v->caller)
-               seq_printf(m, " %pS", v->caller);
+                       if (v->caller)
+                               seq_printf(m, " %pS", v->caller);
 
-       if (v->nr_pages)
-               seq_printf(m, " pages=%d", v->nr_pages);
+                       if (v->nr_pages)
+                               seq_printf(m, " pages=%d", v->nr_pages);
 
-       if (v->phys_addr)
-               seq_printf(m, " phys=%pa", &v->phys_addr);
+                       if (v->phys_addr)
+                               seq_printf(m, " phys=%pa", &v->phys_addr);
 
-       if (v->flags & VM_IOREMAP)
-               seq_puts(m, " ioremap");
+                       if (v->flags & VM_IOREMAP)
+                               seq_puts(m, " ioremap");
 
-       if (v->flags & VM_ALLOC)
-               seq_puts(m, " vmalloc");
+                       if (v->flags & VM_ALLOC)
+                               seq_puts(m, " vmalloc");
 
-       if (v->flags & VM_MAP)
-               seq_puts(m, " vmap");
+                       if (v->flags & VM_MAP)
+                               seq_puts(m, " vmap");
 
-       if (v->flags & VM_USERMAP)
-               seq_puts(m, " user");
+                       if (v->flags & VM_USERMAP)
+                               seq_puts(m, " user");
 
-       if (v->flags & VM_DMA_COHERENT)
-               seq_puts(m, " dma-coherent");
+                       if (v->flags & VM_DMA_COHERENT)
+                               seq_puts(m, " dma-coherent");
 
-       if (is_vmalloc_addr(v->pages))
-               seq_puts(m, " vpages");
+                       if (is_vmalloc_addr(v->pages))
+                               seq_puts(m, " vpages");
 
-       show_numa_info(m, v);
-       seq_putc(m, '\n');
+                       show_numa_info(m, v);
+                       seq_putc(m, '\n');
+               }
+               spin_unlock(&vn->busy.lock);
+       }
 
        /*
         * As a final step, dump "unpurged" areas.
         */
-final:
-       if (list_is_last(&va->list, &vn->busy.head))
-               show_purge_info(m);
-
+       show_purge_info(m);
        return 0;
 }
 
-static const struct seq_operations vmalloc_op = {
-       .start = s_start,
-       .next = s_next,
-       .stop = s_stop,
-       .show = s_show,
-};
-
 static int __init proc_vmalloc_init(void)
 {
+       void *priv_data = NULL;
+
        if (IS_ENABLED(CONFIG_NUMA))
-               proc_create_seq_private("vmallocinfo", 0400, NULL,
-                               &vmalloc_op,
-                               nr_node_ids * sizeof(unsigned int), NULL);
-       else
-               proc_create_seq("vmallocinfo", 0400, NULL, &vmalloc_op);
+               priv_data = kmalloc(nr_node_ids * sizeof(unsigned int), GFP_KERNEL);
+
+       proc_create_single_data("vmallocinfo",
+               0400, NULL, vmalloc_info_show, priv_data);
+
        return 0;
 }
 module_init(proc_vmalloc_init);