]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - mm/vmalloc.c
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-artful-kernel.git] / mm / vmalloc.c
index 285f0e7d28e71ac4ed039706a509fdc44cfa8d0c..0fdf96803c5b59623792a24e57015fb0e25098bb 100644 (file)
@@ -359,6 +359,12 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
        if (unlikely(!va))
                return ERR_PTR(-ENOMEM);
 
+       /*
+        * Only scan the relevant parts containing pointers to other objects
+        * to avoid false negatives.
+        */
+       kmemleak_scan_area(&va->rb_node, SIZE_MAX, gfp_mask & GFP_RECLAIM_MASK);
+
 retry:
        spin_lock(&vmap_area_lock);
        /*
@@ -1635,7 +1641,7 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
 
        addr = __vmalloc_area_node(area, gfp_mask, prot, node);
        if (!addr)
-               goto fail;
+               return NULL;
 
        /*
         * In this function, newly allocated vm_struct has VM_UNINITIALIZED
@@ -1645,11 +1651,11 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        clear_vm_uninitialized_flag(area);
 
        /*
-        * A ref_count = 3 is needed because the vm_struct and vmap_area
-        * structures allocated in the __get_vm_area_node() function contain
-        * references to the virtual address of the vmalloc'ed block.
+        * A ref_count = 2 is needed because vm_struct allocated in
+        * __get_vm_area_node() contains a reference to the virtual address of
+        * the vmalloc'ed block.
         */
-       kmemleak_alloc(addr, real_size, 3, gfp_mask);
+       kmemleak_alloc(addr, real_size, 2, gfp_mask);
 
        return addr;
 
@@ -2562,6 +2568,11 @@ static void show_numa_info(struct seq_file *m, struct vm_struct *v)
                if (!counters)
                        return;
 
+               /* Pair with smp_wmb() in clear_vm_uninitialized_flag() */
+               smp_rmb();
+               if (v->flags & VM_UNINITIALIZED)
+                       return;
+
                memset(counters, 0, nr_node_ids * sizeof(unsigned int));
 
                for (nr = 0; nr < v->nr_pages; nr++)
@@ -2578,23 +2589,15 @@ static int s_show(struct seq_file *m, void *p)
        struct vmap_area *va = p;
        struct vm_struct *v;
 
-       if (va->flags & (VM_LAZY_FREE | VM_LAZY_FREEING))
+       /*
+        * s_show can encounter race with remove_vm_area, !VM_VM_AREA on
+        * behalf of vmap area is being tear down or vm_map_ram allocation.
+        */
+       if (!(va->flags & VM_VM_AREA))
                return 0;
 
-       if (!(va->flags & VM_VM_AREA)) {
-               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);
-               return 0;
-       }
-
        v = va->vm;
 
-       /* Pair with smp_wmb() in clear_vm_uninitialized_flag() */
-       smp_rmb();
-       if (v->flags & VM_UNINITIALIZED)
-               return 0;
-
        seq_printf(m, "0x%pK-0x%pK %7ld",
                v->addr, v->addr + v->size, v->size);