vmalloc fixes and improvements #2
Subsystems (2)
cover vmalloc fixes and improvements #2
Hopefully got attribution right.
Patches 1-3 fix "[Bug #11903] regression: vmalloc easily fail", and these should go upstream for 2.6.28. They've been tested and shown to fix the problem, and I've tested them here on my XFS stress test as well. The off-by-one bug, I tested and verified in a userspace test harness (it doesn't actually cause any corruption, but just suboptimal use of space).
Patches 4,5 are improvements to information exported to user. Not very risky, but not urgent either.
Patches 6,7 improve locking and debugging modes a bit. I have not included the changes to guard pages this time. They need a bit more explanation and code review to justify. And probably some more philosophical discussions on the mm list...
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 1/7 mm: vmalloc allocator off by one
Fix off by one bug in the KVA allocator that can leave gaps in the address space.
---
mm/vmalloc.c +1 -1
@@ -362,7 +362,7 @@ retry: goto found; } -while (addr + size >= first->va_start && addr + size <= vend) { +while (addr + size > first->va_start && addr + size <= vend) { addr =ALIGN (first->va_end +PAGE_SIZE , align); n =rb_next (&first->rb_node);
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 2/7 mm: vmalloc failure flush fix
In reply to [email protected]An initial vmalloc failure should start off a synchronous flush of lazy areas, in case someone is in progress flushing them already, which could cause us to return an allocation failure even if there is plenty of KVA free.
---
mm/vmalloc.c +13 -2
@@ -522,13 +522,24 @@ static void __purge_vmap_area_lazy(unsig }/* +* Kick off a purge of the outstanding lazy areas. Don't bother if somebody +* is already purging. +*/ +static void try_purge_vmap_area_lazy (void ) +{ +unsigned long start =ULONG_MAX , end =0 ; + +__purge_vmap_area_lazy (&start, &end,0 ,0 ); +} + +/* * Kick off a purge of the outstanding lazy areas. */ static void purge_vmap_area_lazy (void ) {unsigned long start =ULONG_MAX , end =0 ; -__purge_vmap_area_lazy (&start, &end,0 ,0 ); +__purge_vmap_area_lazy (&start, &end,1 ,0 ); }/*
@@ -539,7 +550,7 @@ static void free_unmap_vmap_area(struct va->flags |=VM_LAZY_FREE ;atomic_add ((va->va_end - va->va_start) >>PAGE_SHIFT , &vmap_lazy_nr);if (unlikely (atomic_read (&vmap_lazy_nr) >lazy_max_pages ())) -purge_vmap_area_lazy (); +try_purge_vmap_area_lazy (); }static struct vmap_area *find_vmap_area (unsigned long addr)
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 3/7 mm: vmalloc search restart fix
In reply to [email protected]Current vmalloc restart search for a free area in case we can't find one. The reason is there are areas which are lazily freed, and could be possibly freed now. However, current implementation start searching the tree from the last failing address, which is pretty much by definition at the end of address space. So, we fail.
The proposal of this patch is to restart the search from the beginning of the requested vstart address. This fixes the regression in running KVM virtual machines for me, described in http://lkml.org/lkml/2008/10/28/349, caused by commit db64fe02258f1507e13fe5212a989922323685ce.
--- mm/vmalloc.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
mm/vmalloc.c +2 -2
@@ -324,14 +324,14 @@ static struct vmap_area *alloc_vmap_areaBUG_ON (size & ~PAGE_MASK ); - addr =ALIGN (vstart, align); - va =kmalloc_node (sizeof (struct vmap_area ), gfp_mask &GFP_RECLAIM_MASK , node);if (unlikely (!va))return ERR_PTR (-ENOMEM ); retry: + addr =ALIGN (vstart, align); +spin_lock (&vmap_area_lock);/* XXX: could have a last_hole cache */ n = vmap_area_root.rb_node;
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 4/7 mm: vmalloc tweak failure printk
In reply to [email protected]If we can't service a vmalloc allocation, show size of the allocation that actually failed. Useful for debugging.
--- mm/vmalloc.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
mm/vmalloc.c +3 -2
@@ -381,8 +381,9 @@ found: goto retry; }if (printk_ratelimit ()) -printk (KERN_WARNING "vmap allocation failed: " -"use vmalloc=<size> to increase size.\n" ); +printk (KERN_WARNING +"vmap allocation for size %lu failed: " +"use vmalloc=<size> to increase size.\n" , size);return ERR_PTR (-EBUSY ); }
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 5/7 mm: vmalloc improve vmallocinfo
In reply to [email protected]If we do that, output of files like /proc/vmallocinfo will show things like "vmalloc_32", "vmalloc_user", or whomever the caller was as the caller. This info is not as useful as the real caller of the allocation.
So, proposal is to call __vmalloc_node node directly, with matching parameters to save the caller information
--- mm/vmalloc.c | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-)
mm/vmalloc.c +8 -4
@@ -1356,7 +1356,8 @@ void *vmalloc_user(unsigned long size)struct vm_struct *area;void *ret; - ret =__vmalloc (size,GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,PAGE_KERNEL ); + ret =__vmalloc_node (size,GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, +PAGE_KERNEL ,-1 ,__builtin_return_address (0 ));if (ret) { area =find_vm_area (ret); area->flags |=VM_USERMAP ;
@@ -1401,7 +1402,8 @@ EXPORT_SYMBOL(vmalloc_node);void *vmalloc_exec (unsigned long size) { -return __vmalloc (size,GFP_KERNEL | __GFP_HIGHMEM,PAGE_KERNEL_EXEC ); +return __vmalloc_node (size,GFP_KERNEL | __GFP_HIGHMEM,PAGE_KERNEL_EXEC , +-1 ,__builtin_return_address (0 )); }#if defined(CONFIG_64BIT ) && defined(CONFIG_ZONE_DMA32 )
@@ -1421,7 +1423,8 @@ void *vmalloc_exec(unsigned long size)*/ void *vmalloc_32 (unsigned long size) { -return __vmalloc (size,GFP_VMALLOC32 ,PAGE_KERNEL ); +return __vmalloc_node (size,GFP_VMALLOC32 ,PAGE_KERNEL , +-1 ,__builtin_return_address (0 )); }EXPORT_SYMBOL (vmalloc_32);
@@ -1437,7 +1440,8 @@ void *vmalloc_32_user(unsigned long sizestruct vm_struct *area;void *ret; - ret =__vmalloc (size,GFP_VMALLOC32 | __GFP_ZERO,PAGE_KERNEL ); + ret =__vmalloc_node (size,GFP_VMALLOC32 | __GFP_ZERO,PAGE_KERNEL , +-1 ,__builtin_return_address (0 ));if (ret) { area =find_vm_area (ret); area->flags |=VM_USERMAP ;
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 6/7 mm: vmalloc use mutex for purge
In reply to [email protected]The vmalloc purge lock can be a mutex so we can sleep while a purge is going on (purge involves a global kernel TLB invalidate, so it can take quite a while).
---
mm/vmalloc.c +5 -4
@@ -14,6 +14,7 @@#include <linux/highmem.h> #include <linux/slab.h> #include <linux/spinlock.h> +#include <linux/mutex.h> #include <linux/interrupt.h> #include <linux/proc_fs.h> #include <linux/seq_file.h>
@@ -473,7 +474,7 @@ static atomic_t vmap_lazy_nr = ATOMIC_INstatic void __purge_vmap_area_lazy (unsigned long *start,unsigned long *end,int sync,int force_flush) { -static DEFINE_SPINLOCK (purge_lock); +static DEFINE_MUTEX (purge_lock);LIST_HEAD (valist);struct vmap_area *va;int nr =0 ;
@@ -484,10 +485,10 @@ static void __purge_vmap_area_lazy(unsig* the case that isn't actually used at the moment anyway. */ if (!sync && !force_flush) { -if (!spin_trylock (&purge_lock)) +if (!mutex_trylock (&purge_lock))return ; }else -spin_lock (&purge_lock); +mutex_lock (&purge_lock);rcu_read_lock ();list_for_each_entry_rcu (va, &vmap_area_list, list) {
@@ -519,7 +520,7 @@ static void __purge_vmap_area_lazy(unsig__free_vmap_area (va);spin_unlock (&vmap_area_lock); } -spin_unlock (&purge_lock); +mutex_unlock (&purge_lock); }/*
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 7/7 mm: vmalloc make lazy unmapping configurable
In reply to [email protected]Lazy unmapping in the vmalloc code has now opened the possibility for use after free bugs to go undetected. We can catch those by forcing an unmap and flush (which is going to be slow, but that's what happens).
---
mm/vmalloc.c +24 -0
@@ -434,6 +434,27 @@ static void unmap_vmap_area(struct vmap_vunmap_page_range (va->va_start, va->va_end); } +static void vmap_debug_free_range (unsigned long start,unsigned long end) +{ +/* +* Unmap page tables and force a TLB flush immediately if +* CONFIG_DEBUG_PAGEALLOC is set. This catches use after free +* bugs similarly to those in linear kernel virtual address +* space after a page has been freed. +* +* All the lazy freeing logic is still retained, in order to +* minimise intrusiveness of this debugging feature. +* +* This is going to be *slow* (linear kernel virtual address +* debugging doesn't do a broadcast TLB flush so it is a lot +* faster). +*/ +#ifdef CONFIG_DEBUG_PAGEALLOC +vunmap_page_range (start, end); +flush_tlb_kernel_range (start, end); +#endif +} +/* * lazy_max_pages is the maximum amount of virtual address space we gather up * before attempting to purge with a TLB flush.
@@ -896,6 +917,7 @@ void vm_unmap_ram(const void *mem, unsigBUG_ON (addr & (PAGE_SIZE -1 ));debug_check_no_locks_freed (mem, size); +vmap_debug_free_range (addr, addr+size);if (likely (count <=VMAP_MAX_ALLOC ))vb_free (mem, size);
@@ -1110,6 +1132,8 @@ struct vm_struct *remove_vm_area(const vif (va && va->flags &VM_VM_AREA ) {struct vm_struct *vm = va->private;struct vm_struct *tmp, **p; + +vmap_debug_free_range (va->va_start, va->va_end);free_unmap_vmap_area (va); vm->size -=PAGE_SIZE ;
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 8 lines · On Tue, Nov 11, 2008 at 12:35:15AM +1100, [email protected] wrote:
Hopefully got attribution right.
Patches 1-3 fix "[Bug #11903] regression: vmalloc easily fail", and these should go upstream for 2.6.28. They've been tested and shown to fix the problem, and I've tested them here on my XFS stress test as well. The off-by-one bug, I tested and verified in a userspace test harness (it doesn't actually cause any corruption, but just suboptimal use of space).
Quoted 9 lines
Patches 4,5 are improvements to information exported to user. Not very risky, but not urgent either.
Patches 6,7 improve locking and debugging modes a bit. I have not included the changes to guard pages this time. They need a bit more explanation and code review to justify. And probably some more philosophical discussions on the mm list...
ok, news on this one inclusion?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 12 lines · Glauber Costa
Quoted 11 lines · On Tue, Nov 11, 2008 at 12:35:15AM +1100, [email protected] wrote:
Hopefully got attribution right.
Patches 1-3 fix "[Bug #11903] regression: vmalloc easily fail", and these should go upstream for 2.6.28. They've been tested and shown to fix the problem, and I've tested them here on my XFS stress test as well. The off-by-one bug, I tested and verified in a userspace test harness (it doesn't actually cause any corruption, but just suboptimal use of space).
Patches 4,5 are improvements to information exported to user. Not very risky, but not urgent either.
Quoted 8 lines
Quoted 6 lines
Patches 6,7 improve locking and debugging modes a bit. I have not included the changes to guard pages this time. They need a bit more explanation and code review to justify. And probably some more philosophical discussions on the mm list...
ok, news on this one inclusion?
Just waiting on Andrew. It won't get lost :)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>